qinchaoyue 6 hónapja
szülő
commit
527407deb6
23 módosított fájl, 1091 hozzáadás és 581 törlés
  1. 137 367
      src/Hotline.Api/Controllers/Bi/BiCallController.cs
  2. 51 0
      src/Hotline.Application.Tests/Application/YiBinCallReportApplicationTest.cs
  3. 45 0
      src/Hotline.Application.Tests/Application/ZiGongCallReportApplicationTest.cs
  4. 3 0
      src/Hotline.Application.Tests/Startup.cs
  5. 156 21
      src/Hotline.Application/StatisticalReport/CallReport/CallReportApplicationBase.cs
  6. 9 6
      src/Hotline.Application/StatisticalReport/CallReport/LuZhouCallReportApplication.cs
  7. 91 20
      src/Hotline.Application/StatisticalReport/CallReport/YiBinCallReportApplication.cs
  8. 9 1
      src/Hotline.Application/StatisticalReport/CallReport/ZiGongCallReportApplication.cs
  9. 143 143
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  10. 38 0
      src/Hotline.Application/StatisticalReport/ExportApplication.cs
  11. 9 2
      src/Hotline.Application/StatisticalReport/ICallReportApplication.cs
  12. 14 0
      src/Hotline.Application/StatisticalReport/IExportApplication.cs
  13. 151 0
      src/Hotline.Repository.SqlSugar/CallCenter/CallNativeRepository.cs
  14. 2 2
      src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs
  15. 45 5
      src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs
  16. 127 1
      src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs
  17. 1 0
      src/Hotline.Share/Enums/CallCenter/EOnState.cs
  18. 34 4
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  19. 5 1
      src/Hotline/Caching/Interfaces/ISystemSettingCacheManager.cs
  20. 12 0
      src/Hotline/Caching/Services/SystemSettingCacheManager.cs
  21. 4 1
      src/Hotline/CallCenter/Calls/CallNative.cs
  22. 4 6
      src/Hotline/CallCenter/Calls/ICallNativeRepository.cs
  23. 1 1
      src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs

+ 137 - 367
src/Hotline.Api/Controllers/Bi/BiCallController.cs

@@ -33,11 +33,11 @@ public class BiCallController : BaseController
     private readonly IRepository<User> _userRepository;
     private readonly IRepository<TelRest> _telRestRepository;
     private readonly IMapper _mapper;
-    private readonly ITrCallRecordRepository _trCallRecordRepositoryEx;
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly IRepository<Work> _workRepository;
     private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
     private readonly ICallReportApplication _callReportApplication;
+    private readonly IExportApplication _exportApplication;
 
 
 
@@ -46,22 +46,21 @@ public class BiCallController : BaseController
         IRepository<User> userRepository,
         IRepository<TelRest> telRestRepository,
         IMapper mapper,
-        ITrCallRecordRepository trCallRecordRepositoryEx,
         ISystemSettingCacheManager systemSettingCacheManager,
         ISystemDicDataCacheManager sysDicDataCacheManager,
         IRepository<Work> workRepository,
-        ICallReportApplication callReportApplication)
+        ICallReportApplication callReportApplication,
+        IExportApplication exportApplication)
     {
         _trCallRecordRepository = trCallRecordRepository;
         _userRepository = userRepository;
         _telRestRepository = telRestRepository;
         _mapper = mapper;
-        _trCallRecordRepositoryEx = trCallRecordRepositoryEx;
         _systemSettingCacheManager = systemSettingCacheManager;
         _workRepository = workRepository;
         _sysDicDataCacheManager = sysDicDataCacheManager;
         _callReportApplication = callReportApplication;
-
+        _exportApplication = exportApplication;
     }
 
     /// <summary>
@@ -72,56 +71,7 @@ public class BiCallController : BaseController
     [HttpGet("calls")]
     [AllowAnonymous]
     public async Task<List<BiCallDto>> QueryCallsAsync([FromQuery] BiQueryCallsDto dto)
-    {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-        #region 注释
-        //var items = await _trCallRecordRepository.Queryable()
-        //    .Where(d => d.CreatedTime >= dto.StartTime && d.CreatedTime <= dto.EndTime)
-        //    .Where(d => d.CallDirection == ECallDirection.In)
-        //    .WhereIF(!string.IsNullOrEmpty(dto.Line), d => d.Gateway == dto.Line)
-        //    .Select(d => new
-        //    {
-        //        d.CreatedTime.Year,
-        //        d.CreatedTime.Month,
-        //        d.CreatedTime.Day,
-        //        d.CreatedTime.Hour,
-        //        d.AnsweredTime,
-        //        d.EndBy
-        //    })
-        //    .MergeTable()
-        //    .GroupBy(d => new
-        //    {
-        //        d.Year,
-        //        d.Month,
-        //        d.Day,
-        //        d.Hour
-        //    })
-        //    .Select(d => new BiCallDto
-        //    {
-        //        Hour = d.Hour,
-        //        Total = SqlFunc.AggregateCount(d.Hour),
-        //        Answered = SqlFunc.AggregateSum(SqlFunc.IIF(d.AnsweredTime != null, 1, 0)),
-        //        Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(d.AnsweredTime == null && d.EndBy != null && d.EndBy.Value == EEndBy.To, 1, 0))
-        //    })
-        //    .OrderBy(d => d.Hour)
-        //    .ToListAsync(HttpContext.RequestAborted);
-
-        //if (items.Count < 24)
-        //{
-        //    for (var i = 0; i < 24; i++)
-        //    {
-        //        var item = items.FirstOrDefault(d => d.Hour == i);
-        //        if (item is null)
-        //            items.Add(new BiCallDto { Hour = i });
-        //    }
-
-        //    items = items.OrderBy(d => d.Hour).ToList();
-        //}
-        #endregion
-
-        return await _trCallRecordRepositoryEx.GetQueryCalls(dto.StartTime.Value, dto.EndTime.Value, dto.Keyword);
-
-    }
+        =>  await _callReportApplication.QueryCallsAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 话务统计分析---导出
@@ -131,35 +81,22 @@ public class BiCallController : BaseController
     [HttpPost("calls_export")]
     [AllowAnonymous]
     public async Task<FileStreamResult> ExportQueryCallsAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
-    {
-        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-
-        var list = await _trCallRecordRepositoryEx.GetQueryCalls(dto.QueryDto.StartTime.Value, dto.QueryDto.EndTime.Value, dto.QueryDto.Keyword);
-
-        if (list != null && list.Count > 0)
-        {
-            list.Add(new BiCallDto()
-            {
-                HourRange = "合计",
-                Hour = 13,
-                Total = list.Sum(p => p.Total),
-                Answered = list.Sum(p => p.Answered),
-                Hanguped = list.Sum(p => p.Hanguped)
-            });
-        }
-
-
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-        var dtos = list
-            .Select(stu => _mapper.Map(stu, typeof(BiCallDto), dynamicClass))
-            .Cast<object>()
-            .ToList();
-
-        var stream = ExcelHelper.CreateStream(dtos);
-
-        return ExcelStreamResult(stream, "话务统计分析");
-    }
+        => ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+                dto,
+                await _callReportApplication.QueryCallsAsync(dto.QueryDto, HttpContext.RequestAborted),
+                list => 
+                {
+                    list.Add(new BiCallDto()
+                    {
+                        HourRange = "合计",
+                        Hour = 13,
+                        Total = list.Sum(p => p.Total),
+                        Answered = list.Sum(p => p.Answered),
+                        Hanguped = list.Sum(p => p.Hanguped)
+                    });
+                }),
+            "话务统计分析");
 
     /// <summary>
     /// 话务日期明细
@@ -169,9 +106,6 @@ public class BiCallController : BaseController
     [HttpGet("query_calls_detail")]
     public async Task<object> QueryCallsDetailAsync([FromQuery] BiQueryCallsDto dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
         var items = await _callReportApplication.QueryCallsDetailAsync(dto);
 
         var total = new QueryCallsDetailDto
@@ -204,40 +138,32 @@ public class BiCallController : BaseController
     [HttpPost("query_calls_detail_export")]
     public async Task<FileStreamResult> QueryCallsDetailExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
     {
-        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        var items = await _callReportApplication.QueryCallsDetailAsync(dto.QueryDto);
-
-        var total = new QueryCallsDetailDto
-        {
-            Date = "合计",
-            Hour = "",
-            InTotal = items.Sum(p => p.InTotal),
-            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
-            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
-            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
-            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
-            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
-            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
-            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
-            QueueByeCount = items.Sum(p => p.QueueByeCount),
-            IvrByeCount = items.Sum(p => p.IvrByeCount),
-            OutTotal = items.Sum(p => p.OutTotal),
-            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
-        };
-        items.Add(total);
-
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-        var dtos = items
-            .Select(stu => _mapper.Map(stu, typeof(QueryCallsDetailDto), dynamicClass))
-            .Cast<object>()
-            .ToList();
-
-        var stream = ExcelHelper.CreateStream(dtos);
-
-        return ExcelStreamResult(stream, "话务日期明细数据");
+        return ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+                dto,
+                await _callReportApplication.QueryCallsDetailAsync(dto.QueryDto),
+                items => { 
+                    var total = new QueryCallsDetailDto
+                    {
+                        Date = "合计",
+                        Hour = "",
+                        InTotal = items.Sum(p => p.InTotal),
+                        InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+                        NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+                        TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+                        InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+                        InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+                        TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+                        TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+                        QueueByeCount = items.Sum(p => p.QueueByeCount),
+                        IvrByeCount = items.Sum(p => p.IvrByeCount),
+                        OutTotal = items.Sum(p => p.OutTotal),
+                        OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+                    };
+                    items.Add(total);
+                    }
+                )
+            , "话务日期明细数据");
 
     }
 
@@ -247,12 +173,10 @@ public class BiCallController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("query_incall_calls_list")]
-    public async Task<PagedDto<TrCallDtoNew>> GetInCallCallListAsync([FromQuery] BiQueryCallsDto dto)
+    public async Task<PagedDto<CallRecordOutDto>> GetInCallCallListAsync([FromQuery] BiQueryCallsDto dto)
     {
-        var (total, items) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-
-        return new PagedDto<TrCallDtoNew>(total, _mapper.Map<IReadOnlyList<TrCallDtoNew>>(items));
+        var (total, items) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto, false);
+        return new PagedDto<CallRecordOutDto>(total, items);
     }
 
     /// <summary>
@@ -263,32 +187,24 @@ public class BiCallController : BaseController
     [HttpPost("query_incall_calls_list_export")]
     public async Task<FileStreamResult> GetInCallCallListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
     {
-        var query = _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto);
-        List<TrCallRecord> data;
-        if (dto.IsExportAll)
-        {
-            data = await query.ToListAsync(HttpContext.RequestAborted);
-        }
-        else
-        {
-            var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-            data = items;
-        }
-
-        var dataDtos = _mapper.Map<ICollection<TrCallDtoNew>>(data);
+        var (total, data) = await _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto, dto.IsExportAll);
 
         dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
 
