OrderController.cs 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146
  1. using DotNetCore.CAP;
  2. using Hotline.Application.FlowEngine;
  3. using Hotline.Caching.Interfaces;
  4. using Hotline.File;
  5. using Hotline.FlowEngine.Definitions;
  6. using Hotline.FlowEngine.Workflows;
  7. using Hotline.Orders;
  8. using Hotline.Orders.Notifications;
  9. using Hotline.Permissions;
  10. using Hotline.Quality;
  11. using Hotline.Repository.SqlSugar.Extensions;
  12. using Hotline.Repository.SqlSugar.Ts;
  13. using Hotline.Settings;
  14. using Hotline.Settings.Hotspots;
  15. using Hotline.Settings.TimeLimits;
  16. using Hotline.Share.Dtos;
  17. using Hotline.Share.Dtos.FlowEngine;
  18. using Hotline.Share.Dtos.Order;
  19. using Hotline.Share.Dtos.Settings;
  20. using Hotline.Share.Enums.Order;
  21. using Hotline.Share.Enums.Quality;
  22. using Hotline.Share.Enums.Settings;
  23. using Hotline.Share.Mq;
  24. using Hotline.Share.Requests;
  25. using MapsterMapper;
  26. using MediatR;
  27. using Microsoft.AspNetCore.Mvc;
  28. using SqlSugar;
  29. using Hotline.FlowEngine.WorkflowModules;
  30. using XF.Domain.Authentications;
  31. using XF.Domain.Constants;
  32. using XF.Domain.Exceptions;
  33. using XF.Domain.Repository;
  34. using XF.Utility.EnumExtensions;
  35. using Microsoft.IdentityModel.Tokens;
  36. namespace Hotline.Api.Controllers;
  37. /// <summary>
  38. /// 工单
  39. /// </summary>
  40. public class OrderController : BaseController
  41. {
  42. private readonly IOrderDomainService _orderDomainService;
  43. private readonly IOrderRepository _orderRepository;
  44. private readonly IWorkflowApplication _workflowApplication;
  45. private readonly IWorkflowDomainService _workflowDomainService;
  46. private readonly IRepository<Hotspot> _hotspotTypeRepository;
  47. private readonly ISystemOrganizeRepository _organizeRepository;
  48. private readonly IDefinitionDomainService _definitionDomainService;
  49. private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
  50. private readonly ISessionContext _sessionContext;
  51. private readonly IMapper _mapper;
  52. private readonly IMediator _mediator;
  53. private readonly IRepository<OrderPublish> _orderPublishRepository;
  54. private readonly IRepository<OrderVisit> _orderVisitRepository;
  55. private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
  56. private readonly ICapPublisher _capPublisher;
  57. private readonly IRepository<OrderDelay> _orderDelayRepository;
  58. private readonly ITimeLimitDomainService _timeLimitDomainService;
  59. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  60. private readonly IRepository<OrderRedo> _orderRedoRepository;
  61. private readonly IRepository<OrderSupervise> _orderSuperviseRepository;
  62. private readonly IRepository<OrderUrge> _orderUrgeRepository;
  63. private readonly IFileRepository _fileRepository;
  64. private readonly IRepository<OrderScreen> _orderScreenRepository;
  65. private readonly IRepository<OrderPublishHistory> _orderPublishHistoryRepository;
  66. private readonly IRepositoryTextSearch<OrderTs> _repositoryts;
  67. private readonly IQualityRepository _qualityRepository;
  68. private readonly IRepository<Workflow> _workflowRepository;
  69. private readonly ICitizenRepository _citizenRepository;
  70. private readonly IRepository<CitizenLabelDetail> _labelDetailRepository;
  71. private readonly IRepository<RepeatableEvent> _repeatableEventRepository;
  72. private readonly IRepeatableEventDetailRepository _repeatableEventDetailRepository;
  73. private readonly IRepository<OrderWord> _orderWrodRepository;
  74. private readonly IRepository<OrderObserve> _orderObserveRepository;
  75. public OrderController(
  76. IOrderDomainService orderDomainService,
  77. IOrderRepository orderRepository,
  78. IWorkflowApplication workflowApplication,
  79. IWorkflowDomainService workflowDomainService,
  80. IRepository<Hotspot> hotspotTypeRepository,
  81. ISystemOrganizeRepository organizeRepository,
  82. IDefinitionDomainService definitionDomainService,
  83. ISystemDicDataCacheManager sysDicDataCacheManager,
  84. ISessionContext sessionContext,
  85. IMapper mapper,
  86. IMediator mediator,
  87. IRepository<OrderPublish> orderPublishRepository,
  88. IRepository<OrderVisit> orderVisitRepository,
  89. IRepository<OrderVisitDetail> orderVisitedDetailRepository,
  90. ICapPublisher capPublisher,
  91. IRepository<OrderDelay> orderDelayRepository,
  92. ITimeLimitDomainService timeLimitDomainService,
  93. ISystemSettingCacheManager systemSettingCacheManager,
  94. IRepository<OrderRedo> orderRedoRepository,
  95. IRepository<OrderSupervise> orderSuperviseRepository,
  96. IRepository<OrderUrge> orderUrgeRepository,
  97. IFileRepository fileRepository,
  98. IRepository<OrderScreen> orderScreenRepository,
  99. IRepository<OrderPublishHistory> orderPublishHistoryRepository,
  100. IRepositoryTextSearch<OrderTs> repositoryts,
  101. IQualityRepository qualityRepository,
  102. IRepository<Workflow> workflowRepository,
  103. ICitizenRepository citizenRepository,
  104. IRepository<CitizenLabelDetail> labelDetailRepository,
  105. IRepository<RepeatableEvent> repeatableEventRepository,
  106. IRepeatableEventDetailRepository repeatableEventDetailRepository,
  107. IRepository<OrderWord> orderWrodRepository,
  108. IRepository<OrderObserve> orderObserveRepository
  109. )
  110. {
  111. _orderDomainService = orderDomainService;
  112. _orderRepository = orderRepository;
  113. _workflowApplication = workflowApplication;
  114. _workflowDomainService = workflowDomainService;
  115. _hotspotTypeRepository = hotspotTypeRepository;
  116. _organizeRepository = organizeRepository;
  117. _definitionDomainService = definitionDomainService;
  118. _sysDicDataCacheManager = sysDicDataCacheManager;
  119. _sessionContext = sessionContext;
  120. _mapper = mapper;
  121. _mediator = mediator;
  122. _orderPublishRepository = orderPublishRepository;
  123. _orderVisitRepository = orderVisitRepository;
  124. _orderVisitedDetailRepository = orderVisitedDetailRepository;
  125. _capPublisher = capPublisher;
  126. _orderDelayRepository = orderDelayRepository;
  127. _timeLimitDomainService = timeLimitDomainService;
  128. _systemSettingCacheManager = systemSettingCacheManager;
  129. _orderRedoRepository = orderRedoRepository;
  130. _orderSuperviseRepository = orderSuperviseRepository;
  131. _orderUrgeRepository = orderUrgeRepository;
  132. _fileRepository = fileRepository;
  133. _orderScreenRepository = orderScreenRepository;
  134. _orderPublishHistoryRepository = orderPublishHistoryRepository;
  135. _repositoryts = repositoryts;
  136. _qualityRepository = qualityRepository;
  137. _workflowRepository = workflowRepository;
  138. _citizenRepository = citizenRepository;
  139. _labelDetailRepository = labelDetailRepository;
  140. _repeatableEventRepository = repeatableEventRepository;
  141. _repeatableEventDetailRepository = repeatableEventDetailRepository;
  142. _orderWrodRepository = orderWrodRepository;
  143. _orderObserveRepository = orderObserveRepository;
  144. }
  145. #region 工单发布
  146. /// <summary>
  147. /// 查询(工单发布)
  148. /// </summary>
  149. /// <param name="dto"></param>
  150. /// <returns></returns>
  151. [Permission(EPermission.PublishOrderList)]
  152. [HttpGet("publish")]
  153. public async Task<PagedDto<PublishDto>> PublishOrderList([FromQuery] QueryOrderPublishDto dto)
  154. {
  155. var (total, items) = await _orderRepository.Queryable()
  156. .Includes(d => d.OrderPublish)
  157. .Where(x => x.Status == EOrderStatus.Filed)
  158. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  159. d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
  160. .WhereIF(dto.PubState == EPubState.Pub, d => d.Status >= EOrderStatus.Published)
  161. .WhereIF(dto.PubState == EPubState.NoPub, d => d.Status < EOrderStatus.Published)
  162. .WhereIF(!string.IsNullOrEmpty(dto.PubMan),
  163. d => d.Acceptor.Name.Contains(dto.PubMan!) || d.Acceptor.StaffNo.Contains(dto.PubMan!))
  164. .WhereIF(dto.PubRange == EPublicState.Pub, d => d.OrderPublish.PublishState)
  165. .WhereIF(dto.PubRange == EPublicState.NoPub, d => !d.OrderPublish.PublishState)
  166. .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
  167. .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
  168. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  169. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  170. .WhereIF(dto.FiledTimeStart.HasValue, d => d.OrderPublish.CreationTime >= dto.CreationTimeStart)
  171. .WhereIF(dto.FiledTimeEnd.HasValue, d => d.OrderPublish.CreationTime <= dto.CreationTimeEnd)
  172. .OrderBy(d => d.CreationTime)
  173. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  174. return new PagedDto<PublishDto>(total, _mapper.Map<IReadOnlyList<PublishDto>>(items));
  175. }
  176. /// <summary>
  177. /// 发布工单
  178. /// </summary>
  179. /// <returns></returns>
  180. [Permission(EPermission.PublishOrder)]
  181. [HttpPost("publish")]
  182. public async Task PublishOrder([FromBody] PublishOrderDto dto)
  183. {
  184. //验证订单
  185. var order = await _orderRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  186. if (order is null)
  187. throw UserFriendlyException.SameMessage("未找到工单,无法发布");
  188. //新增发布工单
  189. OrderPublish orderPublish = new OrderPublish();
  190. orderPublish.OrderId = order.Id;
  191. orderPublish.No = order.No;
  192. orderPublish.PublishState = dto.PublishState;
  193. orderPublish.ArrangeTitle = dto.ArrangeTitle;
  194. orderPublish.ArrangeContent = dto.ArrangeContent;
  195. orderPublish.ArrangeOpinion = dto.ArrangeOpinion;
  196. orderPublish.ProPublishState = dto.ProPublishState;
  197. orderPublish.FeedBackPhone = dto.FeedBackPhone;
  198. orderPublish.NoPubReason = dto.NoPubReason;
  199. orderPublish.CreatorName = _sessionContext.UserName;
  200. string id = await _orderPublishRepository.AddAsync(orderPublish);
  201. order.Publish(orderPublish.PublishState);
  202. await _orderRepository.UpdateAsync(order);
  203. var orderVisit = new OrderVisit();
  204. orderVisit.No = order.No;
  205. orderVisit.OrderId = order.Id;
  206. orderVisit.VisitState = EVisitState.WaitForVisit;
  207. orderVisit.PublishTime = DateTime.Now;
  208. string visitId = await _orderVisitRepository.AddAsync(orderVisit);
  209. //新增回访信息
  210. var visitedDetail = new List<OrderVisitDetail>();
  211. var seatDetail = new OrderVisitDetail();
  212. seatDetail.VisitId = visitId;
  213. seatDetail.VisitTarget = EVisitTarget.Seat;
  214. visitedDetail.Add(seatDetail);
  215. foreach (var item in dto.IdNames)
  216. {
  217. var orgDetail = new OrderVisitDetail();
  218. orgDetail.VisitId = visitId;
  219. orgDetail.VisitOrgCode = item.Key;
  220. orgDetail.VisitOrgName = item.Value;
  221. orgDetail.VisitTarget = EVisitTarget.Org;
  222. visitedDetail.Add(orgDetail);
  223. }
  224. await _mediator.Publish(new AddVisitNotify(visitedDetail), HttpContext.RequestAborted);
  225. //TODO 中国政府网
  226. if (order.SourceChannelCode == "ZGZFW")
  227. {
  228. }
  229. //TODO 省政民互动
  230. if (order.SourceChannelCode == "ZMHD")
  231. {
  232. }
  233. }
  234. /// <summary>
  235. /// 发布页面基础信息
  236. /// </summary>
  237. /// <returns></returns>
  238. [Permission(EPermission.PublishOrderPageBase)]
  239. [HttpGet("publish-order-pagebase/{id}")]
  240. public async Task<PublishOrderPageBaseDto> PublishOrderPageBase(string id)
  241. {
  242. var order = await _orderRepository.Queryable()
  243. .Includes(d => d.Acceptor)
  244. .Includes(d => d.OrderComplain)
  245. .FirstAsync(d => d.Id == id);
  246. if (order is null)
  247. throw UserFriendlyException.SameMessage("未知工单,无法发布");
  248. var res = new PublishOrderPageBaseDto()
  249. {
  250. SourceChannel = order.SourceChannel,
  251. OrderTitle = order.Title,
  252. Content = order.Content,
  253. ActualOpinion = order.ActualOpinion
  254. };
  255. var (idName, idNames) =
  256. await _workflowDomainService.GetUnvisitOrgsAsync(order.WorkflowId, HttpContext.RequestAborted);
  257. res.ActualHandleOrgName = idName;
  258. res.idNames = idNames.ToList();
  259. return res;
  260. }
  261. /// <summary>
  262. /// 已发布列表
  263. /// </summary>
  264. /// <param name="dto"></param>
  265. /// <returns></returns>
  266. [Permission(EPermission.PublishedOrderList)]
  267. [HttpGet("published")]
  268. public async Task<PagedDto<PublishedDto>> PublishedOrderList([FromQuery] PagedKeywordRequest dto)
  269. {
  270. var (total, items) = await _orderPublishRepository.Queryable()
  271. .Includes(x => x.Order)
  272. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  273. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  274. .OrderBy(d => d.CreationTime)
  275. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  276. return new PagedDto<PublishedDto>(total, _mapper.Map<IReadOnlyList<PublishedDto>>(items));
  277. }
  278. /// <summary>
  279. /// 发布详情
  280. /// </summary>
  281. /// <param name="id"></param>
  282. /// <returns></returns>
  283. [Permission(EPermission.PublishedOrder)]
  284. [HttpGet("published-order/{id}")]
  285. public async Task<PublishedEntityDto> PublishedOrder(string id)
  286. {
  287. var publishedOrder = await _orderPublishRepository.GetAsync(id, HttpContext.RequestAborted);
  288. if (publishedOrder is null)
  289. {
  290. throw UserFriendlyException.SameMessage("未知数据!");
  291. }
  292. var pubentity = _mapper.Map<PublishedEntityDto>(publishedOrder);
  293. var visit = await _orderVisitRepository.Queryable().Includes(x => x.OrderVisitDetails)
  294. .OrderByDescending(x => x.CreationTime)
  295. .FirstAsync(x => x.OrderId == publishedOrder.OrderId, HttpContext.RequestAborted);
  296. if (visit != null)
  297. {
  298. var details = visit.OrderVisitDetails.Where(x => x.VisitTarget == EVisitTarget.Org).ToList();
  299. if (details != null && details.Count > 0)
  300. {
  301. pubentity.IdNames = new List<Kv>();
  302. details.ForEach(f => pubentity.IdNames.Add(new Kv() { Key = f.VisitOrgCode, Value = f.VisitOrgName }));
  303. }
  304. }
  305. return pubentity;
  306. }
  307. /// <summary>
  308. /// 修改发布内容
  309. /// </summary>
  310. /// <param name="dto"></param>
  311. /// <returns></returns>
  312. [Permission(EPermission.PublishedModify)]
  313. [HttpPost("published-order-modify")]
  314. public async Task PublishedModify([FromBody] PublishOrderModifyDto dto)
  315. {
  316. var publishOrder = await _orderPublishRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  317. if (publishOrder is null)
  318. {
  319. throw UserFriendlyException.SameMessage("无效数据");
  320. }
  321. var history = new OrderPublishHistory();
  322. history.ArrangeTitleBefor = publishOrder.ArrangeTitle;
  323. history.ArrangeTitleAfter = dto.ArrangeTitle;
  324. history.ArrangeContentBefor = publishOrder.ArrangeContent;
  325. history.ArrangeContentAfter = dto.ArrangeContent;
  326. history.ArrangeOpinionBefor = publishOrder.ArrangeOpinion;
  327. history.ArrangeOpinionAfter = dto.ArrangeOpinion;
  328. history.No = publishOrder.No;
  329. history.OrderId = publishOrder.OrderId;
  330. history.OrderPublishId = publishOrder.Id;
  331. publishOrder.ArrangeTitle = dto.ArrangeTitle;
  332. publishOrder.ArrangeContent = dto.ArrangeContent;
  333. publishOrder.ArrangeOpinion = dto.ArrangeOpinion;
  334. await _orderPublishRepository.UpdateAsync(publishOrder, HttpContext.RequestAborted);
  335. await _orderPublishHistoryRepository.AddAsync(history, HttpContext.RequestAborted);
  336. }
  337. /// <summary>
  338. /// 发布修改记录
  339. /// </summary>
  340. /// <param name="id"></param>
  341. /// <returns></returns>
  342. [Permission(EPermission.QueryPublishedHistory)]
  343. [HttpGet("published-history-list/{id}")]
  344. public async Task<List<OrderPublishHistory>> QueryPublishedHistory(string id)
  345. {
  346. return await _orderPublishHistoryRepository.Queryable().Where(x => x.OrderPublishId == id)
  347. .OrderByDescending(x => x.CreationTime).ToListAsync(HttpContext.RequestAborted);
  348. }
  349. #endregion
  350. #region 工单回访
  351. /// <summary>
  352. /// 回访列表
  353. /// </summary>
  354. /// <param name="dto"></param>
  355. /// <returns></returns>
  356. [Permission(EPermission.QueryOrderVisitList)]
  357. [HttpGet("visit")]
  358. public async Task<PagedDto<OrderVisitDto>> QueryOrderVisitList([FromQuery] QueryOrderVisitDto dto)
  359. {
  360. var (total, items) = await _orderVisitRepository.Queryable()
  361. .Includes(x => x.Order)
  362. .Includes(x => x.Employee)
  363. .Includes(x => x.OrderVisitDetails)
  364. .WhereIF(dto.VisitState == EVisitStateQuery.NoVisit,
  365. x => x.VisitState == Share.Enums.Order.EVisitState.WaitForVisit ||
  366. x.VisitState == Share.Enums.Order.EVisitState.NoSatisfiedWaitForVisit)
  367. .WhereIF(dto.VisitState == EVisitStateQuery.Visited,
  368. x => x.VisitState == Share.Enums.Order.EVisitState.Visited)
  369. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  370. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  371. .OrderBy(x => x.CreationTime)
  372. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  373. return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
  374. }
  375. /// <summary>
  376. /// 回访详情
  377. /// </summary>
  378. /// <returns></returns>
  379. [Permission(EPermission.VisitInfo)]
  380. [HttpGet("visit/{id}")]
  381. public async Task<object> VisitInfo(string id)
  382. {
  383. var orderVisit = await _orderVisitRepository.Queryable()
  384. .Includes(x => x.Order)
  385. .Includes(x => x.Employee)
  386. .Includes(x => x.OrderVisitDetails)
  387. .FirstAsync(x => x.Id == id, HttpContext.RequestAborted);
  388. if (orderVisit is null)
  389. {
  390. throw UserFriendlyException.SameMessage("未知工单回访");
  391. }
  392. int visitCount = await _orderVisitRepository.CountAsync(
  393. x => x.OrderId == orderVisit.OrderId && x.VisitState == Share.Enums.Order.EVisitState.Visited,
  394. HttpContext.RequestAborted);
  395. int againCount = await _orderVisitRepository.CountAsync(
  396. x => x.OrderId == orderVisit.OrderId && x.AgainState == EAgainState.DoAgain, HttpContext.RequestAborted);
  397. var voiceEvaluate = EnumExts.GetDescriptions<EVoiceEvaluate>();
  398. var seatEvaluate = EnumExts.GetDescriptions<ESeatEvaluate>();
  399. var visitSatisfaction = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitSatisfaction);
  400. var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason);
  401. var visitManner = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.VisitManner);
  402. return new
  403. {
  404. OrderVisitModel = orderVisit,
  405. VisitCount = visitCount,
  406. AgainCount = againCount,
  407. VisitSatisfaction = visitSatisfaction,
  408. DissatisfiedReason = dissatisfiedReason,
  409. VisitManner = visitManner,
  410. ViceEvaluate = voiceEvaluate,
  411. SeatEvaluate = seatEvaluate
  412. };
  413. }
  414. /// <summary>
  415. /// 回访明细
  416. /// </summary>
  417. /// <returns></returns>
  418. [Permission(EPermission.VisitDetailList)]
  419. [HttpGet("visit/detail")]
  420. public async Task<PagedDto<OrderVisitDetailDto>> VisitDetailList([FromQuery] VisitDetailListDto dto)
  421. {
  422. var (total, items) = await _orderVisitedDetailRepository.Queryable()
  423. .Includes(x => x.OrderVisit, s => s.Order)
  424. .WhereIF(dto.VisitState == EVisitStateQuery.NoVisit,
  425. x => x.OrderVisit.VisitState == Share.Enums.Order.EVisitState.WaitForVisit || x.OrderVisit.VisitState ==
  426. Share.Enums.Order.EVisitState.NoSatisfiedWaitForVisit)
  427. .WhereIF(dto.VisitState == EVisitStateQuery.Visited,
  428. x => x.OrderVisit.VisitState == Share.Enums.Order.EVisitState.Visited)
  429. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  430. d => d.OrderVisit.Order.Title.Contains(dto.Keyword!) || d.OrderVisit.Order.No.Contains(dto.Keyword!))
  431. .OrderByDescending(x => x.CreationTime)
  432. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  433. return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
  434. }
  435. /// <summary>
  436. /// 回访保存
  437. /// </summary>
  438. /// <returns></returns>
  439. [Permission(EPermission.Visit)]
  440. [HttpPost("visit")]
  441. public async Task Visit([FromBody] VisitDto dto)
  442. {
  443. //var visit = await _orderVisitRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  444. var visit = await _orderVisitRepository.Queryable()
  445. .Includes(d => d.Order)
  446. .Includes(d => d.OrderVisitDetails)
  447. .FirstAsync(d => d.Id == dto.Id, HttpContext.RequestAborted);
  448. if (visit is null)
  449. throw UserFriendlyException.SameMessage("未知回访信息");
  450. if (visit.VisitState == EVisitState.Visited)
  451. throw UserFriendlyException.SameMessage("已回访,不能重复回访");
  452. var first = dto.VisitDetails.FirstOrDefault(x => x.VisitTarget == EVisitTarget.Org);
  453. //更新主表
  454. if (dto.IsPutThrough)
  455. {
  456. visit.VisitState = Share.Enums.Order.EVisitState.Visited;
  457. visit.VisitTime = DateTime.Now;
  458. visit.VisitType = EVisitType.ArtificialVisit;
  459. }
  460. visit.IsPutThrough = dto.IsPutThrough;
  461. visit.AgainState = dto.IsAgain ? EAgainState.NeedAgain : EAgainState.NoAgain;
  462. visit.EmployeeId = _sessionContext.UserId;
  463. if (first != null)
  464. {
  465. visit.NowEvaluate = first.OrgProcessingResults;
  466. }
  467. //await _orderVisitRepository.UpdateAsync(visit,HttpContext.RequestAborted);
  468. //update order
  469. if (dto.IsPutThrough)
  470. {
  471. if (first != null)
  472. {
  473. visit.Order.Visited(first.OrgProcessingResults.Key, first.OrgProcessingResults.Value);
  474. }
  475. //_mapper.Map(dto.VisitDetails,visit.OrderVisitDetails);
  476. for (int i = 0; i < visit.OrderVisitDetails.Count; i++)
  477. {
  478. var detail = visit.OrderVisitDetails[i];
  479. var detaildto = dto.VisitDetails.FirstOrDefault(x => x.Id == detail.Id);
  480. if (detaildto != null)
  481. {
  482. _mapper.Map(detaildto, visit.OrderVisitDetails[i]);
  483. }
  484. }
  485. await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
  486. await _orderVisitedDetailRepository.UpdateRangeAsync(visit.OrderVisitDetails, HttpContext.RequestAborted);
  487. await _orderRepository.UpdateAsync(visit.Order, HttpContext.RequestAborted);
  488. var orderDto = _mapper.Map<OrderDto>(visit.Order);
  489. if (first != null)
  490. {
  491. //推省上
  492. _capPublisher.Publish(EventNames.HotlineOrderVisited,
  493. new PublishVisitDto()
  494. {
  495. Order = orderDto,
  496. No = visit.No,
  497. VisitType = visit.VisitType,
  498. VisitName = visit.CreatorName,
  499. VisitTime = visit.VisitTime,
  500. VisitRemark = first.VisitContent,
  501. AreaCode = visit.Order.AreaCode!,
  502. SubjectResultSatifyCode = first.OrgProcessingResults.Key,
  503. FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
  504. ClientGuid = ""
  505. });
  506. }
  507. if (first != null)
  508. {
  509. //写入质检
  510. await _qualityRepository.AddQualityAsync(EQualitySource.Visit, visit.Order.Id, visit.Id, HttpContext.RequestAborted);
  511. }
  512. }
  513. }
  514. /// <summary>
  515. /// 批量分配回访人员
  516. /// </summary>
  517. /// <param name="dto"></param>
  518. /// <returns></returns>
  519. [HttpPost("visit/distribution")]
  520. public async Task<DistributionVisitRspDto> DistributionVisit([FromBody] DistributionVisitDto dto)
  521. {
  522. int error = 0;
  523. foreach (var id in dto.Ids)
  524. {
  525. var visit = await _orderVisitRepository.Queryable().FirstAsync(d => d.Id == id, HttpContext.RequestAborted);
  526. if (visit != null && visit.VisitState != EVisitState.WaitForVisit)
  527. {
  528. visit.EmployeeId = dto.EmployeeId;
  529. await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
  530. }
  531. else
  532. {
  533. error++;
  534. }
  535. }
  536. return new DistributionVisitRspDto() { ErrorCount = error, SuccessCount = dto.Ids.Count - error };
  537. }
  538. #endregion
  539. #region 工单重办
  540. /// <summary>
  541. /// 重办查询
  542. /// </summary>
  543. /// <param name="dto"></param>
  544. /// <returns></returns>
  545. [Permission(EPermission.QueryOrderRedoRecord)]
  546. [HttpGet("redo")]
  547. public async Task<PagedDto<OrderRedo>> QueryOrderRedo([FromQuery] QueryOrderRedoRecordDto dto)
  548. {
  549. var (total, items) = await _orderRedoRepository.Queryable()
  550. .Includes(x => x.Order)
  551. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  552. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  553. .OrderByDescending(x => x.CreationTime)
  554. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  555. return new PagedDto<OrderRedo>(total, items);
  556. }
  557. /// <summary>
  558. /// 重办详情
  559. /// </summary>
  560. /// <param name="id"></param>
  561. /// <returns></returns>
  562. [Permission(EPermission.OrderRedoRecord)]
  563. [HttpGet("redo/{id}")]
  564. public async Task<OrderRedo> GetOrderRedo(string id)
  565. {
  566. return await _orderRedoRepository.Queryable()
  567. .Includes(x => x.Order)
  568. .FirstAsync(x => x.Id == id);
  569. }
  570. /// <summary>
  571. /// 发起重办
  572. /// </summary>
  573. [HttpPost("redo")]
  574. public async Task<string> AddRedo([FromBody] OrderRedoStartFlowDto dto)
  575. {
  576. var redo = _mapper.Map<OrderRedo>(dto.Data);
  577. redo.CreatorName = _sessionContext.UserName ?? string.Empty;
  578. redo.CreatorOrgName = _sessionContext.OrgName ?? string.Empty;
  579. //redo.TimeLimitCount = dto.Workflow.Extension.TimeLimitCount;
  580. //redo.TimeLimitUnit = dto.Workflow.Extension.TimeLimitUnit;
  581. //todo
  582. var handler = dto.Workflow.NextHandlers.First();
  583. redo.RedoOrgCode = handler.Key;
  584. redo.RedoOrgCode = handler.Value;
  585. var id = await _orderRedoRepository.AddAsync(redo, HttpContext.RequestAborted);
  586. try
  587. {
  588. var order = await _orderRepository.GetAsync(dto.Data.OrderId, HttpContext.RequestAborted);
  589. if (order == null)
  590. throw UserFriendlyException.SameMessage("无效工单编号");
  591. if (string.IsNullOrEmpty(order.WorkflowId))
  592. throw UserFriendlyException.SameMessage("无效工单流程编号");
  593. var redoFlowDto = _mapper.Map<RecallDto>(dto.Workflow);
  594. redoFlowDto.WorkflowId = order.WorkflowId;
  595. await _workflowApplication.RedoAsync(redoFlowDto, HttpContext.RequestAborted);
  596. return id;
  597. }
  598. catch (Exception e)
  599. {
  600. await _orderRedoRepository.RemoveAsync(id, cancellationToken: HttpContext.RequestAborted);
  601. throw new UserFriendlyException($"发起重办失败,{e.Message}");
  602. }
  603. }
  604. /// <summary>
  605. /// 重办基础数据
  606. /// </summary>
  607. /// <returns></returns>
  608. [HttpGet("base-data-redo")]
  609. public async Task<dynamic> BaseDataRedo()
  610. {
  611. var rsp = new
  612. {
  613. OrderRedoReasonOptions = EnumExts.GetDescriptions<EOrderRedoReason>(),
  614. };
  615. return rsp;
  616. }
  617. #endregion
  618. #region 工单延期
  619. /// <summary>
  620. /// 可申请延期工单
  621. /// </summary>
  622. /// <param name="dto"></param>
  623. /// <returns></returns>
  624. [Permission(EPermission.CanDelayOrderList)]
  625. [HttpGet("candelay")]
  626. public async Task<PagedDto<OrderDto>> CanDelayOrderList([FromQuery] CanDelayOrderListDto dto)
  627. {
  628. var (total, items) = await _orderRepository.Queryable()
  629. .Includes(d => d.Acceptor)
  630. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  631. d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
  632. .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.Filed &&
  633. SqlFunc.Subqueryable<OrderDelay>()
  634. .Where(s => s.OrderId == d.Id && s.DelayState == EDelayState.Examining).NotAny())
  635. .OrderByDescending(d => d.CreationTime)
  636. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  637. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  638. }
  639. /// <summary>
  640. /// 申请延期
  641. /// </summary>
  642. /// <param name="dto"></param>
  643. /// <returns></returns>
  644. [Permission(EPermission.ApplyDelay)]
  645. [HttpPost("delay")]
  646. public async Task ApplyDelay([FromBody] DelayStartFlowDto dto)
  647. {
  648. var delaydto = _mapper.Map<ApplyDelayDto>(dto.Data);
  649. //验证工单是否可以申请
  650. var order = await _orderRepository.GetAsync(delaydto.OrderId, HttpContext.RequestAborted);
  651. if (order is null)
  652. throw UserFriendlyException.SameMessage("无效工单");
  653. //验证工单是否在办理中
  654. if (order.Status == EOrderStatus.WaitForAccept || order.Status == EOrderStatus.Filed)
  655. throw UserFriendlyException.SameMessage("当前工单状态不能申请延期");
  656. bool IsHas = await _orderDelayRepository.AnyAsync(x => x.OrderId == delaydto.OrderId && x.DelayState == EDelayState.Examining, HttpContext.RequestAborted);
  657. if (IsHas)
  658. throw UserFriendlyException.SameMessage("该存在延期申请正在审核");
  659. //验证延期次数
  660. var setting = _systemSettingCacheManager.GetSetting(SettingConstants.DelayNum);
  661. int count = await _orderDelayRepository.CountAsync(x => x.OrderId == delaydto.OrderId);
  662. if (count > int.Parse(setting?.SettingValue[0]))
  663. throw UserFriendlyException.SameMessage("延期申请已超过系统预定设置,不能申请");
  664. var model = _mapper.Map<OrderDelay>(delaydto);
  665. model.EmployeeId = _sessionContext.UserId;
  666. model.ApplyOrgName = _sessionContext.OrgName;
  667. model.ApplyOrgCode = _sessionContext.OrgId;
  668. model.BeforeDelay = order.ExpiredTime;
  669. model.DelayState = EDelayState.Examining;
  670. if (model.BeforeDelay != null)
  671. {
  672. model.AfterDelay = _timeLimitDomainService.CalcEndTime(model.BeforeDelay.Value, delaydto.DelayUnit, delaydto.DelayNum, false)?.EndTime;//todo
  673. }
  674. model.ApplyDelayTime = DateTime.Now;
  675. model.No = order.No;
  676. var id = await _orderDelayRepository.AddAsync(model, HttpContext.RequestAborted);
  677. try
  678. {
  679. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  680. startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderDelay;
  681. startDto.Title = model.DelayReason;
  682. string workFlowId = await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
  683. model.WorkFlowId = workFlowId;
  684. await _orderDelayRepository.UpdateAsync(model, HttpContext.RequestAborted);
  685. }
  686. catch (Exception ex)
  687. {
  688. await _orderDelayRepository.RemoveAsync(id, false, HttpContext.RequestAborted);
  689. throw new UserFriendlyException($"工单延期流程失败!, {ex.Message}", "工单延期流程失败");
  690. }
  691. }
  692. /// <summary>
  693. /// 延期列表
  694. /// </summary>
  695. /// <returns></returns>
  696. [Permission(EPermission.DelayList)]
  697. [HttpGet("delay")]
  698. public async Task<PagedDto<OrderDelay>> DelayList([FromQuery] DelayListDto dto)
  699. {
  700. var (total, items) = await _orderDelayRepository.Queryable()
  701. .Includes(x => x.Order)
  702. .Includes(x => x.Employee)
  703. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  704. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  705. .WhereIF(dto.IsApply, x => x.DelayState != EDelayState.Examining)
  706. .WhereIF(!dto.IsApply, x => x.DelayState == EDelayState.Examining)
  707. .WhereIF(dto.DelayState != null, x => x.DelayState == dto.DelayState)
  708. .OrderByDescending(x => x.CreationTime)
  709. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  710. return new PagedDto<OrderDelay>(total, _mapper.Map<IReadOnlyList<OrderDelay>>(items));
  711. }
  712. /// <summary>
  713. /// 延期详情
  714. /// </summary>
  715. /// <param name="id"></param>
  716. /// <returns></returns>
  717. [Permission(EPermission.DelayEntity)]
  718. [HttpGet("delay/{id}")]
  719. public async Task<OrderDelay> DelayEntity(string id)
  720. {
  721. return await _orderDelayRepository.Queryable()
  722. .Includes(x => x.Order)
  723. .Includes(x => x.Employee)
  724. .FirstAsync(x => x.Id == id);
  725. }
  726. /// <summary>
  727. /// 计算期满时间
  728. /// </summary>
  729. /// <param name="dto"></param>
  730. /// <returns></returns>
  731. [Permission(EPermission.DelayCalcEndTime)]
  732. [HttpPost("delay/calc-endtime")]
  733. public async Task<TimeResult?> DelayCalcEndTime([FromBody] DelayCalcEndTimeDto dto)
  734. {
  735. return _timeLimitDomainService.CalcEndTime(dto.BeginTime, dto.DelayUnit, dto.DelayNum, false);
  736. }
  737. /// <summary>
  738. /// 查询工单延期流程开启参数
  739. /// </summary>
  740. /// <returns></returns>
  741. [HttpGet("delay/startflow")]
  742. public async Task<NextStepsDto> GetDelayFlowStartOptions()
  743. {
  744. return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderDelay, HttpContext.RequestAborted);
  745. }
  746. /// <summary>
  747. /// 延期页面基础信息
  748. /// </summary>
  749. /// <returns></returns>
  750. [HttpGet("delay/basedata")]
  751. public async Task<object> DelayBaseData()
  752. {
  753. var rsp = new
  754. {
  755. DelayState = EnumExts.GetDescriptions<EDelayState>(),
  756. TimeType = EnumExts.GetDescriptions<ETimeType>()
  757. };
  758. return rsp;
  759. }
  760. #endregion
  761. #region 工单甄别
  762. /// <summary>
  763. /// 工单甄别待申请列表
  764. /// </summary>
  765. /// <param name="dto"></param>
  766. /// <returns></returns>
  767. [Permission(EPermission.MayOrderScreenList)]
  768. [HttpGet("mayscreen")]
  769. public async Task<PagedDto<OrderVisitDetailDto>> MayScreenList([FromQuery] MayScreenListDto dto)
  770. {
  771. var query = _orderVisitedDetailRepository.Queryable()
  772. .Includes(x => x.OrderVisit)
  773. .Includes(x => x.OrderVisit, y => y.Order)
  774. .Includes(x => x.OrderVisit, y => y.Employee);
  775. if (_sessionContext.OrgId != null && !_sessionContext.OrgId.StartsWith("001"))
  776. {
  777. query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.OrderVisit.Order.Title.Contains(dto.Keyword!) || d.OrderVisit.Order.No.Contains(dto.Keyword!))
  778. .Where(d => d.VisitTarget == EVisitTarget.Org && d.VisitOrgCode == _sessionContext.OrgId && (
  779. SqlFunc.JsonField(d.OrgProcessingResults, "Name") == "不满意" || SqlFunc.JsonField(d.OrgProcessingResults, "Name") == "非常不满意" ||
  780. SqlFunc.JsonField(d.OrgHandledAttitude, "Name") == "不满意" || SqlFunc.JsonField(d.OrgHandledAttitude, "Name") == "非常不满意"
  781. ));
  782. }
  783. else
  784. {
  785. query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.OrderVisit.Order.Title.Contains(dto.Keyword!) || d.OrderVisit.Order.No.Contains(dto.Keyword!))
  786. .Where(d => d.VisitTarget == EVisitTarget.Org && (
  787. SqlFunc.JsonField(d.OrgProcessingResults, "Name") == "不满意" || SqlFunc.JsonField(d.OrgProcessingResults, "Name") == "非常不满意" ||
  788. SqlFunc.JsonField(d.OrgHandledAttitude, "Name") == "不满意" || SqlFunc.JsonField(d.OrgHandledAttitude, "Name") == "非常不满意"
  789. ));
  790. }
  791. var (total, items) = await query
  792. .OrderBy(x => x.CreationTime)
  793. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  794. return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
  795. }
  796. /// <summary>
  797. /// 工单甄别列表
  798. /// </summary>
  799. /// <param name="dto"></param>
  800. /// <returns></returns>
  801. [Permission(EPermission.OrderScreenList)]
  802. [HttpGet("screen")]
  803. public async Task<PagedDto<OrderScreenListDto>> ScreenList([FromQuery] ScreenListDto dto)
  804. {
  805. var (total, items) = await _orderScreenRepository.Queryable()
  806. .Includes(x => x.Order)
  807. .Includes(x => x.VisitDetail)
  808. .Includes(x => x.Visit, d => d.Order)
  809. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Visit.Order.Title.Contains(dto.Keyword!) || d.Visit.Order.No.Contains(dto.Keyword!))
  810. .WhereIF(dto.Status == EScreenStatus.Apply || dto.Status == EScreenStatus.Approval || dto.Status == EScreenStatus.End, x => x.Status == dto.Status)
  811. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  812. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  813. .OrderByDescending(x => x.CreationTime)
  814. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  815. return new PagedDto<OrderScreenListDto>(total, _mapper.Map<IReadOnlyList<OrderScreenListDto>>(items));
  816. }
  817. /// <summary>
  818. /// 开始工单甄别流程
  819. /// </summary>
  820. [Permission(EPermission.ApplyScreen)]
  821. [HttpPost("screen/startflow")]
  822. public async Task StartFlow([FromBody] ScreenStartFlowDto dto)
  823. {
  824. int screenCount = await _orderScreenRepository.CountAsync(x => x.VisitDetailId == dto.Data.VisitDetailId && (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval));
  825. if (screenCount > 0)
  826. throw UserFriendlyException.SameMessage("该工单已提起甄别申请,正在审批过程中,不能申请");
  827. var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyNum);
  828. int count = await _orderScreenRepository.CountAsync(x => x.OrderId == dto.Data.OrderId && x.Status == EScreenStatus.Refuse);
  829. if (count > int.Parse(setting?.SettingValue[0]))
  830. throw UserFriendlyException.SameMessage("甄别申请已超过系统预定设置,不能申请");
  831. var visit = await _orderVisitRepository.GetAsync(dto.Data.VisitId, HttpContext.RequestAborted);
  832. setting = _systemSettingCacheManager.GetSetting(SettingConstants.ScreenApplyEndTime);
  833. var endTime = _timeLimitDomainService.CalcEndTime(visit.VisitTime.Value, ETimeType.WorkDay, int.Parse(setting?.SettingValue[0]), false).EndTime.Value;
  834. if (DateTime.Now > endTime)
  835. throw UserFriendlyException.SameMessage("甄别申请时限已超过系统预定设置,不能申请");
  836. var model = _mapper.Map<OrderScreen>(dto.Data);
  837. model.Status = EScreenStatus.Apply;
  838. model.ApplyEndTime = endTime;
  839. var id = await _orderScreenRepository.AddAsync(model, HttpContext.RequestAborted);
  840. if (dto.Data.Files.Any()) await _fileRepository.AddFileAsync(dto.Data.Files, id, HttpContext.RequestAborted);
  841. var workflowId = string.Empty;
  842. try
  843. {
  844. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  845. startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderScreen;
  846. startDto.Title = dto.Data.Content;
  847. workflowId = await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
  848. var screen = await _orderScreenRepository.GetAsync(id, HttpContext.RequestAborted);
  849. if (screen != null)
  850. {
  851. screen.WorkFlowId = workflowId;
  852. await _orderScreenRepository.UpdateAsync(screen, HttpContext.RequestAborted);
  853. }
  854. }
  855. catch (Exception e)
  856. {
  857. await _orderScreenRepository.RemoveAsync(id);
  858. id = string.Empty;
  859. throw new UserFriendlyException($"工单开启甄别流程失败!, {e.Message}", "工单开启甄别流程失败");
  860. }
  861. if (!string.IsNullOrEmpty(id))
  862. {
  863. var screen = await _orderScreenRepository.GetAsync(x => x.Id == id);
  864. if (screen != null)
  865. {
  866. var screenDto = _mapper.Map<OrderScreenListDto>(screen);
  867. var order = await _orderRepository.GetAsync(x => x.Id == dto.Data.OrderId);
  868. if (order != null && order.Source == ESource.ProvinceStraight)
  869. {
  870. var orderDto = _mapper.Map<OrderDto>(order);
  871. //推省上
  872. _capPublisher.Publish(EventNames.HotlineOrderScreenApply, new PublishScreenDto()
  873. {
  874. Order = orderDto,
  875. Screen = screenDto,
  876. ClientGuid = ""
  877. });
  878. }
  879. }
  880. }
  881. }
  882. /// <summary>
  883. /// 查询工单甄别流程开启参数
  884. /// </summary>
  885. /// <returns></returns>
  886. [HttpGet("screen/startflow")]
  887. public async Task<NextStepsDto> GetScreenFlowStartOptionsAsync()
  888. {
  889. //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderScreen,
  890. // HttpContext.RequestAborted);
  891. return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderScreen,
  892. HttpContext.RequestAborted);
  893. }
  894. /// <summary>
  895. /// 查询工单甄别流程参数
  896. /// </summary>
  897. /// <returns></returns>
  898. [HttpGet("screen/workflow/{id}")]
  899. public async Task<string> GetScreenWorkFlowAsync(string id)
  900. {
  901. var workflow = await _workflowRepository.Queryable().FirstAsync(x => x.ExternalId == id);
  902. return workflow.Id;
  903. }
  904. /// <summary>
  905. /// 列表页面基础数据
  906. /// </summary>
  907. /// <returns></returns>
  908. [HttpGet("screen/base")]
  909. public async Task<object> ScreenBaseData()
  910. {
  911. var rsp = new
  912. {
  913. ScreenStatus = EnumExts.GetDescriptions<EScreenStatus>(),
  914. ScreenType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ScreenType),
  915. };
  916. return rsp;
  917. }
  918. /// <summary>
  919. /// 甄别详情
  920. /// </summary>
  921. /// <param name="id"></param>
  922. /// <returns></returns>
  923. [Permission(EPermission.ScreenEntity)]
  924. [HttpGet("screen/{id}")]
  925. public async Task<OrderScreen> ScreenEntity(string id)
  926. {
  927. return await _orderScreenRepository.Queryable()
  928. .Includes(x => x.Visit, d => d.Order)
  929. .FirstAsync(x => x.Id == id);
  930. }
  931. #endregion
  932. #region 工单督办
  933. /// <summary>
  934. /// 工单督办列表
  935. /// </summary>
  936. /// <param name="dto"></param>
  937. /// <returns></returns>
  938. [Permission(EPermission.SuperviseOrderList)]
  939. [HttpGet("supervise")]
  940. public async Task<PagedDto<SuperviseOrderDto>> SuperviseList([FromQuery] SuperviseListDto dto)
  941. {
  942. var (total, items) = await _orderSuperviseRepository.Queryable()
  943. .Includes(x => x.Order)
  944. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  945. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  946. .WhereIF(dto.SuperviseState > -1, x => x.State == dto.SuperviseState)
  947. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  948. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  949. .OrderByDescending(x => x.CreationTime)
  950. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  951. return new PagedDto<SuperviseOrderDto>(total, _mapper.Map<IReadOnlyList<SuperviseOrderDto>>(items));
  952. }
  953. /// <summary>
  954. /// 申请督办
  955. /// </summary>
  956. /// <param name="dto"></param>
  957. /// <returns></returns>
  958. [Permission(EPermission.ApplySupervise)]
  959. [HttpPost("supervise/apply")]
  960. public async Task ApplySupervise([FromBody] ApplyOrderSuperviseDto dto)
  961. {
  962. if (!dto.SuperviseOrgDtos.Any())
  963. throw UserFriendlyException.SameMessage("请选择被督办部门");
  964. //验证工单是否可以申请
  965. var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted);
  966. if (order is null)
  967. throw UserFriendlyException.SameMessage("无效工单");
  968. foreach (var item in dto.SuperviseOrgDtos)
  969. {
  970. var model = _mapper.Map<OrderSupervise>(dto);
  971. model.OrgId = item.OrgId;
  972. model.OrgName = item.OrgName;
  973. model.CreatorOrgName = _sessionContext.OrgName;
  974. model.CrUser = _sessionContext.UserName;
  975. model.State = 0;
  976. var id = await _orderSuperviseRepository.AddAsync(model, HttpContext.RequestAborted);
  977. if (dto.Files.Any()) await _fileRepository.AddFileAsync(dto.Files, id, HttpContext.RequestAborted);
  978. if (dto.AcceptSms)
  979. {
  980. //TODO 发送短信
  981. }
  982. //推省上
  983. if (!string.IsNullOrEmpty(id) && order.Source == ESource.ProvinceStraight)
  984. {
  985. var orderDto = _mapper.Map<OrderDto>(order);
  986. var supervise = await _orderSuperviseRepository.GetAsync(x => x.Id == id);
  987. if (supervise != null)
  988. {
  989. var superviseDto = _mapper.Map<SuperviseOrderDto>(supervise);
  990. _capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto()
  991. {
  992. Order = orderDto,
  993. Supervise = superviseDto,
  994. ClientGuid = ""
  995. });
  996. }
  997. }
  998. }
  999. }
  1000. /// <summary>
  1001. /// 回复督办
  1002. /// </summary>
  1003. /// <param name="dto"></param>
  1004. /// <returns></returns>
  1005. [Permission(EPermission.ReplySupervise)]
  1006. [HttpPost("supervise/reply")]
  1007. public async Task ReplySupervise([FromBody] ReplyOrderSuperviseDto dto)
  1008. {
  1009. //验证是否存在督办
  1010. var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1011. if (supervise is null)
  1012. throw UserFriendlyException.SameMessage("无效督办");
  1013. if (supervise.State > 0)
  1014. throw UserFriendlyException.SameMessage("督办已回复,请勿重复回复");
  1015. _mapper.Map(dto, supervise);
  1016. supervise.ReplyId = _sessionContext.UserId;
  1017. supervise.ReUser = _sessionContext.UserName;
  1018. supervise.ReplyTime = DateTime.Now;
  1019. supervise.State = 1;
  1020. if (dto.Files.Any()) await _fileRepository.AddFileAsync(dto.Files, supervise.Id, HttpContext.RequestAborted);
  1021. await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted);
  1022. var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted);
  1023. //推省上
  1024. if (order != null && order.Source == ESource.ProvinceStraight)
  1025. {
  1026. var orderDto = _mapper.Map<OrderDto>(order);
  1027. var superviseDto = _mapper.Map<SuperviseOrderDto>(supervise);
  1028. _capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto()
  1029. {
  1030. Order = orderDto,
  1031. Supervise = superviseDto,
  1032. ClientGuid = ""
  1033. });
  1034. }
  1035. }
  1036. /// <summary>
  1037. /// 签收督办
  1038. /// </summary>
  1039. /// <param name="dto"></param>
  1040. /// <returns></returns>
  1041. [Permission(EPermission.SignSupervise)]
  1042. [HttpPost("supervise/sign")]
  1043. public async Task SignSupervise([FromBody] SignOrderSuperviseDto dto)
  1044. {
  1045. //验证是否存在督办
  1046. var supervise = await _orderSuperviseRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1047. if (supervise is null)
  1048. throw UserFriendlyException.SameMessage("无效督办");
  1049. supervise.SignTime = DateTime.Now;
  1050. supervise.SignUser = _sessionContext.UserName;
  1051. await _orderSuperviseRepository.UpdateAsync(supervise, HttpContext.RequestAborted);
  1052. var order = await _orderRepository.GetAsync(supervise.OrderId, HttpContext.RequestAborted);
  1053. //推省上
  1054. if (order != null && order.Source == ESource.ProvinceStraight)
  1055. {
  1056. var orderDto = _mapper.Map<OrderDto>(order);
  1057. var superviseDto = _mapper.Map<SuperviseOrderDto>(supervise);
  1058. _capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishSuperviseDto()
  1059. {
  1060. Order = orderDto,
  1061. Supervise = superviseDto,
  1062. ClientGuid = ""
  1063. });
  1064. }
  1065. }
  1066. /// <summary>
  1067. /// 督办详情
  1068. /// </summary>
  1069. /// <param name="id"></param>
  1070. /// <returns></returns>
  1071. [Permission(EPermission.SuperviseEntity)]
  1072. [HttpGet("supervise/{id}")]
  1073. public async Task<OrderSupervise> SuperviseEntity(string id)
  1074. {
  1075. return await _orderSuperviseRepository.Queryable()
  1076. .Includes(x => x.Order)
  1077. .FirstAsync(x => x.Id == id);
  1078. }
  1079. #endregion
  1080. #region 工单催办
  1081. /// <summary>
  1082. /// 工单催办列表
  1083. /// </summary>
  1084. /// <param name="dto"></param>
  1085. /// <returns></returns>
  1086. [Permission(EPermission.UrgeOrderList)]
  1087. [HttpGet("urge")]
  1088. public async Task<PagedDto<UrgeOrderDto>> UrgeList([FromQuery] UrgeListDto dto)
  1089. {
  1090. var (total, items) = await _orderUrgeRepository.Queryable()
  1091. .Includes(x => x.Order)
  1092. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  1093. d => d.Order.Title.Contains(dto.Keyword!) || d.Order.No.Contains(dto.Keyword!))
  1094. .WhereIF(dto.SuperviseState > -1, x => x.State == dto.SuperviseState)
  1095. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  1096. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  1097. .OrderByDescending(x => x.CreationTime)
  1098. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1099. return new PagedDto<UrgeOrderDto>(total, _mapper.Map<IReadOnlyList<UrgeOrderDto>>(items));
  1100. }
  1101. /// <summary>
  1102. /// 申请催办
  1103. /// </summary>
  1104. /// <param name="dto"></param>
  1105. /// <returns></returns>
  1106. [Permission(EPermission.ApplyUrge)]
  1107. [HttpPost("urge/apply")]
  1108. public async Task ApplyUrge([FromBody] ApplyOrderUrgeDto dto)
  1109. {
  1110. if (!dto.UrgeOrgDtos.Any())
  1111. throw UserFriendlyException.SameMessage("请选择被催办部门");
  1112. //验证工单是否可以申请
  1113. var order = await _orderRepository.GetAsync(dto.OrderId, HttpContext.RequestAborted);
  1114. if (order is null)
  1115. throw UserFriendlyException.SameMessage("无效工单");
  1116. foreach (var item in dto.UrgeOrgDtos)
  1117. {
  1118. var model = _mapper.Map<OrderUrge>(dto);
  1119. model.OrgId = item.OrgId;
  1120. model.OrgName = item.OrgName;
  1121. model.CreatorOrgName = _sessionContext.OrgName;
  1122. model.CrUser = _sessionContext.UserName;
  1123. model.State = 0;
  1124. var id = await _orderUrgeRepository.AddAsync(model, HttpContext.RequestAborted);
  1125. if (dto.Files.Any()) await _fileRepository.AddFileAsync(dto.Files, id, HttpContext.RequestAborted);
  1126. if (dto.AcceptSms)
  1127. {
  1128. //TODO 发送短信
  1129. }
  1130. //推省上
  1131. if (!string.IsNullOrEmpty(id) && order.Source == ESource.ProvinceStraight)
  1132. {
  1133. var orderDto = _mapper.Map<OrderDto>(order);
  1134. var urge = await _orderUrgeRepository.GetAsync(x => x.Id == id);
  1135. if (urge != null)
  1136. {
  1137. var urgeDto = _mapper.Map<UrgeOrderDto>(urge);
  1138. _capPublisher.Publish(EventNames.HotlineOrderSuperviseCourse, new PublishUrgeDto()
  1139. {
  1140. Order = orderDto,
  1141. Urge = urgeDto,
  1142. ClientGuid = ""
  1143. });
  1144. }
  1145. }
  1146. }
  1147. }
  1148. /// <summary>
  1149. /// 回复催办
  1150. /// </summary>
  1151. /// <param name="dto"></param>
  1152. /// <returns></returns>
  1153. [Permission(EPermission.ReplyUrge)]
  1154. [HttpPost("urge/reply")]
  1155. public async Task ReplyUrge([FromBody] ReplyOrderUrgeDto dto)
  1156. {
  1157. //验证是否存在催办
  1158. var urge = await _orderUrgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1159. if (urge is null)
  1160. throw UserFriendlyException.SameMessage("无效催办");
  1161. if (urge.State > 0)
  1162. throw UserFriendlyException.SameMessage("督办已回复,请勿重复回复");
  1163. _mapper.Map(dto, urge);
  1164. urge.ReplyId = _sessionContext.UserId;
  1165. urge.ReUser = _sessionContext.UserName;
  1166. urge.ReplyContent = dto.ReplyContent;
  1167. urge.ReplyTime = DateTime.Now;
  1168. urge.State = 1;
  1169. if (dto.Files.Any()) await _fileRepository.AddFileAsync(dto.Files, urge.Id, HttpContext.RequestAborted);
  1170. await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
  1171. }
  1172. /// <summary>
  1173. /// 签收催办
  1174. /// </summary>
  1175. /// <param name="dto"></param>
  1176. /// <returns></returns>
  1177. [Permission(EPermission.SignUrge)]
  1178. [HttpPost("urge/sign")]
  1179. public async Task SignUrge([FromBody] SignOrderUrgeDto dto)
  1180. {
  1181. //验证是否存在催办
  1182. var urge = await _orderUrgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1183. if (urge is null)
  1184. throw UserFriendlyException.SameMessage("无效催办");
  1185. urge.SignUser = _sessionContext.UserName;
  1186. urge.SignTime = DateTime.Now;
  1187. await _orderUrgeRepository.UpdateAsync(urge, HttpContext.RequestAborted);
  1188. }
  1189. /// <summary>
  1190. /// 催办详情
  1191. /// </summary>
  1192. /// <param name="id"></param>
  1193. /// <returns></returns>
  1194. [Permission(EPermission.UrgeEntity)]
  1195. [HttpGet("urge/{id}")]
  1196. public async Task<OrderUrge> UrgeEntity(string id)
  1197. {
  1198. return await _orderUrgeRepository.Queryable()
  1199. .Includes(x => x.Order)
  1200. .FirstAsync(x => x.Id == id);
  1201. }
  1202. #endregion
  1203. #region 工单办理
  1204. /// <summary>
  1205. /// 工单列表
  1206. /// </summary>
  1207. /// <param name="dto"></param>
  1208. /// <returns></returns>
  1209. [Permission(EPermission.OrderQuery)]
  1210. [HttpGet]
  1211. public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
  1212. {
  1213. var (total, items) = await _orderRepository.Queryable()
  1214. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  1215. d => d.Title.Contains(dto.Keyword!) || d.No.Contains(dto.Keyword!))
  1216. .WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content!))
  1217. .WhereIF(dto.AcceptTypes.Any(), d => dto.AcceptTypes.Contains(d.AcceptType))
  1218. .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannel))
  1219. .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId))
  1220. .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!))
  1221. //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
  1222. .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.Workflow.ActualHandleOrgCode))
  1223. .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo),
  1224. d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!))
  1225. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  1226. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  1227. .WhereIF(dto.EmergencyLevels.Any(), d => dto.EmergencyLevels.Contains(d.EmergencyLevel))
  1228. .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo),
  1229. d => d.FromPhone.Contains(dto.PhoneNo!) || d.Contact.Contains(dto.PhoneNo!))
  1230. .WhereIF(!string.IsNullOrEmpty(dto.PushTypeCode), d => d.PushTypeCode == dto.PushTypeCode)
  1231. .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart)
  1232. .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd)
  1233. .WhereIF(dto.Statuses.Any(), d => dto.Statuses.Contains(d.Status))
  1234. .OrderByDescending(d => d.CreationTime)
  1235. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1236. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  1237. }
  1238. /// <summary>
  1239. /// 历史工单
  1240. /// </summary>
  1241. /// <param name="dto"></param>
  1242. /// <returns></returns>
  1243. [Permission(EPermission.OrderHistory)]
  1244. [HttpGet("history")]
  1245. public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderHistoryDto dto)
  1246. {
  1247. var (total, items) = await _orderRepository.Queryable()
  1248. .Where(d => d.FromPhone == dto.PhoneNo)
  1249. .WhereIF(!string.IsNullOrEmpty(dto.OrderId), d => d.Id != dto.OrderId)
  1250. .OrderByDescending(d => d.CreationTime)
  1251. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1252. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  1253. }
  1254. /// <summary>
  1255. /// 查询重复工单
  1256. /// </summary>
  1257. [HttpGet("duplicate")]
  1258. public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDuplicateDto dto)
  1259. {
  1260. if (!dto.OrderIds.Any())
  1261. return new PagedDto<OrderDto>(0, new List<OrderDto>());
  1262. var (total, items) = await _orderRepository.Queryable()
  1263. .Where(d => dto.OrderIds.Contains(d.Id))
  1264. .OrderByDescending(d => d.CreationTime)
  1265. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1266. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  1267. }
  1268. /// <summary>
  1269. /// 查询工单详情
  1270. /// </summary>
  1271. /// <param name="id"></param>
  1272. /// <returns></returns>
  1273. [Permission(EPermission.GetOrder)]
  1274. [HttpGet("{id}")]
  1275. public async Task<OrderDto> Get(string id)
  1276. {
  1277. var order = await _orderRepository.Queryable()
  1278. .Includes(d => d.Acceptor)
  1279. .Includes(d => d.OrderComplain)
  1280. .Includes(d => d.OrderReport)
  1281. .FirstAsync(d => d.Id == id);
  1282. if (order == null)
  1283. return new();
  1284. var canHandle = false;
  1285. if (!string.IsNullOrEmpty(order?.WorkflowId))
  1286. {
  1287. var (workflow, handlePermission) = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
  1288. order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
  1289. withSteps: true, withSupplements: true,
  1290. cancellationToken: HttpContext.RequestAborted);
  1291. order.Workflow = workflow;
  1292. canHandle = handlePermission;
  1293. await _mediator.Publish(new GetOrderDetailNotify(order.Workflow,
  1294. _sessionContext.RequiredUserId, _sessionContext.UserName,
  1295. _sessionContext.RequiredOrgId, _sessionContext.OrgName,
  1296. _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName));
  1297. }
  1298. var dto = _mapper.Map<OrderDto>(order!);
  1299. if (order?.Workflow != null)
  1300. dto.Workflow.CanHandle = canHandle;
  1301. var repeatablesMap = await _repeatableEventDetailRepository.Queryable()
  1302. .Includes(x => x.Order)
  1303. .Where(x => x.OrderId == id).Distinct().ToListAsync();
  1304. var repeatables = _mapper.Map<List<RepeatableEventDetailOpDto>>(repeatablesMap);
  1305. dto.RepeatableEventDetails = repeatables;
  1306. return dto;
  1307. }
  1308. /// <summary>
  1309. /// 新增工单
  1310. /// </summary>
  1311. /// <param name="dto"></param>
  1312. /// <returns></returns>
  1313. [Permission(EPermission.OrderAdd)]
  1314. [HttpPost]
  1315. public async Task<string> Add([FromBody] AddOrderDto dto)
  1316. {
  1317. var order = _mapper.Map<Order>(dto);
  1318. var orderId = await _orderDomainService.AddAsync(order, HttpContext.RequestAborted);
  1319. if (dto.Tags.Any()) await _repositoryts.AddVectorAsync(orderId, DateTime.Now, dto.Tags, HttpContext.RequestAborted);
  1320. if (dto.Files.Any()) await _fileRepository.AddFileAsync(dto.Files, orderId, HttpContext.RequestAborted);
  1321. if (dto.RepeatableEventDetails?.Any() ?? false)
  1322. {
  1323. dto.RepeatableEventDetails.ForEach(x => x.OrderId = orderId);
  1324. List<RepeatableEventDetail> repeatables = _mapper.Map<List<RepeatableEventDetail>>(dto.RepeatableEventDetails);
  1325. await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted);
  1326. }
  1327. return orderId;
  1328. }
  1329. /// <summary>
  1330. /// 删除工单
  1331. /// </summary>
  1332. /// <param name="id"></param>
  1333. /// <returns></returns>
  1334. [Permission(EPermission.OrderRemove)]
  1335. [HttpDelete("{id}")]
  1336. public async Task Remove(string id)
  1337. {
  1338. var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
  1339. if (order == null) return;
  1340. if (order.Status != EOrderStatus.WaitForAccept)
  1341. throw UserFriendlyException.SameMessage("非草稿工单不可删除");
  1342. await _orderRepository.RemoveAsync(order);
  1343. }
  1344. /// <summary>
  1345. /// 更新工单信息
  1346. /// </summary>
  1347. /// <param name="dto"></param>
  1348. /// <returns></returns>
  1349. [Permission(EPermission.OrderUpdate)]
  1350. [HttpPut]
  1351. public async Task Update([FromBody] UpdateOrderDto dto)
  1352. {
  1353. var order = await _orderRepository.Queryable()
  1354. .Includes(d => d.OrderComplain)
  1355. .Includes(d => d.OrderReport)
  1356. .FirstAsync(d => d.Id == dto.Id);
  1357. if (order == null)
  1358. throw UserFriendlyException.SameMessage("无效工单编号");
  1359. if (order.Status != EOrderStatus.WaitForAccept || !string.IsNullOrEmpty(order.WorkflowId))
  1360. throw UserFriendlyException.SameMessage("工单已发起流程");
  1361. if (order?.OrderComplain is not null)
  1362. await _orderRepository.RemoveOrderComplainAsync(order.OrderComplain, HttpContext.RequestAborted);
  1363. if (order?.OrderReport is not null)
  1364. await _orderRepository.RemoveOrderReportAsync(order.OrderReport, HttpContext.RequestAborted);
  1365. if (dto.Tags.Any()) await _repositoryts.UpdateVectorAsync(dto.Id, dto.Tags, HttpContext.RequestAborted);
  1366. if (dto.RepeatableEventDetails?.Any() ?? false)
  1367. {
  1368. var reAdds = dto.RepeatableEventDetails.Where(x => string.IsNullOrEmpty(x.OrderId) && !x.IsDeleted).ToList();
  1369. var reDeletes = dto.RepeatableEventDetails.Where(x => !string.IsNullOrEmpty(x.OrderId) && x.IsDeleted).ToList();
  1370. reAdds.ForEach(x => x.OrderId = dto.Id);
  1371. List<RepeatableEventDetail> repeatables = _mapper.Map<List<RepeatableEventDetail>>(reAdds);
  1372. await _repeatableEventDetailRepository.AddRangeAsync(repeatables, HttpContext.RequestAborted);
  1373. if (reDeletes?.Any()?? false)
  1374. {
  1375. await _repeatableEventDetailRepository.DeleteAsync(reDeletes, HttpContext.RequestAborted);
  1376. }
  1377. }
  1378. _mapper.Map(dto, order);
  1379. await _orderRepository.UpdateOrderNavAsync(order, HttpContext.RequestAborted);
  1380. }
  1381. /// <summary>
  1382. /// 开始流程
  1383. /// </summary>
  1384. /// <param name="id">工单id</param>
  1385. /// <param name="dto">流程开启参数</param>
  1386. /// <returns></returns>
  1387. [HttpPost("{id}/startflow")]
  1388. [Obsolete]
  1389. public async Task StartFlow(string id, [FromBody] StartWorkflowDto dto)
  1390. {
  1391. var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
  1392. if (order == null)
  1393. throw UserFriendlyException.SameMessage("无效工单编号");
  1394. if (order.Status != EOrderStatus.WaitForAccept || !string.IsNullOrEmpty(order.WorkflowId))
  1395. throw UserFriendlyException.SameMessage("工单已发起流程");
  1396. dto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle;
  1397. dto.Title = order.Title;
  1398. order.StartManageFlow();
  1399. await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
  1400. await _workflowApplication.StartWorkflowAsync(dto, order.Id, HttpContext.RequestAborted);
  1401. }
  1402. /// <summary>
  1403. /// 开始工单办理流程
  1404. /// </summary>
  1405. [HttpPost("startflow")]
  1406. public async Task StartFlow([FromBody] OrderStartFlowDto dto)
  1407. {
  1408. var id = dto.Data.Id;
  1409. var isAdd = string.IsNullOrEmpty(dto.Data.Id);
  1410. if (isAdd)
  1411. {
  1412. id = await Add(_mapper.Map<AddOrderDto>(dto.Data));
  1413. }
  1414. else
  1415. {
  1416. await Update(dto.Data);
  1417. }
  1418. try
  1419. {
  1420. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  1421. startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderHandle;
  1422. startDto.Title = dto.Data.Title;
  1423. await _workflowApplication.StartWorkflowAsync(startDto, id, HttpContext.RequestAborted);
  1424. }
  1425. catch (Exception e)
  1426. {
  1427. if (isAdd)
  1428. await Remove(id);
  1429. throw new UserFriendlyException($"工单开启流程失败!, {e.Message}", "工单开启流程失败");
  1430. }
  1431. }
  1432. /// <summary>
  1433. /// 查询工单办理流程开启参数
  1434. /// </summary>
  1435. /// <returns></returns>
  1436. [HttpGet("startflow")]
  1437. public async Task<NextStepsDto> GetFlowStartOptionsAsync()
  1438. {
  1439. //return await _workflowApplication.GetStartOptionsAsync(WorkflowModuleConsts.OrderHandle,
  1440. // HttpContext.RequestAborted);
  1441. return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderHandle,
  1442. HttpContext.RequestAborted);
  1443. }
  1444. /// <summary>
  1445. /// 列表页面基础数据
  1446. /// </summary>
  1447. /// <returns></returns>
  1448. [HttpGet("base-data")]
  1449. public async Task<object> BaseData()
  1450. {
  1451. var rsp = new
  1452. {
  1453. AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
  1454. ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
  1455. OrgsOptions = await _organizeRepository.GetOrgJson(),
  1456. EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
  1457. PushTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType),
  1458. OrderStatusOptions = EnumExts.GetDescriptions<EOrderStatus>(),
  1459. };
  1460. return rsp;
  1461. }
  1462. /// <summary>
  1463. /// 新增页面基础数据
  1464. /// </summary>
  1465. /// <returns></returns>
  1466. [HttpGet("base-data-add")]
  1467. public async Task<object> BaseDataAdd()
  1468. {
  1469. var rsp = new
  1470. {
  1471. ChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
  1472. AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
  1473. EmergencyLevelOptions = EnumExts.GetDescriptions<EEmergencyLevel>(),
  1474. PushTypeOptions =_sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PushType),
  1475. GenderOptions = EnumExts.GetDescriptions<EGender>(),
  1476. IdentityTypeOptions = EnumExts.GetDescriptions<EIdentityType>(),
  1477. LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType),
  1478. AgeRangeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AgeRange),
  1479. OrderTypeOptions = EnumExts.GetDescriptions<EOrderType>(),
  1480. };
  1481. return rsp;
  1482. }
  1483. /// <summary>
  1484. /// 扩展信息新增页面基础数据
  1485. /// </summary>
  1486. /// <returns></returns>
  1487. [HttpGet("base-data-ext")]
  1488. public async Task<object> BaseDataExtension()
  1489. {
  1490. var rsp = new
  1491. {
  1492. LicenceTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.LicenceType),
  1493. IdentityTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProviderIdentityType),
  1494. IdentityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Identity),
  1495. NationalityOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nationality),
  1496. NationOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Nation),
  1497. MarketTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.MarketType),
  1498. IndustryClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.IndustryClassify),
  1499. BrandOptions =_sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.Brand),
  1500. ObjectClassifyOptions =_sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ObjectClassify),
  1501. ComplainClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ComplainClassify),
  1502. ReportClassifyOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ReportClassify),
  1503. SalesModeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesMode),
  1504. ECommercePlatformOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ECommercePlatform),
  1505. PatentTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.PatentType),
  1506. AffairTargetOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AffairTarget),
  1507. ComplainTypeOptions = EnumExts.GetDescriptions<EComplainType>().Select(d => new Kv(d.Key.ToString(), d.Value)),
  1508. SalesChannelOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.SalesChannel),
  1509. };
  1510. return rsp;
  1511. }
  1512. /// <summary>
  1513. /// 扩展信息新增页面基础数据
  1514. /// </summary>
  1515. /// <returns></returns>
  1516. [HttpPost("order_repeatable_event")]
  1517. public async Task<bool> RepeatableEvent(QueryRepeatableEventDto dto)
  1518. {
  1519. var exp = Expressionable.Create<Order>()
  1520. .OrIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.HotspotSpliceName.EndsWith(dto.HotspotSpliceName!))
  1521. .OrIF(!string.IsNullOrEmpty(dto.Address), x => x.Address != null && x.Address.EndsWith(dto.Address!));
  1522. var count = await _orderRepository.Queryable()
  1523. .Where(exp.ToExpression())
  1524. .Where(d => d.CreationTime.ToString("yyyy-MM-dd") == DateTime.Now.ToString("yyyy-MM-dd"))
  1525. .CountAsync();
  1526. var setting = _systemSettingCacheManager.GetSetting(SettingConstants.RepeatableEventNum);
  1527. return count >= int.Parse(setting?.SettingValue[0] ?? "0");
  1528. }
  1529. #endregion
  1530. #region 工单待办
  1531. /// <summary>
  1532. /// 查询待办工单
  1533. /// </summary>
  1534. /// <param name="dto"></param>
  1535. /// <returns></returns>
  1536. [HttpGet("waited")]
  1537. public async Task<PagedDto<OrderWaitedDto>> QueryWaited([FromQuery] PagedRequest dto)
  1538. {
  1539. if (dto.PageSize > 100)
  1540. dto.PageSize = 100;
  1541. var (total, items) = await _orderRepository.Queryable()
  1542. .OrderBy(d => d.ExpiredTime)
  1543. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1544. var dtos = _mapper.Map<IReadOnlyList<OrderWaitedDto>>(items);
  1545. //calc expired description
  1546. var now = DateTime.Now;
  1547. foreach (var waitedDto in dtos)
  1548. {
  1549. var ts = waitedDto.ExpiredTime - now;
  1550. if (ts.Value.TotalDays <= 0)
  1551. {
  1552. //已超期
  1553. waitedDto.ExpiredDescription = $"已超期{Math.Abs(ts.Value.TotalDays):F1}天";
  1554. }
  1555. else
  1556. {
  1557. //未超期
  1558. waitedDto.ExpiredDescription = $"{ts.Value.TotalDays:F1}天后超期";
  1559. }
  1560. }
  1561. return new PagedDto<OrderWaitedDto>(total, dtos);
  1562. }
  1563. #endregion
  1564. #region 市民信息
  1565. /// <summary>
  1566. /// 新增市民信息
  1567. /// </summary>
  1568. /// <param name="dtos"></param>
  1569. /// <returns></returns>
  1570. [Permission(EPermission.AddCitizen)]
  1571. [HttpPost("citizen")]
  1572. public async Task Add([FromBody] CitizenAddDto dto)
  1573. {
  1574. var citizen = await _citizenRepository.CountAsync(x => x.PhoneNumber == dto.PhoneNumber, HttpContext.RequestAborted);
  1575. if (citizen > 0)
  1576. throw UserFriendlyException.SameMessage("市民联系电话信息重复");
  1577. await _citizenRepository.AddAsync(dto, HttpContext.RequestAborted);
  1578. }
  1579. /// <summary>
  1580. /// 删除市民信息
  1581. /// </summary>
  1582. /// <param name="dto"></param>
  1583. /// <returns></returns>
  1584. [Permission(EPermission.DeleteCitizen)]
  1585. [HttpDelete("citizen")]
  1586. public async Task Delete([FromBody] CitizenDeleteDto dto)
  1587. {
  1588. await _citizenRepository.RemoveAsync(x => x.Id == dto.Id);
  1589. }
  1590. /// <summary>
  1591. /// 更新市民信息
  1592. /// </summary>
  1593. /// <param name="dto"></param>
  1594. /// <returns></returns>
  1595. [Permission(EPermission.UpdateCitizen)]
  1596. [HttpPut("citizen")]
  1597. public async Task Update([FromBody] CitizenUpdateDto dto)
  1598. {
  1599. var citizen = await _citizenRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1600. if (citizen is null)
  1601. throw UserFriendlyException.SameMessage("无效市民信息");
  1602. _mapper.Map(dto, citizen);
  1603. citizen.LastModificationName = _sessionContext.UserName;
  1604. await _citizenRepository.UpdateAsync(citizen, HttpContext.RequestAborted);
  1605. }
  1606. /// <summary>
  1607. /// 获取市民信息列表
  1608. /// </summary>
  1609. /// <param name="dto"></param>
  1610. /// <returns></returns>
  1611. [Permission(EPermission.CitizenList)]
  1612. [HttpGet("citizen/list")]
  1613. public async Task<PagedDto<CitizenDto>> List([FromQuery] CitizenListDto dto)
  1614. {
  1615. var (total, items) = await _citizenRepository.Queryable()
  1616. .OrderByDescending(x => x.CreationTime)
  1617. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1618. return new PagedDto<CitizenDto>(total, _mapper.Map<IReadOnlyList<CitizenDto>>(items));
  1619. }
  1620. /// <summary>
  1621. /// 获取市民信息
  1622. /// </summary>
  1623. /// <param name="id"></param>
  1624. /// <returns></returns>
  1625. [Permission(EPermission.CitizenEntity)]
  1626. [HttpGet("citizen/{id}")]
  1627. public async Task<Citizen> CitizenEntity(string id)
  1628. {
  1629. return await _citizenRepository.Queryable()
  1630. .Includes(x => x.labelDetails)
  1631. .FirstAsync(x => x.Id == id);
  1632. }
  1633. /// <summary>
  1634. /// 获取市民信息
  1635. /// </summary>
  1636. /// <param name="id"></param>
  1637. /// <returns></returns>
  1638. [HttpGet("citizen_phone/{phone}")]
  1639. public async Task<object> Citizen(string phone)
  1640. {
  1641. //市民基本信息
  1642. var citizen = await _citizenRepository.Queryable()
  1643. .Includes(x => x.labelDetails)
  1644. .FirstAsync(x => x.PhoneNumber == phone);
  1645. //工单历史
  1646. var oders = await _orderRepository.Queryable().Where(x => x.Contact == phone).OrderBy(x => x.CreationTime, OrderByType.Desc).ToListAsync();
  1647. var allOrderNum = oders.Count;
  1648. var endOrderNum = oders.Count(x => x.Status == EOrderStatus.Published || x.Status == EOrderStatus.Visited || x.Status == EOrderStatus.Filed);
  1649. var handOrderNum = oders.Count(x => x.Status == EOrderStatus.Handling || x.Status == EOrderStatus.Countersigning);
  1650. var DissatisfactionNum = await _orderVisitedDetailRepository.Queryable()
  1651. .Includes(x => x.OrderVisit)
  1652. .Where(x => SqlFunc.JsonField(x.OrgProcessingResults, "Name") == "不满意" || SqlFunc.JsonField(x.OrgProcessingResults, "Name") == "非常不满意")
  1653. .Distinct().Select(s => new { s.OrderVisit.OrderId }).CountAsync();
  1654. //来电历史
  1655. //TODO 等待通讯对接完成 还缺少 上次来电时间
  1656. //关注诉求
  1657. var hotspotNames = string.Join(",", oders.Select(x => x.HotspotName).Distinct().Take(5).ToList());
  1658. var rsp = new
  1659. {
  1660. Citizen = citizen,
  1661. LastCallTime = DateTime.Now,
  1662. Order = new { allOrderNum = allOrderNum, endOrderNum = endOrderNum, handOrderNum = handOrderNum, DissatisfactionNum = DissatisfactionNum },
  1663. CallHistory = new { AllCallNum = 0, ConnectNum = 0, CallBackNum = 0 },
  1664. HotspotNames = hotspotNames,
  1665. };
  1666. return rsp;
  1667. }
  1668. /// <summary>
  1669. /// 新增市民标签信息
  1670. /// </summary>
  1671. /// <param name="dtos"></param>
  1672. /// <returns></returns>
  1673. [HttpPost("citizen_label")]
  1674. public async Task Add([FromBody] LabelDetailAddDto dto)
  1675. {
  1676. var label = await _labelDetailRepository.CountAsync(x => x.CitizenId == dto.CitizenId && x.Label == dto.Label, HttpContext.RequestAborted);
  1677. if (label > 0)
  1678. throw UserFriendlyException.SameMessage("市民联系标签信息重复");
  1679. await _citizenRepository.LabelAddAsync(dto, HttpContext.RequestAborted);
  1680. }
  1681. /// <summary>
  1682. /// 删除市民标签信息
  1683. /// </summary>
  1684. /// <param name="dto"></param>
  1685. /// <returns></returns>
  1686. [HttpDelete("citizen_label")]
  1687. public async Task Delete([FromBody] LabelDetailDeleteDto dto)
  1688. {
  1689. var label = await _labelDetailRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted);
  1690. if (label == null || (label.CreatorName != _sessionContext.UserName))
  1691. throw UserFriendlyException.SameMessage("市民联系标签信息错误");
  1692. await _citizenRepository.LabelDeleteAsync(label, HttpContext.RequestAborted);
  1693. }
  1694. /// <summary>
  1695. /// 获取市民标签信息列表
  1696. /// </summary>
  1697. /// <param name="dto"></param>
  1698. /// <returns></returns>
  1699. [HttpGet("citizen_label/list")]
  1700. public async Task<PagedDto<LabelDetailDto>> List([FromQuery] CitizenQueryDto dto)
  1701. {
  1702. var (total, items) = await _labelDetailRepository.Queryable()
  1703. .Includes(x => x.Citizen)
  1704. .WhereIF(!string.IsNullOrEmpty(dto.Label), x => x.Label.Contains(dto.Label!))
  1705. .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName != null && x.CreatorName.Contains(dto.CreatorName!))
  1706. .Where(x => x.CitizenId == dto.CitizenId)
  1707. .OrderByDescending(x => x.CreationTime)
  1708. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1709. return new PagedDto<LabelDetailDto>(total, _mapper.Map<IReadOnlyList<LabelDetailDto>>(items));
  1710. }
  1711. #endregion
  1712. #region 重复性事件
  1713. /// <summary>
  1714. /// 新增重复性事件
  1715. /// </summary>
  1716. /// <param name="dtos"></param>
  1717. /// <returns></returns>
  1718. [Permission(EPermission.AddRepeatableEvent)]
  1719. [HttpPost("repeatable_event")]
  1720. public async Task Add([FromBody] RepeatableEventAddDto dto)
  1721. {
  1722. var repeatable = _mapper.Map<RepeatableEvent>(dto);
  1723. var repeatableId = await _repeatableEventRepository.AddAsync(repeatable, HttpContext.RequestAborted);
  1724. List<RepeatableEventDetail> detail;
  1725. if (!string.IsNullOrEmpty(repeatableId) && dto.Details.Any())
  1726. dto.Details.ForEach(x => x.RepeatableId = repeatableId);
  1727. detail = _mapper.Map<List<RepeatableEventDetail>>(dto.Details);
  1728. if (detail.Any())
  1729. await _repeatableEventDetailRepository.AddRangeAsync(detail, HttpContext.RequestAborted);
  1730. }
  1731. /// <summary>
  1732. /// 删除重复性事件
  1733. /// </summary>
  1734. /// <param name="dto"></param>
  1735. /// <returns></returns>
  1736. [Permission(EPermission.DeleteRepeatableEvent)]
  1737. [HttpDelete("repeatable_event")]
  1738. public async Task Delete([FromBody] RepeatableEventDeleteDto dto)
  1739. {
  1740. await _repeatableEventRepository.RemoveAsync(x => x.Id == dto.Id);
  1741. await _repeatableEventDetailRepository.RemoveAsync(x => x.RepeatableId == dto.Id);
  1742. }
  1743. /// <summary>
  1744. /// 删除重复性事件明细
  1745. /// </summary>
  1746. /// <param name="dto"></param>
  1747. /// <returns></returns>
  1748. [Permission(EPermission.DeleteRepeatableEventDetail)]
  1749. [HttpDelete("repeatable_event_detail/{id}")]
  1750. public async Task Delete([FromBody] string id )
  1751. {
  1752. await _repeatableEventDetailRepository.RemoveAsync(x => x.Id == id);
  1753. }
  1754. /// <summary>
  1755. /// 更新重复性事件
  1756. /// </summary>
  1757. /// <param name="dto"></param>
  1758. /// <returns></returns>
  1759. [Permission(EPermission.UpdateRepeatableEvent)]
  1760. [HttpPut("repeatable_event")]
  1761. public async Task Update([FromBody] RepeatableEventUpdateDto dto)
  1762. {
  1763. var repeatable = await _repeatableEventRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1764. if (repeatable is null)
  1765. throw UserFriendlyException.SameMessage("无效重复性事件");
  1766. _mapper.Map(dto, repeatable);
  1767. repeatable.LastModificationName = _sessionContext.UserName;
  1768. await _repeatableEventRepository.UpdateAsync(repeatable, HttpContext.RequestAborted);
  1769. List<RepeatableEventDetail> detail;
  1770. if (dto.Details.Any())
  1771. dto.Details.ForEach(x => x.RepeatableId = dto.Id);
  1772. await _repeatableEventDetailRepository.DeleteAsync(dto.Id, HttpContext.RequestAborted);
  1773. detail = _mapper.Map<List<RepeatableEventDetail>>(dto.Details);
  1774. if (detail.Any())
  1775. await _repeatableEventDetailRepository.AddRangeAsync(detail, HttpContext.RequestAborted);
  1776. }
  1777. /// <summary>
  1778. /// 获取重复性事件列表
  1779. /// </summary>
  1780. /// <param name="dto"></param>
  1781. /// <returns></returns>
  1782. [Permission(EPermission.RepeatableEventList)]
  1783. [HttpGet("repeatable_event/list")]
  1784. public async Task<PagedDto<RepeatableEventDto>> List([FromQuery] RepeatableEventListDto dto)
  1785. {
  1786. var (total, items) = await _repeatableEventRepository.Queryable()
  1787. .Includes(x => x.Details)
  1788. .Includes(x => x.Details, y => y.Order)
  1789. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword!) || (d.KeyWords != null && d.KeyWords.Contains(dto.Keyword!)))
  1790. .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
  1791. .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
  1792. .WhereIF(!string.IsNullOrEmpty(dto.Code), x => x.Code != null && x.Code.Contains(dto.Code!))
  1793. .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Title.Contains(dto.Title!))
  1794. .WhereIF(!string.IsNullOrEmpty(dto.KeyWords), x => x.KeyWords != null && x.KeyWords.Contains(dto.KeyWords!))
  1795. .OrderByDescending(x => x.CreationTime)
  1796. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1797. return new PagedDto<RepeatableEventDto>(total, _mapper.Map<IReadOnlyList<RepeatableEventDto>>(items));
  1798. }
  1799. /// <summary>
  1800. /// 获取重复性事件
  1801. /// </summary>
  1802. /// <param name="id"></param>
  1803. /// <returns></returns>
  1804. [Permission(EPermission.RepeatableEventEntity)]
  1805. [HttpGet("repeatable_event")]
  1806. public async Task<RepeatableEvent> CitizenEntity([FromQuery] RepeatableEventEntityDto dto)
  1807. {
  1808. return await _repeatableEventRepository.Queryable()
  1809. .Includes(x => x.Details.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!)).ToList())
  1810. .Includes(x => x.Details, y => y.Order)
  1811. .FirstAsync(x => x.Id == dto.Id);
  1812. }
  1813. #endregion
  1814. #region 工单词库
  1815. /// <summary>
  1816. /// 新增工单词库
  1817. /// </summary>
  1818. /// <param name="dtos"></param>
  1819. /// <returns></returns>
  1820. [Permission(EPermission.AddOrderWord)]
  1821. [HttpPost("order_word")]
  1822. public async Task Add([FromBody] OrderWordAddDto dto)
  1823. {
  1824. var word = _mapper.Map<OrderWord>(dto);
  1825. await _orderWrodRepository.AddAsync(word, HttpContext.RequestAborted);
  1826. }
  1827. /// <summary>
  1828. /// 删除工单词库
  1829. /// </summary>
  1830. /// <param name="dto"></param>
  1831. /// <returns></returns>
  1832. [Permission(EPermission.DeleteOrderWord)]
  1833. [HttpDelete("order_word")]
  1834. public async Task Delete([FromBody] OrderWordDeleteDto dto)
  1835. {
  1836. await _orderRepository.RemoveOrderWrodBatchAsync(dto.Ids, HttpContext.RequestAborted);
  1837. }
  1838. /// <summary>
  1839. /// 更新工单词库
  1840. /// </summary>
  1841. /// <param name="dto"></param>
  1842. /// <returns></returns>
  1843. [Permission(EPermission.UpdateOrderWord)]
  1844. [HttpPut("order_word")]
  1845. public async Task Update([FromBody] OrderWordUpdateDto dto)
  1846. {
  1847. var word = await _orderWrodRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1848. if (word is null)
  1849. throw UserFriendlyException.SameMessage("无效工单词库");
  1850. _mapper.Map(dto, word);
  1851. word.LastModificationName = _sessionContext.UserName;
  1852. await _orderWrodRepository.UpdateAsync(word, HttpContext.RequestAborted);
  1853. }
  1854. /// <summary>
  1855. /// 获取工单词库列表
  1856. /// </summary>
  1857. /// <param name="dto"></param>
  1858. /// <returns></returns>
  1859. [Permission(EPermission.OrderWordList)]
  1860. [HttpGet("order_word/list")]
  1861. public async Task<PagedDto<OrderWordDto>> List([FromQuery] OrderWordListDto dto)
  1862. {
  1863. var (total, items) = await _orderWrodRepository.Queryable()
  1864. .WhereIF(!string.IsNullOrEmpty(dto.Tag), x => x.Tag == dto.Tag!)
  1865. .WhereIF(!string.IsNullOrEmpty(dto.Classify), x => x.Classify.Contains(dto.Classify!))
  1866. .WhereIF(!string.IsNullOrEmpty(dto.Synonym), x => x.Synonym != null && x.Synonym.Contains(dto.Synonym!))
  1867. .OrderByDescending(x => x.CreationTime)
  1868. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1869. return new PagedDto<OrderWordDto>(total, _mapper.Map<IReadOnlyList<OrderWordDto>>(items));
  1870. }
  1871. /// <summary>
  1872. /// 获取工单词库
  1873. /// </summary>
  1874. /// <param name="id"></param>
  1875. /// <returns></returns>
  1876. [HttpGet("order_word/{id}")]
  1877. public async Task<OrderWord> OrderWordEntity(string id)
  1878. {
  1879. return await _orderWrodRepository.Queryable()
  1880. .FirstAsync(x => x.Id == id);
  1881. }
  1882. /// <summary>
  1883. /// 获取工单词库基本信息
  1884. /// </summary>
  1885. /// <returns></returns>
  1886. [HttpGet("order_word/base")]
  1887. public async Task<object> Base()
  1888. {
  1889. var rsp = new
  1890. {
  1891. OrderWordClassify = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderWordClassify),
  1892. };
  1893. return rsp;
  1894. }
  1895. #endregion
  1896. #region 工单观察
  1897. /// <summary>
  1898. /// 新增工单观察
  1899. /// </summary>
  1900. /// <param name="dtos"></param>
  1901. /// <returns></returns>
  1902. [Permission(EPermission.AddOrderObserve)]
  1903. [HttpPost("order_observe")]
  1904. public async Task Add([FromBody] OrderObserveAddDto dto)
  1905. {
  1906. var observe = _mapper.Map<OrderObserve>(dto);
  1907. await _orderObserveRepository.AddAsync(observe, HttpContext.RequestAborted);
  1908. }
  1909. /// <summary>
  1910. /// 删除工单观察
  1911. /// </summary>
  1912. /// <param name="dto"></param>
  1913. /// <returns></returns>
  1914. [Permission(EPermission.DeleteOrderObserve)]
  1915. [HttpDelete("order_observe")]
  1916. public async Task Delete([FromBody] OrderObserveDeleteDto dto)
  1917. {
  1918. await _orderRepository.RemoveOrderObserveBatchAsync(dto.Ids, HttpContext.RequestAborted);
  1919. }
  1920. /// <summary>
  1921. /// 更新工单观察
  1922. /// </summary>
  1923. /// <param name="dto"></param>
  1924. /// <returns></returns>
  1925. [Permission(EPermission.UpdateOrderObserve)]
  1926. [HttpPut("order_observe")]
  1927. public async Task Update([FromBody] OrderObserveUpdateDto dto)
  1928. {
  1929. var word = await _orderObserveRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
  1930. if (word is null)
  1931. throw UserFriendlyException.SameMessage("无效工单观察");
  1932. _mapper.Map(dto, word);
  1933. await _orderObserveRepository.UpdateAsync(word, HttpContext.RequestAborted);
  1934. }
  1935. /// <summary>
  1936. /// 获取工单观察列表
  1937. /// </summary>
  1938. /// <param name="dto"></param>
  1939. /// <returns></returns>
  1940. [Permission(EPermission.OrderObserveList)]
  1941. [HttpGet("order_observe/list")]
  1942. public async Task<PagedDto<OrderObserveDto>> List([FromQuery] OrderObserveListDto dto)
  1943. {
  1944. var (total, items) = await _orderObserveRepository.Queryable()
  1945. .Includes(x=>x.Order)
  1946. .WhereIF(dto.IsProvince.HasValue, x => x.Order.IsProvince == dto.IsProvince)
  1947. .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title!))
  1948. .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!))
  1949. .OrderByDescending(x => x.CreationTime)
  1950. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  1951. return new PagedDto<OrderObserveDto>(total, _mapper.Map<IReadOnlyList<OrderObserveDto>>(items));
  1952. }
  1953. /// <summary>
  1954. /// 获取工单观察
  1955. /// </summary>
  1956. /// <param name="id"></param>
  1957. /// <returns></returns>
  1958. [HttpGet("order_observe/{id}")]
  1959. public async Task<OrderObserve> OrderObserveEntity(string id)
  1960. {
  1961. return await _orderObserveRepository.Queryable()
  1962. .FirstAsync(x => x.Id == id);
  1963. }
  1964. #endregion
  1965. }