EndWorkflowHandler.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. using DotNetCore.CAP;
  2. using Hotline.Article;
  3. using Hotline.CallCenter.Tels;
  4. using Hotline.FlowEngine.Notifications;
  5. using Hotline.FlowEngine.WorkflowModules;
  6. using Hotline.FlowEngine.Workflows;
  7. using Hotline.KnowledgeBase;
  8. using Hotline.Orders;
  9. using Hotline.Repository.SqlSugar.Orders;
  10. using Hotline.Settings;
  11. using Hotline.Share.Dtos;
  12. using Hotline.Share.Dtos.FlowEngine.Workflow;
  13. using Hotline.Share.Dtos.Order;
  14. using Hotline.Share.Enums.Order;
  15. using Hotline.Share.Mq;
  16. using MapsterMapper;
  17. using MediatR;
  18. using Microsoft.AspNetCore.Http;
  19. using XF.Domain.Exceptions;
  20. using XF.Domain.Repository;
  21. namespace Hotline.Application.Handlers.FlowEngine;
  22. public class EndWorkflowHandler : INotificationHandler<EndWorkflowNotify>
  23. {
  24. private readonly IKnowledgeDomainService _knowledgeDomainService;
  25. private readonly IOrderDomainService _orderDomainService;
  26. private readonly ITelDomainService _telDomainService;
  27. private readonly IOrderRepository _orderRepository;
  28. private readonly ICapPublisher _capPublisher;
  29. private readonly IMapper _mapper;
  30. private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
  31. private readonly IRepository<OrderScreen> _orderScreenRepository;
  32. private readonly IRepository<Bulletin> _bulletinRepository;
  33. private readonly IRepository<Circular> _circularRepository;
  34. private readonly IRepositorySqlSugar<CircularReadGroup> _circularReadGroupRepository;
  35. private readonly IRepositorySqlSugar<CircularRecord> _circularRecordRepository;
  36. private readonly ICircularRecordDomainService _circularRecordDomainService;
  37. private readonly IRepository<OrderVisit> _orderVisitRepository;
  38. private readonly IRepository<OrderDelay> _orderDelayRepository;
  39. private readonly IRepository<OrderVisitApply> _orderVisitApplyRepository;
  40. public EndWorkflowHandler(
  41. IKnowledgeDomainService knowledgeDomainService,
  42. IOrderDomainService orderDomainService,
  43. ITelDomainService telDomainService,
  44. IOrderRepository orderRepository,
  45. ICapPublisher capPublisher,
  46. IMapper mapper,
  47. IRepository<OrderVisitDetail> orderVisitedDetailRepository,
  48. IRepository<OrderScreen> orderScreenRepository,
  49. IRepository<Bulletin> bulletinRepository,
  50. IRepository<Circular> circularRepository,
  51. IRepository<CircularReadGroup> circularReadGroupRepository,
  52. IRepository<CircularRecord> circularRecordRepository,
  53. ICircularRecordDomainService circularRecordDomainService,
  54. IRepository<OrderDelay> orderDelayRepository,
  55. IRepository<OrderVisit> orderVisitRepository,
  56. IRepository<OrderVisitApply> orderVisitApplyRepository
  57. )
  58. {
  59. _knowledgeDomainService = knowledgeDomainService;
  60. _orderDomainService = orderDomainService;
  61. _telDomainService = telDomainService;
  62. _orderRepository = orderRepository;
  63. _capPublisher = capPublisher;
  64. _mapper = mapper;
  65. _orderScreenRepository = orderScreenRepository;
  66. _orderVisitedDetailRepository = orderVisitedDetailRepository;
  67. _bulletinRepository = bulletinRepository;
  68. _circularRepository = circularRepository;
  69. _circularReadGroupRepository = circularReadGroupRepository;
  70. _circularRecordRepository = circularRecordRepository;
  71. _circularRecordDomainService = circularRecordDomainService;
  72. _orderDelayRepository = orderDelayRepository;
  73. _orderVisitRepository = orderVisitRepository;
  74. _orderVisitApplyRepository = orderVisitApplyRepository;
  75. }
  76. /// <summary>Handles a notification</summary>
  77. /// <param name="notification">The notification</param>
  78. /// <param name="cancellationToken">Cancellation token</param>
  79. public async Task Handle(EndWorkflowNotify notification, CancellationToken cancellationToken)
  80. {
  81. var workflow = notification.Workflow;
  82. //审批是否通过
  83. var isReviewPass = workflow.IsReviewPass();
  84. switch (workflow.ModuleCode)
  85. {
  86. case WorkflowModuleConsts.KnowledgeAdd://新增知识库
  87. case WorkflowModuleConsts.KnowledgeUpdate://修改知识库
  88. case WorkflowModuleConsts.KnowledgeDelete://删除知识库
  89. await _knowledgeDomainService.EndWorkKnowledge(workflow, cancellationToken);
  90. break;
  91. case WorkflowModuleConsts.TelRestApply:
  92. await _telDomainService.TelRestApplyPassAsync(workflow.ExternalId, cancellationToken);
  93. break;
  94. case WorkflowModuleConsts.OrderHandle:
  95. var order = await _orderDomainService.GetOrderAsync(workflow.ExternalId, cancellationToken);
  96. order.CheckIfFiled();
  97. _mapper.Map(workflow, order);
  98. order.Filed();
  99. await _orderRepository.UpdateAsync(order, cancellationToken);
  100. await _capPublisher.PublishAsync(EventNames.HotlineOrderFiled, new OrderFlowDto
  101. {
  102. Order = _mapper.Map<OrderDto>(order),
  103. WorkflowTrace = _mapper.Map<WorkflowTraceDto>(notification.Trace)
  104. }, cancellationToken: cancellationToken);
  105. break;
  106. case WorkflowModuleConsts.OrderScreen:
  107. var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);
  108. if (screen != null)
  109. {
  110. if (isReviewPass)
  111. {
  112. screen.Status = EScreenStatus.End;
  113. screen.ReplyContent = workflow.ActualOpinion;
  114. await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
  115. var visitDetail =
  116. await _orderVisitedDetailRepository.GetAsync(screen.VisitDetailId, cancellationToken);
  117. if (visitDetail != null)
  118. {
  119. var screenSatisfy = new Kv() { Key = "6", Value = "甄别满意" };
  120. visitDetail.OrgProcessingResults = screenSatisfy;
  121. visitDetail.OrgHandledAttitude = screenSatisfy;
  122. await _orderVisitedDetailRepository.UpdateAsync(visitDetail, cancellationToken);
  123. //获取回访信息
  124. var visit = await _orderVisitRepository.Queryable().Includes(x => x.Order)
  125. .Includes(x => x.OrderVisitDetails)
  126. .Where(x => x.Id == screen.VisitId).FirstAsync(cancellationToken);
  127. if (visit != null)
  128. {
  129. //获取回访明细
  130. var visitDe = visit.OrderVisitDetails.First(x => x.Id == screen.VisitDetailId);
  131. //推省上
  132. _capPublisher.Publish(EventNames.HotlineOrderScreenApplyed,
  133. new PublishVisitDto()
  134. {
  135. Order = _mapper.Map<OrderDto>(visit.Order),
  136. No = visit.No,
  137. VisitType = visit.VisitType,
  138. VisitName = visit.CreatorName,
  139. VisitTime = visit.VisitTime,
  140. VisitRemark = visitDe.VisitContent,
  141. AreaCode = visit.Order.AreaCode!,
  142. SubjectResultSatifyCode = visitDe.OrgProcessingResults?.Key,
  143. FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
  144. ClientGuid = ""
  145. });
  146. }
  147. }
  148. }
  149. else
  150. {
  151. screen.Status = EScreenStatus.Refuse;
  152. screen.ReplyContent = workflow.ActualOpinion;
  153. await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
  154. }
  155. }
  156. break;
  157. case WorkflowModuleConsts.BulletinApply:
  158. var bulletin = await _bulletinRepository.GetAsync(workflow.ExternalId, cancellationToken);
  159. if (bulletin != null)
  160. {
  161. if (isReviewPass)
  162. {
  163. bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewPass;
  164. bulletin.BulletinTime = DateTime.Now;
  165. }
  166. else
  167. {
  168. bulletin.BulletinState = Share.Enums.Article.EBulletinState.ReviewNoPass;
  169. }
  170. await _bulletinRepository.UpdateAsync(bulletin, cancellationToken);
  171. }
  172. break;
  173. case WorkflowModuleConsts.CircularApply:
  174. var circular = await _circularRepository.GetAsync(workflow.ExternalId, cancellationToken);
  175. if (circular != null)
  176. {
  177. if (isReviewPass)
  178. {
  179. //更新审核状态
  180. circular.CircularState = Share.Enums.Article.ECircularState.ReviewPass;
  181. circular.CircularTime = DateTime.Now;
  182. await _circularRepository.UpdateAsync(circular, cancellationToken);
  183. //更新阅读数量
  184. if (circular.CircularType == Share.Enums.Article.ECircularType.Person)
  185. {
  186. //个人
  187. var userlist = await _circularReadGroupRepository.Queryable()
  188. .Where(x => x.CircularId == circular.Id)
  189. .Select(x => x.UserId)
  190. .ToListAsync(cancellationToken);
  191. if (userlist != null && userlist.Count > 0)
  192. {
  193. await _circularRecordDomainService.RecordUserHandle(userlist, true);
  194. }
  195. }
  196. else
  197. {
  198. //部门
  199. var orglist = await _circularReadGroupRepository.Queryable()
  200. .Where(x => x.CircularId == circular.Id)
  201. .Select(x => x.OrgId)
  202. .ToListAsync(cancellationToken);
  203. if (orglist != null && orglist.Count > 0)
  204. {
  205. await _circularRecordDomainService.RecordOrgHandle(orglist, true);
  206. }
  207. }
  208. }
  209. else
  210. {
  211. circular.CircularState = Share.Enums.Article.ECircularState.ReviewNoPass;
  212. await _circularRepository.UpdateAsync(circular, cancellationToken);
  213. }
  214. }
  215. break;
  216. case WorkflowModuleConsts.OrderDelay:
  217. var delay = await _orderDelayRepository.GetAsync(workflow.ExternalId, cancellationToken);
  218. if (delay != null)
  219. {
  220. if (isReviewPass)
  221. {
  222. delay.DelayState = isReviewPass ? EDelayState.Pass : EDelayState.NoPass;
  223. await _orderDelayRepository.UpdateAsync(delay, cancellationToken);
  224. //处理工单延期TODO
  225. }
  226. else
  227. {
  228. delay.DelayState = EDelayState.NoPass;
  229. await _orderDelayRepository.UpdateAsync(delay, cancellationToken);
  230. }
  231. }
  232. break;
  233. case WorkflowModuleConsts.VisitApply:
  234. //获取单据
  235. var visitApply = await _orderVisitApplyRepository.GetAsync(workflow.ExternalId, cancellationToken);
  236. if (visitApply!=null)
  237. {
  238. if (isReviewPass)
  239. {
  240. //处理申请单
  241. visitApply.VisitApplyState = EVisitApplyState.Pass;
  242. await _orderVisitApplyRepository.UpdateAsync(visitApply, cancellationToken);
  243. //处理原回访数据
  244. var visitModel = await _orderVisitRepository.GetAsync(visitApply.OrderVisitId, cancellationToken);
  245. if (visitModel != null)
  246. {
  247. visitModel.VisitState = EVisitState.None;
  248. await _orderVisitRepository.UpdateAsync(visitModel, cancellationToken);
  249. //处理新回访数据
  250. //查询原回访数据子表
  251. var visitModelNew = _mapper.Map<OrderVisit>(visitModel);
  252. visitModelNew.InitId();
  253. visitModelNew.CreationTime = DateTime.Now;
  254. visitModelNew.CreatorId = string.Empty;
  255. visitModelNew.CreatorName = string.Empty;
  256. visitModelNew.CreatorOrgId = string.Empty;
  257. visitModelNew.CreatorOrgName = string.Empty;
  258. visitModelNew.CreatorOrgLevel = 0;
  259. visitModelNew.AreaId = string.Empty;
  260. visitModelNew.VisitState = EVisitState.WaitForVisit;
  261. var id = await _orderVisitRepository.AddAsync(visitModelNew, cancellationToken);
  262. var visitModelDetail = await _orderVisitedDetailRepository.Queryable().Where(x => x.VisitId == visitModel.Id).ToListAsync(cancellationToken);
  263. var visitDetailListNew = new List<OrderVisitDetail>();
  264. //TODO
  265. foreach (var item in visitModelDetail)
  266. {
  267. var visitDetail = new OrderVisitDetail();
  268. visitDetail.VisitId = id;
  269. visitDetail.VisitOrgCode = item.VisitOrgCode;
  270. visitDetail.VisitOrgName = item.VisitOrgName;
  271. visitDetail.VisitTarget = item.VisitTarget;
  272. visitDetailListNew.Add(visitDetail);
  273. }
  274. await _orderVisitedDetailRepository.AddRangeAsync(visitDetailListNew, cancellationToken);
  275. }
  276. }
  277. else
  278. {
  279. //处理申请单
  280. visitApply.VisitApplyState = EVisitApplyState.NoPass;
  281. await _orderVisitApplyRepository.UpdateAsync(visitApply, cancellationToken);
  282. }
  283. }
  284. break;
  285. }
  286. }
  287. }