-        var dtos = dataDtos
-            .Select(stu => _mapper.Map(stu, typeof(TrCallDtoNew), dynamicClass))
+        var dtos = data
+            .Select(stu => _mapper.Map(stu, typeof(CallRecordOutDto), dynamicClass))
             .Cast<object>()
             .ToList();
 
         var stream = ExcelHelper.CreateStream(dtos);
 
-        string name = dto.QueryDto.TypeCode == "2" ? "话务日期-接通明细数据" : "话务日期-总量明细数据";
 
-        return ExcelStreamResult(stream, name);
+        return ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+            dto,
+            (await _callReportApplication.QueryCallsDetailInTotalAsync(dto.QueryDto, dto.IsExportAll)).Item2
+            ),
+            dto.QueryDto.TypeCode == "2" ? "话务日期-接通明细数据" : "话务日期-总量明细数据");
 
     }
 
@@ -298,26 +214,9 @@ public class BiCallController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet("query_calls_hour_detail_list")]
-    public async Task<object> QueryCallsHourDetailListAsync([FromQuery] BiQueryCallsDto dto)
+    public async Task<TotalDataList<QueryCallsDetailDto>> QueryCallsHourDetailListAsync([FromQuery] BiQueryCallsDto dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        //超时接通量
-        int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
-        //坐席超时挂断时间
-        int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
-
-        //未接秒挂时间
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        //呼入有效时间
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        //接通秒挂时间
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
-
-        var items = await _trCallRecordRepositoryEx.QueryCallsHourDetail(dto.StartTime.Value, dto.EndTime.Value, noConnectByeTimes, effectiveTimes
-              , connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.Keyword);
-
+        var items =  await _callReportApplication.QueryCallsHourDetailAsync(dto, HttpContext.RequestAborted);
         var total = new QueryCallsDetailDto
         {
             Date = "",
@@ -336,7 +235,7 @@ public class BiCallController : BaseController
             OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
         };
 
-        return new { List = items, Total = total };
+        return new TotalDataList<QueryCallsDetailDto>(items, total);
 
     }
 
@@ -347,57 +246,33 @@ public class BiCallController : BaseController
     /// <returns></returns>
     [HttpPost("query_calls_hour_detail_list_export")]
     public async Task<FileStreamResult> QueryCallsHourDetailListExportAsync([FromBody] ExportExcelDto<BiQueryCallsDto> dto)
-    {
-        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        //超时接通量
-        int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
-        //坐席超时挂断时间
-        int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
-
-        //未接秒挂时间
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        //呼入有效时间
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        //接通秒挂时间
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        => ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+                dto, 
+                await _callReportApplication.QueryCallsHourDetailAsync(dto.QueryDto, HttpContext.RequestAborted),
+                items => 
+                { 
+                    var total = new QueryCallsDetailDto
+                    {
+                        Date = "",
+                        Hour = "合计",
+                        InTotal = items.Sum(p => p.InTotal),
+                        InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
+                        NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
+                        TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
+                        InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
+                        InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
+                        TimeoutConnection = items.Sum(p => p.TimeoutConnection),
+                        TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
+                        QueueByeCount = items.Sum(p => p.QueueByeCount),
+                        IvrByeCount = items.Sum(p => p.IvrByeCount),
+                        OutTotal = items.Sum(p => p.OutTotal),
+                        OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
+                    };
+                    items.Add(total);
+                })
+            , "话务日期明细-时间段");
 
-        var items = await _trCallRecordRepositoryEx.QueryCallsHourDetail(dto.QueryDto.StartTime.Value, dto.QueryDto.EndTime.Value, noConnectByeTimes, effectiveTimes
-              , connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.QueryDto.Keyword);
-
-        var total = new QueryCallsDetailDto
-        {
-            Date = "",
-            Hour = "合计",
-            InTotal = items.Sum(p => p.InTotal),
-            InConnectionQuantity = items.Sum(p => p.InConnectionQuantity),
-            NotAcceptedHang = items.Sum(p => p.NotAcceptedHang),
-            TotalDurationIncomingCalls = items.Sum(p => p.TotalDurationIncomingCalls),
-            InAvailableAnswer = items.Sum(p => p.InAvailableAnswer),
-            InHangupImmediateWhenAnswered = items.Sum(p => p.InHangupImmediateWhenAnswered),
-            TimeoutConnection = items.Sum(p => p.TimeoutConnection),
-            TimeoutSuspension = items.Sum(p => p.TimeoutSuspension),
-            QueueByeCount = items.Sum(p => p.QueueByeCount),
-            IvrByeCount = items.Sum(p => p.IvrByeCount),
-            OutTotal = items.Sum(p => p.OutTotal),
-            OutConnectionQuantity = items.Sum(p => p.OutConnectionQuantity)
-        };
-
-        items.Add(total);
-
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-        var dtos = items
-            .Select(stu => _mapper.Map(stu, typeof(QueryCallsDetailDto), dynamicClass))
-            .Cast<object>()
-            .ToList();
-
-        var stream = ExcelHelper.CreateStream(dtos);
-
-        return ExcelStreamResult(stream, "话务日期明细-时间段");
-
-    }
 
     /// <summary>
     /// 坐席话务统计分析
@@ -405,42 +280,32 @@ public class BiCallController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpPost("seats/export")]
-    public async Task<FileStreamResult> ExportSeatss([FromBody] ExportExcelDto<ReportPagedRequest> dto)
+    public async Task<FileStreamResult> ExportSeatss([FromBody] ExportExcelDto<ReportRequiredPagedRequest> dto)
     {
-        if (!dto.QueryDto.StartTime.HasValue || !dto.QueryDto.EndTime.HasValue) 
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        var list =  await _callReportApplication.QuerySeatCallAsync(dto.QueryDto);
-        if (list != null && list.Count > 0)
-        {
-            list.Add(new BiSeatCallsDto()
-            {
-                Name = "合计",
-                InTotal = list.Sum(p => p.InTotal),
-                InAnswered = list.Sum(p => p.InAnswered),
-	        InHangupImmediate = list.Sum(p => p.InHangupImmediate),
-                InHanguped = list.Sum(m => m.InHanguped),
-                OutDurationAvg = list.Sum(m => m.OutDurationAvg),
-                InAvailableAnswer = list.Sum(m => m.InAvailableAnswer),
-                InHangupImmediateWhenAnswered = list.Sum(m => m.InHangupImmediateWhenAnswered),
-                OutTotal = list.Sum(m => m.OutTotal),
-                OutAnswered = list.Sum(m => m.OutAnswered),
-                LoginDuration = list.Sum(m => m.LoginDuration),
-                RestDuration = list.Sum(m => m.RestDuration),
-                InDurationAvg = list.Sum(m => m.InDurationAvg)
-            });
-        }
-
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-        var dtos = list
-            .Select(stu => _mapper.Map(stu, typeof(BiSeatCallsDto), dynamicClass))
-            .Cast<object>()
-            .ToList();
-
-        var stream = ExcelHelper.CreateStream(dtos);
-
-        return ExcelStreamResult(stream, "坐席话务统计分析");
+        return ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+                dto,
+                await _callReportApplication.QuerySeatCallAsync(dto.QueryDto, HttpContext.RequestAborted),
+                list => 
+                {
+                    list.Add(new BiSeatCallsDto()
+                    {
+                        Name = "合计",
+                        InTotal = list.Sum(p => p.InTotal),
+                        InAnswered = list.Sum(p => p.InAnswered),
+                    InHangupImmediate = list.Sum(p => p.InHangupImmediate),
+                        InHanguped = list.Sum(m => m.InHanguped),
+                        OutDurationAvg = list.Sum(m => m.OutDurationAvg),
+                        InAvailableAnswer = list.Sum(m => m.InAvailableAnswer),
+                        InHangupImmediateWhenAnswered = list.Sum(m => m.InHangupImmediateWhenAnswered),
+                        OutTotal = list.Sum(m => m.OutTotal),
+                        OutAnswered = list.Sum(m => m.OutAnswered),
+                        LoginDuration = list.Sum(m => m.LoginDuration),
+                        RestDuration = list.Sum(m => m.RestDuration),
+                        InDurationAvg = list.Sum(m => m.InDurationAvg)
+                    });
+                })
+            , "坐席话务统计分析");
     }
 
     /// <summary>
@@ -450,55 +315,8 @@ public class BiCallController : BaseController
     /// <returns></returns>
     [HttpGet("seats")]
     [AllowAnonymous]
-    public async Task<IReadOnlyList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportPagedRequest dto)
-    {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        //获取配置
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
-
-        var list = await _userRepository.Queryable()
-              .LeftJoin<TrCallRecord>((u, c) => u.Id == c.UserId)
-              .Where(u => !u.IsDeleted && u.UserType == EUserType.Seat)
-              .WhereIF(dto.StartTime.HasValue, (u, c) => c.CreatedTime >= dto.StartTime.Value)
-              .WhereIF(dto.EndTime.HasValue, (u, c) => c.CreatedTime <= dto.EndTime.Value)
-              .GroupBy((u, c) => new { c.UserName, c.UserId })
-              .Select((u, c) => new BiSeatCallsDto
-              {
-                  Name = c.UserName,
-                  UserId = c.UserId,
-                  InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In, 1, 0)),
-                  OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out, 1, 0)),
-                  InAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, 1, 0)),
-                  OutAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, 1, 0)),
-                  InHangupImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null && c.RingTimes < noConnectByeTimes, 1, 0)),
-                  InHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null, 1, 0)),
-                  InDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, c.Duration, 0))),
-                  OutDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, c.Duration, 0))),
-                  InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration >= effectiveTimes, 1, 0)),
-                  InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration < connectByeTimes, 1, 0)),
-              })
-              .MergeTable()
-              .ToListAsync(HttpContext.RequestAborted);
-
-
-        list.ForEach(d =>
-        {
-            d.LoginDuration = _workRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.WorkingDuration);
-            if (d.LoginDuration != null)
-            {
-                d.LoginDuration = Math.Round(d.LoginDuration.Value, digits: 2);
-            }
-            d.RestDuration = _telRestRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.RestDuration);
-            d.RestDuration = Math.Round(d.RestDuration, digits: 2);
-        });
-
-
-        return list;
-    }
+    public async Task<IReadOnlyList<BiSeatCallsDto>> QuerySeatCallsAsync([FromQuery] ReportRequiredPagedRequest dto)
+        => await _callReportApplication.QuerySeatCallAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 小休统计
@@ -509,14 +327,11 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<IReadOnlyList<BiSeatRestDto>> QuerySeatRest([FromQuery] QuerySeatRestRequest dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
         return await _telRestRepository.Queryable()
             .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
             .WhereIF(!string.IsNullOrEmpty(dto.StaffNo), x => x.StaffNo.Contains(dto.StaffNo))
-            .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime.Value)
-            .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime.Value)
+            .Where(x => x.CreationTime >= dto.StartTime)
+            .Where(x => x.CreationTime <= dto.EndTime)
             .GroupBy(x => new { x.UserId, x.StaffNo, x.UserName })
             .Select(x => new BiSeatRestDto
             {
@@ -541,28 +356,8 @@ public class BiCallController : BaseController
     [AllowAnonymous]
     public async Task<PagedDto<BiSeatSwitchDto>> QuerySeatSwitch([FromQuery] QuerySeatSwitchRequest dto)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) 
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        var (total, items) = await _trCallRecordRepository.Queryable()
-            .Where(x => !string.IsNullOrEmpty(x.AgentTransferNumber))
-            .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
-            .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.CDPN.Contains(dto.CDPN))
-            .WhereIF(dto.StartTime.HasValue, x => x.CreatedTime >= dto.StartTime.Value)
-            .WhereIF(dto.EndTime.HasValue, x => x.CreatedTime <= dto.EndTime.Value)
-            .Select(x => new BiSeatSwitchDto
-            {
-                UserId = x.UserId,
-                CPN = x.CPN,
-                CDPN = x.CDPN,
-                CreatedTime = x.CreatedTime,
-                TelNo = x.AgentTransferNumber,
-                UserName = x.UserName,
-            })
-            .OrderByDescending(x => x.CreatedTime)
-            .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-
-        return new PagedDto<BiSeatSwitchDto>(total, _mapper.Map<IReadOnlyList<BiSeatSwitchDto>>(items));
+        var (total, items) = await _callReportApplication.QuerySeatSwitchAsync(dto, HttpContext.RequestAborted);
+        return new PagedDto<BiSeatSwitchDto>(total, items);
     }
 
     /// <summary>
