BiOrderController.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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. using Microsoft.AspNetCore.Authorization;
  18. namespace Hotline.Api.Controllers.Bi
  19. {
  20. public class BiOrderController : BaseController
  21. {
  22. private readonly IOrderRepository _orderRepository;
  23. private readonly IRepository<Hotspot> _hotspotTypeRepository;
  24. private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
  25. private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
  26. private readonly IRepository<OrderDelay> _orderDelayRepository;
  27. private readonly IMapper _mapper;
  28. private readonly IRepository<WorkflowCountersign> _workflowCountersignRepository;
  29. private readonly IRepository<OrderSpecial> _orderSpecialRepository;
  30. private readonly IRepository<OrderVisit> _orderVisitRepository;
  31. public BiOrderController(
  32. IOrderRepository orderRepository,
  33. IRepository<Hotspot> hotspotTypeRepository,
  34. ISystemDicDataCacheManager sysDicDataCacheManager,
  35. IRepository<OrderVisitDetail> orderVisitDetailRepository,
  36. IRepository<OrderDelay> orderDelayRepository,
  37. IRepository<WorkflowCountersign> workflowCountersignRepository,
  38. IRepository<OrderSpecial> orderSpecialRepository,
  39. IMapper mapper,
  40. IRepository<OrderVisit> orderVisitRepository
  41. )
  42. {
  43. _orderRepository = orderRepository;
  44. _hotspotTypeRepository = hotspotTypeRepository;
  45. _sysDicDataCacheManager = sysDicDataCacheManager;
  46. _orderVisitDetailRepository = orderVisitDetailRepository;
  47. _orderDelayRepository = orderDelayRepository;
  48. _workflowCountersignRepository = workflowCountersignRepository;
  49. _orderSpecialRepository = orderSpecialRepository;
  50. _mapper = mapper;
  51. _orderVisitRepository = orderVisitRepository;
  52. }
  53. /// <summary>
  54. /// 部门数据统计
  55. /// </summary>
  56. /// <param name="dto"></param>
  57. /// <returns></returns>
  58. [HttpGet("org_data_list")]
  59. public async Task<PagedDto<OrderBiOrgDataListVo>> OrgDataList([FromQuery] ReportPagedRequest dto)
  60. {
  61. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  62. var queryOrder = _orderRepository.Queryable(false, false, false)
  63. .LeftJoin<SystemOrganize>((x, o) => x.ActualHandleOrgCode == o.Id)
  64. .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
  65. .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
  66. .GroupBy((x, o) => new { x.ActualHandleOrgCode, o.Name })
  67. .Select((x, o) => new OrderBiOrgDataListVo
  68. {
  69. OrgName = o.Name,
  70. OrgId = x.ActualHandleOrgCode,
  71. HandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ExpiredTime < x.FiledTime, 1, 0)),
  72. NoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status < 300 && x.ExpiredTime < SqlFunc.GetDate(), 1, 0)),
  73. }).MergeTable();
  74. var queryCountersign = _workflowCountersignRepository.Queryable()
  75. .LeftJoin<WorkflowCountersignMember>((x,o)=>x.Id ==o.WorkflowCountersignId)
  76. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  77. .WhereIF(dto.EndTime.HasValue, x=> x.CreationTime <= dto.EndTime)
  78. .GroupBy((x,o)=> o.Key)
  79. .Select((x,o) => new OrderBiOrgDataListVo
  80. {
  81. OrgId = o.Key,
  82. CounterHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(o.IsHandled,1,0)),
  83. CounterNoHandlerExtendedNum = SqlFunc.AggregateSum(SqlFunc.IIF(!o.IsHandled, 1, 0)),
  84. }).MergeTable();
  85. var query = queryOrder.LeftJoin(queryCountersign,(or,co)=>or.OrgId == co.OrgId)
  86. .Select((or,co) => new OrderBiOrgDataListVo {
  87. OrgName = or.OrgName,
  88. OrgId = or.OrgId,
  89. HandlerExtendedNum =or.HandlerExtendedNum,
  90. NoHandlerExtendedNum =or.NoHandlerExtendedNum,
  91. CounterHandlerExtendedNum =co.CounterHandlerExtendedNum,
  92. CounterNoHandlerExtendedNum =co.CounterNoHandlerExtendedNum
  93. }).MergeTable();
  94. query = query.WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.OrgName.Contains(dto.Keyword!));
  95. switch (dto.SortField)
  96. {
  97. case "handlerExtendedNum":
  98. query = dto.SortRule == 0 ? query.OrderBy(x => x.HandlerExtendedNum) : query.OrderByDescending(x => x.HandlerExtendedNum);
  99. break;
  100. case "counterHandlerExtendedNum":
  101. query = dto.SortRule == 0 ? query.OrderBy(x => x.CounterHandlerExtendedNum) : query.OrderByDescending(x => x.CounterHandlerExtendedNum);
  102. break;
  103. case "noHandlerExtendedNum":
  104. query = dto.SortRule == 0 ? query.OrderBy(x => x.NoHandlerExtendedNum) : query.OrderByDescending(x => x.NoHandlerExtendedNum);
  105. break;
  106. case "counterNoHandlerExtendedNum":
  107. query = dto.SortRule == 0 ? query.OrderBy(x => x.CounterNoHandlerExtendedNum) : query.OrderByDescending(x => x.CounterNoHandlerExtendedNum);
  108. break;
  109. }
  110. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  111. return new PagedDto<OrderBiOrgDataListVo>(total, items);
  112. }
  113. /// <summary>
  114. /// 中心统计
  115. /// </summary>
  116. /// <param name="dto"></param>
  117. /// <returns></returns>
  118. [HttpGet("centre_data_list")]
  119. public async Task<PagedDto<OrderBiCentreDataListVo>> CentreDataList([FromQuery] ReportPagedRequest dto)
  120. {
  121. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  122. var query = _orderRepository.Queryable(false, false, false)
  123. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  124. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  125. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.AcceptorName.Contains(dto.Keyword!))
  126. .GroupBy(x => new { x.AcceptorId, x.AcceptorName })
  127. .Select(x => new OrderBiCentreDataListVo
  128. {
  129. UserName = x.AcceptorName,
  130. UserId = x.AcceptorId,
  131. CentreArchive = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ProcessType == EProcessType.Zhiban, 1, 0)),
  132. CentreCareOf = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status >= 300 && x.ProcessType == EProcessType.Jiaoban, 1, 0)),
  133. //NoCentreCareOf = SqlFunc.AggregateSum(SqlFunc.IIF((int)x.Status < 300 && x.ExpiredTime > x.FiledTime, 1, 0)),
  134. Invalid = SqlFunc.AggregateSum(SqlFunc.IIF(x.AcceptType == "无效", 1, 0)),
  135. Repeat = SqlFunc.AggregateSum(SqlFunc.IIF(x.DuplicateIds != null && SqlFunc.JsonArrayLength(x.DuplicateIds) > 0, 1, 0))
  136. }).MergeTable();
  137. switch (dto.SortField)
  138. {
  139. case "centreArchive":
  140. query = dto.SortRule == 0 ? query.OrderBy(x => x.CentreArchive) : query.OrderByDescending(x => x.CentreArchive);
  141. break;
  142. case "centreCareOf":
  143. query = dto.SortRule == 0 ? query.OrderBy(x => x.CentreCareOf) : query.OrderByDescending(x => x.CentreCareOf);
  144. break;
  145. case "noCentreCareOf":
  146. query = dto.SortRule == 0 ? query.OrderBy(x => x.NoCentreCareOf) : query.OrderByDescending(x => x.NoCentreCareOf);
  147. break;
  148. case "invalid":
  149. query = dto.SortRule == 0 ? query.OrderBy(x => x.Invalid) : query.OrderByDescending(x => x.Invalid);
  150. break;
  151. case "repeat":
  152. query = dto.SortRule == 0 ? query.OrderBy(x => x.Repeat) : query.OrderByDescending(x => x.Repeat);
  153. break;
  154. }
  155. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  156. return new PagedDto<OrderBiCentreDataListVo>(total, items);
  157. }
  158. /// <summary>
  159. /// 热点数据小计统计
  160. /// </summary>
  161. /// <param name="dto"></param>
  162. /// <returns></returns>
  163. [HttpGet("hotspot_subtotal_data_list")]
  164. public async Task<PagedDto<HotspotDataLsitVo>> HotspotSubtotalDataLsit([FromQuery] HotspotSubtotalReportPagedRequest dto)
  165. {
  166. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  167. var query = _hotspotTypeRepository.Queryable(false, true)
  168. .LeftJoin<Order>((x, o) => o.HotspotSpliceName != null && (x.HotSpotFullName == o.HotspotSpliceName || o.HotspotSpliceName.Contains(x.HotSpotFullName)) && o.IsDeleted == false)
  169. .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
  170. .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= dto.EndTime)
  171. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => x.HotSpotName.Contains(dto.Keyword!))
  172. .Where((x, o) => x.ParentId == dto.Id)
  173. .Where((x, o) => x.IsDeleted == false)
  174. .GroupBy((x, o) => new { x.Id, x.HotSpotName })
  175. .Select((x, o) => new HotspotDataLsitVo
  176. {
  177. Id = x.Id,
  178. Name = x.HotSpotName,
  179. Num = SqlFunc.AggregateSum(SqlFunc.IIF(o.Id != null, 1, 0)),
  180. }).MergeTable();
  181. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  182. return new PagedDto<HotspotDataLsitVo>(total, items);
  183. }
  184. /// <summary>
  185. /// 热点数据统计
  186. /// </summary>
  187. /// <param name="dto"></param>
  188. /// <returns></returns>
  189. [HttpGet("hotspot_data_list")]
  190. public async Task<object> HotspotDataLsit([FromQuery] HotspotReportPagedRequest dto)
  191. {
  192. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  193. if (dto.Type == 0 && (!dto.ChainStartTime.HasValue || !dto.ChainEndTime.HasValue)) throw UserFriendlyException.SameMessage("请选择环比时间!");
  194. var items = await _hotspotTypeRepository.Queryable(false, true)
  195. .LeftJoin<Order>((x, o) => o.HotspotSpliceName != null && (x.HotSpotName == o.HotspotSpliceName || o.HotspotSpliceName.Contains(x.HotSpotName)) && o.IsDeleted == false)
  196. .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= dto.StartTime)
  197. .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= dto.EndTime)
  198. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => x.HotSpotName.Contains(dto.Keyword!))
  199. .Where((x, o) => x.ParentId == dto.Id)
  200. .Where((x, o) => x.IsDeleted == false)
  201. .GroupBy((x, o) => new { x.Id, x.HotSpotName })
  202. .Select((x, o) => new HotspotDataLsitVo
  203. {
  204. Id = x.Id,
  205. Name = x.HotSpotName,
  206. Num = SqlFunc.AggregateSum(SqlFunc.IIF(o.Id != null, 1, 0)),
  207. Sublevel = SqlFunc.AggregateSum(SqlFunc.IIF(x.HotSpotName != o.HotspotName, 1, 0)) > 0,
  208. }).MergeTable().ToListAsync();
  209. var chainStartTime = dto.StartTime;
  210. var chainEndTime = dto.EndTime;
  211. switch (dto.Type)
  212. {
  213. case 1://日
  214. chainStartTime = dto.StartTime.Value.AddDays(-1);
  215. chainEndTime = dto.EndTime.Value.AddDays(-1);
  216. break;
  217. case 2://月
  218. chainStartTime = dto.StartTime.Value.AddMonths(-1);
  219. chainEndTime = dto.EndTime.Value.AddMonths(-1);
  220. break;
  221. case 3://年
  222. chainStartTime = dto.StartTime.Value.AddYears(-1);
  223. chainEndTime = dto.EndTime.Value.AddYears(-1);
  224. break;
  225. case 0:
  226. chainStartTime = dto.ChainStartTime.Value;
  227. chainEndTime = dto.ChainEndTime.Value;
  228. break;
  229. }
  230. var chainItems = await _hotspotTypeRepository.Queryable(false, true)
  231. .LeftJoin<Order>((x, o) => o.HotspotSpliceName != null && (x.HotSpotName == o.HotspotSpliceName || o.HotspotSpliceName.Contains(x.HotSpotName)) && o.IsDeleted == false)
  232. .WhereIF(dto.StartTime.HasValue, (x, o) => o.CreationTime >= chainStartTime)
  233. .WhereIF(dto.EndTime.HasValue, (x, o) => o.CreationTime <= chainEndTime)
  234. .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (x, o) => x.HotSpotName.Contains(dto.Keyword!))
  235. .Where((x, o) => x.ParentId == dto.Id)
  236. .Where((x, o) => x.IsDeleted == false)
  237. .GroupBy((x, o) => new { x.Id, x.HotSpotName })
  238. .Select((x, o) => new
  239. {
  240. Id = x.Id,
  241. ChainNum = SqlFunc.AggregateSum(SqlFunc.IIF(o.Id != null, 1, 0)),
  242. }).MergeTable().ToListAsync();
  243. var res = (from t1 in items
  244. join t2 in chainItems on t1.Id equals t2.Id into t1_t2
  245. from item in t1_t2.DefaultIfEmpty()
  246. select new
  247. {
  248. Id = t1.Id,
  249. Name = t1.Name,
  250. Num = t1.Num,
  251. Sublevel = t1.Sublevel,
  252. Children = new List<HotspotDataLsitVo>(),
  253. ChainNum = t1_t2.Select(x => x.ChainNum).FirstOrDefault(),
  254. ChainRate = t1_t2.Select(x => x.ChainNum).FirstOrDefault() > 0 ?
  255. ((double.Parse(t1.Num.ToString()) - double.Parse(t1_t2.Select(x => x.ChainNum).FirstOrDefault().ToString())) / double.Parse(t1_t2.Select(x => x.ChainNum).FirstOrDefault().ToString()) * 100).ToString("F2") + "%" : "100.00%",
  256. }).ToList();
  257. var total = new
  258. {
  259. Id = "0",
  260. Name = "合计",
  261. Num = res.Sum(x => x.Num),
  262. Sublevel = false,
  263. Children = new List<HotspotDataLsitVo>(),
  264. ChainNum = res.Sum(x => x.ChainNum),
  265. ChainRate = res.Sum(x => x.ChainNum) > 0 ? ((double.Parse(res.Sum(x => x.Num).ToString()) - double.Parse(res.Sum(x => x.ChainNum).ToString())) / double.Parse(res.Sum(x => x.ChainNum).ToString()) * 100).ToString("F2") + "%" : "100.00%"
  266. };
  267. return new {List =res ,Total = total };
  268. }
  269. /// <summary>
  270. /// 部门不满意统计
  271. /// </summary>
  272. /// <param name="dto"></param>
  273. /// <returns></returns>
  274. [HttpGet("visit-nosatisfied")]
  275. public async Task<object> QueryVisitNoSatisfied([FromQuery] QueryVisitNoSatiisfiedRequest dto)
  276. {
  277. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  278. var dissatisfiedReason = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.DissatisfiedReason);
  279. List<dynamic>? list = new List<dynamic>();
  280. //DataTable dt = new DataTable();
  281. foreach (var item in dissatisfiedReason)
  282. {
  283. var table = _orderVisitDetailRepository.Queryable()
  284. .Includes(x => x.OrderVisit)
  285. .Where(x => x.VisitTarget == Share.Enums.Order.EVisitTarget.Org)
  286. .Where(x => x.OrgNoSatisfiedReason != null)
  287. .Where(x => x.OrderVisit.VisitState == EVisitState.Visited)
  288. .Where(x => !string.IsNullOrEmpty(x.VisitOrgName))
  289. .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.VisitOrgName.Contains(dto.OrgName))
  290. .WhereIF(dto.StartTime.HasValue, x => x.OrderVisit.VisitTime >= dto.StartTime.Value)
  291. .WhereIF(dto.EndTime.HasValue, x => x.OrderVisit.VisitTime <= dto.EndTime.Value)
  292. .GroupBy(x => new { x.VisitOrgName, x.VisitOrgCode })
  293. .Select(x => new BiVisitNoSatisfiedDto
  294. {
  295. Count = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(x.OrgNoSatisfiedReason, "Key", item.DicDataValue), 1, 0)),
  296. Key = item.DicDataValue,
  297. OrgName = x.VisitOrgName,
  298. OrgCode = x.VisitOrgCode
  299. })
  300. .OrderByDescending(x => x.Count)
  301. //.ToPivotTable(x => x.Key, x => x.OrgName, x => x.Sum(x => x.Count));
  302. .ToPivotList(x => x.Key,x=> new { x.OrgCode,x.OrgName }, x => x.Sum(x => x.Count));
  303. list.AddRange(table);
  304. }
  305. return new { DicReason = dissatisfiedReason, Data = list };
  306. }
  307. /// <summary>
  308. /// 部门不满意统计明细
  309. /// </summary>
  310. /// <param name="dto"></param>
  311. /// <returns></returns>
  312. [HttpGet("visit-nosatisfied-detail")]
  313. public async Task<PagedDto<OrderVisitDetailDto>> BiQueryVisitNoSatisfiedDetail([FromQuery]BiQueryVisitNoSatisfiedDetailDto dto)
  314. {
  315. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  316. var (total,items) = await _orderVisitDetailRepository.Queryable()
  317. .Includes(x => x.OrderVisit, d => d.Order)
  318. .Includes(x => x.OrderVisit, d => d.Employee)
  319. .Where(x => x.VisitOrgCode == dto.OrgCode)
  320. .Where(x => x.OrderVisit.VisitState == EVisitState.Visited)
  321. .Where(x => x.OrderVisit.VisitTime >= dto.StartTime.Value)
  322. .Where(x => x.OrderVisit.VisitTime <= dto.EndTime.Value)
  323. .Where(x => SqlFunc.JsonListObjectAny(x.OrgNoSatisfiedReason, "Key", dto.DissatisfiedKey))
  324. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),x=>x.OrderVisit.Order.No.Contains(dto.Keyword) || x.OrderVisit.Order.Title.Contains(dto.Keyword))
  325. .OrderBy(x => x.OrderVisit.VisitTime)
  326. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  327. return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
  328. }
  329. /// <summary>
  330. /// 部门延期统计
  331. /// </summary>
  332. /// <param name="dto"></param>
  333. /// <returns></returns>
  334. [HttpGet("order-delay-data-list")]
  335. public async Task<IReadOnlyList<BiOrderDelayDataDto>> QueryOrderDelayDataList([FromQuery] QueryOrderDelayDataListRequest dto)
  336. {
  337. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  338. var list = await _orderDelayRepository.Queryable()
  339. .LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgCode == o.Id)
  340. .WhereIF(dto.StartTime.HasValue, (x, o) => x.CreationTime >= dto.StartTime)
  341. .WhereIF(dto.EndTime.HasValue, (x, o) => x.CreationTime <= dto.EndTime)
  342. .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Contains(dto.OrgName))
  343. .GroupBy(x => new { x.ApplyOrgCode, x.ApplyOrgName })
  344. .Select(x => new BiOrderDelayDataDto
  345. {
  346. OrgName = x.ApplyOrgName,
  347. OrgCode = x.ApplyOrgCode,
  348. PassTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Pass, 1, 0)),
  349. NoPassTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.NoPass, 1, 0)),
  350. ExaminingTotal = SqlFunc.AggregateSum(SqlFunc.IIF(x.DelayState == EDelayState.Examining, 1, 0)),
  351. 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))
  352. }).ToListAsync();
  353. return list;
  354. }
  355. /// <summary>
  356. /// 特提统计
  357. /// </summary>
  358. /// <param name="dto"></param>
  359. /// <returns></returns>
  360. [HttpGet("special_data_list")]
  361. public async Task<PagedDto<OrderBiSpecialListVo>> SpecialDataList([FromQuery] ReportPagedRequest dto)
  362. {
  363. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  364. var query = _orderSpecialRepository.Queryable()
  365. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  366. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  367. .GroupBy(x => new { x.Cause })
  368. .Select(x => new OrderBiSpecialListVo
  369. {
  370. Cause = x.Cause,
  371. OrderNum = SqlFunc.AggregateSum(SqlFunc.IIF(true, 1, 0)),
  372. MaxSpecialTime = SqlFunc.AggregateMax(x.CreationTime),
  373. })
  374. .MergeTable();
  375. switch (dto.SortField)
  376. {
  377. case "cause":
  378. query = dto.SortRule == 0 ? query.OrderBy(x => x.Cause) : query.OrderByDescending(x => x.Cause);
  379. break;
  380. case "orderNum":
  381. query = dto.SortRule == 0 ? query.OrderBy(x => x.OrderNum) : query.OrderByDescending(x => x.OrderNum);
  382. break;
  383. case "maxSpecialTime":
  384. query = dto.SortRule == 0 ? query.OrderBy(x => x.MaxSpecialTime) : query.OrderByDescending(x => x.MaxSpecialTime);
  385. break;
  386. }
  387. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  388. return new PagedDto<OrderBiSpecialListVo>(total, items);
  389. }
  390. /// <summary>
  391. /// 获取工单特提信息列表
  392. /// </summary>
  393. /// <param name="dto"></param>
  394. /// <returns></returns>
  395. [HttpGet("special_data_list/list")]
  396. public async Task<PagedDto<OrderSpecialDto>> List([FromQuery] OrderSpecialListDto dto)
  397. {
  398. if(!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  399. var (total, items) = await _orderSpecialRepository.Queryable()
  400. .Includes(x => x.Order)
  401. .WhereIF(!string.IsNullOrEmpty(dto.Keyword),
  402. x => x.Order.No.Contains(dto.Keyword!) || x.Order.Title.Contains(dto.Keyword!))
  403. .WhereIF(!string.IsNullOrEmpty(dto.Cause),
  404. x => x.Cause != null && x.Cause.Equals(dto.Cause))
  405. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  406. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  407. .WhereIF(dto.State.HasValue, x => x.State == dto.State)
  408. .OrderByDescending(x => x.CreationTime)
  409. .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
  410. return new PagedDto<OrderSpecialDto>(total, _mapper.Map<IReadOnlyList<OrderSpecialDto>>(items));
  411. }
  412. /// <summary>
  413. /// 受理类型前十
  414. /// </summary>
  415. /// <param name="dto"></param>
  416. /// <returns></returns>
  417. [HttpGet("accept_type_top10_list")]
  418. public async Task<PagedDto<AcceptTypeTop10Vo>> AcceptTypeTop10List([FromQuery] ReportPagedRequest dto)
  419. {
  420. if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
  421. dto.PageIndex = 1;
  422. dto.PageSize = 10;
  423. var query = _orderRepository.Queryable(false, false, false)
  424. .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
  425. .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
  426. .Select(x => new
  427. {
  428. AcceptType = x.AcceptType,
  429. OneHotspot = SqlFunc.Substring(x.HotspotSpliceName, 0, SqlFunc.CharIndex("-", x.HotspotSpliceName + "-")),
  430. Id = x.Id
  431. }).MergeTable()
  432. .GroupBy(x => new { x.OneHotspot })
  433. .Select(x => new AcceptTypeTop10Vo
  434. {
  435. Name = x.OneHotspot,
  436. ValidAccept = SqlFunc.AggregateSum(SqlFunc.IIF(true, 1, 0)),
  437. Consult = SqlFunc.AggregateSum(SqlFunc.IIF("咨询".Equals(x.AcceptType), 1, 0)),
  438. Report = SqlFunc.AggregateSum(SqlFunc.IIF("举报".Equals(x.AcceptType), 1, 0)),
  439. Complaint = SqlFunc.AggregateSum(SqlFunc.IIF("投诉".Equals(x.AcceptType), 1, 0)),
  440. SeekHelp = SqlFunc.AggregateSum(SqlFunc.IIF("求助".Equals(x.AcceptType), 1, 0)),
  441. Suggest = SqlFunc.AggregateSum(SqlFunc.IIF("建议".Equals(x.AcceptType), 1, 0)),
  442. Opinion = SqlFunc.AggregateSum(SqlFunc.IIF("意见".Equals(x.AcceptType), 1, 0)),
  443. Rests = SqlFunc.AggregateSum(SqlFunc.IIF("其他".Equals(x.AcceptType), 1, 0)),
  444. BenefitThePeople = SqlFunc.AggregateSum(SqlFunc.IIF("惠民帮助".Equals(x.AcceptType), 1, 0)),
  445. Praise = SqlFunc.AggregateSum(SqlFunc.IIF("表扬".Equals(x.AcceptType), 1, 0)),
  446. }).MergeTable();
  447. switch (dto.SortField)
  448. {
  449. case "validAccept":
  450. query = dto.SortRule == 0 ? query.OrderBy(x => x.ValidAccept) : query.OrderByDescending(x => x.ValidAccept);
  451. break;
  452. case "consult":
  453. query = dto.SortRule == 0 ? query.OrderBy(x => x.Consult) : query.OrderByDescending(x => x.Consult);
  454. break;
  455. case "report":
  456. query = dto.SortRule == 0 ? query.OrderBy(x => x.Report) : query.OrderByDescending(x => x.Report);
  457. break;
  458. case "complaint":
  459. query = dto.SortRule == 0 ? query.OrderBy(x => x.Complaint) : query.OrderByDescending(x => x.Complaint);
  460. break;
  461. case "seekHelp":
  462. query = dto.SortRule == 0 ? query.OrderBy(x => x.SeekHelp) : query.OrderByDescending(x => x.SeekHelp);
  463. break;
  464. case "suggest":
  465. query = dto.SortRule == 0 ? query.OrderBy(x => x.Suggest) : query.OrderByDescending(x => x.Suggest);
  466. break;
  467. case "opinion":
  468. query = dto.SortRule == 0 ? query.OrderBy(x => x.Opinion) : query.OrderByDescending(x => x.Opinion);
  469. break;
  470. case "rests":
  471. query = dto.SortRule == 0 ? query.OrderBy(x => x.Rests) : query.OrderByDescending(x => x.Rests);
  472. break;
  473. case "benefitThePeople":
  474. query = dto.SortRule == 0 ? query.OrderBy(x => x.BenefitThePeople) : query.OrderByDescending(x => x.BenefitThePeople);
  475. break;
  476. case "praise":
  477. query = dto.SortRule == 0 ? query.OrderBy(x => x.Praise) : query.OrderByDescending(x => x.Praise);
  478. break;
  479. default:
  480. query = query.OrderByDescending(x => x.ValidAccept);
  481. break;
  482. }
  483. var (total, items) = await query.ToPagedListAsync(dto, HttpContext.RequestAborted);
  484. return new PagedDto<AcceptTypeTop10Vo>(total, items);
  485. }
  486. /// <summary>
  487. /// 热点类型部门统计
  488. /// </summary>
  489. /// <param name="dto"></param>
  490. /// <returns></returns>
  491. [HttpGet("hotport-org-statistics")]
  492. public async Task<object> HotPortJoinOrgStatistics([FromQuery]HotPortJoinOrgStatisticsRequest dto)
  493. {
  494. return await _orderRepository.HotPortJoinOrgStatistics(dto.StartTime, dto.EndTime);
  495. }
  496. /// <summary>
  497. /// 回访量统计
  498. /// </summary>
  499. /// <returns></returns>
  500. [HttpGet("visit-measure-statistics")]
  501. public async Task<List<VisitMeasureStatisticsDto>> VisitMeasureStatistics(DateTime StartDate,DateTime EndDate,string? VisitName)
  502. {
  503. EndDate = EndDate.AddDays(1).AddSeconds(-1);
  504. var list = await _orderVisitRepository.Queryable()
  505. .Includes(x => x.Employee)
  506. .Where(x => x.VisitTime >= StartDate && x.VisitTime <= EndDate && x.VisitState == EVisitState.Visited)
  507. .WhereIF(!string.IsNullOrEmpty(VisitName),x=>x.Employee.Name.Contains(VisitName))
  508. .GroupBy(x=> new { x.EmployeeId,x.Employee.Name })
  509. .Select(x=> new VisitMeasureStatisticsDto()
  510. {
  511. VisitName = x.Employee.Name,
  512. AiVisitCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitType== EVisitType.ChipVoiceVisit,1,0)),
  513. ArtificialVisitCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.VisitType == EVisitType.ArtificialVisit,1,0)),
  514. SumCount = SqlFunc.AggregateCount(x.EmployeeId)
  515. })
  516. .ToListAsync();
  517. return list;
  518. }
  519. /// <summary>
  520. /// 热点类型小类统计
  521. /// </summary>
  522. /// <param name="StartDate"></param>
  523. /// <param name="EndDate"></param>
  524. /// <param name="TypeId">0:全部 ,1:市民,2:企业</param>
  525. /// <returns></returns>
  526. [HttpGet("hotspot-statistics")]
  527. public async Task<object> HotspotStatistics(DateTime StartDate,DateTime EndDate,int TypeId,string? HotspotCode)
  528. {
  529. EndDate = EndDate.AddDays(1).AddSeconds(-1);
  530. if (string.IsNullOrEmpty(HotspotCode))
  531. {
  532. var list = await _hotspotTypeRepository.Queryable()
  533. .LeftJoin<Order>((it, o) => it.Id == o.HotspotId)
  534. .Where((it, o) => o.StartTime >= StartDate && o.StartTime <= EndDate && o.Id!=null)
  535. .WhereIF(TypeId==1,(it,o)=> o.IdentityType == EIdentityType.Citizen)
  536. .WhereIF(TypeId==2,(it,o)=> o.IdentityType == EIdentityType.Enterprise)
  537. .GroupBy((it, o) => new { Id = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")) })
  538. .Select((it, o) => new
  539. {
  540. HotspotCode = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>("2")),
  541. SumCount = SqlFunc.AggregateCount(it.HotSpotName)
  542. })
  543. .MergeTable()
  544. .LeftJoin<Hotspot>((x,q)=> x.HotspotCode == q.Id)
  545. .Select((x, q) => new {
  546. HotspotCode = x.HotspotCode,
  547. SumCount = x.SumCount,
  548. HotspotName = q.HotSpotName,
  549. HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.HotspotCode).Any()
  550. })
  551. .ToListAsync();
  552. return list;
  553. }
  554. else
  555. {
  556. string count = (HotspotCode.Length + 2).ToString();
  557. string countx = HotspotCode.Length.ToString();
  558. var list = await _hotspotTypeRepository.Queryable()
  559. .LeftJoin<Order>((it, o)=> it.Id == o.HotspotId)
  560. .Where((it, o) => o.StartTime >= StartDate && o.StartTime <= EndDate && it.ParentId.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(countx)) == HotspotCode)
  561. .WhereIF(TypeId == 1, (it, o) => o.IdentityType == EIdentityType.Citizen)
  562. .WhereIF(TypeId == 2, (it, o) => o.IdentityType == EIdentityType.Enterprise)
  563. .GroupBy((it, o) => new { Id = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)) })
  564. .Select((it, o) => new
  565. {
  566. HotspotCode = it.Id.Substring(SqlFunc.MappingColumn<int>("0"), SqlFunc.MappingColumn<int>(count)),
  567. SumCount = SqlFunc.AggregateCount(it.HotSpotName)
  568. })
  569. .MergeTable()
  570. .LeftJoin<Hotspot>((x, q) => x.HotspotCode == q.Id)
  571. .Select((x, q) => new
  572. {
  573. HotspotCode = x.HotspotCode,
  574. SumCount = x.SumCount,
  575. HotspotName = q.HotSpotName,
  576. HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.HotspotCode).Any()
  577. })
  578. .ToListAsync();
  579. return list;
  580. }
  581. }
  582. /// <summary>
  583. /// 部门满意度统计
  584. /// </summary>
  585. /// <param name="StartDate"></param>
  586. /// <param name="EndDate"></param>
  587. /// <param name="OrgName"></param>
  588. /// <param name="TypeId">1:办件结果 2:办件态度</param>
  589. /// <param name="LineNum"></param>
  590. /// <returns></returns>
  591. [HttpGet("visit-org-satisfaction-statistics")]
  592. public async Task<List<VisitAndOrgSatisfactionStatisticsDto>> VisitAndOrgSatisfactionStatistics(DateTime StartDate, DateTime EndDate, string OrgName, int TypeId, string? LineNum)
  593. {
  594. EndDate = EndDate.AddDays(1).AddSeconds(-1);
  595. var list = await _orderVisitDetailRepository.Queryable()
  596. .Includes(x => x.OrderVisit)
  597. .Where(x => x.OrderVisit.VisitTime >= StartDate && x.OrderVisit.VisitTime <= EndDate && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
  598. .WhereIF(!string.IsNullOrEmpty(OrgName), x => x.VisitOrgName.Contains(OrgName))
  599. .GroupBy(x => new { x.VisitOrgCode, x.VisitOrgName })
  600. .Select(x => new VisitAndOrgSatisfactionStatisticsDto()
  601. {
  602. OrgName = x.VisitOrgName,
  603. OrgCode = x.VisitOrgCode,
  604. TotalSumCount = SqlFunc.AggregateCount(x.VisitOrgCode),
  605. VerySatisfiedCount = SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonListObjectAny(x.OrgProcessingResults,"key","5"),1,0)),//非常满意数
  606. })
  607. .ToListAsync();
  608. return list;
  609. }
  610. }
  611. }