OrderTerminateController.cs 11 KB

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