@@ -572,16 +367,7 @@ public class BiCallController : BaseController
     [HttpGet("hourcall")]
     [AllowAnonymous]
     public async Task<List<TrCallHourDto>> QueryHourCall([FromQuery] BiQueryHourCallDto dto)
-    {
-        if (!dto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-        //获取配置
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
-        var list = await _trCallRecordRepositoryEx.GetCallHourList(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, dto.Source);
-        return list;
-    }
+        => await _callReportApplication.GetCallHourListAsync(dto, HttpContext.RequestAborted);
 
     /// <summary>
     /// 小时统计--导出
@@ -590,39 +376,23 @@ public class BiCallController : BaseController
     [HttpPost("hourcall/export")]
     [AllowAnonymous]
     public async Task<FileStreamResult> ExportQueryHourCall([FromBody] ExportExcelDto<BiQueryHourCallDto> dto)
-    {
-         if (!dto.QueryDto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-        //获取配置
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
-        var list = await _trCallRecordRepositoryEx.GetCallHourList(dto.QueryDto.StartTime, dto.QueryDto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, dto.QueryDto.Source);
-
-        if (list != null && list.Count > 0)
-        {
-            list.Add(new TrCallHourDto()
-            {
-                HourTo = "合计",
-                EffectiveCount = list.Sum(p => p.EffectiveCount),
-                ConnectByeCount = list.Sum(p => p.ConnectByeCount),
-                NoConnectByeCount = list.Sum(p => p.NoConnectByeCount),
-                QueueByeCount = list.Sum(m => m.QueueByeCount),
-                IvrByeCount = list.Sum(m => m.IvrByeCount)
-            });
-        }
-
-        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-        var dtos = list
-            .Select(stu => _mapper.Map(stu, typeof(TrCallHourDto), dynamicClass))
-            .Cast<object>()
-            .ToList();
-
-        var stream = ExcelHelper.CreateStream(dtos);
-
-        return ExcelStreamResult(stream, "通话时段分析");
-    }
+        => ExcelStreamResult(
+            await _exportApplication.FittingAsync(
+                dto,
+                await _callReportApplication.GetCallHourListAsync(dto.QueryDto, HttpContext.RequestAborted),
+                list => 
+                {
+                    list.Add(new TrCallHourDto()
+                    {
+                        HourTo = "合计",
+                        EffectiveCount = list.Sum(p => p.EffectiveCount),
+                        ConnectByeCount = list.Sum(p => p.ConnectByeCount),
+                        NoConnectByeCount = list.Sum(p => p.NoConnectByeCount),
+                        QueueByeCount = list.Sum(m => m.QueueByeCount),
+                        IvrByeCount = list.Sum(m => m.IvrByeCount)
+                    });
+                })
+            , "通话时段分析");
 
 
     /// <summary>

+ 51 - 0
src/Hotline.Application.Tests/Application/YiBinCallReportApplicationTest.cs

@@ -0,0 +1,51 @@
+using Hotline.Application.StatisticalReport.CallReport;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Requests;
+using Hotline.Share.Tools;
+using NPOI.SS.Formula.Functions;
+using Shouldly;
+using SqlSugar.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Tests.Application;
+public class YiBinCallReportApplicationTest
+{
+    private readonly YiBinCallReportApplication _yiBinCallReportApplication;
+
+    public YiBinCallReportApplicationTest(YiBinCallReportApplication yiBinCallReportApplication)
+    {
+        _yiBinCallReportApplication = yiBinCallReportApplication;
+    }
+
+    [Fact]
+    public async Task QueryCallsDetailInTotal_Test()
+    {
+        var inDto = new BiQueryCallsDto
+        {
+            StartTime = "2024-04-11".ObjToDate(),
+            EndTime = "2024-04-11 23:59:59".ObjToDate()
+        };
+        var (total, items) = await _yiBinCallReportApplication.QueryCallsDetailInTotalAsync(inDto, true);
+        items.Any(m => m.OrderId.NotNullOrEmpty()).ShouldBe(true);
+        items.Any(m => m.OrderNo.NotNullOrEmpty()).ShouldBe(true);
+        items.Any(m => m.OrderTitle.NotNullOrEmpty()).ShouldBe(true);
+    }
+
+    [Fact]
+    public async Task QuerySeatCall_Test()
+    {
+        var inDto = new ReportPagedRequest
+        {
+            StartTime = "2024-06-01".ObjToDate(),
+            EndTime = "2024-06-30 23:59:59".ObjToDate()
+        };
+
+        var result = await _yiBinCallReportApplication.QuerySeatCallAsync(inDto, new CancellationToken());
+        result.ShouldNotBeNull();
+    }
+
+}

+ 45 - 0
src/Hotline.Application.Tests/Application/ZiGongCallReportApplicationTest.cs

@@ -0,0 +1,45 @@
+using Hotline.Application.StatisticalReport.CallReport;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Requests;
+using Shouldly;
+using SqlSugar.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Tests.Application;
+public class ZiGongCallReportApplicationTest
+{
+    private readonly ZiGongCallReportApplication _ziGongCallReportApplication;
+
+    public ZiGongCallReportApplicationTest(ZiGongCallReportApplication ziGongCallReportApplication)
+    {
+        _ziGongCallReportApplication = ziGongCallReportApplication;
+    }
+
+    [Fact]
+    public async Task QueryCallsDetailInTotal_Test()
+    {
+        var inDto = new BiQueryCallsDto {
+            StartTime = "2024-07-29".ObjToDate(),
+            EndTime = "2024-07-29 23:59:59".ObjToDate()
+        };
+        var (total, items) = await _ziGongCallReportApplication.QueryCallsDetailInTotalAsync(inDto, false);
+        total.ShouldNotBe(0);
+    }
+
+    [Fact]
+    public async Task QuerySeatCall_Test()
+    {
+        var inDto = new ReportPagedRequest
+        {
+            StartTime = "2024-06-01".ObjToDate(),
+            EndTime = DateTime.Now
+        };
+
+        var result = await _ziGongCallReportApplication.QuerySeatCallAsync(inDto, new CancellationToken());
+        result.ShouldNotBeNull();
+    }
+}

+ 3 - 0
src/Hotline.Application.Tests/Startup.cs

@@ -45,6 +45,7 @@ using Hotline.Application.CallCenter;
 using Hotline.Application.CallCenter.Calls;
 using Hotline.CallCenter.Configs;
 using Tr.Sdk;
+using Hotline.Application.StatisticalReport.CallReport;
 
 namespace Hotline.Application.Tests;
 public class Startup
@@ -145,6 +146,8 @@ public class Startup
             services.AddScoped<YiBinExpireTimeLimit>();
             services.AddScoped<ZiGongExpireTimeLimit>();
             services.AddScoped<LuZhouExpireTimeLimit>();
+            services.AddScoped<ZiGongCallReportApplication>();
+            services.AddScoped<YiBinCallReportApplication>();
             services.AddScoped<IMediator, MediatorMock>();
 
             ServiceLocator.Instance = services.BuildServiceProvider();

+ 156 - 21
src/Hotline.Application/StatisticalReport/CallReport/CallReportApplicationBase.cs

@@ -1,11 +1,19 @@
 using Hotline.Caching.Interfaces;
+using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.CallCenter.Calls;
 using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Settings;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Requests;
 using SqlSugar;
+using XF.Domain.Exceptions;
+using Hotline.Orders;
+using Hotline.Share.Enums.User;
+using Hotline.Users;
+using XF.Domain.Repository;
+using Hotline.CallCenter.Tels;
 
 namespace Hotline.Application.StatisticalReport.CallReport;
 
@@ -13,11 +21,30 @@ public abstract class CallReportApplicationBase : ICallReportApplication
 {
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly ICallNativeRepository _callNativeRepository;
+    private readonly IRepository<User> _userRepository;
+    private readonly IRepository<Work> _workRepository;
+    private readonly IRepository<TelRest> _telRestRepository;
 
-    protected CallReportApplicationBase(ISystemSettingCacheManager systemSettingCacheManager, ICallNativeRepository callNativeRepository)
+    protected CallReportApplicationBase(ISystemSettingCacheManager systemSettingCacheManager, ICallNativeRepository callNativeRepository, IRepository<User> userRepository, IRepository<Work> workRepository, IRepository<TelRest> telRestRepository)
     {
         _systemSettingCacheManager = systemSettingCacheManager;
         _callNativeRepository = callNativeRepository;
+        _userRepository = userRepository;
+        _workRepository = workRepository;
+        _telRestRepository = telRestRepository;
+    }
+
+    public virtual async Task<List<TrCallHourDto>> GetCallHourListAsync(BiQueryHourCallDto dto, CancellationToken requestAborted)
+    {
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
+        return await _callNativeRepository.GetCallHourList(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, dto.Source);
+    }
+
+    public virtual async Task<List<BiCallDto>> QueryCallsAsync(BiQueryCallsDto dto, CancellationToken cancellationToken)
+    {
+        return await _callNativeRepository.GetQueryCalls(dto.StartTime, dto.EndTime, dto.Line);
     }
 
     /// <summary>
@@ -25,7 +52,7 @@ public abstract class CallReportApplicationBase : ICallReportApplication
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    public override async Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto)
+    public virtual async Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto)
     {
         //超时接通量
         int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
@@ -33,32 +60,32 @@ public abstract class CallReportApplicationBase : ICallReportApplication
         int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
 
         //未接秒挂时间
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
         //呼入有效时间
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
         //接通秒挂时间
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
 
         var callData = await _callNativeRepository.Queryable()
                 .Where(p => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime)
                  // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
-                 .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
+                 .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.ToNo == dto.Keyword)
                  .GroupBy(p => p.CreationTime.ToString("yyyy-MM-dd"))
                 .Select(p => new QueryCallsDetailDto
                 {
                     Date = p.CreationTime.ToString("yyyy-MM-dd"),
-                    InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
-                    InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
-                    NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingTimes <= noConnectByeTimes && p.RingTimes > 0 && p.CallDirection == ECallDirection.In, 1, 0)), //未接通秒挂
-                    TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.OnState == EOnState.On, p.Duration, 0)), //呼入总时长
-                    InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
-                    InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
-                    TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.RingTimes >= CallInOverConnRingTime, 1, 0)),//超时接通量
-                    TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
-                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.QueueTims > 0 && p.RingTimes == 0 && p.OnState == EOnState.NoOn, 1, 0)), //队列挂断
-                    IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
-                    OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
-                    OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
+                    InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In, 1, 0)),//呼入总量
+                    InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
+                    NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingDuration <= noConnectByeTimes && p.RingDuration > 0 && p.Direction == ECallDirection.In, 1, 0)), //未接通秒挂
+                    TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, p.Duration, 0)), //呼入总时长
+                    InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
+                    InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
+                    TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.RingDuration >= CallInOverConnRingTime, 1, 0)),//超时接通量
+                    TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
+                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.WaitDuration > 0 && p.RingDuration == 0 && p.AnsweredTime == null, 1, 0)), //队列挂断
+                    IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.AnsweredTime == null, 1, 0)), //IVR挂断
+                    OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.Out, 1, 0)),//呼出总量
+                    OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime != null && p.Direction == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
                 })
                 .OrderBy(p => p.Date)
                 .ToListAsync();
