WorkflowNextHandler.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. using DotNetCore.CAP;
  2. using Hotline.Application.JudicialManagement;
  3. using Hotline.Application.Quality;
  4. using Hotline.Caching.Interfaces;
  5. using Hotline.EventBus;
  6. using Hotline.FlowEngine.Notifications;
  7. using Hotline.FlowEngine.WorkflowModules;
  8. using Hotline.FlowEngine.Workflows;
  9. using Hotline.JudicialManagement.Notifies;
  10. using Hotline.KnowledgeBase;
  11. using Hotline.Orders;
  12. using Hotline.Push.Notifies;
  13. using Hotline.Settings;
  14. using Hotline.Settings.TimeLimits;
  15. using Hotline.Share.Dtos.FlowEngine.Workflow;
  16. using Hotline.Share.Dtos.Order;
  17. using Hotline.Share.Enums.FlowEngine;
  18. using Hotline.Share.Enums.Order;
  19. using Hotline.Share.Enums.Push;
  20. using Hotline.Share.Enums.Quality;
  21. using Hotline.Share.Mq;
  22. using Hotline.Users;
  23. using MapsterMapper;
  24. using MediatR;
  25. using Microsoft.AspNetCore.Http;
  26. using Microsoft.Extensions.Logging;
  27. using XF.Domain.Authentications;
  28. using XF.Domain.Entities;
  29. using XF.Domain.Repository;
  30. namespace Hotline.Application.Handlers.FlowEngine;
  31. public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
  32. {
  33. private readonly IOrderDomainService _orderDomainService;
  34. private readonly IOrderRepository _orderRepository;
  35. private readonly ICapPublisher _capPublisher;
  36. private readonly IMapper _mapper;
  37. private readonly ILogger<WorkflowNextHandler> _logger;
  38. private readonly IQualityApplication _qualityApplication;
  39. private readonly IOrderDelayRepository _orderDelayRepository;
  40. private readonly IKnowledgeRepository _knowledgeRepository;
  41. private readonly ISessionContext _sessionContext;
  42. private readonly IRepository<User> _userRepository;
  43. private readonly IMediator _mediator;
  44. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  45. private readonly Publisher _publisher;
  46. public WorkflowNextHandler(
  47. IOrderDomainService orderDomainService,
  48. IOrderRepository orderRepository,
  49. ICapPublisher capPublisher,
  50. IMapper mapper,
  51. ILogger<WorkflowNextHandler> logger,
  52. IQualityApplication qualityApplication,
  53. IKnowledgeRepository knowledgeRepository,
  54. ISessionContext sessionContext,
  55. IOrderDelayRepository orderDelayRepository,
  56. IRepository<User> userRepository,
  57. IMediator mediator,
  58. ISystemSettingCacheManager systemSettingCacheManager,
  59. Publisher publisher)
  60. {
  61. _orderDomainService = orderDomainService;
  62. _orderRepository = orderRepository;
  63. _capPublisher = capPublisher;
  64. _mapper = mapper;
  65. _logger = logger;
  66. _qualityApplication = qualityApplication;
  67. _orderDelayRepository = orderDelayRepository;
  68. _knowledgeRepository = knowledgeRepository;
  69. _sessionContext = sessionContext;
  70. _userRepository = userRepository;
  71. _mediator = mediator;
  72. _systemSettingCacheManager = systemSettingCacheManager;
  73. _publisher = publisher;
  74. }
  75. /// <summary>Handles a notification</summary>
  76. /// <param name="notification">The notification</param>
  77. /// <param name="cancellationToken">Cancellation token</param>
  78. public async Task Handle(NextStepNotify notification, CancellationToken cancellationToken)
  79. {
  80. try
  81. {
  82. //_logger.LogInformation(
  83. // $"收到{nameof(NextStepNotify)}, notification: {JsonConvert.SerializeObject(notification)}");
  84. var workflow = notification.Workflow;
  85. var data = notification.Dto;
  86. var assignInfo = notification.FlowAssignInfo;
  87. var currentTag = string.IsNullOrEmpty(notification.Trace.Tag)
  88. ? null
  89. : System.Text.Json.JsonSerializer.Deserialize<DefinitionTag>(notification.Trace.Tag);
  90. var nextTag = string.IsNullOrEmpty(notification.NextStepDefine.Tag)
  91. ? null
  92. : System.Text.Json.JsonSerializer.Deserialize<DefinitionTag>(notification.NextStepDefine.Tag);
  93. switch (workflow.ModuleCode)
  94. {
  95. case WorkflowModuleConsts.OrderHandle:
  96. var order = await _orderDomainService.GetOrderAsync(workflow.ExternalId, withHotspot: true,
  97. withAcceptor: true, withExtension: true, cancellationToken: cancellationToken);
  98. order.CheckIfFiled();
  99. order.UpdateHandlingStatus(workflow.IsInCountersign);
  100. _mapper.Map(workflow, order);
  101. //var expiredTimeChanged = false;
  102. //if (data.FlowDirection.HasValue
  103. // && data.External.TimeLimit.HasValue
  104. // && data.External.TimeLimitUnit.HasValue)
  105. //{
  106. // // 1. calc expiredTime 2. update order.expiredTime 3. update workflow.expiredTime 4. publish province
  107. // // var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
  108. // // data.External.TimeLimitUnit.Value,
  109. // // data.External.TimeLimit.Value, data.FlowDirection is EFlowDirection.OrgToCenter);
  110. // var expiredTimeConfig = _timeLimitDomainService.CalcEndTime(DateTime.Now,
  111. // new TimeConfig(data.External.TimeLimit.Value, data.External.TimeLimitUnit.Value), order.AcceptTypeCode);
  112. // if (data.FlowDirection is EFlowDirection.OrgToCenter)
  113. // {
  114. // order.OrgToCenter(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
  115. // expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
  116. // }
  117. // else if (data.FlowDirection is EFlowDirection.CenterToOrg)
  118. // {
  119. // order.CenterToOrg(expiredTimeConfig.TimeText, expiredTimeConfig.Count,
  120. // expiredTimeConfig.TimeType, expiredTimeConfig.ExpiredTime, expiredTimeConfig.NearlyExpiredTime);
  121. // //写入质检
  122. // await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
  123. // }
  124. // await _workflowDomainService.UpdateExpiredTimeAsync(workflow,
  125. // expiredTimeConfig.ExpiredTime, expiredTimeConfig.TimeText,
  126. // expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
  127. // expiredTimeChanged = true;
  128. //}
  129. await _orderRepository.Updateable(order).ExecuteCommandAsync(cancellationToken);
  130. //await _orderRepository.UpdateAsync(order, cancellationToken);
  131. //司法行政监督管理-推诿工单
  132. //如果没开启则不处理
  133. var isOpenJudicialManagement = _systemSettingCacheManager.GetSetting(SettingConstants.IsOpenJudicialManagement)?.SettingValue[0];
  134. if (isOpenJudicialManagement == "true" && notification.Trace.StepType != EStepType.Summary && notification.Trace.StepType != EStepType.End && !notification.Trace.IsCountersignEndStep)
  135. await _publisher.PublishAsync(new AddPassTheBuckOrderNotify(order, _sessionContext.RequiredOrgId, _sessionContext.OrgName),
  136. PublishStrategy.ParallelWhenAll, cancellationToken);
  137. try
  138. {
  139. if (notification.Dto.IsSms)
  140. {
  141. switch (notification.FlowAssignInfo.FlowAssignType)
  142. {
  143. case EFlowAssignType.Org:
  144. var orgCodes = notification.Trace.NextHandlers.Select(x => x.OrgId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
  145. var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
  146. var orgList = await _userRepository.Queryable()
  147. .Where(x => orgCodes.Contains(x.OrgId) && x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id)))
  148. .ToListAsync(cancellationToken);
  149. foreach (var item in orgList)
  150. {
  151. if (!string.IsNullOrEmpty(item.PhoneNo))
  152. {
  153. var messageDto = new Share.Dtos.Push.MessageDto
  154. {
  155. PushBusiness = EPushBusiness.OrderSend,
  156. ExternalId = order.Id,
  157. OrderId = order.Id,
  158. PushPlatform = EPushPlatform.Sms,
  159. Remark = order.Title,
  160. Name = item.Name,
  161. TemplateCode = "1007",
  162. Params = new List<string>() { order.No },
  163. TelNumber = item.PhoneNo,
  164. };
  165. await _mediator.Publish(new PushMessageNotify(messageDto), cancellationToken);
  166. }
  167. }
  168. break;
  169. case EFlowAssignType.User:
  170. var userCodes = notification.Trace.NextHandlers.Select(x=>x.UserId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
  171. var userList = await _userRepository.Queryable()
  172. .Where(x => userCodes.Contains(x.Id) && !string.IsNullOrEmpty(x.PhoneNo))
  173. .ToListAsync(cancellationToken);
  174. foreach (var item in userList)
  175. {
  176. var messageDto = new Share.Dtos.Push.MessageDto
  177. {
  178. PushBusiness = EPushBusiness.OrderSend,
  179. ExternalId = order.Id,
  180. OrderId = order.Id,
  181. PushPlatform = EPushPlatform.Sms,
  182. Remark = order.Title,
  183. Name = item.Name,
  184. TemplateCode = "1007",
  185. Params = new List<string>() { order.No },
  186. TelNumber = item.PhoneNo,
  187. };
  188. await _mediator.Publish(new PushMessageNotify(messageDto), cancellationToken);
  189. }
  190. break;
  191. default:
  192. break;
  193. }
  194. }
  195. }
  196. catch { }
  197. var orderDto = _mapper.Map<OrderDto>(order);
  198. await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowHandled, new OrderFlowDto
  199. {
  200. Order = orderDto,
  201. WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace),
  202. ExpiredTimeChanged = notification.ExpiredTimeChanged,
  203. HandlerOrgLevel = notification.HandlerOrgId.CalcOrgLevel()
  204. }, cancellationToken: cancellationToken);
  205. if (data.FlowDirection is EFlowDirection.CenterToOrg)
  206. await _qualityApplication.AddQualityAsync(EQualitySource.Send, order.Id, cancellationToken);
  207. break;
  208. case WorkflowModuleConsts.KnowledgeAdd:
  209. case WorkflowModuleConsts.KnowledgeUpdate:
  210. case WorkflowModuleConsts.KnowledgeDelete:
  211. //var knowledgeWork = await _knowledgeWorkFlowRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
  212. var knowledge = await _knowledgeRepository.Queryable().Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
  213. knowledge.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
  214. await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
  215. break;
  216. //case WorkflowModuleConsts.OrderScreen:
  217. // var screen = await _orderScreenRepository.Queryable().Includes(x => x.Order)
  218. // .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
  219. // if (screen != null)
  220. // {
  221. // screen.Status = EScreenStatus.Approval;
  222. // screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
  223. // //如果下个节点是省审批,则修改为省甄别
  224. // if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org && nextTag.Value == TagDefaults.TagValue.Province)
  225. // screen.IsProScreen = true;
  226. // await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
  227. // }
  228. // if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org)
  229. // {
  230. // switch (nextTag.Value)
  231. // {
  232. // case TagDefaults.TagValue.Province:
  233. // if (screen != null)
  234. // {
  235. // var screenDto = _mapper.Map<OrderScreenListDto>(screen);
  236. // if (screen.Order != null && screen.Order.Source == ESource.ProvinceStraight)
  237. // {
  238. // var screenOrderDto = _mapper.Map<OrderDto>(screen.Order);
  239. // //推省上
  240. // _capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto()
  241. // {
  242. // Order = screenOrderDto,
  243. // Screen = screenDto,
  244. // ClientGuid = ""
  245. // });
  246. // //try
  247. // //{
  248. // // await _provinceService.ScreenCaseInfoSend(new PublishScreenDto()
  249. // // {
  250. // // Order = screenOrderDto,
  251. // // Screen = screenDto,
  252. // // ClientGuid = ""
  253. // // }, cancellationToken);
  254. // //}
  255. // //catch (Exception e)
  256. // //{
  257. // // _logger.LogError(
  258. // // "_provinceService.ScreenCaseInfoSend throw exception: {ex}", e.Message);
  259. // //}
  260. // }
  261. // }
  262. // break;
  263. // }
  264. // }
  265. //OrderScreenDetail detail = new OrderScreenDetail
  266. //{
  267. // ScreenId = screen.Id
  268. //};
  269. //detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName, 1);
  270. //await _orderScreenDetailRepository.AddAsync(detail, cancellationToken);
  271. //break;
  272. case WorkflowModuleConsts.OrderDelay:
  273. var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order)
  274. .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
  275. if (orderDelay != null)
  276. {
  277. orderDelay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
  278. await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
  279. }
  280. if (nextTag is not null && nextTag.Type == TagDefaults.TagType.Org)
  281. {
  282. switch (nextTag.Value)
  283. {
  284. case TagDefaults.TagValue.Province:
  285. //TODO 发起省延期审批
  286. //var orderDelay = await _orderDelayRepository.Queryable().Includes(x => x.Order)
  287. // .Where(x => x.Id == workflow.ExternalId).FirstAsync(cancellationToken);
  288. try
  289. {
  290. if (orderDelay != null)
  291. {
  292. orderDelay.DelayApplyType = EDelayApplyType.ProvinceApply;
  293. orderDelay.IsProDelay = true;
  294. await _orderDelayRepository.UpdateAsync(orderDelay);
  295. //推送
  296. var publishOrderDelay = _mapper.Map<PublishOrderDelayDto>(orderDelay);
  297. await _capPublisher.PublishAsync(EventNames.HotlineOrderApplyDelay, publishOrderDelay, cancellationToken: cancellationToken);
  298. //await _provinceService.DelayCaseInfoSend(publishOrderDelay, cancellationToken);
  299. }
  300. }
  301. catch (Exception e)
  302. {
  303. _logger.LogError("_provinceService.DelayCaseInfoSend throw exception: {ex}",
  304. e.Message);
  305. }
  306. break;
  307. }
  308. }
  309. break;
  310. }
  311. }
  312. catch (Exception e)
  313. {
  314. _logger.LogError($"{nameof(WorkflowNextHandler)}异常,{e}");
  315. throw;
  316. }
  317. }
  318. }