OrderController.cs 98 KB

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