@@ -66,13 +93,121 @@ public abstract class CallReportApplicationBase : ICallReportApplication
         return callData;
     }
 
-    public virtual ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto)
+    /// <summary>
+    /// 话务日期明细-呼入总量/接通总量
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public virtual async Task<(int, List<CallRecordOutDto>)> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto, bool isAll)
     {
-        throw new NotImplementedException();
+        var query = _callNativeRepository.Queryable()
+                .LeftJoin<Order>((p, o) => p.Id == o.CallId)
+                .Where((p, o) => p.CreationTime >= dto.StartTime && p.CreationTime <= dto.EndTime && p.Direction == ECallDirection.In)
+                .WhereIF(dto.TypeCode == "2", (p, o) => p.AnsweredTime != null)
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), (p, o) => p.TelNo == dto.Keyword)
+                 .OrderByDescending((p, o) => p.CreationTime)
+                 .Select((p, o) => new CallRecordOutDto
+                 {
+                     OrderId = o.Id,
+                     OrderNo = o.No,
+                     OrderTitle = o.Title,
+                 }, true);
+
+        if (isAll)
+        {
+            return (0, await query.ToListAsync());
+        }
+        return await query.ToPagedListAsync(dto.PageIndex, dto.PageSize);
+    }
+
+    public virtual async Task<List<QueryCallsDetailDto>> QueryCallsHourDetailAsync(BiQueryCallsDto dto, CancellationToken cancellationToken)
+    {
+        //超时接通量
+        int CallInOverConnRingTime = _systemSettingCacheManager.CallInOverConnRingTime;
+        //坐席超时挂断时间
+        int SeatChaoTime = _systemSettingCacheManager.SeatChaoTime;
+        //未接秒挂时间
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        //呼入有效时间
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        //接通秒挂时间
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
+        return await _callNativeRepository.QueryCallsHourDetail(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.Line);
     }
 
-    public virtual async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto)
+    /// <summary>
+    /// 坐席话务统计分析
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public virtual async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto, CancellationToken cancellationToken)
+    {
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
+
+        var list = await _userRepository.Queryable()
+              .LeftJoin<CallNative>((u, c) => u.Id == c.UserId)
+              .Where(u => !u.IsDeleted && u.UserType == EUserType.Seat)
+              .WhereIF(dto.StartTime.HasValue, (u, c) => c.CreationTime >= dto.StartTime.Value)
+              .WhereIF(dto.EndTime.HasValue, (u, c) => c.CreationTime <= dto.EndTime.Value)
+              .GroupBy((u, c) => new { c.UserName, c.UserId })
+              .Select((u, c) => new BiSeatCallsDto
+              {
+                  Name = c.UserName,
+                  UserId = c.UserId,
+                  InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In, 1, 0)),
+                  OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.Out, 1, 0)),
+                  InAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime != null, 1, 0)),
+                  OutAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.Out && c.AnsweredTime != null, 1, 0)),
+                  InHangupImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime == null && c.RingDuration < noConnectByeTimes, 1, 0)),
+                  InHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime == null, 1, 0)),
+                  InDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime != null, c.Duration, 0))),
+                  OutDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.Direction == ECallDirection.Out && c.AnsweredTime != null, c.Duration, 0))),
+                  InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime != null && c.Duration >= effectiveTimes, 1, 0)),
+                  InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.Direction == ECallDirection.In && c.AnsweredTime != null && c.Duration < connectByeTimes, 1, 0)),
+              })
+              .MergeTable()
+              .ToListAsync();
+
+        list.ForEach(d =>
+        {
+            d.LoginDuration = _workRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.WorkingDuration);
+            if (d.LoginDuration != null)
+            {
+                d.LoginDuration = Math.Round(d.LoginDuration.Value, digits: 2);
+            }
+            d.RestDuration = _telRestRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.RestDuration);
+            d.RestDuration = Math.Round(d.RestDuration, digits: 2);
+        });
+
+        return list;
+
+    }
+
+    public Task<List<BiSeatCallsDto>> QuerySeatCallAsync(ReportRequiredPagedRequest dto, CancellationToken cancellationToken)
     {
         throw new NotImplementedException();
     }
+
+    public virtual async Task<(int, List<BiSeatSwitchDto>)> QuerySeatSwitchAsync(QuerySeatSwitchRequest dto, CancellationToken cancellationToken)
+    {
+        return await _callNativeRepository.Queryable()
+            .Where(x => !string.IsNullOrEmpty(x.TelNo))
+            .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
+            .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.ToNo.Contains(dto.CDPN))
+            .Where(x => x.CreationTime >= dto.StartTime)
+            .Where(x => x.CreationTime <= dto.EndTime)
+            .Select(x => new BiSeatSwitchDto
+            {
+                UserId = x.UserId,
+                CPN = x.FromNo,
+                CDPN = x.ToNo,
+                CreatedTime = x.CreationTime,
+                TelNo = x.TelNo,
+                UserName = x.UserName,
+            })
+            .OrderByDescending(x => x.CreatedTime)
+            .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
+    }
 }

+ 9 - 6
src/Hotline.Application/StatisticalReport/CallReport/LuZhouCallReportApplication.cs

@@ -1,14 +1,17 @@
-using Hotline.DI;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Tels;
+using Hotline.DI;
+using Hotline.Repository.SqlSugar.CallCenter;
+using Hotline.Users;
 using XF.Domain.Dependency;
+using XF.Domain.Repository;
 
 namespace Hotline.Application.StatisticalReport.CallReport;
 
 [Injection(AppScopes = EAppScope.LuZhou)]
 public class LuZhouCallReportApplication : CallReportApplicationBase, ICallReportApplication, IScopeDependency
 {
+    public LuZhouCallReportApplication(ISystemSettingCacheManager systemSettingCacheManager, ICallNativeRepository callNativeRepository, IRepository<User> userRepository, IRepository<Work> workRepository, IRepository<TelRest> telRestRepository) : base(systemSettingCacheManager, callNativeRepository, userRepository, workRepository, telRestRepository)
+    {
+    }
 }

+ 91 - 20
src/Hotline.Application/StatisticalReport/CallReport/YiBinCallReportApplication.cs

@@ -1,9 +1,12 @@
 using Hotline.Caching.Interfaces;
+using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Tels;
 using Hotline.DI;
+using Hotline.Repository.SqlSugar.CallCenter;
 using Hotline.Settings;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.User;
 using Hotline.Share.Requests;
@@ -12,30 +15,42 @@ using SqlSugar;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
+using Microsoft.AspNetCore.Http;
 
 namespace Hotline.Application.StatisticalReport.CallReport;
 
 [Injection(AppScopes = EAppScope.YiBin)]
-public class YiBinCallReportApplication : CallReportApplicationBase,  ICallReportApplication, IScopeDependency
+public class YiBinCallReportApplication : CallReportApplicationBase, ICallReportApplication, IScopeDependency
 {
     private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+    private readonly ITrCallRecordRepository _trCallRecordRepositoryEx;
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly IRepository<User> _userRepository;
     private readonly IRepository<Work> _workRepository;
     private readonly IRepository<TelRest> _telRestRepository;
+    private readonly ICallNativeRepository _callNativeRepository;
 
     public YiBinCallReportApplication(
         IRepository<TrCallRecord> trCallRecordRepository,
         ISystemSettingCacheManager systemSettingCacheManager,
         IRepository<User> userRepository,
         IRepository<Work> workRepository,
-        IRepository<TelRest> telRestRepository)
+        IRepository<TelRest> telRestRepository,
+        ICallNativeRepository callNativeRepository,
+        ITrCallRecordRepository trCallRecordRepositoryEx) : base(systemSettingCacheManager, callNativeRepository, userRepository, workRepository, telRestRepository)
     {
         _trCallRecordRepository = trCallRecordRepository;
         _systemSettingCacheManager = systemSettingCacheManager;
         _userRepository = userRepository;
         _workRepository = workRepository;
         _telRestRepository = telRestRepository;
+        _callNativeRepository = callNativeRepository;
+        _trCallRecordRepositoryEx = trCallRecordRepositoryEx;
+    }
+
+    public override async Task<List<BiCallDto>> QueryCallsAsync(BiQueryCallsDto dto, CancellationToken cancellationToken)
+    {
+        return await _trCallRecordRepositoryEx.GetQueryCalls(dto.StartTime, dto.EndTime, dto.Keyword);
     }
 
     /// <summary>
