OrderApplication.cs 24 KB

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