OrderTerminateController.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. [Permission(EPermission.CanOrderTerminate)]
  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.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(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. //[Permission(EPermission.ApplyTerminate)]
  138. [HttpPost("startflow")]
  139. [LogFilter("开始工单终止流程")]
  140. public async Task StartFlow([FromBody] TerminateStartFlowDto dto)
  141. {
  142. var screenAny = await _orderTerminateRepository.AnyAsync(x =>
  143. x.OrderId == dto.Data.OrderId && x.Status == ETerminateStatus.Approval);
  144. if (screenAny)
  145. throw UserFriendlyException.SameMessage("该工单已提起终止申请,正在审批过程中,不能申请");
  146. var isNoPass = await _orderTerminateRepository.AnyAsync(x => x.Status == ETerminateStatus.Refuse && x.OrderId == dto.Data.OrderId);
  147. if (isNoPass)
  148. throw UserFriendlyException.SameMessage("该工单已被拒绝过甄别申请,不能再次申请");
  149. var model = _mapper.Map<OrderTerminate>(dto.Data);
  150. model.Status = ETerminateStatus.Approval ;
  151. model.InitId();
  152. if (dto.Data.Files.Any())
  153. model.FileJson = await _fileRepository.AddFileAsync(dto.Data.Files, model.Id, "", HttpContext.RequestAborted);
  154. else
  155. model.FileJson = new List<Share.Dtos.File.FileJson>();
  156. await _orderTerminateRepository.AddAsync(model, HttpContext.RequestAborted);
  157. try
  158. {
  159. var startDto = _mapper.Map<StartWorkflowDto>(dto.Workflow);
  160. startDto.DefinitionModuleCode = WorkflowModuleConsts.OrderTerminate;
  161. startDto.Opinion = dto.Data.Content;
  162. startDto.Title = "申请终止流程";
  163. await _workflowApplication.StartWorkflowAsync(startDto, _sessionContext, model.Id,
  164. 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.Content = dto.Data.Content;
  186. model.IsRecommit = true;
  187. await _orderTerminateRepository.UpdateAsync(model, HttpContext.RequestAborted);
  188. try
  189. {
  190. dto.NextWorkflow.WorkflowId = model.WorkflowId;
  191. await _workflowApplication.NextAsync(dto.NextWorkflow, _sessionContext,
  192. 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.SendBack)
  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> ScreenBaseData()
  265. {
  266. var rsp = new
  267. {
  268. Status = EnumExts.GetDescriptions<ETerminateStatus>(),
  269. };
  270. return rsp;
  271. }
  272. }
  273. }