@@ -49,13 +64,12 @@ public class YiBinCallReportApplication : CallReportApplicationBase,  ICallRepor
         int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
         //坐席超时挂断时间
         int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
-
         //未接秒挂时间
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
         //呼入有效时间
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
         //接通秒挂时间
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
 
         var callData = await _trCallRecordRepository.Queryable()
                 .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime)
@@ -89,19 +103,29 @@ public class YiBinCallReportApplication : CallReportApplicationBase,  ICallRepor
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    public override ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto)
+    public override async Task<(int, List<CallRecordOutDto>)> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto, bool isAll)
     {
-        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-            throw UserFriendlyException.SameMessage("请选择时间!");
-
-        return _trCallRecordRepository.Queryable()
+        var query = _trCallRecordRepository.Queryable()
                  .Includes(p => p.Order)
                 .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime && p.CallDirection == ECallDirection.In)
                 .WhereIF(dto.TypeCode == "2", p => p.OnState == EOnState.On && p.AnsweredTime != null)
-                 // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
                  .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
                  .OrderByDescending(p => p.CreatedTime)
-                .MergeTable();
+                 .Select(m => new CallRecordOutDto()
+                 {
+                     FromNo = m.CPN,
+                     ToNo = m.CDPN,
+                     Direction = m.CallDirection,
+                     EndTime = m.OverTime,
+                     OrderId = m.Order.Id,
+                     OrderTitle = m.Order.Title,
+                     OrderNo = m.Order.No
+                 }, true);
+        if (isAll)
+        {
+            return (0, await query.ToListAsync());
+        }
+        return await query.ToPagedListAsync(dto.PageIndex, dto.PageSize);
     }
 
     /// <summary>
@@ -109,17 +133,18 @@ public class YiBinCallReportApplication : CallReportApplicationBase,  ICallRepor
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    public override async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto)
+    public override async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportRequiredPagedRequest dto, CancellationToken cancellationToken)
     {
-        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+        //获取配置
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
 
         var list = await _userRepository.Queryable()
               .LeftJoin<TrCallRecord>((u, c) => u.Id == c.UserId)
               .Where(u => !u.IsDeleted && u.UserType == EUserType.Seat)
-              .WhereIF(dto.StartTime.HasValue, (u, c) => c.CreatedTime >= dto.StartTime.Value)
-              .WhereIF(dto.EndTime.HasValue, (u, c) => c.CreatedTime <= dto.EndTime.Value)
+              .Where((u, c) => c.CreatedTime >= dto.StartTime)
+              .Where((u, c) => c.CreatedTime <= dto.EndTime)
               .GroupBy((u, c) => new { c.UserName, c.UserId })
               .Select((u, c) => new BiSeatCallsDto
               {
@@ -137,7 +162,7 @@ public class YiBinCallReportApplication : CallReportApplicationBase,  ICallRepor
                   InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration < connectByeTimes, 1, 0)),
               })
               .MergeTable()
-              .ToListAsync();
+              .ToListAsync(cancellationToken);
 
 
         list.ForEach(d =>
@@ -151,6 +176,52 @@ public class YiBinCallReportApplication : CallReportApplicationBase,  ICallRepor
             d.RestDuration = Math.Round(d.RestDuration, digits: 2);
         });
 
+
         return list;
+    }
+
+    public override async Task<List<QueryCallsDetailDto>> QueryCallsHourDetailAsync(BiQueryCallsDto dto, CancellationToken cancellationToken)
+    {
+        //超时接通量
+        int CallInOverConnRingTime = _systemSettingCacheManager.CallInOverConnRingTime;
+        //坐席超时挂断时间
+        int SeatChaoTime = _systemSettingCacheManager.SeatChaoTime;
+        //未接秒挂时间
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        //呼入有效时间
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        //接通秒挂时间
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
+        return await _trCallRecordRepositoryEx.QueryCallsHourDetail(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes
+              , connectByeTimes, CallInOverConnRingTime, SeatChaoTime, dto.Keyword);
+    }
 
+    public override async Task<(int, List<BiSeatSwitchDto>)> QuerySeatSwitchAsync(QuerySeatSwitchRequest dto, CancellationToken cancellationToken)
+    {
+        return await _trCallRecordRepository.Queryable()
+            .Where(x => !string.IsNullOrEmpty(x.AgentTransferNumber))
+            .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))
+            .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.CDPN.Contains(dto.CDPN))
+            .Where(x => x.CreatedTime >= dto.StartTime)
+            .Where(x => x.CreatedTime <= dto.EndTime)
+            .Select(x => new BiSeatSwitchDto
+            {
+                UserId = x.UserId,
+                CPN = x.CPN,
+                CDPN = x.CDPN,
+                CreatedTime = x.CreatedTime,
+                TelNo = x.AgentTransferNumber,
+                UserName = x.UserName,
+            })
+            .OrderByDescending(x => x.CreatedTime)
+            .ToPagedListAsync(dto.PageIndex, dto.PageSize, cancellationToken);
+    }
+
+    public override async Task<List<TrCallHourDto>> GetCallHourListAsync(BiQueryHourCallDto dto, CancellationToken requestAborted)
+    {
+        int noConnectByeTimes = _systemSettingCacheManager.NoConnectByeTimes;
+        int effectiveTimes = _systemSettingCacheManager.EffectiveTimes;
+        int connectByeTimes = _systemSettingCacheManager.ConnectByeTimes;
+        return await _trCallRecordRepositoryEx.GetCallHourList(dto.StartTime, dto.EndTime, noConnectByeTimes, effectiveTimes, connectByeTimes, dto.Source);
     }
+}

+ 9 - 1
src/Hotline.Application/StatisticalReport/CallReport/ZiGongCallReportApplication.cs

@@ -1,9 +1,17 @@
-using Hotline.DI;
+using Hotline.Caching.Interfaces;
+using Hotline.CallCenter.Tels;
+using Hotline.DI;
+using Hotline.Repository.SqlSugar.CallCenter;
+using Hotline.Users;
 using XF.Domain.Dependency;
+using XF.Domain.Repository;
 
 namespace Hotline.Application.StatisticalReport.CallReport;
 
 [Injection(AppScopes = EAppScope.ZiGong)]
 public class ZiGongCallReportApplication : CallReportApplicationBase, ICallReportApplication, IScopeDependency
 {
+    public ZiGongCallReportApplication(ISystemSettingCacheManager systemSettingCacheManager, ICallNativeRepository callNativeRepository, IRepository<User> userRepository, IRepository<Work> workRepository, IRepository<TelRest> telRestRepository) : base(systemSettingCacheManager, callNativeRepository, userRepository, workRepository, telRestRepository)
+    {
+    }
 }

+ 143 - 143
src/Hotline.Application/StatisticalReport/CallReportApplication.cs

@@ -1,156 +1,156 @@
-using Hotline.Caching.Interfaces;
-using Hotline.CallCenter.Calls;
-using Hotline.CallCenter.Tels;
-using Hotline.Settings;
-using Hotline.Share.Dtos.CallCenter;
-using Hotline.Share.Enums.CallCenter;
-using Hotline.Share.Enums.User;
-using Hotline.Share.Requests;
-using Hotline.Users;
-using Microsoft.AspNetCore.Http;
-using SqlSugar;
-using XF.Domain.Dependency;
-using XF.Domain.Exceptions;
-using XF.Domain.Repository;
+//using Hotline.Caching.Interfaces;
+//using Hotline.CallCenter.Calls;
+//using Hotline.CallCenter.Tels;
+//using Hotline.Settings;
+//using Hotline.Share.Dtos.CallCenter;
+//using Hotline.Share.Enums.CallCenter;
+//using Hotline.Share.Enums.User;
+//using Hotline.Share.Requests;
+//using Hotline.Users;
+//using Microsoft.AspNetCore.Http;
+//using SqlSugar;
+//using XF.Domain.Dependency;
+//using XF.Domain.Exceptions;
+//using XF.Domain.Repository;
 
-namespace Hotline.Application.StatisticalReport
-{
-    public class CallReportApplication : ICallReportApplication, IScopeDependency
-    {
-        private readonly IRepository<TrCallRecord> _trCallRecordRepository;
-        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
-        private readonly IRepository<User> _userRepository;
-        private readonly IRepository<Work> _workRepository;
-        private readonly IRepository<TelRest> _telRestRepository;
+//namespace Hotline.Application.StatisticalReport
+//{
+    //public class CallReportApplication : ICallReportApplication, IScopeDependency
+    //{
+    //    private readonly IRepository<TrCallRecord> _trCallRecordRepository;
+    //    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+    //    private readonly IRepository<User> _userRepository;
+    //    private readonly IRepository<Work> _workRepository;
+    //    private readonly IRepository<TelRest> _telRestRepository;
 
-        public CallReportApplication(
-            IRepository<TrCallRecord> trCallRecordRepository,
-            ISystemSettingCacheManager systemSettingCacheManager,
-            IRepository<User> userRepository,
-            IRepository<Work> workRepository,
-            IRepository<TelRest> telRestRepository)
-        {
-            _trCallRecordRepository = trCallRecordRepository;
-            _systemSettingCacheManager = systemSettingCacheManager;
-            _userRepository = userRepository;
-            _workRepository = workRepository;
-            _telRestRepository = telRestRepository;
-        }
+    //    public CallReportApplication(
+    //        IRepository<TrCallRecord> trCallRecordRepository,
+    //        ISystemSettingCacheManager systemSettingCacheManager,
+    //        IRepository<User> userRepository,
+    //        IRepository<Work> workRepository,
+    //        IRepository<TelRest> telRestRepository)
+    //    {
+    //        _trCallRecordRepository = trCallRecordRepository;
+    //        _systemSettingCacheManager = systemSettingCacheManager;
+    //        _userRepository = userRepository;
+    //        _workRepository = workRepository;
+    //        _telRestRepository = telRestRepository;
+    //    }
 
-        /// <summary>
-        /// 话务日期明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        public async Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto)
-        {
-            //超时接通量
-            int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
-            //坐席超时挂断时间
-            int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
+    //    /// <summary>
+    //    /// 话务日期明细
+    //    /// </summary>
+    //    /// <param name="dto"></param>
+    //    /// <returns></returns>
+    //    public async Task<List<QueryCallsDetailDto>> QueryCallsDetailAsync(BiQueryCallsDto dto)
+    //    {
+    //        //超时接通量
+    //        int CallInOverConnRingTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
+    //        //坐席超时挂断时间
+    //        int SeatChaoTime = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
 
-            //未接秒挂时间
-            int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-            //呼入有效时间
-            int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-            //接通秒挂时间
-            int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+    //        //未接秒挂时间
+    //        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+    //        //呼入有效时间
+    //        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+    //        //接通秒挂时间
+    //        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
 
-            var callData = await _trCallRecordRepository.Queryable()
-                    .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime)
-                     // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
-                     .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
-                     .GroupBy(p => p.CreatedTime.ToString("yyyy-MM-dd"))
-                    .Select(p => new QueryCallsDetailDto
-                    {
-                        Date = p.CreatedTime.ToString("yyyy-MM-dd"),
-                        InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
-                        InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
-                        NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingTimes <= noConnectByeTimes && p.RingTimes > 0 && p.CallDirection == ECallDirection.In, 1, 0)), //未接通秒挂
-                        TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.OnState == EOnState.On, p.Duration, 0)), //呼入总时长
-                        InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
-                        InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
-                        TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.RingTimes >= CallInOverConnRingTime, 1, 0)),//超时接通量
-                        TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
-                        QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.QueueTims > 0 && p.RingTimes == 0 && p.OnState == EOnState.NoOn, 1, 0)), //队列挂断
-                        IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
-                        OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
-                        OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
-                    })
-                    .OrderBy(p => p.Date)
-                    .ToListAsync();
+    //        var callData = await _trCallRecordRepository.Queryable()
+    //                .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime)
+    //                 // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+    //                 .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
+    //                 .GroupBy(p => p.CreatedTime.ToString("yyyy-MM-dd"))
+    //                .Select(p => new QueryCallsDetailDto
+    //                {
+    //                    Date = p.CreatedTime.ToString("yyyy-MM-dd"),
+    //                    InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In, 1, 0)),//呼入总量
+    //                    InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
+    //                    NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingTimes <= noConnectByeTimes && p.RingTimes > 0 && p.CallDirection == ECallDirection.In, 1, 0)), //未接通秒挂
+    //                    TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.OnState == EOnState.On, p.Duration, 0)), //呼入总时长
+    //                    InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
+    //                    InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
+    //                    TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.RingTimes >= CallInOverConnRingTime, 1, 0)),//超时接通量
+    //                    TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
+    //                    QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.QueueTims > 0 && p.RingTimes == 0 && p.OnState == EOnState.NoOn, 1, 0)), //队列挂断
+    //                    IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.OnState == EOnState.NoOn, 1, 0)), //IVR挂断
+    //                    OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.CallDirection == ECallDirection.Out, 1, 0)),//呼出总量
+    //                    OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.OnState == EOnState.On && p.CallDirection == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
+    //                })
+    //                .OrderBy(p => p.Date)
+    //                .ToListAsync();
 
