workflow_state_service.py 17 KB

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