OrderApplication.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. using DotNetCore.CAP;
  2. using Hotline.Application.Quality;
  3. using Hotline.Caching.Interfaces;
  4. using Hotline.File;
  5. using Hotline.FlowEngine.Workflows;
  6. using Hotline.Orders;
  7. using Hotline.Repository.SqlSugar.Extensions;
  8. using Hotline.Repository.SqlSugar.Ts;
  9. using Hotline.Settings.TimeLimits;
  10. using Hotline.Share.Dtos;
  11. using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
  12. using Hotline.Share.Dtos.File;
  13. using Hotline.Share.Dtos.FlowEngine;
  14. using Hotline.Share.Dtos.FlowEngine.Workflow;
  15. using Hotline.Share.Dtos.Order;
  16. using Hotline.Share.Dtos.Settings;
  17. using Hotline.Share.Enums.Order;
  18. using Hotline.Share.Enums.Quality;
  19. using Hotline.Share.Enums.Settings;
  20. using Hotline.Tools;
  21. using MapsterMapper;
  22. using SqlSugar;
  23. using XF.Domain.Authentications;
  24. using XF.Domain.Constants;
  25. using XF.Domain.Dependency;
  26. using XF.Domain.Exceptions;
  27. using XF.Domain.Repository;
  28. namespace Hotline.Application.Orders;
  29. public class OrderApplication : IOrderApplication, IScopeDependency
  30. {
  31. private readonly IOrderDomainService _orderDomainService;
  32. private readonly IWorkflowDomainService _workflowDomainService;
  33. private readonly IOrderRepository _orderRepository;
  34. private readonly ITimeLimitDomainService _timeLimitDomainService;
  35. private readonly IMapper _mapper;
  36. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  37. private readonly IRepository<OrderWord> _orderWrodRepository;
  38. private readonly IRepositoryTextSearch<OrderTs> _repositoryts;
  39. private readonly IFileRepository _fileRepository;
  40. private readonly ISessionContext _sessionContext;
  41. private readonly IRepository<OrderVisit> _orderVisitRepository;
  42. private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
  43. private readonly IQualityApplication _qualityApplication;
  44. private readonly ICapPublisher _capPublisher;
  45. public OrderApplication(
  46. IOrderDomainService orderDomainService,
  47. IOrderRepository orderRepository,
  48. IWorkflowDomainService workflowDomainService,
  49. ITimeLimitDomainService timeLimitDomainService,
  50. ISystemSettingCacheManager systemSettingCacheManager,
  51. IMapper mapper,
  52. IRepository<OrderWord> orderWrodRepository,
  53. IRepositoryTextSearch<OrderTs> repositoryts,
  54. IFileRepository fileRepository,
  55. ISessionContext sessionContext,
  56. IRepository<OrderVisit> orderVisitRepository,
  57. IRepository<OrderVisitDetail> orderVisitDetailRepository,
  58. IQualityApplication qualityApplication,
  59. ICapPublisher capPublisher
  60. )
  61. {
  62. _orderDomainService = orderDomainService;
  63. _workflowDomainService = workflowDomainService;
  64. _orderRepository = orderRepository;
  65. _timeLimitDomainService = timeLimitDomainService;
  66. _mapper = mapper;
  67. _systemSettingCacheManager = systemSettingCacheManager;
  68. _orderWrodRepository = orderWrodRepository;
  69. _repositoryts = repositoryts;
  70. _fileRepository = fileRepository;
  71. _sessionContext = sessionContext;
  72. _orderVisitRepository = orderVisitRepository;
  73. _orderVisitDetailRepository = orderVisitDetailRepository;
  74. _qualityApplication = qualityApplication;
  75. _capPublisher = capPublisher;
  76. }
  77. /// <summary>
  78. /// 更新工单办理期满时间(延期调用,其他不调用)
  79. /// 1.更新工单 2.更新流程 3.推送省平台
  80. /// </summary>
  81. /// <returns></returns>
  82. public async Task DelayOrderExpiredTimeAsync(string orderId, int timeCount, ETimeType timeType, CancellationToken cancellationToken)
  83. {
  84. var order = await _orderDomainService.GetOrderAsync(orderId, cancellationToken: cancellationToken);
  85. var expiredTimeConfig =
  86. _timeLimitDomainService.CalcEndTime(DateTime.Now, new TimeConfig(timeCount, timeType), order.AcceptTypeCode);
  87. order.TimeLimit = expiredTimeConfig.TimeText;
  88. order.TimeLimitCount = expiredTimeConfig.Count;
  89. order.TimeLimitUnit = expiredTimeConfig.TimeType;
  90. order.ExpiredTime = expiredTimeConfig.ExpiredTime;
  91. order.NearlyExpiredTime = expiredTimeConfig.NearlyExpiredTime;
  92. //if (string.IsNullOrEmpty(order.WorkflowId))
  93. // throw new UserFriendlyException("该工单流程id异常");
  94. //var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, cancellationToken: cancellationToken);
  95. //await _workflowDomainService.UpdateExpiredTimeAsync(workflow, expiredTimeConfig.ExpiredTime,
  96. // expiredTimeConfig.TimeText, expiredTimeConfig.Count, expiredTimeConfig.TimeType, expiredTimeConfig.NearlyExpiredTime, cancellationToken);
  97. if (string.IsNullOrEmpty(order.WorkflowId))
  98. throw new UserFriendlyException("该工单流程id异常");
  99. await _workflowDomainService.UpdateUnhandleExpiredTimeAsync(order.WorkflowId, expiredTimeConfig.ExpiredTime, cancellationToken);
  100. await _orderRepository.UpdateAsync(order, cancellationToken);
  101. }
  102. /// <summary>
  103. /// 新增工单办理流程记录
  104. /// </summary>
  105. public async Task AddOrderTracesAsync(string orderId, ICollection<WorkflowTraceDto> traces, CancellationToken cancellationToken)
  106. {
  107. var order = await _orderRepository.GetAsync(orderId, cancellationToken);
  108. if (order is null)
  109. throw new UserFriendlyException("工单不存在");
  110. if (string.IsNullOrEmpty(order.WorkflowId))
  111. throw new UserFriendlyException("工单未开启流程");
  112. await _workflowDomainService.AddTracesAsync(order.WorkflowId, _mapper.Map<List<WorkflowTrace>>(traces),
  113. cancellationToken);
  114. }
  115. /// <summary>
  116. /// 撤销工单
  117. /// </summary>
  118. public async Task CancelOrderAsync(string orderId, string opinion, CancellationToken cancellationToken)
  119. {
  120. var order = await _orderRepository.GetAsync(orderId, cancellationToken);
  121. if (order is null)
  122. throw new UserFriendlyException("工单不存在");
  123. if (!string.IsNullOrEmpty(order.WorkflowId))
  124. {
  125. //结束流程
  126. await _workflowDomainService.TerminateAsync(new TerminateDto
  127. {
  128. WorkflowId = order.WorkflowId,
  129. Opinion = opinion
  130. }, cancellationToken);
  131. }
  132. //归档工单
  133. var now = DateTime.Now;
  134. var handleDuration = order.StartTime.HasValue
  135. ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
  136. now, order.ProcessType is EProcessType.Zhiban)
  137. : 0;
  138. var fileDuration = order.CenterToOrgTime.HasValue
  139. ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
  140. now, order.ProcessType is EProcessType.Zhiban)
  141. : 0;
  142. var allDuration = order.StartTime.HasValue
  143. ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
  144. order.ProcessType is EProcessType.Zhiban)
  145. : 0;
  146. order.File(now, handleDuration, fileDuration, allDuration);
  147. await _orderRepository.UpdateAsync(order, cancellationToken);
  148. }
  149. /// <summary>
  150. /// 即将超期列表
  151. /// </summary>
  152. /// <param name="dto"></param>
  153. /// <param name="cancellationToken"></param>
  154. /// <returns></returns>
  155. public async Task<PagedDto<OrderDto>> GetAboutToExpireAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
  156. {
  157. var setting = _systemSettingCacheManager.GetSetting(SettingConstants.OrderAboutToExpire);
  158. var value = setting?.SettingValue[0];
  159. value = string.IsNullOrEmpty(value) ? "0" : value;
  160. DateTime stTime = DateTime.Now.AddDays(int.Parse(value));
  161. stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
  162. DateTime stTime2 = _timeLimitDomainService.WorkDay(DateTime.Now);
  163. var (total, items) = await _orderRepository.Queryable(viewFilter: true)
  164. .WhereIF(dto.IsProvince.HasValue, x => x.IsProvince == dto.IsProvince)
  165. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Title.Contains(dto.Keyword!) || x.No.Contains(dto.Keyword!))
  166. .Where(x => x.ExpiredTime != null &&
  167. x.Status != EOrderStatus.Filed && x.Status != EOrderStatus.Published && x.Status != EOrderStatus.Visited && stTime >= x.ExpiredTime.Value && stTime2 <= x.ExpiredTime.Value)
  168. .OrderByDescending(x => x.CreationTime)
  169. .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
  170. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  171. }
  172. // /// <summary>
  173. // /// 即将超期节点列表
  174. // /// </summary>
  175. // /// <param name="dto"></param>
  176. // /// <param name="cancellationToken"></param>
  177. // /// <returns></returns>
  178. //public async Task<PagedDto<WorkflowOrderDto>> GetAboutToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
  179. //{
  180. // var setting = _systemSettingCacheManager.GetSetting(SettingConstants.OrderAboutToExpire);
  181. // var value = setting?.SettingValue[0];
  182. // value = string.IsNullOrEmpty(value) ? "0" : value;
  183. // DateTime stTime = DateTime.Now.AddDays(int.Parse(value));
  184. // stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
  185. // DateTime stTime2 = _timeLimitDomainService.WorkDay(DateTime.Now);
  186. // RefAsync<int> total = 0;
  187. // var items = await Db.Queryable<Workflow>()
  188. // .LeftJoin<Order>((x, o) => x.ExternalId == o.Id)
  189. // .Where(x => x.ModuleCode == "OrderHandle")
  190. // .WhereIF(dto.IsProvince.HasValue, (x, o) => o.IsProvince == dto.IsProvince)
  191. // .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => o.Title.Contains(dto.Keyword!) || o.No.Contains(dto.Keyword!))
  192. // .Where((x, o) => (int)x.Status < 20 && stTime >= x.ExpiredTime && stTime2 <= x.ExpiredTime)
  193. // .Select((x, o) => new WorkflowOrder { Order = o }, true)
  194. // .OrderByDescending(x => x.CreationTime)
  195. // .ToPageListAsync(dto.PageIndex, dto.PageSize, total, cancellationToken);
  196. // return new PagedDto<WorkflowOrderDto>(total, _mapper.Map<IReadOnlyList<WorkflowOrderDto>>(items));
  197. //}
  198. /// <summary>
  199. /// 已超期列表
  200. /// </summary>
  201. /// <param name="dto"></param>
  202. /// <param name="cancellationToken"></param>
  203. /// <returns></returns>
  204. public async Task<PagedDto<OrderDto>> GetToExpireAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
  205. {
  206. DateTime stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
  207. var (total, items) = await _orderRepository.Queryable(viewFilter: true)
  208. .WhereIF(dto.IsProvince.HasValue, x => x.IsProvince == dto.IsProvince)
  209. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Title.Contains(dto.Keyword!) || x.No.Contains(dto.Keyword!))
  210. //.WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
  211. //.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title!))
  212. .Where(x => x.ExpiredTime != null &&
  213. (((x.Status == EOrderStatus.Filed || x.Status == EOrderStatus.Published || x.Status == EOrderStatus.Visited) && x.FiledTime >= x.ExpiredTime) ||
  214. ((x.Status != EOrderStatus.Filed && x.Status != EOrderStatus.Published && x.Status != EOrderStatus.Visited) && stTime >= x.ExpiredTime.Value)))
  215. .OrderByDescending(x => x.CreationTime)
  216. .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
  217. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  218. }
  219. // /// <summary>
  220. // /// 已超期节点列表
  221. // /// </summary>
  222. // /// <param name="dto"></param>
  223. // /// <param name="cancellationToken"></param>
  224. // /// <returns></returns>
  225. // public async Task<PagedDto<WorkflowOrderDto>> GetToExpireNodeAsync(AboutToExpireListDto dto, CancellationToken cancellationToken)
  226. // {
  227. // DateTime stTime = _timeLimitDomainService.WorkDay(DateTime.Now);
  228. //RefAsync<int> total = 0;
  229. //var items= await Db.Queryable<Workflow>()
  230. // .LeftJoin<Order>((x,o)=>x.ExternalId == o.Id)
  231. // .Where(x => x.ModuleCode == "OrderHandle")
  232. // .WhereIF(dto.IsProvince.HasValue, (x, o) => o.IsProvince == dto.IsProvince)
  233. // .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => o.Title.Contains(dto.Keyword!) || o.No.Contains(dto.Keyword!))
  234. // .Where((x,o) => (((int)x.Status >= 20 && x.EndTime >= x.ExpiredTime) || ((int)x.Status < 20 && stTime >= x.ExpiredTime)))
  235. // .Select((x, o) => new WorkflowOrder { Order = o }, true)
  236. // .OrderByDescending(x => x.CreationTime)
  237. // .ToPageListAsync(dto.PageIndex, dto.PageSize, total, cancellationToken);
  238. // return new PagedDto<WorkflowOrderDto>(total, _mapper.Map<IReadOnlyList<WorkflowOrderDto>>(items));
  239. // }
  240. /// <summary>
  241. /// 工单关键字分词
  242. /// </summary>
  243. /// <param name="inputStr"></param>
  244. /// <returns></returns>
  245. public async Task OrderParticiple(string inputStr, string orderId, CancellationToken cancellationToken)
  246. {
  247. var words = await _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("普通标签")).Select(x => x.Tag).ToListAsync(cancellationToken);
  248. var res = new List<string>();
  249. if (words.Any()) res = ParticipleTool.SegMMDouble(inputStr, ref words);
  250. var participles = await _orderWrodRepository.Queryable().In(x => x.Tag, res).ToListAsync(cancellationToken);
  251. if (participles.Any())
  252. {
  253. //关键词
  254. var tags = participles.Select(x => x.Tag).ToList();
  255. var tagsStr = string.Join(",", tags);
  256. await _orderRepository.Updateable().SetColumns(x => x.TagNames == tagsStr).Where(x => x.Id == orderId).ExecuteCommandAsync(cancellationToken);
  257. List<string> synonyms = participles.Select(x => x.Synonym).ToList();
  258. if (synonyms.Any())
  259. {
  260. var synonymsStr = string.Join(",", synonyms);
  261. synonyms = synonymsStr.Split(",").Distinct().ToList();
  262. tags.AddRange(synonyms);
  263. }
  264. var vector = await _orderRepository.Queryable().Where(x => x.Id == orderId).ToListAsync(cancellationToken);
  265. if (vector.Any()) await _repositoryts.UpdateVectorAsync(orderId, tags, cancellationToken);
  266. else await _repositoryts.AddVectorAsync(orderId, DateTime.Now, tags, cancellationToken);
  267. }
  268. }
  269. public async Task OrderSensitiveParticiple(string inputStr, string orderId, CancellationToken cancellationToken)
  270. {
  271. var words = await _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("敏感标签")).Select(x => x.Tag).ToListAsync(cancellationToken);
  272. var res = new List<string>();
  273. if (words.Any()) res = ParticipleTool.SegMMDouble(inputStr, ref words);
  274. if (res.Any())
  275. {
  276. var intersect = words.Intersect(res).ToList();
  277. await _orderRepository.Updateable().SetColumns(o => new Order() { Sensitive = intersect }).Where(o => o.Id == orderId).ExecuteCommandAsync(cancellationToken);
  278. }
  279. }
  280. /// <summary>
  281. /// 接收外部平台工单
  282. /// </summary>
  283. public Task<AddOrderResponse> ReceiveOrderFromExternalAsync(AddOrderDto dto, ISessionContext current, CancellationToken cancellationToken)
  284. {
  285. switch (dto.Source)
  286. {
  287. case ESource.ProvinceStraight:
  288. return ReceiveOrderFromProvinceAsync(dto, dto.Files, current, cancellationToken);
  289. case ESource.Police110:
  290. case ESource.CityDataExchangeLz:
  291. case ESource.ConvergenceMedia:
  292. case ESource.WebPortal:
  293. return ReceiveOrderFromOtherPlatformAsync(dto, dto.Files, current, cancellationToken);
  294. case ESource.Hotline:
  295. case ESource.HotlineImport:
  296. default:
  297. throw new ArgumentOutOfRangeException();
  298. }
  299. }
  300. /// <summary>
  301. /// 接收外部平台修改工单附件
  302. /// </summary>
  303. public async Task UpdateOrderFilesAnonymousAsync(UpdateOrderFilesDto dto, CancellationToken cancellationToken)
  304. {
  305. if (string.IsNullOrEmpty(dto.Id) && string.IsNullOrEmpty(dto.OrderNo))
  306. throw new UserFriendlyException("工单外部编号不能为空");
  307. var order = await _orderRepository.Queryable()
  308. .FirstAsync(d => d.Id == dto.Id || d.No == dto.OrderNo, cancellationToken);
  309. if (order != null && dto.Files != null && dto.Files.Any())
  310. {
  311. order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, "", cancellationToken);
  312. await _orderRepository.UpdateAsync(order, cancellationToken);
  313. }
  314. }
  315. /// <summary>
  316. /// 工单回访
  317. /// </summary>
  318. /// <param name="dto"></param>
  319. /// <param name="cancellationToken"></param>
  320. /// <returns></returns>
  321. public async Task OrderVisitWeb(OrderVisitWebDto dto, CancellationToken cancellationToken)
  322. {
  323. var visit = await _orderVisitRepository.Queryable()
  324. .Includes(x => x.Order)
  325. .Includes(x => x.OrderVisitDetails)
  326. .FirstAsync(x => x.Id == dto.Id);
  327. if (visit != null)
  328. {
  329. var first = dto.OrderVisitDetailDto.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org);
  330. if (first != null)
  331. {
  332. visit.NowEvaluate = first.OrgProcessingResults;
  333. visit.Order.Visited(first.OrgProcessingResults.Key, first.OrgProcessingResults.Value);
  334. }
  335. visit.VisitState = EVisitState.Visited;
  336. visit.VisitTime = dto.VisitTime;
  337. visit.VisitType = dto.VisitType;
  338. for (int i = 0; i < visit.OrderVisitDetails.Count; i++)
  339. {
  340. var detail = visit.OrderVisitDetails[i];
  341. var detaildto = dto.OrderVisitDetailDto.FirstOrDefault(x => x.Id == detail.Id);
  342. if (detaildto != null)
  343. {
  344. _mapper.Map(detaildto, visit.OrderVisitDetails[i]);
  345. }
  346. }
  347. await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
  348. await _orderVisitDetailRepository.UpdateRangeAsync(visit.OrderVisitDetails, cancellationToken);
  349. await _orderRepository.UpdateAsync(visit.Order, cancellationToken);
  350. var orderDto = _mapper.Map<OrderDto>(visit.Order);
  351. if (first != null)
  352. {
  353. //推省上
  354. await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
  355. new PublishVisitDto()
  356. {
  357. Order = orderDto,
  358. No = visit.No,
  359. VisitType = visit.VisitType,
  360. VisitName = visit.CreatorName,
  361. VisitTime = visit.VisitTime,
  362. VisitRemark = string.IsNullOrEmpty(first.VisitContent) ? first.OrgProcessingResults?.Value : first.VisitContent,
  363. AreaCode = visit.Order.AreaCode!,
  364. SubjectResultSatifyCode = first.OrgProcessingResults.Key,
  365. FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
  366. ClientGuid = ""
  367. }, cancellationToken: cancellationToken);
  368. }
  369. //写入质检
  370. await _qualityApplication.AddQualityAsync(EQualitySource.Visit, orderDto.Id, visit.Id,
  371. cancellationToken);
  372. }
  373. }
  374. public ISugarQueryable<Order> QueryOrders(QueryOrderDto dto)
  375. {
  376. var isCenter = _sessionContext.OrgIsCenter;
  377. return _orderRepository.Queryable(viewFilter: isCenter ? false : true)
  378. .Includes(x => x.OrderScreens)
  379. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!)) //标题
  380. .WhereIF(!string.IsNullOrEmpty(dto.ProvinceNo), d => d.ProvinceNo.Contains(dto.ProvinceNo)) //省本地编号
  381. .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No.Contains(dto.No)) //工单编码
  382. //.WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
  383. .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptTypeCode)) //受理类型
  384. .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
  385. .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
  386. .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) //转接号码
  387. //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
  388. .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
  389. .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
  390. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
  391. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
  392. .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel)) //紧急程度
  393. .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), d => d.FromPhone.Contains(dto.FromPhone)) //来电号码
  394. .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.Contact.Contains(dto.PhoneNo!)) //联系电话
  395. .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode) //推送分类
  396. .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart) //超期时间开始
  397. .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd) //超期时间结束
  398. .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status)) //工单状态
  399. .WhereIF(dto.Statuses.Any(d => d == EOrderStatus.SpecialToUnAccept), d => d.Status <= EOrderStatus.SpecialToUnAccept)
  400. .WhereIF(!string.IsNullOrEmpty(dto.ActualHandlerName), d => d.ActualHandlerName.Contains(dto.ActualHandlerName)) //接办人
  401. .WhereIF(dto.IsScreen == true, d => d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //有甄别
  402. .WhereIF(dto.IsScreen == false, d => !d.OrderScreens.Any(x => x.Status != EScreenStatus.Refuse)) //无甄别
  403. .WhereIF(!string.IsNullOrEmpty(dto.CurrentStepCode), d => d.ActualHandleStepCode == dto.CurrentStepCode) //当前办理节点
  404. .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
  405. .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.ActualHandleTime <= dto.ActualHandleTimeEnd) //办结时间结束
  406. .WhereIF(dto.IsOverTime == true, d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //是 超期
  407. .WhereIF(dto.IsOverTime == false, d => (d.ExpiredTime > DateTime.Now && d.Status < EOrderStatus.Filed) || (d.ExpiredTime > d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //否 超期
  408. .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
  409. .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName.Contains(dto.FromName)) //来电人姓名
  410. .WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
  411. .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, x => x.IsProvince == true)
  412. .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.IsProvince == false)
  413. .WhereIF(!string.IsNullOrEmpty(dto.SensitiveWord), x => SqlFunc.JsonArrayAny(x.Sensitive, dto.SensitiveWord))
  414. .WhereIF(dto.IsSensitiveWord.HasValue && dto.IsSensitiveWord == true, x => x.Sensitive != null && SqlFunc.JsonArrayLength(x.Sensitive) > 0)
  415. .OrderByDescending(d => d.CreationTime);
  416. }
  417. #region private
  418. /// <summary>
  419. /// 接受外部工单(除省平台)
  420. /// </summary>
  421. /// <param name="dto"></param>
  422. /// <param name="cancellationToken"></param>
  423. /// <returns></returns>
  424. private async Task<AddOrderResponse> ReceiveOrderFromOtherPlatformAsync(AddOrderDto dto, List<FileDto> files,
  425. ISessionContext current, CancellationToken cancellationToken)
  426. {
  427. if (string.IsNullOrEmpty(dto.ExternalId))
  428. throw new UserFriendlyException("工单外部编号不能为空");
  429. var order = await _orderRepository.Queryable()
  430. .FirstAsync(d => d.ExternalId == dto.ExternalId, cancellationToken);
  431. if (order == null)
  432. {
  433. order = _mapper.Map<Order>(dto);
  434. order.InitId();
  435. if (files != null && files.Any())
  436. order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
  437. await _orderDomainService.AddAsync(order, cancellationToken: cancellationToken);
  438. }
  439. else
  440. {
  441. _mapper.Map(dto, order);
  442. if (files != null && files.Any())
  443. order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
  444. await _orderRepository.UpdateAsync(order, cancellationToken);
  445. }
  446. return _mapper.Map<AddOrderResponse>(order);
  447. }
  448. /// <summary>
  449. /// 接受省平台工单
  450. /// </summary>
  451. private async Task<AddOrderResponse> ReceiveOrderFromProvinceAsync(AddOrderDto dto, List<FileDto> files,
  452. ISessionContext current, CancellationToken cancellationToken)
  453. {
  454. if (string.IsNullOrEmpty(dto.ProvinceNo))
  455. throw new UserFriendlyException("无效省工单编号");
  456. var orderExtension = await _orderDomainService.GetOrderExtensionsAsync(dto.ProvinceNo, cancellationToken);
  457. var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
  458. if (order is null)
  459. {
  460. order = _mapper.Map<Order>(dto);
  461. order.InitId();
  462. if (files != null && files.Any())
  463. order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
  464. await _orderDomainService.AddAsync(order, cancellationToken: cancellationToken);
  465. if (orderExtension is not null)
  466. {
  467. orderExtension.Id = order.Id;
  468. if (dto.OrderExtension != null)
  469. _mapper.Map(dto.OrderExtension, orderExtension);
  470. await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
  471. }
  472. }
  473. else
  474. {
  475. _mapper.Map(dto, order);
  476. if (files != null && files.Any())
  477. order.FileJson = await _fileRepository.AddFileAsync(files, order.Id, "", cancellationToken);
  478. await _orderRepository.UpdateAsync(order, cancellationToken);
  479. if (orderExtension is not null)
  480. {
  481. orderExtension.Id = order.Id;
  482. if (dto.OrderExtension != null)
  483. _mapper.Map(dto.OrderExtension, orderExtension);
  484. await _orderDomainService.UpdateExtensionAsync(orderExtension, cancellationToken);
  485. }
  486. //特提(撤回至发起)
  487. if (!string.IsNullOrEmpty(order.WorkflowId))
  488. await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, "省工单重派", current, cancellationToken);
  489. }
  490. return _mapper.Map<AddOrderResponse>(order);
  491. }
  492. #endregion
  493. }