-            return callData;
-        }
+    //        return callData;
+    //    }
 
-        /// <summary>
-        /// 话务日期明细-呼入总量/接通总量
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        public ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto)
-        {
-            if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
-                throw UserFriendlyException.SameMessage("请选择时间!");
+    //    /// <summary>
+    //    /// 话务日期明细-呼入总量/接通总量
+    //    /// </summary>
+    //    /// <param name="dto"></param>
+    //    /// <returns></returns>
+    //    public ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto)
+    //    {
+    //        if (!dto.StartTime.HasValue || !dto.EndTime.HasValue)
+    //            throw UserFriendlyException.SameMessage("请选择时间!");
 
-            return _trCallRecordRepository.Queryable()
-                     .Includes(p => p.Order)
-                    .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime && p.CallDirection == ECallDirection.In)
-                    .WhereIF(dto.TypeCode == "2", p => p.OnState == EOnState.On && p.AnsweredTime != null)
-                     // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
-                     .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
-                     .OrderByDescending(p => p.CreatedTime)
-                    .MergeTable();
-        }
+    //        return _trCallRecordRepository.Queryable()
+    //                 .Includes(p => p.Order)
+    //                .Where(p => p.CreatedTime >= dto.StartTime && p.CreatedTime <= dto.EndTime && p.CallDirection == ECallDirection.In)
+    //                .WhereIF(dto.TypeCode == "2", p => p.OnState == EOnState.On && p.AnsweredTime != null)
+    //                 // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+    //                 .WhereIF(!string.IsNullOrEmpty(dto.Keyword), p => p.Gateway == dto.Keyword)
+    //                 .OrderByDescending(p => p.CreatedTime)
+    //                .MergeTable();
+    //    }
 
-        /// <summary>
-        /// 坐席话务统计分析
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        public async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto)
-        {
-            int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
-            int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
-            int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+    //    /// <summary>
+    //    /// 坐席话务统计分析
+    //    /// </summary>
+    //    /// <param name="dto"></param>
+    //    /// <returns></returns>
+    //    public async Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto)
+    //    {
+    //        int noConnectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+    //        int effectiveTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+    //        int connectByeTimes = int.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
 
-            var list = await _userRepository.Queryable()
-                  .LeftJoin<TrCallRecord>((u, c) => u.Id == c.UserId)
-                  .Where(u => !u.IsDeleted && u.UserType == EUserType.Seat)
-                  .WhereIF(dto.StartTime.HasValue, (u, c) => c.CreatedTime >= dto.StartTime.Value)
-                  .WhereIF(dto.EndTime.HasValue, (u, c) => c.CreatedTime <= dto.EndTime.Value)
-                  .GroupBy((u, c) => new { c.UserName, c.UserId })
-                  .Select((u, c) => new BiSeatCallsDto
-                  {
-                      Name = c.UserName,
-                      UserId = c.UserId,
-                      InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In, 1, 0)),
-                      OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out, 1, 0)),
-                      InAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, 1, 0)),
-                      OutAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, 1, 0)),
-                      InHangupImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null && c.RingTimes < noConnectByeTimes, 1, 0)),
-                      InHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null, 1, 0)),
-                      InDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, c.Duration, 0))),
-                      OutDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, c.Duration, 0))),
-                      InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration >= effectiveTimes, 1, 0)),
-                      InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration < connectByeTimes, 1, 0)),
-                  })
-                  .MergeTable()
-                  .ToListAsync();
+    //        var list = await _userRepository.Queryable()
+    //              .LeftJoin<TrCallRecord>((u, c) => u.Id == c.UserId)
+    //              .Where(u => !u.IsDeleted && u.UserType == EUserType.Seat)
+    //              .WhereIF(dto.StartTime.HasValue, (u, c) => c.CreatedTime >= dto.StartTime.Value)
+    //              .WhereIF(dto.EndTime.HasValue, (u, c) => c.CreatedTime <= dto.EndTime.Value)
+    //              .GroupBy((u, c) => new { c.UserName, c.UserId })
+    //              .Select((u, c) => new BiSeatCallsDto
+    //              {
+    //                  Name = c.UserName,
+    //                  UserId = c.UserId,
+    //                  InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In, 1, 0)),
+    //                  OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out, 1, 0)),
+    //                  InAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, 1, 0)),
+    //                  OutAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, 1, 0)),
+    //                  InHangupImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null && c.RingTimes < noConnectByeTimes, 1, 0)),
+    //                  InHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime == null, 1, 0)),
+    //                  InDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null, c.Duration, 0))),
+    //                  OutDurationAvg = SqlFunc.Ceil(SqlFunc.AggregateAvg(SqlFunc.IIF(c.CallDirection == ECallDirection.Out && c.AnsweredTime != null, c.Duration, 0))),
+    //                  InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration >= effectiveTimes, 1, 0)),
+    //                  InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(c.CallDirection == ECallDirection.In && c.AnsweredTime != null && c.Duration < connectByeTimes, 1, 0)),
+    //              })
+    //              .MergeTable()
+    //              .ToListAsync();
 
 
-            list.ForEach(d =>
-            {
-                d.LoginDuration = _workRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.WorkingDuration);
-                if (d.LoginDuration != null)
-                {
-                    d.LoginDuration = Math.Round(d.LoginDuration.Value, digits: 2);
-                }
-                d.RestDuration = _telRestRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.RestDuration);
-                d.RestDuration = Math.Round(d.RestDuration, digits: 2);
-            });
+    //        list.ForEach(d =>
+    //        {
+    //            d.LoginDuration = _workRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.WorkingDuration);
+    //            if (d.LoginDuration != null)
+    //            {
+    //                d.LoginDuration = Math.Round(d.LoginDuration.Value, digits: 2);
+    //            }
+    //            d.RestDuration = _telRestRepository.Queryable().Where(q => q.UserId == d.UserId && q.CreationTime >= dto.StartTime && q.CreationTime <= dto.EndTime).Sum(q => q.RestDuration);
+    //            d.RestDuration = Math.Round(d.RestDuration, digits: 2);
+    //        });
 
-            return list;
-        }
-    }
-}
+    //        return list;
+    //    }
+    //}
+//}

+ 38 - 0
src/Hotline.Application/StatisticalReport/ExportApplication.cs

