BiOrderController.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. using Hotline.Orders;
  2. using Hotline.Repository.SqlSugar.Extensions;
  3. using Hotline.Settings;
  4. using Hotline.Settings.Hotspots;
  5. using Hotline.Share.Dtos;
  6. using Hotline.Share.Dtos.Order;
  7. using Hotline.Share.Enums.Order;
  8. using Microsoft.AspNetCore.Mvc;
  9. using SqlSugar;
  10. using Hotline.Share.Requests;
  11. using XF.Domain.Repository;
  12. using Hotline.Caching.Interfaces;
  13. using Hotline.FlowEngine.Workflows;
  14. using Hotline.Share.Dtos.CallCenter;
  15. using MapsterMapper;
  16. using XF.Domain.Exceptions;
  17. namespace Hotline.Api.Controllers.Bi
  18. {
  19. public class BiOrderController : BaseController
  20. {
  21. private readonly IOrderRepository _orderRepository;
  22. private readonly IRepository<Hotspot> _hotspotTypeRepository;
  23. private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
  24. private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
  25. private readonly IRepository<OrderDelay> _orderDelayRepository;
  26. private readonly IMapper _mapper;
  27. private readonly IRepository<WorkflowCountersign> _workflowCountersignRepository;
  28. private readonly IRepository<OrderSpecial> _orderSpecialRepository;
  29. public BiOrderController(
  30. IOrderRepository orderRepository,
  31. IRepository<Hotspot> hotspotTypeRepository,
  32. ISystemDicDataCacheManager sysDicDataCacheManager,
  33. IRepository<OrderVisitDetail> orderVisitDetailRepository,
  34. IRepository<OrderDelay> orderDelayRepository,
  35. IRepository<WorkflowCountersign> workflowCountersignRepository,
  36. IRepository<OrderSpecial> orderSpecialRepository,
  37. IMapper mapper
  38. )
  39. {
  40. _orderRepository = orderRepository;
  41. _hotspotTypeRepository = hotspotTypeRepository;
  42. _sysDicDataCacheManager = sysDicDataCacheManager;
  43. _orderVisitDetailRepository = orderVisitDetailRepository;
  44. _orderDelayRepository = orderDelayRepository;
  45. _workflowCountersignRepository = workflowCountersignRepository;
  46. _orderSpecialRepository = orderSpecialRepository;
  47. _mapper = mapper;
  48. }
  49. /// <summary>
  50. /// 部门数据统计
  51. /// </summary>
  52. /// <param name="dto"></param>
  53. /// <returns></returns>
  54. [HttpGet("org_data_list")]
  55. public async Task<PagedDto<OrderBiOrgDataListVo>> OrgDataList([FromQuery] ReportPagedRequest dto)
  56. {
  57. //TODO 会签统计待处理 目前缺少关联关系
  58. var queryOrder = _orderRepository.Queryable(false, false, false)
  59. .LeftJoin<SystemOrganize>((x, o) => x.ActualHandleOrgCode == o.Id)
  60. .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
  61. .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
  62. .GroupBy((x, o) => new { x.ActualHandleOrgCode, o.Name })
  63. .Select((x, o) => new OrderBiOrgDataListVo
  64. {
  65. OrgName = o.Name,
  66. OrgId = x.ActualHandleOrgCode,
  67. HandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ExpiredTime > x.FiledTime, 1, 0)),
  68. NoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status < 300 && x.ExpiredTime > x.FiledTime, 1, 0)),
  69. }).MergeTable();
  70. var queryCountersign = _workflowCountersignRepository.Queryable()
  71. .LeftJoin<WorkflowCountersignMember>((x,o)=>x.Id ==o.WorkflowCountersignId)
  72. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  73. .WhereIF(dto.EndTime.HasValue, x=> x.CreationTime <= dto.EndTime)
  74. .GroupBy((x,o)=> o.Key)
  75. .Select((x,o) => new OrderBiOrgDataListVo
  76. {
  77. OrgId = o.Key,
  78. CounterHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(o.IsHandled,1,0)),
  79. CounterNoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(!o.IsHandled, 1, 0)),
  80. }).MergeTable();
  81. var query = queryOrder.LeftJoin(queryCountersign,(or,co)=>or.OrgId == co.OrgId)
  82. .Select((or,co) => new OrderBiOrgDataListVo {
  83. OrgName = or.OrgName,
  84. OrgId = or.OrgId,
  85. HandlerExtendedNum =or.HandlerExtendedNum,
  86. NoHandlerExtendedNum =or.NoHandlerExtendedNum,
  87. CounterHandlerExtendedNum =co.CounterHandlerExtendedNum,
  88. CounterNoHandlerExtendedNum =co.CounterNoHandlerExtendedNum
  89. }).MergeTable();
  90. query = query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrgName.Contains(dto.Keyword!));
  91. switch (dto.SortField)
  92. {
  93. case "handlerExtendedNum":
  94. query = dto.SortRule == 0 ? query.OrderBy(x => x.HandlerExtendedNum) : query.OrderByDescending(x => x.HandlerExtendedNum);
  95. break;
  96. case "counterHandlerExtendedNum":
  97. query = dto.SortRule == 0 ? query.OrderBy(x => x.CounterHandlerExtendedNum) : query.OrderByDescending(x => x.CounterHandlerExtendedNum);
  98. break;
  99. case "noHandlerExtendedNum":
  100. query = dto.SortRule == 0 ? query.OrderBy(x => x.NoHandlerExtendedNum) : query.OrderByDescending(x => x.NoHandlerExtendedNum);
  101. break;
  102. case "counterNoHandlerExtendedNum":
  103. query = dto.SortRule == 0 ? query.OrderBy(x => x.CounterNoHandlerExtendedNum) : query.OrderByDescending(x => x.CounterNoHandlerExtendedNum);
  104. break;
  105. }
  106. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  107. return new PagedDto<OrderBiOrgDataListVo>(total, items);
  108. }
  109. /// <summary>
  110. /// 中心统计
  111. /// </summary>
  112. /// <param name="dto"></param>
  113. /// <returns></returns>
  114. [HttpGet("centre_data_list")]
  115. public async Task<PagedDto<OrderBiCentreDataListVo>> CentreDataList([FromQuery] ReportPagedRequest dto)
  116. {
  117. var query = _orderRepository.Queryable(false, false, false)
  118. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  119. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  120. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.AcceptorName.Contains(dto.Keyword!))
  121. .GroupBy(x => new { x.AcceptorId, x.AcceptorName })
  122. .Select(x => new OrderBiCentreDataListVo
  123. {
  124. UserName = x.AcceptorName,
  125. UserId = x.AcceptorId,
  126. CentreArchive = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ProcessType == EProcessType.Zhiban, 1, 0)),
  127. CentreCareOf = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ProcessType == EProcessType.Jiaoban, 1, 0)),
  128. //NoCentreCareOf = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status < 300 && x.ExpiredTime > x.FiledTime, 1, 0)),
  129. Invalid = SqlFunc.AggregateSum(SqlFunc.IIF(x.AcceptType == "无效", 1, 0)),
  130. Repeat = SqlFunc.AggregateSum(SqlFunc.IIF(x.DuplicateIds != null && SqlFunc.JsonArrayLength(x.DuplicateIds) > 0, 1, 0))
  131. }).MergeTable();
  132. switch (dto.SortField)
  133. {
  134. case "centreArchive":
  135. query = dto.SortRule == 0 ? query.OrderBy(x => x.CentreArchive) : query.OrderByDescending(x => x.CentreArchive);
  136. break;
  137. case "centreCareOf":
  138. query = dto.SortRule == 0 ? query.OrderBy(x => x.CentreCareOf) : query.OrderByDescending(x => x.CentreCareOf);
  139. break;
  140. case "noCentreCareOf":
  141. query = dto.SortRule == 0 ? query.OrderBy(x => x.NoCentreCareOf) : query.OrderByDescending(x => x.NoCentreCareOf);
  142. break;
  143. case "invalid":
  144. query = dto.SortRule == 0 ? query.OrderBy(x => x.Invalid) : query.OrderByDescending(x => x.Invalid);
  145. break;
  146. case "repeat":
  147. query = dto.SortRule == 0 ? query.OrderBy(x => x.Repeat) : query.OrderByDescending(x => x.Repeat);
  148. break;
  149. }
  150. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  151. return new PagedDto<OrderBiCentreDataListVo>(total, items);
  152. }
  153. /// <summary>
  154. /// 热点数据统计
  155. /// </summary>
  156. /// <param name="dto"></param>
  157. /// <returns></returns>
  158. [HttpGet("hotspot_data_list")]
  159. public async Task<PagedDto<HotspotDataLsitVo>> HotspotDataLsit([FromQuery] HotspotReportPagedRequest dto)
  160. {
  161. var query = _hotspotTypeRepository.Queryable(false, true)
  162. .LeftJoin<Order>((x, o) => o.HotspotSpliceName != null && (x.HotSpotFullName == o.HotspotSpliceName || o.HotspotSpliceName.Contains(x.HotSpotFullName)) && o.IsDeleted == false)
  163. .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
  164. .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= dto.EndTime)
  165. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => x.HotSpotName.Contains(dto.Keyword!))
  166. .Where((x, o) => x.ParentId == dto.Id)
  167. .Where((x, o) => x.IsDeleted == false)
  168. .GroupBy((x, o) => new { x.Id, x.HotSpotName })
  169. .Select((x, o) => new HotspotDataLsitVo
  170. {
  171. Id = x.Id,
  172. Name = x.HotSpotName,
  173. Num = SqlFunc.AggregateSum(SqlFunc.IIF(o.Id != null, 1, 0)),
  174. }).MergeTable();
  175. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  176. return new PagedDto<HotspotDataLsitVo>(total, items);
  177. }
  178. /// <summary>
  179. /// 部门不满意统计
  180. /// </summary>
  181. /// <param name="dto"></param>
  182. /// <returns></returns>
  183. [HttpGet("visit-nosatisfied")]
  184. public async Task<object> QueryVisitNoSatisfied([FromQuery] QueryVisitNoSatiisfiedRequest dto)
  185. {
  186. var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason);
  187. List<dynamic>? list = new List<dynamic>();
  188. //DataTable dt = new DataTable();
  189. foreach (var item in dissatisfiedReason)
  190. {
  191. var table = _orderVisitDetailRepository.Queryable()
  192. .Includes(x => x.OrderVisit)
  193. .Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Org)
  194. .Where(x => x.OrgNoSatisfiedReason != null)
  195. .Where(x => x.OrderVisit.VisitState == EVisitState.Visited)
  196. .Where(x => !string.IsNullOrEmpty(x.VisitOrgName))
  197. .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.VisitOrgName.Contains(dto.OrgName))
  198. .WhereIF(dto.StartTime.HasValue, x => x.OrderVisit.VisitTime >= dto.StartTime.Value)
  199. .WhereIF(dto.EndTime.HasValue, x => x.OrderVisit.VisitTime <= dto.EndTime.Value)
  200. .GroupBy(x => new { x.VisitOrgName, x.VisitOrgCode })
  201. .Select(x => new BiVisitNoSatisfiedDto
  202. {
  203. Count = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(x.OrgNoSatisfiedReason, "Key", item.DicDataValue), 1, 0)),
  204. Key = item.DicDataValue,
  205. OrgName = x.VisitOrgName,
  206. OrgCode = x.VisitOrgCode
  207. })
  208. .OrderByDescending(x => x.Count)
  209. //.ToPivotTable(x => x.Key, x => x.OrgName, x => x.Sum(x => x.Count));
  210. .ToPivotList(x => x.Key,x=> new { x.OrgCode,x.OrgName }, x => x.Sum(x => x.Count));
  211. list.AddRange(table);
  212. }
  213. return new { DicReason = dissatisfiedReason, Data = list };
  214. }
  215. /// <summary>
  216. /// 部门不满意统计明细
  217. /// </summary>
  218. /// <param name="dto"></param>
  219. /// <returns></returns>
  220. [HttpGet("visit-nosatisfied-detail")]
  221. public async Task<PagedDto<OrderVisitDetailDto>> BiQueryVisitNoSatisfiedDetail([FromQuery]BiQueryVisitNoSatisfiedDetailDto dto)
  222. {
  223. var (total,items) = await _orderVisitDetailRepository.Queryable()
  224. .Includes(x => x.OrderVisit, d => d.Order)
  225. .Includes(x => x.OrderVisit, d => d.Employee)
  226. .Where(x => x.VisitOrgCode == dto.OrgCode)
  227. .Where(x => x.OrderVisit.VisitState == EVisitState.Visited)
  228. .Where(x => x.OrderVisit.VisitTime >= dto.StartTime.Value)
  229. .Where(x => x.OrderVisit.VisitTime <= dto.EndTime.Value)
  230. .Where(x => SqlFunc.JsonListObjectAny(x.OrgNoSatisfiedReason, "Key", dto.DissatisfiedKey))
  231. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),x=>x.OrderVisit.Order.No.Contains(dto.Keyword) || x.OrderVisit.Order.Title.Contains(dto.Keyword))
  232. .OrderBy(x => x.OrderVisit.VisitTime)
  233. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  234. return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
  235. }
  236. /// <summary>
  237. /// 部门延期统计
  238. /// </summary>
  239. /// <param name="dto"></param>
  240. /// <returns></returns>
  241. [HttpGet("order-delay-data-list")]
  242. public async Task<IReadOnlyList<BiOrderDelayDataDto>> QueryOrderDelayDataList([FromQuery] QueryOrderDelayDataListRequest dto)
  243. {
  244. var list = await _orderDelayRepository.Queryable()
  245. .LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgCode == o.Id)
  246. .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
  247. .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
  248. .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Contains(dto.OrgName))
  249. .GroupBy(x => new { x.ApplyOrgCode, x.ApplyOrgName })
  250. .Select(x => new BiOrderDelayDataDto
  251. {
  252. OrgName = x.ApplyOrgName,
  253. OrgCode = x.ApplyOrgCode,
  254. PassTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Pass, 1, 0)),
  255. NoPassTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.NoPass, 1, 0)),
  256. ExaminingTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Examining, 1, 0)),
  257. AllTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Pass, 1, 0)) + SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.NoPass, 1, 0)) + SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Examining, 1, 0))
  258. }).ToListAsync();
  259. return list;
  260. }
  261. /// <summary>
  262. /// 特提统计
  263. /// </summary>
  264. /// <param name="dto"></param>
  265. /// <returns></returns>
  266. [HttpGet("special_data_list")]
  267. public async Task<PagedDto<OrderBiSpecialListVo>> SpecialDataList([FromQuery] ReportPagedRequest dto)
  268. {
  269. var query = _orderSpecialRepository.Queryable()
  270. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  271. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  272. .GroupBy(x => new { x.Cause })
  273. .Select(x => new OrderBiSpecialListVo
  274. {
  275. Cause = x.Cause,
  276. OrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(true, 1, 0)),
  277. MaxSpecialTime = SqlFunc.AggregateMax(x.CreationTime),
  278. }).MergeTable();
  279. switch (dto.SortField)
  280. {
  281. case "cause":
  282. query = dto.SortRule == 0 ? query.OrderBy(x => x.Cause) : query.OrderByDescending(x => x.Cause);
  283. break;
  284. case "orderNum":
  285. query = dto.SortRule == 0 ? query.OrderBy(x => x.OrderNum) : query.OrderByDescending(x => x.OrderNum);
  286. break;
  287. case "maxSpecialTime":
  288. query = dto.SortRule == 0 ? query.OrderBy(x => x.MaxSpecialTime) : query.OrderByDescending(x => x.MaxSpecialTime);
  289. break;
  290. }
  291. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  292. return new PagedDto<OrderBiSpecialListVo>(total, items);
  293. }
  294. /// <summary>
  295. /// 获取工单特提信息列表
  296. /// </summary>
  297. /// <param name="dto"></param>
  298. /// <returns></returns>
  299. [HttpGet("special_data_list/list")]
  300. public async Task<PagedDto<OrderSpecialDto>> List([FromQuery] OrderSpecialListDto dto)
  301. {
  302. if(!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  303. var (total, items) = await _orderSpecialRepository.Queryable()
  304. .Includes(x => x.Order)
  305. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  306. x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!))
  307. .WhereIF(!string.IsNullOrEmpty(dto.Cause),
  308. x => x.Cause != null && x.Cause.Equals(dto.Cause))
  309. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  310. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  311. .WhereIF(dto.State.HasValue, x => x.State == dto.State)
  312. .OrderByDescending(x => x.CreationTime)
  313. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  314. return new PagedDto<OrderSpecialDto>(total, _mapper.Map<IReadOnlyList<OrderSpecialDto>>(items));
  315. }
  316. }
  317. }