CallNativeRepository.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. using Hotline.CallCenter.Calls;
  2. using Hotline.Orders;
  3. using Hotline.Repository.SqlSugar.DataPermissions;
  4. using Hotline.Settings;
  5. using Hotline.Share.Dtos.CallCenter;
  6. using Hotline.Share.Enums.CallCenter;
  7. using Hotline.Share.Enums.Order;
  8. using Hotline.Share.Tools;
  9. using SqlSugar;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading.Tasks;
  15. using XF.Domain.Dependency;
  16. using XF.Domain.Repository;
  17. namespace Hotline.Repository.SqlSugar.CallCenter;
  18. public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepository, IScopeDependency
  19. {
  20. public CallNativeRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
  21. {
  22. }
  23. public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string source)
  24. {
  25. TimeSpan timeDifference = endDate.Value.Subtract(beginDate).Duration();
  26. int hourDiff = (int)(timeDifference.TotalHours);
  27. //计算时间差
  28. int hour = Convert.ToInt32((endDate - beginDate).Value.TotalHours);
  29. List<DateTime> dts = new List<DateTime>() { beginDate };
  30. for (int i = 0;i < hour - 1;i++)
  31. {
  32. dts.Add(dts.Last().AddHours(1));
  33. }
  34. var list = await Db.Reportable(dts).ToQueryable<DateTime>()
  35. .LeftJoin<CallNative>((it, o) => o.BeginIvrTime >= it.ColumnName && o.BeginIvrTime < it.ColumnName.AddHours(1) && o.Direction == ECallDirection.In && o.CallState != ECallState.Invalid)
  36. //.Where((it, o) => o.CallDirection == ECallDirection.In)
  37. .WhereIF(!string.IsNullOrEmpty(source), (it, o) => o.ToNo == source)
  38. .GroupBy((it, o) => it.ColumnName)
  39. .Select((it, o) => new TrCallHourDto()
  40. {
  41. DateTimeTo = it.ColumnName,
  42. Hour = it.ColumnName.Hour, //小时段
  43. EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null && o.Duration >= effectiveTimes, 1, 0)),//有效接通
  44. ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
  45. NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime == null && o.RingDuration <= noConnectByeTimes && o.RingDuration > 0, 1, 0)), //未接通秒挂
  46. QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallState == ECallState.NotAcceptedHang, 1, 0)), //队列挂断
  47. IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallState == ECallState.IVRNoAccept, 1, 0)), //IVR挂断
  48. })
  49. .MergeTable()
  50. .OrderBy(x => x.Hour)
  51. .ToListAsync();
  52. var resultList = list.GroupBy(x => x.Hour)
  53. .Select(x => new TrCallHourDto()
  54. {
  55. Hour = x.Key,
  56. HourTo = x.Key.ToString().PadLeft(2, '0') + ":00 - " + (x.Key).ToString().PadLeft(2, '0') + ":59",
  57. StartHourTo = x.Key.ToString().PadLeft(2, '0') + ":00",
  58. EndHourTo = x.Key.ToString().PadLeft(2, '0') + ":59",
  59. EffectiveCount = x.Sum(d => d.EffectiveCount),
  60. ConnectByeCount = x.Sum(d => d.ConnectByeCount),
  61. NoConnectByeCount = x.Sum(d => d.NoConnectByeCount),
  62. QueueByeCount = x.Sum(d => d.QueueByeCount),
  63. IvrByeCount = x.Sum(d => d.IvrByeCount),
  64. }).OrderBy(x => hour).ToList();
  65. return resultList;
  66. }
  67. public async Task<int> UpdateReplyTxtAsync(string callId, string replyTxt)
  68. {
  69. return await Updateable()
  70. .Where(m => m.Id == callId)
  71. .SetColumns(m => m.ReplyTxt, replyTxt)
  72. .ExecuteCommandAsync();
  73. }
  74. public async Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line)
  75. {
  76. List<int> dts = new List<int>();
  77. for (int i = 0;i < 24;i++)
  78. {
  79. dts.Add(i);
  80. }
  81. var listHour = Db.Reportable(dts).ToQueryable<int>();
  82. var list = Db.Queryable<CallNative>()
  83. .Where(p => p.BeginIvrTime >= beginDate && p.BeginIvrTime <= endDate && p.CallState != ECallState.Invalid)
  84. .WhereIF(!string.IsNullOrEmpty(Line), p => p.TelNo == Line)
  85. .GroupBy(p => p.BeginIvrTime.Value.Hour)
  86. .Select(p => new
  87. {
  88. Hour = p.BeginIvrTime.Value.Hour, //小时段
  89. InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In, 1, 0)),//呼入总量
  90. InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
  91. NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.RingDuration <= noConnectByeTimes && p.RingDuration > 0 && p.Direction == ECallDirection.In, 1, 0)), //未接通秒挂
  92. TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, p.Duration, 0)), //呼入总时长
  93. InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
  94. InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
  95. TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.RingDuration >= CallInOverConnRingTime, 1, 0)),//超时接通量
  96. TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
  97. QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.CallState == ECallState.NotAcceptedHang, 1, 0)), //队列挂断
  98. IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.CallState == ECallState.IVRNoAccept, 1, 0)), //IVR挂断
  99. OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.Out, 1, 0)),//呼出总量
  100. OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
  101. })
  102. .MergeTable();
  103. var listCall = await listHour.LeftJoin(list, (x, p) => x.ColumnName == p.Hour)
  104. .OrderBy(x => x.ColumnName)
  105. .Select((x, p) => new QueryCallsDetailDto()
  106. {
  107. Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
  108. InTotal = p.InTotal,
  109. InConnectionQuantity = p.InConnectionQuantity,
  110. NotAcceptedHang = p.NotAcceptedHang,
  111. TotalDurationIncomingCalls = p.TotalDurationIncomingCalls,
  112. InAvailableAnswer = p.InAvailableAnswer,
  113. InHangupImmediateWhenAnswered = p.InHangupImmediateWhenAnswered,
  114. TimeoutConnection = p.TimeoutConnection,
  115. TimeoutSuspension = p.TimeoutSuspension,
  116. QueueByeCount = p.QueueByeCount,
  117. IvrByeCount = p.IvrByeCount,
  118. OutTotal = p.OutTotal,
  119. OutConnectionQuantity = p.OutConnectionQuantity
  120. })
  121. .ToListAsync();
  122. return listCall;
  123. }
  124. /// <summary>
  125. /// 话务统计分析
  126. /// </summary>
  127. /// <param name="beginDate"></param>
  128. /// <param name="endDate"></param>
  129. /// <param name="Line"></param>
  130. /// <returns></returns>
  131. public async Task<List<BiCallDto>> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line)
  132. {
  133. List<int> dts = new List<int>();
  134. for (int i = 0;i < 24;i++)
  135. {
  136. dts.Add(i);
  137. }
  138. var listHour = Db.Reportable(dts).ToQueryable<int>();
  139. var list = Db.Queryable<CallNative>()
  140. .Where(p => p.BeginIvrTime >= beginDate && p.BeginIvrTime <= endDate && p.Direction == ECallDirection.In && p.CallState != ECallState.Invalid)
  141. .WhereIF(!string.IsNullOrEmpty(Line), p => p.ToNo == Line)
  142. .GroupBy(p => p.BeginIvrTime.Value.Hour)
  143. .Select(p => new
  144. {
  145. Hour = p.BeginIvrTime.Value.Hour, //小时段
  146. Total = SqlFunc.AggregateCount(p.Id),
  147. Answered = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime != null, 1, 0)), //应答数
  148. Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime == null &&
  149. (p.CallState == ECallState.Missed || p.CallState == ECallState.NotAcceptedHang || p.CallState == ECallState.IVRNoAccept), 1, 0)),//挂断数
  150. })
  151. // .GroupBy(p => p.Hour)
  152. .MergeTable();
  153. var listCall = await listHour.LeftJoin(list, (x, p) => x.ColumnName == p.Hour)
  154. .OrderBy(x => x.ColumnName)
  155. .Select((x, p) => new BiCallDto()
  156. {
  157. Hour = x.ColumnName,
  158. Total = p.Total,
  159. Answered = p.Answered,
  160. Hanguped = p.Hanguped,
  161. })
  162. .ToListAsync();
  163. foreach (var call in listCall)
  164. {
  165. call.HourRange = call.Hour.ToString().PadLeft(2, '0') + ":00 - " + (call.Hour + 1).ToString().PadLeft(2, '0') + ":00";
  166. }
  167. return listCall;
  168. }
  169. /// <summary>
  170. /// 通话时段统计明细
  171. /// </summary>
  172. /// <returns></returns>
  173. public async Task<TotalData<BiSeatSwitchDto>> GetCallList(QueryCallListDto dto, int noConnectByeTimes, int effectiveTimes, int connectByeTimes)
  174. {
  175. TimeSpan endHourTo = DateTime.Now.TimeOfDay;
  176. if (dto.StartHourTo.HasValue)
  177. {
  178. endHourTo = dto.StartHourTo.Value.Add(new TimeSpan(1, 0, 0));
  179. }
  180. RefAsync<int> total = 0;
  181. var res = await Db.Queryable<CallNative>()
  182. .Where(x => x.BeginIvrTime >= dto.StartTime && x.BeginIvrTime <= dto.EndTime)
  183. .Where(x => x.Direction == ECallDirection.In && x.CallState != ECallState.Invalid)
  184. .WhereIF(!string.IsNullOrEmpty(dto.Source), x => x.ToNo == dto.Source)
  185. .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("QueueBye".Equals(dto.Type) || "queueByeCount".Equals(dto.Type)), x => x.CallState == ECallState.NotAcceptedHang) //队列挂断
  186. .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("IvrBye".Equals(dto.Type) || "ivrByeCount".Equals(dto.Type)), x => x.CallState == ECallState.IVRNoAccept)//IVR挂断
  187. .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("Effective".Equals(dto.Type) || "effectiveCount".Equals(dto.Type)), x => x.AnsweredTime != null && x.Duration >= effectiveTimes) //有效接通
  188. .WhereIF(!string.IsNullOrEmpty(dto.Type) && "Invalid".Equals(dto.Type), x => x.AnsweredTime != null && x.Duration < effectiveTimes)//无效接通
  189. .WhereIF(!string.IsNullOrEmpty(dto.Type) && "connectByeCount".Equals(dto.Type), x => x.AnsweredTime != null && x.Duration <= connectByeTimes) //接通秒挂
  190. .WhereIF(!string.IsNullOrEmpty(dto.Type) && "noConnectByeCount".Equals(dto.Type), x => x.AnsweredTime == null && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0) //未接通秒挂
  191. .WhereIF(!string.IsNullOrEmpty(dto.Type) && "count".Equals(dto.Type), x =>
  192. (x.AnsweredTime == null && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0) //未接通秒挂
  193. || (x.AnsweredTime != null && x.Duration <= connectByeTimes) //接通秒挂
  194. || (x.AnsweredTime != null && x.Duration >= effectiveTimes)//有效接通
  195. || (x.CallState == ECallState.IVRNoAccept) //IVR挂断
  196. || (x.CallState == ECallState.NotAcceptedHang))//队列挂断
  197. .WhereIF(dto.StartHourTo.HasValue, x => SqlFunc.ToTime(x.BeginIvrTime.Value.ToString("HH:mm:ss")) >= dto.StartHourTo.Value && SqlFunc.ToTime(x.BeginIvrTime.Value.ToString("HH:mm:ss")) < endHourTo)
  198. .Select(x => new BiSeatSwitchDto
  199. {
  200. Id = x.Id,
  201. CPN = x.FromNo,
  202. CDPN = x.ToNo,
  203. CreatedTime = x.BeginIvrTime.Value
  204. })
  205. .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
  206. return new TotalData<BiSeatSwitchDto>(res, total.Value);
  207. }
  208. public async Task<List<CallHotLineDto>> GetCallHotLineListAsync(BiQueryGateWayDto dto, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int ringTims, List<string> hotLines)
  209. {
  210. var list = await Db.Queryable<CallNative>()
  211. .Where(x => x.BeginIvrTime >= dto.StartTime && x.BeginIvrTime <= dto.EndTime && SqlFunc.Length(x.ToNo) > 4 && x.CallState != ECallState.Invalid)
  212. .Where(x => hotLines.Contains(x.ToNo))
  213. .WhereIF(!string.IsNullOrEmpty(dto.Gateway), x => x.ToNo == dto.Gateway)
  214. .GroupBy(x => x.ToNo)
  215. .Select(x => new CallHotLineDto()
  216. {
  217. GateWay = x.ToNo,
  218. CallInCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In, 1, 0)),//呼入
  219. ConnectCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.AnsweredTime != null, 1, 0)),//接通
  220. NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.Duration == 0 && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0, 1, 0)), //未接通秒挂
  221. EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.Duration >= effectiveTimes, 1, 0)),//有效接通
  222. DurationSum = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.AnsweredTime != null, x.Duration, 0)),//通话总时长
  223. ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.Duration > 0 && x.Duration <= connectByeTimes, 1, 0)), //接通秒挂
  224. TimelyAnswerCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.Direction == ECallDirection.In && x.AnsweredTime != null && x.RingDuration <= ringTims, 1, 0))//及时应答
  225. }).ToListAsync();
  226. return list;
  227. }
  228. }