@@ -0,0 +1,38 @@
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Order;
+using Hotline.Tools;
+using MapsterMapper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Application.StatisticalReport;
+public class ExportApplication : IExportApplication, IScopeDependency
+{
+    private readonly IMapper _mapper;
+
+    public ExportApplication(IMapper mapper)
+    {
+        _mapper = mapper;
+    }
+
+    public async Task<Stream> FittingAsync<T, D>( ExportExcelDto<D> dto, List<T> items,Action<List<T>>? action = null)
+    {
+        if (items != null && items.Count > 0)
+        {
+            action?.Invoke(items);
+        }
+
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+        var dtos = items
+            .Select(stu => _mapper.Map(stu, typeof(BiCallDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        return ExcelHelper.CreateStream(dtos);
+    }
+}

+ 9 - 2
src/Hotline.Application/StatisticalReport/ICallReportApplication.cs

@@ -1,5 +1,6 @@
 using Hotline.CallCenter.Calls;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Requests;
 using SqlSugar;
 
@@ -7,6 +8,8 @@ namespace Hotline.Application.StatisticalReport
 {
     public interface ICallReportApplication
     {
+        Task<List<BiCallDto>> QueryCallsAsync(BiQueryCallsDto dto, CancellationToken cancellationToken);
+
         /// <summary>
         /// 话务日期明细
         /// </summary>
@@ -19,13 +22,17 @@ namespace Hotline.Application.StatisticalReport
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
-        ISugarQueryable<TrCallRecord> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto);
+        Task<(int, List<CallRecordOutDto>)> QueryCallsDetailInTotalAsync(BiQueryCallsDto dto, bool isAll);
 
         /// <summary>
         /// 坐席话务统计分析
         /// </summary>
         /// <param name="dto"></param>
         /// <returns></returns>
-        Task<IList<BiSeatCallsDto>> QuerySeatCallAsync(ReportPagedRequest dto);
+        Task<List<BiSeatCallsDto>> QuerySeatCallAsync(ReportRequiredPagedRequest dto, CancellationToken cancellationToken);
+
+        Task<List<QueryCallsDetailDto>> QueryCallsHourDetailAsync(BiQueryCallsDto dto, CancellationToken cancellationToken);
+        Task<(int, List<BiSeatSwitchDto>)> QuerySeatSwitchAsync(QuerySeatSwitchRequest dto, CancellationToken requestAborted);
+        Task<List<TrCallHourDto>> GetCallHourListAsync(BiQueryHourCallDto dto, CancellationToken requestAborted);
     }
 }

+ 14 - 0
src/Hotline.Application/StatisticalReport/IExportApplication.cs

@@ -0,0 +1,14 @@
+
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Order;
+
+namespace Hotline.Application.StatisticalReport;
+
+/// <summary>
+/// 导出服务
+/// </summary>
+public interface IExportApplication
+{
+    Task<Stream> FittingAsync<T, D>( ExportExcelDto<D>dto, List<T> items, Action<List<T>>? action = null);
+}
+

+ 151 - 0
src/Hotline.Repository.SqlSugar/CallCenter/CallNativeRepository.cs

@@ -2,6 +2,8 @@
 using Hotline.Orders;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Settings;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Tools;
 using SqlSugar;
@@ -19,6 +21,57 @@ public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepos
     public CallNativeRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder) : base(uow, dataPermissionFilterBuilder)
     {
     }
+    public async Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string source)
+    {
+        TimeSpan timeDifference = endDate.Value.Subtract(beginDate).Duration();
+
+        int hourDiff = (int)(timeDifference.TotalHours);
+
+        //计算时间差
+        int hour = Convert.ToInt32((endDate - beginDate).Value.TotalHours);
+
+        List<DateTime> dts = new List<DateTime>() { beginDate };
+        for (int i = 0;i < hour - 1;i++)
+        {
+            dts.Add(dts.Last().AddHours(1));
+        }
+
+        var list = await Db.Reportable(dts).ToQueryable<DateTime>()
+            .LeftJoin<CallNative>((it, o) => o.CreationTime >= it.ColumnName && o.CreationTime < it.ColumnName.AddHours(1) && o.Direction == ECallDirection.In)
+             //.Where((it, o) => o.CallDirection == ECallDirection.In)
+             .WhereIF(!string.IsNullOrEmpty(source), (it, o) => o.ToNo == source)
+            .GroupBy((it, o) => it.ColumnName)
+            .Select((it, o) => new TrCallHourDto()
+            {
+                DateTimeTo = it.ColumnName,
+                Hour = it.ColumnName.Hour, //小时段
+                EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration >= effectiveTimes, 1, 0)),//有效接通
+                ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration > 0 && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
+                NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.Duration == 0 && o.RingDuration <= noConnectByeTimes && o.RingDuration > 0, 1, 0)), //未接通秒挂
+                QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.WaitDuration > 0 && o.RingDuration == 0 && o.AnsweredTime == null, 1, 0)), //队列挂断
+                IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.BeginIvrTime.HasValue && !o.BeginQueueTime.HasValue && !o.BeginRingTime.HasValue && o.AnsweredTime == null, 1, 0)), //IVR挂断
+            })
+            .MergeTable()
+            .OrderBy(x => x.Hour)
+            .ToListAsync();
+
+        var resultList = list.GroupBy(x => x.Hour)
+             .Select(x => new TrCallHourDto()
+             {
+                 Hour = x.Key,
+                 HourTo = x.Key.ToString().PadLeft(2, '0') + ":00 - " + (x.Key).ToString().PadLeft(2, '0') + ":59",
+                 StartHourTo = x.Key.ToString().PadLeft(2, '0') + ":00",
+                 EndHourTo = x.Key.ToString().PadLeft(2, '0') + ":59",
+                 EffectiveCount = x.Sum(d => d.EffectiveCount),
+                 ConnectByeCount = x.Sum(d => d.ConnectByeCount),
+                 NoConnectByeCount = x.Sum(d => d.NoConnectByeCount),
+                 QueueByeCount = x.Sum(d => d.QueueByeCount),
+                 IvrByeCount = x.Sum(d => d.IvrByeCount),
+             }).OrderBy(x => hour).ToList();
+
+        return resultList;
+    }
+
 
     public async Task<int> UpdateReplyTxtAsync(string callId, string replyTxt)
     {
@@ -27,4 +80,102 @@ public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepos
             .SetColumns(m => m.ReplyTxt, replyTxt)
             .ExecuteCommandAsync();
     }
+
+    public async Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line)
+    {
+        List<int> dts = new List<int>();
+        for (int i = 0;i < 24;i++)
+        {
+            dts.Add(i);
+        }
+
+        var listHour = Db.Reportable(dts).ToQueryable<int>();
+
+        var list = Db.Queryable<CallNative>()
+              .Where(p => p.CreationTime >= beginDate && p.CreationTime <= endDate)
+              // .Where(p => p.Gateway != "82826886" && SqlFunc.Length(p.Gateway) != 4)
+              .WhereIF(!string.IsNullOrEmpty(Line), p => p.TelNo == Line)
+               .GroupBy(p => p.CreationTime.Hour)
+               .Select(p => new
+               {
+                   Hour = p.CreationTime.Hour, //小时段
+                   InTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In, 1, 0)),//呼入总量
+                   InConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, 1, 0)),//呼入接通量
+                   NotAcceptedHang = SqlFunc.AggregateSum(SqlFunc.IIF(p.Duration == 0 && p.RingDuration <= noConnectByeTimes && p.RingDuration > 0, 1, 0)), //未接通秒挂
+                   TotalDurationIncomingCalls = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null, p.Duration, 0)), //呼入总时长
+                   InAvailableAnswer = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= effectiveTimes, 1, 0)),//有效接通量
+                   InHangupImmediateWhenAnswered = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.Duration > 0 && p.Duration <= connectByeTimes, 1, 0)), //呼入接通秒挂
+                   TimeoutConnection = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.RingDuration >= CallInOverConnRingTime, 1, 0)),//超时接通量
+                   TimeoutSuspension = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.AnsweredTime != null && p.Duration >= SeatChaoTime, 1, 0)),//超时挂断量
+                   QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.WaitDuration > 0 && p.RingDuration == 0 && p.AnsweredTime == null, 1, 0)), //队列挂断
+                   IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.In && p.BeginIvrTime.HasValue && !p.BeginQueueTime.HasValue && !p.BeginRingTime.HasValue && p.AnsweredTime == null, 1, 0)), //IVR挂断
+                   OutTotal = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.Out, 1, 0)),//呼出总量
+                   OutConnectionQuantity = SqlFunc.AggregateSum(SqlFunc.IIF(p.Direction == ECallDirection.Out && p.AnsweredTime != null, 1, 0))
+               })
+               .MergeTable();
+
+        var listCall = await listHour.LeftJoin(list, (x, p) => x.ColumnName == p.Hour)
+            .OrderBy(x => x.ColumnName)
+           .Select((x, p) => new QueryCallsDetailDto()
+           {
+               Hour = x.ColumnName.ToString() + ":00 - " + x.ColumnName.ToString() + ":59",
+               InTotal = p.InTotal,
+               InConnectionQuantity = p.InConnectionQuantity,
+               NotAcceptedHang = p.NotAcceptedHang,
+               TotalDurationIncomingCalls = p.TotalDurationIncomingCalls,
+               InAvailableAnswer = p.InAvailableAnswer,
+               InHangupImmediateWhenAnswered = p.InHangupImmediateWhenAnswered,
+               TimeoutConnection = p.TimeoutConnection,
+               TimeoutSuspension = p.TimeoutSuspension,
+               QueueByeCount = p.QueueByeCount,
+               IvrByeCount = p.IvrByeCount,
+               OutTotal = p.OutTotal,
+               OutConnectionQuantity = p.OutConnectionQuantity
+           })
+           .ToListAsync();
+
+        return listCall;
+    }
+
+    public async Task<List<BiCallDto>> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line)
+    {
+        List<int> dts = new List<int>();
+        for (int i = 0;i < 24;i++)
+        {
+            dts.Add(i);
+        }
+
+        var listHour = Db.Reportable(dts).ToQueryable<int>();
+
+        var list = Db.Queryable<CallNative>()
+             .Where(p => p.CreationTime >= beginDate && p.CreationTime <= endDate && p.Direction == ECallDirection.In)
+             .WhereIF(!string.IsNullOrEmpty(Line), p => p.ToNo == Line)
+           .GroupBy(p => p.CreationTime.Hour)
+           .Select(p => new
+           {
+               Hour = p.CreationTime.Hour, //小时段
+               Total = SqlFunc.AggregateCount(p.Id),
+               Answered = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime != null, 1, 0)), //应答数
+               Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime == null && p.EndBy != null && p.EndBy.Value == EEndBy.To, 1, 0)),//挂断数
+           })
+           // .GroupBy(p => p.Hour)
+           .MergeTable();
+
+        var listCall = await listHour.LeftJoin(list, (x, p) => x.ColumnName == p.Hour)
+            .OrderBy(x => x.ColumnName)
+           .Select((x, p) => new BiCallDto()
+           {
+               Hour = x.ColumnName,
+               Total = p.Total,
+               Answered = p.Answered,
+               Hanguped = p.Hanguped,
+           })
+           .ToListAsync();
+        foreach (var call in listCall)
+        {
+            call.HourRange = call.Hour.ToString().PadLeft(2, '0') + ":00 - " + (call.Hour + 1).ToString().PadLeft(2, '0') + ":00";
+        }
+
+        return listCall;
+    }
 }

+ 2 - 2
src/Hotline.Repository.SqlSugar/CallCenter/TrCallRecordRepository.cs

@@ -13,7 +13,7 @@ namespace Hotline.Repository.SqlSugar.CallCenter
         {
         }
 
