workflow_state_service.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. import json
  2. from django.db.models import Q
  3. from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  4. from apps.workflow.models import State
  5. from service.account.account_base_service import account_base_service_ins
  6. from service.base_service import BaseService
  7. from service.common.constant_service import constant_service_ins
  8. from service.common.log_service import auto_log
  9. from service.workflow.workflow_custom_field_service import workflow_custom_field_service_ins
  10. from service.workflow.workflow_runscript_service import workflow_run_script_service_ins
  11. from service.workflow.workflow_transition_service import workflow_transition_service_ins
  12. class WorkflowStateService(BaseService):
  13. def __init__(self):
  14. pass
  15. @staticmethod
  16. @auto_log
  17. def get_workflow_states(workflow_id: int)->tuple:
  18. """
  19. 获取流程的状态列表,每个流程的state不会很多,所以不分页
  20. get workflow state queryset
  21. :param workflow_id:
  22. :return:
  23. """
  24. if not workflow_id:
  25. return False, 'except workflow_id but not provided'
  26. else:
  27. workflow_states = State.objects.filter(workflow_id=workflow_id, is_deleted=False).order_by('order_id')
  28. return True, workflow_states
  29. @staticmethod
  30. @auto_log
  31. def get_workflow_states_serialize(workflow_id: int, per_page: int=10, page: int=1, query_value: str='', simple=False)->tuple:
  32. """
  33. 获取序列化工作流状态记录
  34. get restful workflow's state by params
  35. :param workflow_id:
  36. :param per_page:
  37. :param page:
  38. :param query_value:
  39. :param simle: 是否只返回简单数据
  40. :return:
  41. """
  42. if not workflow_id:
  43. return False, 'except workflow_id but not provided'
  44. query_params = Q(workflow_id=workflow_id, is_deleted=False)
  45. if query_value:
  46. query_params &= Q(name__contains=query_value)
  47. workflow_states = State.objects.filter(query_params).order_by('order_id')
  48. paginator = Paginator(workflow_states, per_page)
  49. try:
  50. workflow_states_result_paginator = paginator.page(page)
  51. except PageNotAnInteger:
  52. workflow_states_result_paginator = paginator.page(1)
  53. except EmptyPage:
  54. # If page is out of range (e.g. 9999), deliver last page of results
  55. workflow_states_result_paginator = paginator.page(paginator.num_pages)
  56. workflow_states_object_list = workflow_states_result_paginator.object_list
  57. workflow_states_restful_list = []
  58. for workflow_states_object in workflow_states_object_list:
  59. flag, participant_info = WorkflowStateService.get_format_participant_info(
  60. workflow_states_object.participant_type_id, workflow_states_object.participant)
  61. result_dict = workflow_states_object.get_dict()
  62. result_dict['state_field_str'] = json.loads(result_dict['state_field_str'])
  63. result_dict['label'] = json.loads(result_dict['label'])
  64. result_dict['participant_info'] = participant_info
  65. if simple:
  66. result_new_dict = dict(id=workflow_states_object.id, name=workflow_states_object.name)
  67. result_dict = result_new_dict
  68. workflow_states_restful_list.append(result_dict)
  69. return True, dict(workflow_states_restful_list=workflow_states_restful_list,
  70. paginator_info=dict(per_page=per_page, page=page, total=paginator.count))
  71. @staticmethod
  72. @auto_log
  73. def get_workflow_state_by_id(state_id: int)->tuple:
  74. """
  75. 获取state详情
  76. get state info by id
  77. :param state_id:
  78. :return:
  79. """
  80. if not state_id:
  81. return False, 'except state_id but not provided'
  82. else:
  83. workflow_state = State.objects.filter(id=state_id, is_deleted=False).first()
  84. if not workflow_state:
  85. return False, '工单状态不存在或已被删除'
  86. return True, workflow_state
  87. @classmethod
  88. @auto_log
  89. def get_restful_state_info_by_id(cls, state_id: int)->tuple:
  90. if not state_id:
  91. return False, 'except state_id but not provided'
  92. else:
  93. workflow_state = State.objects.filter(id=state_id, is_deleted=False).first()
  94. if not workflow_state:
  95. return False, '工单状态不存在或已被删除'
  96. state_info_dict = dict(
  97. id=workflow_state.id, name=workflow_state.name, workflow_id=workflow_state.workflow_id,
  98. distribute_type_id=workflow_state.distribute_type_id,
  99. is_hidden=workflow_state.is_hidden, order_id=workflow_state.order_id, type_id=workflow_state.type_id,
  100. participant_type_id=workflow_state.participant_type_id, participant=workflow_state.participant,
  101. state_field=json.loads(workflow_state.state_field_str), label=json.loads(workflow_state.label),
  102. creator=workflow_state.creator, gmt_created=str(workflow_state.gmt_created)[:19])
  103. return True, state_info_dict
  104. @classmethod
  105. @auto_log
  106. def get_workflow_start_state(cls, workflow_id: int)->tuple:
  107. """
  108. 获取工作流初始状态
  109. get workflow's init state
  110. :param workflow_id:
  111. :return:
  112. """
  113. workflow_state_obj = State.objects.filter(
  114. is_deleted=0, workflow_id=workflow_id, type_id=constant_service_ins.STATE_TYPE_START).first()
  115. if workflow_state_obj:
  116. return True, workflow_state_obj
  117. else:
  118. return False, 'This workflow have no init state, please check the config'
  119. @classmethod
  120. @auto_log
  121. def get_states_info_by_state_id_list(cls, state_id_list)->tuple:
  122. state_queryset = State.objects.filter(is_deleted=0, id__in=state_id_list).all()
  123. state_info_dict = {}
  124. for state in state_queryset:
  125. state_dict = state.get_dict()
  126. state_info_dict[state.id] = state_dict
  127. return True, state_info_dict
  128. @classmethod
  129. @auto_log
  130. def get_workflow_end_state(cls, workflow_id: int)->tuple:
  131. """
  132. 获取工作流结束状态
  133. get workflow's end state
  134. :param workflow_id:
  135. :return:
  136. """
  137. workflow_state_obj = State.objects.filter(
  138. is_deleted=0, workflow_id=workflow_id, type_id=constant_service_ins.STATE_TYPE_END).first()
  139. if workflow_state_obj:
  140. return True, workflow_state_obj
  141. else:
  142. return False, '该工作流未配置结束状态,请检查工作流配置'
  143. @classmethod
  144. @auto_log
  145. def get_workflow_init_state(cls, workflow_id: int)->tuple:
  146. """
  147. 获取工作流的初始状态信息,包括允许的transition
  148. get workflow's init state, include allow transition
  149. :param workflow_id:
  150. :return:
  151. """
  152. init_state_obj = State.objects.filter(workflow_id=workflow_id, is_deleted=False, type_id=constant_service_ins.STATE_TYPE_START).first()
  153. if not init_state_obj:
  154. return False, '该工作流尚未配置初始状态'
  155. flag, transition_queryset = workflow_transition_service_ins.get_state_transition_queryset(init_state_obj.id)
  156. if flag is False:
  157. return False, transition_queryset
  158. transition_info_list = []
  159. for transition in transition_queryset:
  160. transition_info_dict = dict(
  161. transition_id=transition.id, transition_name=transition.name,
  162. attribute_type_id=transition.attribute_type_id, field_require_check=transition.field_require_check,
  163. alert_enable=transition.alert_enable, alert_text=transition.alert_text
  164. )
  165. transition_info_list.append(transition_info_dict)
  166. # 工单基础字段及属性
  167. field_list = []
  168. field_list.append(dict(
  169. field_key='title', field_name=u'标题', field_value=None, order_id=20,
  170. field_type_id=constant_service_ins.FIELD_TYPE_STR, field_attribute=constant_service_ins.FIELD_ATTRIBUTE_RO,
  171. description='', field_choice={}, boolean_field_display={}, default_value=None, field_template='',
  172. placeholder='', label={}))
  173. flag, custom_field_dict = workflow_custom_field_service_ins.get_workflow_custom_field(workflow_id)
  174. for key, value in custom_field_dict.items():
  175. field_list.append(dict(field_key=key, field_name=custom_field_dict[key]['field_name'],
  176. field_value=None, order_id=custom_field_dict[key]['order_id'],
  177. field_type_id=custom_field_dict[key]['field_type_id'],
  178. field_attribute=constant_service_ins.FIELD_ATTRIBUTE_RO,
  179. default_value=custom_field_dict[key]['default_value'],
  180. description=custom_field_dict[key]['description'],
  181. placeholder=custom_field_dict[key]['placeholder'],
  182. field_template=custom_field_dict[key]['field_template'],
  183. boolean_field_display=json.loads(custom_field_dict[key]['boolean_field_display'])
  184. if custom_field_dict[key]['boolean_field_display'] else {}, # 之前model允许为空了,为了兼容先这么写,
  185. field_choice=json.loads(custom_field_dict[key]['field_choice']),
  186. label=json.loads(custom_field_dict[key]['label'])
  187. ))
  188. state_field_dict = json.loads(init_state_obj.state_field_str)
  189. state_field_key_list = state_field_dict.keys()
  190. new_field_list = []
  191. for field0 in field_list:
  192. if field0['field_key'] in state_field_key_list:
  193. field0['field_attribute'] = state_field_dict[field0['field_key']]
  194. new_field_list.append(field0)
  195. # 字段排序
  196. new_field_list = sorted(new_field_list, key=lambda r: r['order_id'])
  197. state_info_dict = init_state_obj.get_dict()
  198. state_info_dict.update(
  199. field_list=new_field_list, label=json.loads(init_state_obj.label), transition=transition_info_list)
  200. state_info_dict.pop('state_field_str')
  201. return True, state_info_dict
  202. @classmethod
  203. @auto_log
  204. def get_format_participant_info(cls, participant_type_id: int, participant: str)->tuple:
  205. """
  206. 获取格式化的参与人信息
  207. get format participant info
  208. :param participant_type_id:
  209. :param participant:
  210. :return:
  211. """
  212. participant_name = participant
  213. participant_type_name = ''
  214. participant_alias = ''
  215. if participant_type_id == constant_service_ins.PARTICIPANT_TYPE_PERSONAL:
  216. participant_type_name = '个人'
  217. flag, participant_user_obj = account_base_service_ins.get_user_by_username(participant)
  218. if not flag:
  219. participant_alias = participant
  220. else:
  221. participant_alias = participant_user_obj.alias
  222. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_MULTI:
  223. participant_type_name = '多人'
  224. # 依次获取人员信息
  225. participant_name_list = participant_name.split(',')
  226. participant_alias_list = []
  227. for participant_name0 in participant_name_list:
  228. flag, participant_user_obj = account_base_service_ins.get_user_by_username(participant_name0)
  229. if not flag:
  230. participant_alias_list.append(participant_name0)
  231. else:
  232. participant_alias_list.append(participant_user_obj.alias)
  233. participant_alias = ','.join(participant_alias_list)
  234. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_DEPT:
  235. participant_type_name = '部门'
  236. # 支持多部门
  237. flag, dept_queryset = account_base_service_ins.get_dept_by_ids(participant)
  238. dept_info_dict = {}
  239. for dept0 in dept_queryset:
  240. dept_info_dict[str(dept0.id)] = dept0.name
  241. participant_split_id_str_list = participant.split(',')
  242. participant_dept_info_list = []
  243. for participant_split_id_str in participant_split_id_str_list:
  244. if dept_info_dict.get(participant_split_id_str):
  245. participant_dept_info_list.append(dept_info_dict.get(participant_split_id_str))
  246. else:
  247. participant_dept_info_list.append('未知')
  248. participant_alias = ','.join(participant_dept_info_list)
  249. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_ROLE:
  250. participant_type_name = '角色'
  251. flag, role_obj = account_base_service_ins.get_role_by_id(int(participant))
  252. if flag is False or (not role_obj):
  253. participant_alias = '未知'
  254. else:
  255. participant_alias = role_obj.name
  256. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_VARIABLE:
  257. participant_type_name = '变量'
  258. # 支持多变量的展示
  259. participant_name_list = participant_name.split(',')
  260. participant_name_alias_list = []
  261. for participant_name0 in participant_name_list:
  262. if participant_name0 == 'creator':
  263. participant_name_alias_list.append('工单创建人')
  264. elif participant_name0 == 'creator_tl':
  265. participant_name_alias_list.append('工单创建人tl')
  266. else:
  267. participant_name_alias_list.append('未知')
  268. participant_alias = ','.join(participant_name_alias_list)
  269. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_ROBOT:
  270. if participant:
  271. flag, result = workflow_run_script_service_ins.get_run_script_by_id(int(participant))
  272. if flag:
  273. participant_alias = result.get('script_obj').name
  274. elif participant_type_id == constant_service_ins.PARTICIPANT_TYPE_HOOK:
  275. participant_type_name = 'hook'
  276. participant_alias = participant_name
  277. return True, dict(participant=participant, participant_name=participant_name,
  278. participant_type_id=participant_type_id, participant_type_name=participant_type_name,
  279. participant_alias=participant_alias)
  280. @classmethod
  281. @auto_log
  282. def add_workflow_state(cls, workflow_id: int, name: str, is_hidden: int, order_id: int,
  283. type_id: int, remember_last_man_enable: int, participant_type_id: int, participant: str,
  284. distribute_type_id: int, state_field_str: str, label: str, creator: str,
  285. enable_retreat: int)->tuple:
  286. """
  287. 新增工作流状态
  288. add workflow state
  289. :param workflow_id:
  290. :param name:
  291. :param is_hidden:
  292. :param order_id:
  293. :param type_id:
  294. :param remember_last_man_enable:
  295. :param participant_type_id:
  296. :param participant:
  297. :param distribute_type_id:
  298. :param state_field_str:
  299. :param label:
  300. :param creator:
  301. :param enable_retreat:
  302. :return:
  303. """
  304. workflow_state_obj = State(
  305. workflow_id=workflow_id, name=name, is_hidden=is_hidden, order_id=order_id,
  306. type_id=type_id, remember_last_man_enable=remember_last_man_enable, participant_type_id=participant_type_id,
  307. participant=participant, distribute_type_id=distribute_type_id, state_field_str=state_field_str,
  308. label=label, creator=creator, enable_retreat=enable_retreat)
  309. workflow_state_obj.save()
  310. return True, dict(workflow_state_id=workflow_state_obj.id)
  311. @classmethod
  312. @auto_log
  313. def edit_workflow_state(cls, state_id: int, workflow_id: int, name: str, is_hidden: int,
  314. order_id: int, type_id: int, remember_last_man_enable: int, participant_type_id: int,
  315. participant: str, distribute_type_id: int, state_field_str: str, label: str,
  316. enable_retreat: int)->tuple:
  317. """
  318. 新增工作流状态
  319. edit workflow state
  320. :param state_id:
  321. :param workflow_id:
  322. :param name:
  323. :param sub_workflow_id:
  324. :param is_hidden:
  325. :param order_id:
  326. :param type_id:
  327. :param remember_last_man_enable:
  328. :param participant_type_id:
  329. :param participant:
  330. :param distribute_type_id:
  331. :param state_field_str:
  332. :param label:
  333. :param enable_retreat:
  334. :return:
  335. """
  336. state_obj = State.objects.filter(id=state_id, is_deleted=0)
  337. if state_obj:
  338. state_obj.update(workflow_id=workflow_id, name=name,
  339. is_hidden=is_hidden, order_id=order_id, type_id=type_id,
  340. remember_last_man_enable=remember_last_man_enable, participant_type_id=participant_type_id,
  341. participant=participant, distribute_type_id=distribute_type_id,
  342. state_field_str=state_field_str, label=label, enable_retreat=enable_retreat)
  343. return True, ''
  344. @classmethod
  345. @auto_log
  346. def del_workflow_state(cls, state_id: int)->tuple:
  347. """
  348. 删除状态
  349. :param state_id:
  350. :return:
  351. """
  352. state_obj = State.objects.filter(id=state_id, is_deleted=0)
  353. if state_obj:
  354. state_obj.update(is_deleted=1)
  355. return True, {}
  356. workflow_state_service_ins = WorkflowStateService()