BiCallController.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. using Hotline.Application.ExportExcel;
  2. using Hotline.Application.StatisticalReport;
  3. using Hotline.Application.Systems;
  4. using Hotline.Caching.Interfaces;
  5. using Hotline.CallCenter.Calls;
  6. using Hotline.CallCenter.Tels;
  7. using Hotline.Share.Dtos;
  8. using Hotline.Share.Dtos.CallCenter;
  9. using Hotline.Share.Dtos.Order;
  10. using Hotline.Share.Dtos.TrCallCenter;
  11. using Hotline.Share.Requests;
  12. using Hotline.Tools;
  13. using Hotline.Users;
  14. using MapsterMapper;
  15. using Microsoft.AspNetCore.Authorization;
  16. using Microsoft.AspNetCore.Mvc;
  17. using SqlSugar;
  18. using System.Data;
  19. using XF.Domain.Repository;
  20. namespace Hotline.Api.Controllers.Bi;
  21. /// <summary>
  22. /// 话务报表
  23. /// </summary>
  24. public class BiCallController : BaseController
  25. {
  26. private readonly IRepository<TrCallRecord> _trCallRecordRepository;
  27. private readonly BaseDataApplication _baseDataApplication;
  28. private readonly IRepository<User> _userRepository;
  29. private readonly IRepository<TelRest> _telRestRepository;
  30. private readonly IMapper _mapper;
  31. private readonly ISystemSettingCacheManager _systemSettingCacheManager;
  32. private readonly IRepository<Work> _workRepository;
  33. private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
  34. private readonly ICallReportApplication _callReportApplication;
  35. private readonly IExportApplication _exportApplication;
  36. public BiCallController(
  37. IRepository<TrCallRecord> trCallRecordRepository,
  38. IRepository<User> userRepository,
  39. IRepository<TelRest> telRestRepository,
  40. IMapper mapper,
  41. ISystemSettingCacheManager systemSettingCacheManager,
  42. ISystemDicDataCacheManager sysDicDataCacheManager,
  43. IRepository<Work> workRepository,
  44. ICallReportApplication callReportApplication,
  45. IExportApplication exportApplication,
  46. BaseDataApplication baseDataApplication)
  47. {
  48. _trCallRecordRepository = trCallRecordRepository;
  49. _userRepository = userRepository;
  50. _telRestRepository = telRestRepository;
  51. _mapper = mapper;
  52. _systemSettingCacheManager = systemSettingCacheManager;
  53. _workRepository = workRepository;
  54. _sysDicDataCacheManager = sysDicDataCacheManager;
  55. _callReportApplication = callReportApplication;
  56. _exportApplication = exportApplication;
  57. _baseDataApplication = baseDataApplication;
  58. }
  59. /// <summary>
  60. /// 话务统计分析
  61. /// </summary>
  62. /// <param name="dto"></param>
  63. /// <returns></returns>
  64. [HttpGet("calls")]
  65. [AllowAnonymous]
  66. public async Task<List<BiCallDto>> QueryCallsAsync([FromQuery] BiQueryCallsDto dto)
  67. => await _callReportApplication.QueryCallsAsync(dto, HttpContext.RequestAborted);
  68. /// <summary>
  69. /// 话务统计分析---导出
  70. /// </summary>
  71. /// <param name="dto"></param>
  72. /// <returns></returns>
  73. [HttpPost("calls_export")]
  74. [AllowAnonymous]
  75. public async Task<FileStreamResult> ExportQueryCallsAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
  76. => ExcelStreamResult(
  77. await _exportApplication.FittingAsync(
  78. dto,
  79. await _callReportApplication.QueryCallsAsync(dto.QueryDto, HttpContext.RequestAborted),
  80. list =>
  81. {
  82. list.Add(new BiCallDto()
  83. {
  84. HourRange = "合计",
  85. Hour = 13,
  86. Total = list.Sum(p => p.Total),
  87. Answered = list.Sum(p => p.Answered),
  88. Hanguped = list.Sum(p => p.Hanguped)
  89. });
  90. }),
  91. "话务统计分析");
  92. /// <summary>
  93. /// 话务日期明细
  94. /// </summary>
  95. /// <param name="dto"></param>
  96. /// <returns></returns>
  97. [HttpGet("query_calls_detail")]
  98. public async Task<object> QueryCallsDetailAsync([FromQuery] BiQueryCallsDto dto)
  99. {
  100. var items = await _callReportApplication.QueryCallsDetailAsync(dto);
  101. var total = new QueryCallsDetailDto
  102. {
  103. Date = "合计",
  104. Hour = "",
  105. InTotal = items.Sum(p => p.InTotal),
  106. InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
  107. NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
  108. TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
  109. InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
  110. InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
  111. TimeoutConnection = items.Sum(p => p.TimeoutConnection),
  112. TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
  113. QueueByeCount = items.Sum(p => p.QueueByeCount),
  114. IvrByeCount = items.Sum(p => p.IvrByeCount),
  115. OutTotal = items.Sum(p => p.OutTotal),
  116. OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
  117. };
  118. return new { List = items, Total = total };
  119. }
  120. /// <summary>
  121. /// 话务日期明细--导出
  122. /// </summary>
  123. /// <param name="dto"></param>
  124. /// <returns></returns>
  125. [HttpPost("query_calls_detail_export")]
  126. public async Task<FileStreamResult> QueryCallsDetailExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
  127. {
  128. return ExcelStreamResult(
  129. await _exportApplication.FittingAsync(
  130. dto,
  131. await _callReportApplication.QueryCallsDetailAsync(dto.QueryDto),
  132. items =>
  133. {
  134. var total = new QueryCallsDetailDto
  135. {
  136. Date = "合计",
  137. Hour = "",
  138. InTotal = items.Sum(p => p.InTotal),
  139. InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
  140. NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
  141. TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
  142. InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
  143. InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
  144. TimeoutConnection = items.Sum(p => p.TimeoutConnection),
  145. TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
  146. QueueByeCount = items.Sum(p => p.QueueByeCount),
  147. IvrByeCount = items.Sum(p => p.IvrByeCount),
  148. OutTotal = items.Sum(p => p.OutTotal),
  149. OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
  150. };
  151. items.Add(total);
  152. }
  153. )
  154. , "话务日期明细数据");
  155. }
  156. /// <summary>
  157. /// 话务日期明细--呼入明细
  158. /// </summary>
  159. /// <param name="dto"></param>
  160. /// <returns></returns>
  161. [HttpGet("query_incall_calls_list")]
  162. public async Task<PagedDto<CallRecordOutDto>> GetInCallCallListAsync([FromQuery] BiQueryCallsDto dto)
  163. {
  164. var (total, items) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto, false);
  165. return new PagedDto<CallRecordOutDto>(total, items);
  166. }
  167. /// <summary>
  168. /// 话务日期明细----导出
  169. /// </summary>
  170. /// <param name="dto"></param>
  171. /// <returns></returns>
  172. [HttpPost("query_incall_calls_list_export")]
  173. public async Task<FileStreamResult> GetInCallCallListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
  174. {
  175. var (total, data) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto, dto.IsExportAll);
  176. dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
  177. var dtos = data
  178. .Select(stu => _mapper.Map(stu, typeof(CallRecordOutDto), dynamicClass))
  179. .Cast<object>()
  180. .ToList();
  181. var stream = ExcelHelper.CreateStream(dtos);
  182. return ExcelStreamResult(
  183. await _exportApplication.FittingAsync(
  184. dto,
  185. (await _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto, dto.IsExportAll)).Item2
  186. ),
  187. dto.QueryDto.TypeCode == "2" ? "话务日期-接通明细数据" : "话务日期-总量明细数据");
  188. }
  189. /// <summary>
  190. /// 话务日期明细--时间段
  191. /// </summary>
  192. /// <param name="dto"></param>
  193. /// <returns></returns>
  194. [HttpGet("query_calls_hour_detail_list")]
  195. public async Task<TotalList<QueryCallsDetailDto>> QueryCallsHourDetailListAsync([FromQuery] BiQueryCallsDto dto)
  196. {
  197. var items = await _callReportApplication.QueryCallsHourDetailAsync(dto, HttpContext.RequestAborted);
  198. var total = new QueryCallsDetailDto
  199. {
  200. Date = "",
  201. Hour = "合计",
  202. InTotal = items.Sum(p => p.InTotal),
  203. InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
  204. NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
  205. TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
  206. InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
  207. InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
  208. TimeoutConnection = items.Sum(p => p.TimeoutConnection),
  209. TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
  210. QueueByeCount = items.Sum(p => p.QueueByeCount),
  211. IvrByeCount = items.Sum(p => p.IvrByeCount),
  212. OutTotal = items.Sum(p => p.OutTotal),
  213. OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
  214. };
  215. return new TotalList<QueryCallsDetailDto>(items, total);
  216. }
  217. /// <summary>
  218. /// 话务日期明细--时间段--导出
  219. /// </summary>
  220. /// <param name="dto"></param>
  221. /// <returns></returns>
  222. [HttpPost("query_calls_hour_detail_list_export")]
  223. public async Task<FileStreamResult> QueryCallsHourDetailListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
  224. => ExcelStreamResult(
  225. await _exportApplication.FittingAsync(
  226. dto,
  227. await _callReportApplication.QueryCallsHourDetailAsync(dto.QueryDto, HttpContext.RequestAborted),
  228. items =>
  229. {
  230. var total = new QueryCallsDetailDto
  231. {
  232. Date = "",
  233. Hour = "合计",
  234. InTotal = items.Sum(p => p.InTotal),
  235. InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
  236. NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
  237. TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
  238. InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
  239. InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
  240. TimeoutConnection = items.Sum(p => p.TimeoutConnection),
  241. TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
  242. QueueByeCount = items.Sum(p => p.QueueByeCount),
  243. IvrByeCount = items.Sum(p => p.IvrByeCount),
  244. OutTotal = items.Sum(p => p.OutTotal),
  245. OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
  246. };
  247. items.Add(total);
  248. })
  249. , "话务日期明细-时间段");
  250. /// <summary>
  251. /// 坐席话务统计分析
  252. /// </summary>
  253. /// <param name="dto"></param>
  254. /// <returns></returns>
  255. [HttpPost("seats/export")]
  256. public async Task<FileStreamResult> ExportSeatss([FromBody] ExportExcelDto<ReportRequiredPagedRequest> dto)
  257. {
  258. return ExcelStreamResult(
  259. await _exportApplication.FittingAsync(
  260. dto,
  261. await _callReportApplication.QuerySeatCallAsync(dto.QueryDto, HttpContext.RequestAborted),
  262. list =>
  263. {
  264. list.Add(new BiSeatCallsDto()
  265. {
  266. Name = "合计",
  267. InTotal = list.Sum(p => p.InTotal),
  268. InAnswered = list.Sum(p => p.InAnswered),
  269. InHangupImmediate = list.Sum(p => p.InHangupImmediate),
  270. InHanguped = list.Sum(m => m.InHanguped),
  271. OutDurationAvg = list.Sum(m => m.OutDurationAvg),
  272. InAvailableAnswer = list.Sum(m => m.InAvailableAnswer),
  273. InHangupImmediateWhenAnswered = list.Sum(m => m.InHangupImmediateWhenAnswered),
  274. OutTotal = list.Sum(m => m.OutTotal),
  275. OutAnswered = list.Sum(m => m.OutAnswered),
  276. LoginDuration = list.Sum(m => m.LoginDuration),
  277. RestDuration = list.Sum(m => m.RestDuration),
  278. InDurationAvg = list.Sum(m => m.InDurationAvg)
  279. });
  280. })
  281. , "坐席话务统计分析");
  282. }
  283. /// <summary>
  284. /// 坐席话务统计分析
  285. /// </summary>
  286. /// <param name="dto"></param>
  287. /// <returns></returns>
  288. [HttpGet("seats")]
  289. [AllowAnonymous]
  290. public async Task<IReadOnlyList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportRequiredPagedRequest dto)
  291. => await _callReportApplication.QuerySeatCallAsync(dto, HttpContext.RequestAborted);
  292. /// <summary>
  293. /// 小休统计
  294. /// </summary>
  295. /// <param name="dto"></param>
  296. /// <returns></returns>
  297. [HttpGet("rests")]
  298. [AllowAnonymous]
  299. public async Task<IReadOnlyList<BiSeatRestDto>> QuerySeatRest([FromQuery] QuerySeatRestRequest dto)
  300. {
  301. return await _telRestRepository.Queryable()
  302. .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
  303. .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), x => x.StaffNo.Contains(dto.StaffNo))
  304. .Where(x => x.CreationTime >= dto.StartTime)
  305. .Where(x => x.CreationTime <= dto.EndTime)
  306. .GroupBy(x => new { x.UserId, x.StaffNo, x.UserName })
  307. .Select(x => new BiSeatRestDto
  308. {
  309. UserId = x.UserId,
  310. StaffNo = x.StaffNo,
  311. UserName = x.UserName,
  312. RestCount = SqlFunc.AggregateCount(x.Id),
  313. RestDuration = SqlFunc.AggregateSum(x.RestDuration / 60) / SqlFunc.AggregateCount(x.Id),
  314. CumulativeDuration = SqlFunc.AggregateSum(x.RestDuration / 60)
  315. })
  316. .OrderByIF(dto.SortRule is 0, a => a.RestDuration, OrderByType.Asc)
  317. .OrderByIF(dto.SortRule is 1, a => a.RestDuration, OrderByType.Desc)
  318. .MergeTable()
  319. .ToListAsync(HttpContext.RequestAborted);
  320. }
  321. /// <summary>
  322. /// 坐席转接统计
  323. /// </summary>
  324. /// <param name="dto"></param>
  325. /// <returns></returns>
  326. [HttpGet("seatswitch")]
  327. [AllowAnonymous]
  328. public async Task<PagedDto<BiSeatSwitchDto>> QuerySeatSwitch([FromQuery] QuerySeatSwitchRequest dto)
  329. {
  330. var (total, items) = await _callReportApplication.QuerySeatSwitchAsync(dto, HttpContext.RequestAborted);
  331. return new PagedDto<BiSeatSwitchDto>(total, items);
  332. }
  333. /// <summary>
  334. /// 小时统计
  335. /// </summary>
  336. /// <returns></returns>
  337. [HttpGet("hourcall")]
  338. [AllowAnonymous]
  339. public async Task<List<TrCallHourDto>> QueryHourCall([FromQuery] BiQueryHourCallDto dto)
  340. => await _callReportApplication.GetCallHourListAsync(dto, HttpContext.RequestAborted);
  341. /// <summary>
  342. /// 小时统计--导出
  343. /// </summary>
  344. /// <returns></returns>
  345. [HttpPost("hourcall/export")]
  346. [AllowAnonymous]
  347. public async Task<FileStreamResult> ExportQueryHourCall([FromBody] ExportExcelDto<BiQueryHourCallDto> dto)
  348. => ExcelStreamResult(
  349. await _exportApplication.FittingAsync(
  350. dto,
  351. await _callReportApplication.GetCallHourListAsync(dto.QueryDto, HttpContext.RequestAborted),
  352. list =>
  353. {
  354. list.Add(new TrCallHourDto()
  355. {
  356. HourTo = "合计",
  357. EffectiveCount = list.Sum(p => p.EffectiveCount),
  358. ConnectByeCount = list.Sum(p => p.ConnectByeCount),
  359. NoConnectByeCount = list.Sum(p => p.NoConnectByeCount),
  360. QueueByeCount = list.Sum(m => m.QueueByeCount),
  361. IvrByeCount = list.Sum(m => m.IvrByeCount)
  362. });
  363. })
  364. , "通话时段分析");
  365. /// <summary>
  366. /// 通话时段统计明细
  367. /// </summary>
  368. /// <returns></returns>
  369. [HttpGet("hourcall_list")]
  370. public async Task<object> QueryCallList([FromQuery] QueryCallListDto dto)
  371. => await _callReportApplication.GetCallListAsync(dto, HttpContext.RequestAborted);
  372. /// <summary>
  373. /// 通话时段统计明细获取基本信息
  374. /// </summary>
  375. /// <param name="id"></param>
  376. /// <returns></returns>
  377. [HttpGet("hourcall_list_base")]
  378. public async Task<object> ReTransactBaseData()
  379. => _baseDataApplication
  380. .CallForwardingType()
  381. .CallForwardingSource()
  382. .Build();
  383. /// <summary>
  384. /// 热线号码统计
  385. /// </summary>
  386. /// <param name="StartTime"></param>
  387. /// <param name="EndTime"></param>
  388. /// <returns></returns>
  389. [AllowAnonymous]
  390. [HttpGet("gateway-query")]
  391. public async Task<List<CallHotLineDto>> QueryGateWay([FromQuery] BiQueryGateWayDto dto)
  392. => await _callReportApplication.GetCallHotLineListAsync(dto, HttpContext.RequestAborted);
  393. /// <summary>
  394. /// 热线号码统计导出
  395. /// </summary>
  396. /// <param name="dto"></param>
  397. /// <returns></returns>
  398. [HttpPost("gateway-query/export")]
  399. public async Task<FileStreamResult> ExportQueryGatetWay(ExportExcelDto<BiQueryGateWayDto> dto)
  400. => ExcelStreamResult(
  401. await _exportApplication.FittingAsync(
  402. dto,
  403. await _callReportApplication.GetCallHotLineListAsync(dto.QueryDto, HttpContext.RequestAborted)
  404. )
  405. , "热线号码统计");
  406. }