-        public async Task<List<BiCallDto>?> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line)
+        public async Task<List<BiCallDto>> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line)
         {
             List<int> dts = new List<int>();
             for (int i = 0; i < 24; i++)
@@ -178,7 +178,7 @@ namespace Hotline.Repository.SqlSugar.CallCenter
         /// 通话时段统计明细
         /// </summary>
         /// <returns></returns>
-        public async Task<object> GetCallList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string type, string source, TimeSpan? startHourTo, int pageIndex, int pageSize)
+        public async Task<TotalDataList<>> GetCallList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string type, string source, TimeSpan? startHourTo, int pageIndex, int pageSize)
         {
             TimeSpan endHourTo = DateTime.Now.TimeOfDay;
             if (startHourTo.HasValue)

+ 45 - 5
src/Hotline.Share/Dtos/CallCenter/BiQueryCallsDto.cs

@@ -1,9 +1,30 @@
 using Hotline.Share.Requests;
+using System.ComponentModel.DataAnnotations;
 
 namespace Hotline.Share.Dtos.CallCenter;
 
-public record BiQueryCallsDto: ReportPagedRequest
+public record BiQueryCallsDto : ReportPagedRequest
 {
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [Required(ErrorMessage = "开始时间不能为空")]
+    public new DateTime StartTime
+    {
+        get { return base.StartTime ?? throw new InvalidOperationException("开始时间不能为空"); }
+        set { base.StartTime = value; }
+    }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [Required(ErrorMessage = "结束时间不能为空")]
+    public new DateTime EndTime
+    {
+        get { return base.StartTime ?? throw new InvalidOperationException("结束时间不能为空"); }
+        set { base.StartTime = value; }
+    }
+
     /// <summary>
     /// 线路
     /// </summary>
@@ -17,16 +38,35 @@ public record BiQueryCallsDto: ReportPagedRequest
 
 public class BiQueryHourCallDto
 {
+
     public DateTime StartTime { get; set; }
-    public DateTime? EndTime { get; set; }
-    public string Source {get; set; }
+
+    [Required(ErrorMessage = "结束时间不能为空")]
+    public DateTime EndTime { get; set; }
+    public string Source { get; set; }
 }
 
 public class BiQueryGateWayDto
 {
     public DateTime StartTime { get; set; }
-    
+
     public DateTime EndTime { get; set; }
-    
+
     public string gateway { get; set; }
+}
+
+public class TotalDataList<T>
+{
+    public TotalDataList()
+    {
+        
+    }
+    public TotalDataList(List<T> list, T total)
+    {
+        List = list;
+        Total = total;
+    }
+
+    public T Total { get; set; }
+    public List<T> List { get; set; }
 }

+ 127 - 1
src/Hotline.Share/Dtos/TrCallCenter/TrTelDao.cs

@@ -777,6 +777,133 @@ namespace Hotline.Share.Dtos.TrCallCenter
 		#endregion
 	}
 
+    public class CallRecordOutDto 
+    {
+
+        /// <summary>
+        /// 可直接访问的通话录音地址
+        /// </summary>
+        public string? RecordingFileUrl { get; set; }
+        public string? RecordingBaseAddress { get; set; }
+        public string? RecordingAbsolutePath { get; set; }
+
+        #region 业务字段
+        /// <summary>
+        /// 主叫
+        /// </summary>
+        public string FromNo { get; set; }
+
+        /// <summary>
+        /// 被叫
+        /// </summary>
+        public string ToNo { get; set; }
+
+        /// <summary>
+        /// 响应分机号
+        /// </summary>
+        public string TelNo { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public ECallDirection Direction { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public string DirectionText => Direction.GetDescription();
+
+        /// <summary>
+        /// 挂断方
+        /// </summary>
+        public EEndBy? EndBy { get; set; }
+
+        /// <summary>
+        /// 挂断方
+        /// </summary>
+        public string EndByText => EndBy.GetDescription();
+
+        /// <summary>
+        /// 用户ID
+        /// </summary>
+        public string UserId { get; set; }
+        /// <summary>
+        /// 用户名
+        /// </summary>
+        public string UserName { get; set; }
+
+        /// <summary>
+        /// 开始等待时间
+        /// </summary>
+        public DateTime? BeginQueueTime { get; set; }
+
+        /// <summary>
+        /// 接通时间
+        /// </summary>
+        public DateTime? AnsweredTime { get; set; }
+
+        /// <summary>
+        /// 挂机时间
+        /// </summary>
+        public DateTime EndTime { get; set; }
+
+        /// <summary>
+        /// 通话时长(挂机时间-接通时间)
+        /// </summary>
+        public int Duration { get; set; }
+        #endregion
+
+        #region 第三方系统字段(兼容前端)
+        /// <summary>
+        /// 主叫
+        /// </summary>
+        public string Cpn { get; set; }
+
+        /// <summary>
+        /// 被叫
+        /// </summary>
+        public string Cdpn { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public ECallDirection CallDirection { get; set; }
+
+        /// <summary>
+        /// 呼叫方向
+        /// </summary>
+        public string CallDirectionText => CallDirection.GetDescription();
+        /// <summary>
+        /// 挂机时间
+        /// </summary>
+        public DateTime OverTime { get; set; }
+        #endregion
+
+        /// <summary>
+        /// 工单Id
+        /// </summary>
+        public string OrderId { get; set; }
+
+        /// <summary>
+        /// 工单编号
+        /// </summary>
+        public string OrderNo { get; set; }
+
+        /// <summary>
+        /// 工单标题
+        /// </summary>
+        public string OrderTitle { get; set; }
+        public string Id { get; set; }
+    }
+
+    public class TrDto
+    {
+        prop
+        CPN = x.CPN,
+                    CDPN = x.CDPN,
+                    CreatedTime = x.CreatedTime
+    }
+
     public class TrCallDtoNew
     {
         /// <summary>
@@ -806,7 +933,6 @@ namespace Hotline.Share.Dtos.TrCallCenter
         /// </summary>
         public string EndByText => EndBy.GetDescription();
 
-
         /// <summary>
         /// 坐席侧通话流水,无坐席参与则为手机侧通话流水
         /// </summary>

+ 1 - 0
src/Hotline.Share/Enums/CallCenter/EOnState.cs

@@ -9,6 +9,7 @@ namespace Hotline.Share.Enums.CallCenter
         /// </summary>
         [Description("接通")]
         On = 1,
+
         /// <summary>
         /// 未接通
         /// </summary>

+ 34 - 4
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -1,5 +1,6 @@
 using Hotline.Share.Dtos;
 using Hotline.Share.Enums.Order;
+using System.ComponentModel.DataAnnotations;
 using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Requests;
@@ -9,12 +10,12 @@ public record PagedKeywordRequest : PagedRequest
     /// <summary>
     /// 开始时间
     /// </summary>
-    public DateTime? StartTime { get; set; }
+    public virtual DateTime? StartTime { get; set; }
 
     /// <summary>
     /// 结束时间
     /// </summary>
-    public DateTime? EndTime { get; set; }
+    public virtual DateTime? EndTime { get; set; }
 
     public string? Keyword { get; set; }
 
@@ -85,6 +86,35 @@ public record ReportPagedRequest : PagedKeywordRequest
     public int? TypeId { get; set; }
 }
 
+public record ReportRequiredPagedRequest : PagedKeywordRequest
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    [Required(ErrorMessage = "开始时间不能为空")]
+    public new DateTime StartTime
+    {
+        get { return base.StartTime ?? throw new InvalidOperationException("开始时间不能为空"); }
+        set { base.StartTime = value; }
+    }
+
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    [Required(ErrorMessage = "结束时间不能为空")]
+    public new DateTime EndTime
+    {
+        get { return base.StartTime ?? throw new InvalidOperationException("结束时间不能为空"); }
+        set { base.StartTime = value; }
+    }
+
+    /// <summary>
+    /// 来电/信人身份0:全部 ,1:市民,2:企业
+    /// </summary>
+    public int? TypeId { get; set; }
+}
+
+
 public record OrgDataListDetailRequest : PagedRequest
 {
     /// <summary>
@@ -197,7 +227,7 @@ public record HotspotReportPagedRequest : ReportPagedRequest
 }
 
 
-public record QuerySeatRestRequest : ReportPagedRequest
+public record QuerySeatRestRequest : ReportRequiredPagedRequest
 {
     public string? UserName { get; set; }
 
@@ -205,7 +235,7 @@ public record QuerySeatRestRequest : ReportPagedRequest
 
 }
 
-public record QuerySeatSwitchRequest : ReportPagedRequest
+public record QuerySeatSwitchRequest : ReportRequiredPagedRequest
 {
     public string? UserName { get; set; }
 

+ 5 - 1
src/Hotline/Caching/Interfaces/ISystemSettingCacheManager.cs

@@ -5,7 +5,11 @@ namespace Hotline.Caching.Interfaces
     public interface ISystemSettingCacheManager
     {
         SystemSetting? GetSetting(string code);
-
         void DelSystemSetting(string code);
+        int NoConnectByeTimes { get; }
+        int EffectiveTimes { get; }
+        int ConnectByeTimes { get; }
+        int CallInOverConnRingTime { get; }
+        int SeatChaoTime { get; }
     }
 }

+ 12 - 0
src/Hotline/Caching/Services/SystemSettingCacheManager.cs

@@ -35,5 +35,17 @@ namespace Hotline.Caching.Services
         {
             _cacheSystemSetting.Remove(code);
         }
+
+        public int EffectiveTimes
+            => int.Parse(GetSetting(SettingConstants.EffectiveTimes)?.SettingValue[0]);
+
+        public int ConnectByeTimes 
+            => int.Parse(GetSetting(SettingConstants.ConnectByeTimes)?.SettingValue[0]);
+
+        public int NoConnectByeTimes => int.Parse(GetSetting(SettingConstants.NoConnectByeTimes)?.SettingValue[0]);
+
+        public int CallInOverConnRingTime => int.Parse(GetSetting(SettingConstants.CallInOverConnRingTime)?.SettingValue[0]);
+
+        public int SeatChaoTime => int.Parse(GetSetting(SettingConstants.SeatChaoTime)?.SettingValue[0]);
     }
 }

+ 4 - 1
src/Hotline/CallCenter/Calls/CallNative.cs

@@ -17,11 +17,14 @@ namespace Hotline.CallCenter.Calls
     public class CallNative : CreationEntity
     {
         /// <summary>
-        ///  
+        /// 通话记录编号
         /// </summary>
         [SugarColumn(ColumnDescription = "通话记录编号")]
         public string CallNo { get; set; }
 
+        /// <summary>
+        /// 通话方向
+        /// </summary>
         [SugarColumn(ColumnDescription = "通话方向")]
         public ECallDirection Direction { get; set; }
 

+ 4 - 6
src/Hotline/CallCenter/Calls/ICallNativeRepository.cs

@@ -1,14 +1,12 @@
 using Hotline.CallCenter.Calls;
-using Hotline.Share.Enums.Order;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Hotline.Share.Dtos.CallCenter;
 using XF.Domain.Repository;
 
 namespace Hotline.Repository.SqlSugar.CallCenter;
 public interface ICallNativeRepository : IRepository<CallNative>
 {
     Task<int> UpdateReplyTxtAsync(string callId, string replyTxt);
+    Task<List<BiCallDto>> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line);
+    Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line);
+    Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, string source);
 }

+ 1 - 1
src/Hotline/CallCenter/Calls/ITrCallRecordRepository.cs

@@ -19,7 +19,7 @@ namespace Hotline.CallCenter.Calls
         /// <returns></returns>
         Task<List<QueryCallsDetailDto>> QueryCallsHourDetail(DateTime beginDate, DateTime endDate, int noConnectByeTimes, int effectiveTimes, int connectByeTimes, int CallInOverConnRingTime, int SeatChaoTime, string? Line);
 
-        Task<List<BiCallDto>?> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line);
+        Task<List<BiCallDto>> GetQueryCalls(DateTime beginDate, DateTime endDate, string? Line);
         Task<List<TrCallHourDto>?> GetCallHourList(DateTime beginDate, DateTime? endDate, int noConnectByeTimes, int effectiveTimes,int connectByeTimes, string source);