OrderTerminateController.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using Hotline.Orders;
  2. using Hotline.Permissions;
  3. using Hotline.Quality;
  4. using Hotline.Share.Dtos.Quality;
  5. using Hotline.Share.Dtos;
  6. using Microsoft.AspNetCore.Mvc;
  7. using XF.Domain.Authentications;
  8. using XF.Domain.Exceptions;
  9. using XF.Domain.Repository;
  10. using Hotline.Api.Filter;
  11. using Hotline.Caching.Services;
  12. using Hotline.FlowEngine.WorkflowModules;
  13. using Hotline.Repository.SqlSugar.Orders;
  14. using Hotline.Settings;
  15. using Hotline.Share.Dtos.FlowEngine;
  16. using Hotline.Share.Dtos.Order;
  17. using Hotline.Share.Enums.FlowEngine;
  18. using Hotline.Share.Enums.Order;
  19. using Hotline.Share.Enums.Settings;
  20. using SqlSugar;
  21. using XF.Utility.EnumExtensions;
  22. using MapsterMapper;
  23. using Hotline.File;
  24. using Hotline.Application.FlowEngine;
  25. using Hotline.FlowEngine.Workflows;
  26. using Hotline.Repository.SqlSugar.Extensions;
  27. using Hotline.Application.Orders;
  28. using Hotline.Share.Requests;
  29. using Hotline.Tools;
  30. namespace Hotline.Api.Controllers
  31. {
  32. /// <summary>
  33. /// 终止管理
  34. /// </summary>
  35. public class OrderTerminateController : BaseController
  36. {
  37. private readonly ISessionContext _sessionContext;
  38. private readonly IMapper _mapper;
  39. private readonly IFileRepository _fileRepository;
  40. private readonly IWorkflowApplication _workflowApplication;
  41. private readonly IRepository<Workflow> _workflowRepository;
  42. private readonly IWorkflowDomainService _workflowDomainService;
  43. private readonly IOrderRepository _orderRepository;
  44. private readonly IOrderDomainService _orderDomainService;
  45. private readonly IOrderTerminateRepository _orderTerminateRepository;
  46. private readonly IOrderApplication _orderApplication;
  47. public OrderTerminateController(
  48. ISessionContext sessionContext,
  49. IMapper mapper,
  50. IFileRepository fileRepository,
  51. IWorkflowApplication workflowApplication,
  52. IRepository<Workflow> workflowRepository,
  53. IWorkflowDomainService workflowDomainService,
  54. IOrderRepository orderRepository,
  55. IOrderDomainService orderDomainService,
  56. IOrderTerminateRepository orderTerminateRepository,
  57. IOrderApplication orderApplication
  58. )
  59. {
  60. _sessionContext = sessionContext;
  61. _mapper = mapper;
  62. _fileRepository = fileRepository;
  63. _workflowApplication = workflowApplication;
  64. _workflowRepository = workflowRepository;
  65. _workflowDomainService = workflowDomainService;
  66. _orderRepository = orderRepository;
  67. _orderDomainService = orderDomainService;
  68. _orderTerminateRepository = orderTerminateRepository;
  69. _orderApplication= orderApplication;
  70. }
  71. /// <summary>
  72. /// 工单终止待申请列表
  73. /// </summary>
  74. /// <param name="dto"></param>
  75. /// <returns></returns>
  76. [HttpGet("may-terminate")]
  77. public async Task<PagedDto<OrderDto>> MayOrderTerminateList([FromQuery] OrderTerminateListDto dto)
  78. {
  79. var isAdmin = _orderDomainService.IsCheckAdmin();
  80. var (total, items) =await _orderRepository.Queryable(isAdmin:isAdmin)
  81. .Includes(d=>d.OrderTerminates)
  82. .Where(d=> SqlFunc.Subqueryable<OrderTerminate>().Where(t=> t.OrderId == d.Id && t.Status != ETerminateStatus.SendBackStart).NotAny())
  83. .Where(d => d.Status >= EOrderStatus.Filed && d.ActualHandleOrgCode.StartsWith(_sessionContext.OrgId))
  84. .WhereIF(!string.IsNullOrEmpty(dto.No),d=>d.No!.Contains(dto.No!))
  85. .WhereIF(!string.IsNullOrEmpty(dto.Title), d => d.Title!.Contains(dto.Title!))
  86. .WhereIF(dto.ApplyStartTime.HasValue && dto.ApplyEndTime.HasValue,
  87. d => d.OrderTerminates.Any(t=>t.CreationTime >= dto.ApplyStartTime && t.CreationTime<= dto.ApplyEndTime))
  88. .WhereIF(dto.StartTime.HasValue && dto.EndTime.HasValue,d=>d.StartTime >= dto.StartTime && d.StartTime <= dto.EndTime)
  89. .OrderByDescending(d => d.StartTime)
  90. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  91. return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
  92. }
  93. /// <summary>
  94. /// 工单终止列表
  95. /// </summary>
  96. /// <param name="dto"></param>
  97. /// <returns></returns>
  98. [HttpGet]
  99. public async Task<PagedDto<OrderTerminateEntityDto>> OrderTerminateList([FromQuery] OrderTerminateListDto dto)
  100. {
  101. var (total, items) = await _orderApplication.OrderTerminateList(dto)
  102. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  103. return new PagedDto<OrderTerminateEntityDto>(total, _mapper.Map<IReadOnlyList<OrderTerminateEntityDto>>(items));
  104. }
  105. /// <summary>
  106. /// 工单终止列表导出
  107. /// </summary>
  108. /// <param name="dto"></param>
  109. /// <returns></returns>
  110. [HttpPost("export")]
  111. public async Task<FileStreamResult> OrderTerminateListExport([FromBody] ExportExcelDto<OrderTerminateListDto> dto)
  112. {
  113. var query = _orderApplication.OrderTerminateList(dto.QueryDto);
  114. List<OrderTerminate> data;
  115. if (dto.IsExportAll)
  116. {
  117. data = await query.ToListAsync(HttpContext.RequestAborted);
  118. }
  119. else
  120. {
  121. var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
  122. data = items;
  123. }
  124. var dataDtos = _mapper.Map<ICollection<OrderTerminateEntityDto>>(data);
  125. dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
  126. var dtos = dataDtos
  127. .Select(stu => _mapper.Map(stu, typeof(OrderTerminateEntityDto), dynamicClass))
  128. .Cast<object>()
  129. .ToList();
  130. var stream = ExcelHelper.CreateStream(dtos);
  131. return ExcelStreamResult(stream, "工单终止列表");
  132. }
  133. /// <summary>
  134. /// 开始工单终止流程
  135. /// </summary>
  136. [HttpPost("startflow")]
  137. [LogFilter("开始工单终止流程")]
  138. public async Task StartFlow([FromBody] StartWorkflowDto<OrderTerminateDto> dto)
  139. {
  140. var screenAny = await _orderTerminateRepository.AnyAsync(x =>
  141. x.OrderId == dto.Data.OrderId && x.Status == ETerminateStatus.Approval);
  142. if (screenAny)
  143. throw UserFriendlyException.SameMessage("该工单已提起终止申请,正在审批过程中,不能申请");
  144. var isNoPass = await _orderTerminateRepository.AnyAsync(x => x.Status == ETerminateStatus.Refuse && x.OrderId == dto.Data.OrderId);
  145. if (isNoPass)
  146. throw UserFriendlyException.SameMessage("该工单已被拒绝过甄别申请,不能再次申请");
  147. var model = _mapper.Map<OrderTerminate>(dto.Data);
  148. model.Status = ETerminateStatus.Approval ;
  149. model.InitId();
  150. if (dto.Data.Files.Any())
  151. model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted);
  152. else
  153. model.FileJson = new List<Share.Dtos.File.FileJson>();
  154. await _orderTerminateRepository.AddAsync(model, HttpContext.RequestAborted);
  155. try
  156. {
  157. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  158. startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderTerminate;
  159. startDto.Opinion = dto.Data.Content;
  160. startDto.Title = "申请终止流程";
  161. await _workflowApplication.StartWorkflowAsync(startDto, model.Id, cancellationToken: HttpContext.RequestAborted);
  162. }
  163. catch (Exception e)
  164. {
  165. await _orderTerminateRepository.RemoveAsync(model.Id);
  166. model.Id = string.Empty;
  167. throw new UserFriendlyException($"工单开启终止流程失败!, {e.Message}", "工单开启终止流程失败");
  168. }
  169. }
  170. /// <summary>
  171. /// 工单终止修改后下一步流程
  172. /// </summary>
  173. [HttpPost("initial_nextFlow")]
  174. [LogFilter("办理工单终止流程")]
  175. public async Task InitialNextFlow([FromBody] TerminateNextFlowDto dto)
  176. {
  177. var model = await _orderTerminateRepository.GetAsync(dto.Data.Id);
  178. if (dto.Data.Files.Any())
  179. model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted);
  180. else
  181. model.FileJson = new List<Share.Dtos.File.FileJson>();
  182. model.Content = dto.Data.Content;
  183. model.IsRecommit = true;
  184. await _orderTerminateRepository.UpdateAsync(model, HttpContext.RequestAborted);
  185. try
  186. {
  187. dto.NextWorkflow.WorkflowId = model.WorkflowId;
  188. await _workflowDomainService.NextAsync(_sessionContext, dto.NextWorkflow, cancellationToken: HttpContext.RequestAborted);
  189. }
  190. catch (Exception e)
  191. {
  192. throw new UserFriendlyException($"工单终止下一步流程失败!, {e.Message}", "工单终止下一步流程失败");
  193. }
  194. }
  195. /// <summary>
  196. /// 查询工单终止流程开启参数
  197. /// </summary>
  198. /// <returns></returns>
  199. [HttpGet("screen/startflow")]
  200. public async Task<NextStepsDto> GetTerminateFlowStartOptionsAsync()
  201. {
  202. return await _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.OrderTerminate,
  203. HttpContext.RequestAborted);
  204. }
  205. /// <summary>
  206. /// 查询工单终止流程参数
  207. /// </summary>
  208. /// <returns></returns>
  209. [HttpGet("workflow/{id}")]
  210. public async Task<string> GetTerminateWorkFlowAsync(string id)
  211. {
  212. var workflow = await _workflowRepository.Queryable().FirstAsync(x => x.ExternalId == id);
  213. return workflow.Id;
  214. }
  215. /// <summary>
  216. /// 甄别查询流程办理下一步可选节点
  217. /// </summary>
  218. /// <param name="workflowId"></param>
  219. /// <returns></returns>
  220. [HttpGet("{workflowId}/nextsteps")]
  221. public async Task<NextStepsDto> OrderTerminateNextsteps(string workflowId)
  222. {
  223. return await _workflowApplication.GetNextStepsAsync(workflowId, HttpContext.RequestAborted);
  224. }
  225. /// <summary>
  226. /// 终止详情
  227. /// </summary>
  228. /// <param name="id"></param>
  229. /// <returns></returns>
  230. [HttpGet("{id}")]
  231. public async Task<OrderTerminateEntityDto> Entity(string id)
  232. {
  233. var model = await _orderTerminateRepository.Queryable()
  234. .Includes(x => x.Order)
  235. .Includes(x => x.Workflow, d => d.Steps)
  236. .FirstAsync(x => x.Id == id);
  237. var rspModel = _mapper.Map<OrderTerminateEntityDto>(model);
  238. rspModel.IsCanHandle = model.Workflow?.IsCanHandle(
  239. _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false;
  240. if (model.Status == ETerminateStatus.SendBackStart)
  241. rspModel.IsCanHandle = false;
  242. rspModel.Handle = false;
  243. if (!string.IsNullOrEmpty(rspModel.WorkflowId))
  244. {
  245. rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId,
  246. _sessionContext.RequiredOrgId, HttpContext.RequestAborted);
  247. }
  248. if (rspModel.FileJson != null && rspModel.FileJson.Any())
  249. {
  250. var ids = rspModel.FileJson.Select(x => x.Id).ToList();
  251. rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
  252. }
  253. return rspModel;
  254. }
  255. /// <summary>
  256. /// 列表页面基础数据
  257. /// </summary>
  258. /// <returns></returns>
  259. [HttpGet("base")]
  260. public async Task<object> BaseData()
  261. {
  262. var rsp = new
  263. {
  264. Status = EnumExts.GetDescriptions<ETerminateStatus>(),
  265. };
  266. return rsp;
  267. }
  268. /// <summary>
  269. /// 终止修改理由
  270. /// </summary>
  271. /// <param name="dto"></param>
  272. /// <returns></returns>
  273. [HttpPut("update_content")]
  274. [LogFilter("终止修改理由")]
  275. public async Task Update([FromBody] OrderTerminateContentDto dto)
  276. {
  277. await _orderTerminateRepository.Updateable().SetColumns(x => new OrderTerminate { Content = dto.Content }).Where(x => x.Id == dto.Id).ExecuteCommandAsync();
  278. }
  279. }
  280. }