소스 검색

Merge branch 'test' of http://110.188.24.182:10023/Fengwo/hotline into test

田爽 5 달 전
부모
커밋
1b11ba3993

+ 1 - 1
src/Hotline.Api/Controllers/AiController.cs

@@ -679,7 +679,7 @@ namespace Hotline.Api.Controllers
                                     {
                                         //x.OrgNoSatisfiedReason = new List<Kv>() { new Kv() { Key = "7", Value = "未回复" } };
                                         //TODO 记录不满意原因到内容中供人工回访甄别选择不满意原因
-                                        if (dto.CallTimes.Value>=1 && orgProcessingResults is null)
+                                        if (dto.CallTimes.Value>=1 && orgProcessingResults == null && isSolve == null && isContact ==null)
                                         {
                                             orgProcessingResults = new Kv() { Key = "0", Value = "默认满意" };
                                             aiOrderVisitDetail.OrderVisit.VisitState = EVisitState.Visited;

+ 9 - 13
src/Hotline.Api/Controllers/OrderController.cs

@@ -74,6 +74,7 @@ using Hotline.Caching.Services;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.BlackLists;
 using Hotline.Share.Mq;
+using Hotline.Share.Dtos.CallCenter;
 
 namespace Hotline.Api.Controllers;
 
@@ -978,8 +979,8 @@ public class OrderController : BaseController
         }
 
         var seat = orderVisit.OrderVisitDetails.FirstOrDefault(m => m.VisitTarget == EVisitTarget.Seat);
-         //if (orderVisit.VisitState == EVisitState.WaitForVisit)
-        if(seat.VoiceEvaluate == null)
+        //if (orderVisit.VisitState == EVisitState.WaitForVisit)
+        if (seat.VoiceEvaluate == null)
         {
             if (!_appOptions.Value.IsYiBin)
             {
@@ -987,7 +988,7 @@ public class OrderController : BaseController
                 var callNative = await _callApplication.GetReplyVoiceOrDefaultByOrderIdAsync(orderVisit.OrderId);
                 seat.VoiceEvaluate = callNative;
             }
-           
+
         }
         if (seat.SeatEvaluate is null)
         {
@@ -1047,14 +1048,9 @@ public class OrderController : BaseController
     [LogFilter("工单回访")]
     public async Task Visit([FromBody] VisitDto dto)
     {
-        var seconds = _systemSettingCacheManager.VisitCallDelaySecond;
-        if (dto.CallId.NotNullOrEmpty())
-        {
-            await _capPublisher.PublishDelayAsync(TimeSpan.FromSeconds(seconds), EventNames.VisitCallDelay, dto, cancellationToken: HttpContext.RequestAborted);
-
-            dto.CallId = await _callApplication.GetOrSetCallIdAsync(dto.CallId, HttpContext.RequestAborted);
-        }
-
+        // 发送延迟关联通话记录消息
+        await _callApplication.PublishVisitRelevanceCallIdAsync(dto.Adapt<VisitRelevanceCallIdDto>(), HttpContext.RequestAborted);
+        dto.CallId = await _callApplication.GetOrSetCallIdAsync(dto.CallId, HttpContext.RequestAborted);
         await _orderApplication.SaveOrderVisit(dto, HttpContext.RequestAborted);
     }
 
@@ -4105,9 +4101,9 @@ public class OrderController : BaseController
                         d.Status != EOrderStatus.SpecialToUnAccept &&
                         d.Status != EOrderStatus.HandOverToUnAccept)
             .WhereIF(dto.QueryType is 3,
-                d => SqlFunc.Subqueryable<OrderSpecial>().Where(os => os.OrderId == d.Id  && os.IsDeleted == false && os.SpecialType == ESpecialType.ReTransact).Any())
+                d => SqlFunc.Subqueryable<OrderSpecial>().Where(os => os.OrderId == d.Id && os.IsDeleted == false && os.SpecialType == ESpecialType.ReTransact).Any())
             .Where(d => SqlFunc.Subqueryable<OrderDelay>().Where(od => od.OrderId == d.Id && od.IsDeleted == false && od.DelayState == EDelayState.Examining).NotAny())
-            .Where(d => SqlFunc.Subqueryable<OrderSendBackAudit>().Where(osba => osba.OrderId == d.Id && osba.IsDeleted == false  && osba.State == ESendBackAuditState.Apply)
+            .Where(d => SqlFunc.Subqueryable<OrderSendBackAudit>().Where(osba => osba.OrderId == d.Id && osba.IsDeleted == false && osba.State == ESendBackAuditState.Apply)
                 .NotAny())
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword))

+ 20 - 16
src/Hotline.Api/Controllers/TestController.cs

@@ -307,25 +307,29 @@ ICallApplication callApplication,
 
         foreach (var item in list)
         {
-            var visit = item.OrderVisits.FirstOrDefault();
-            if (visit != null)
+            try
             {
-                //推省上
-                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
-                new PublishVisitDto()
+                var visit = item.OrderVisits.FirstOrDefault();
+                if (visit != null)
                 {
-                    Order = _mapper.Map<OrderDto>(item),
-                    No = visit.No,
-                    VisitType = visit.VisitType,
-                    VisitName = visit.CreatorName,
-                    VisitTime = visit.VisitTime,
-                    VisitRemark = "满意",
-                    AreaCode = item.AreaCode!,
-                    SubjectResultSatifyCode = "4",
-                    FirstSatisfactionCode = "4",
-                    ClientGuid = ""
-                }, cancellationToken: HttpContext.RequestAborted);
+                    //推省上
+                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
+                    new PublishVisitDto()
+                    {
+                        Order = _mapper.Map<OrderDto>(item),
+                        No = visit.No,
+                        VisitType = visit.VisitType,
+                        VisitName = visit.CreatorName,
+                        VisitTime = visit.VisitTime,
+                        VisitRemark = "满意",
+                        AreaCode = item.AreaCode!,
+                        SubjectResultSatifyCode = "4",
+                        FirstSatisfactionCode = "4",
+                        ClientGuid = ""
+                    }, cancellationToken: HttpContext.RequestAborted);
+                }
             }
+            catch {}
         }
     }
 

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

@@ -93,4 +93,72 @@ public class ZiGongCallReportApplicationTest
         result.Any(m => m.InConnectionRate.IsNullOrEmpty()).ShouldBeFalse();
         result.ShouldNotBeNull();
     }
+
+    /// <summary>
+    /// 测试通话时段分析中的数量是否和通话时段明细表中的数量是否相等
+    /// </summary>
+    /// <returns></returns>
+    [Fact]
+    public async Task HourCall_Test()
+    {
+        var inDto = new BiQueryHourCallDto
+        {
+            StartTime = "2024-10-30 00:00:00".ObjToDate(),
+            EndTime = "2024-10-30 23:59:59".ObjToDate()
+        };
+
+        var hourList = await _ziGongCallReportApplication.GetCallHourListAsync(inDto, CancellationToken.None);
+        var hour = hourList.Where(m => m.Hour == 7).FirstOrDefault();
+        var bInDto = new QueryCallListDto
+        {
+            Type = "effectiveCount",
+            PageIndex = 1,
+            PageSize = 20,
+            StartHourTo = TimeSpan.Parse("07:00"),
+            StartTime = "2024-10-30 00:00:00".ObjToDate(),
+            EndTime = "2024-10-30 23:59:59".ObjToDate()
+        };
+        var bhour = await _ziGongCallReportApplication.GetCallListAsync(bInDto, CancellationToken.None);
+        bhour.Total.ShouldBe(hour.EffectiveCount, "effectiveCount 列表和详情的数量对不上");
+
+        hour = hourList.Where(m => m.Hour == 12).FirstOrDefault();
+        bInDto = new QueryCallListDto
+        {
+            Type = "connectByeCount",
+            PageIndex = 1,
+            PageSize = 20,
+            StartHourTo = TimeSpan.Parse("12:00"),
+            StartTime = "2024-10-30 00:00:00".ObjToDate(),
+            EndTime = "2024-10-30 23:59:59".ObjToDate()
+        };
+        bhour = await _ziGongCallReportApplication.GetCallListAsync(bInDto, CancellationToken.None);
+        bhour.Total.ShouldBe(hour.ConnectByeCount, "connectByeCount 列表和详情的数量对不上");
+
+        hour = hourList.Where(m => m.Hour == 9).FirstOrDefault();
+        bInDto = new QueryCallListDto
+        {
+            Type = "noConnectByeCount",
+            PageIndex = 1,
+            PageSize = 20,
+            StartHourTo = TimeSpan.Parse("9:00"),
+            StartTime = "2024-10-30 00:00:00".ObjToDate(),
+            EndTime = "2024-10-30 23:59:59".ObjToDate()
+        };
+        bhour = await _ziGongCallReportApplication.GetCallListAsync(bInDto, CancellationToken.None);
+        bhour.Total.ShouldBe(hour.NoConnectByeCount, "noConnectByeCount 列表和详情的数量对不上");
+
+        hour = hourList.Where(m => m.Hour == 6).FirstOrDefault();
+        bInDto = new QueryCallListDto
+        {
+            Type = "count",
+            PageIndex = 1,
+            PageSize = 20,
+            StartHourTo = TimeSpan.Parse("06:00"),
+            StartTime = "2024-10-30 00:00:00".ObjToDate(),
+            EndTime = "2024-10-30 23:59:59".ObjToDate()
+        };
+        bhour = await _ziGongCallReportApplication.GetCallListAsync(bInDto, CancellationToken.None);
+        bhour.Total.ShouldBe(hour.Count, "Count 列表和详情的数量对不上");
+
+    }
 }

+ 2 - 1
src/Hotline.Application.Tests/Domain/OrderVisitDomainServiceTest.cs

@@ -96,13 +96,14 @@ public class OrderVisitDomainServiceTest
     public async Task UpdateSmsReply_Test(string content, string visitState, string orgResuktKey, string orgResuktValue)
     {
         var visit = await _orderVisitRepository.Queryable()
+            .Includes(m => m.Order)
             .Where(m => m.VisitState == EVisitState.SMSVisiting)
             .OrderByDescending(m => m.CreationTime)
             .FirstAsync();
         if (visit == null) return;
         visit.ShouldNotBeNull("缺少测试数据");
 
-        var message = new MessageDto { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content };
+        var message = new MessageDto { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content , TelNumber = visit.Order.Contact};
         var dto = new PushReceiveMessageDto();
         await _orderVisitDomainService.UpdateSmsReplyAsync(message);
         visit = _orderVisitRepository.Get(visit.Id);

+ 26 - 4
src/Hotline.Application/CallCenter/DefaultCallApplication.cs

@@ -1,4 +1,5 @@
-using Hotline.Caching.Interfaces;
+using DotNetCore.CAP;
+using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Tels;
@@ -11,6 +12,7 @@ using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.Order;
+using Hotline.Share.Mq;
 using Hotline.Share.Tools;
 using Hotline.Users;
 using MapsterMapper;
@@ -26,6 +28,8 @@ namespace Hotline.Application.CallCenter;
 public abstract class DefaultCallApplication : ICallApplication
 {
     private readonly IRepository<Tel> _telRepository;
+    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+    private readonly ICapPublisher _capPublisher;
     private readonly IRepository<TelGroup> _telGroupRepository;
     private readonly IWorkRepository _workRepository;
     private readonly ITelRestRepository _telRestRepository;
@@ -56,7 +60,9 @@ public abstract class DefaultCallApplication : ICallApplication
         ILogger<DefaultCallApplication> logger,
         IOrderVisitDomainService orderVisitDomainService,
         ICallDomainService callDomainService,
-        IOrderVisitRepository orderVisitRepository)
+        IOrderVisitRepository orderVisitRepository,
+        ISystemSettingCacheManager systemSettingCacheManager,
+        ICapPublisher capPublisher)
     {
         _telRepository = telRepository;
         _telGroupRepository = telGroupRepository;
@@ -73,6 +79,8 @@ public abstract class DefaultCallApplication : ICallApplication
         _orderVisitDomainService = orderVisitDomainService;
         _callDomainService = callDomainService;
         _orderVisitRepository = orderVisitRepository;
+        _systemSettingCacheManager = systemSettingCacheManager;
+        _capPublisher = capPublisher;
     }
 
     public DefaultCallApplication()
@@ -287,8 +295,9 @@ public abstract class DefaultCallApplication : ICallApplication
     /// <summary>
     /// 依据通话记录编号获取映射后的callId
     /// </summary>
-    public virtual async Task<string> GetOrSetCallIdAsync(string callNo, CancellationToken cancellationToken)
+    public virtual async Task<string?> GetOrSetCallIdAsync(string? callNo, CancellationToken cancellationToken)
     {
+        if (callNo == null) return null;
         var callOrder = await _callIdRelationRepository.GetAsync(callNo, cancellationToken);
         if (callOrder == null)
         {
@@ -311,6 +320,19 @@ public abstract class DefaultCallApplication : ICallApplication
         return callOrder.CallId;
     }
 
+    /// <summary>
+    /// 发送延迟消息让回访去关联通话记录
+    /// </summary>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    public virtual async Task PublishVisitRelevanceCallIdAsync(VisitRelevanceCallIdDto dto, CancellationToken cancellationToken)
+    {
+        if (dto.CallId.IsNullOrEmpty()) return;
+
+        var seconds = _systemSettingCacheManager.VisitCallDelaySecond;
+        await _capPublisher.PublishDelayAsync(TimeSpan.FromSeconds(seconds), EventNames.VisitCallDelay, dto, cancellationToken: cancellationToken);
+    }
+
     public async Task<CallidRelation> GetRelationAsync(string callNo, CancellationToken cancellation)
     {
         return await _callIdRelationRepository.GetAsync(callNo, cancellation);
@@ -400,7 +422,7 @@ public abstract class DefaultCallApplication : ICallApplication
     /// 保存回访详情时发送延迟消息同步通话记录
     /// 如果回访通话记录有多条, 需要关联通话时长最长的那条
     /// </summary>
-    public async Task OrderVisitRelevanceCallIdAsync(VisitDto dto, CancellationToken cancellationToken)
+    public virtual async Task OrderVisitRelevanceCallIdAsync(VisitDto dto, CancellationToken cancellationToken)
     {
         var visit = await _orderVisitRepository.GetAsync(dto.Id);
         if (visit == null) return;

+ 8 - 1
src/Hotline.Application/CallCenter/ICallApplication.cs

@@ -77,7 +77,14 @@ namespace Hotline.Application.CallCenter
         /// <summary>
         /// 依据通话记录编号获取映射后的callId
         /// </summary>
-        Task<string> GetOrSetCallIdAsync(string callNo, CancellationToken cancellationToken);
+        Task<string?> GetOrSetCallIdAsync(string? callNo, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 发送延迟消息让回访去关联通话记录
+        /// </summary>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task PublishVisitRelevanceCallIdAsync(VisitRelevanceCallIdDto dto, CancellationToken cancellationToken);
 
         Task<CallidRelation> GetRelationAsync(string callNo, CancellationToken cancellation);
 

+ 12 - 0
src/Hotline.Application/CallCenter/TianRunCallApplication.cs

@@ -14,12 +14,14 @@ using Hotline.Orders;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Mq;
 using MapsterMapper;
 using Microsoft.AspNetCore.Http;
+using SqlSugar;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -104,6 +106,16 @@ namespace Hotline.Application.CallCenter
             return await Task.FromResult(callNo);
         }
 
+        public override async Task PublishVisitRelevanceCallIdAsync(VisitRelevanceCallIdDto dto, CancellationToken cancellationToken)
+        {
+            return;
+        }
+
+        public override async Task OrderVisitRelevanceCallIdAsync(VisitDto dto, CancellationToken cancellationToken)
+        {
+            return;
+        }
+
         /// <summary>
         /// 查询当前用户的分机状态
         /// </summary>

+ 4 - 2
src/Hotline.Application/CallCenter/XingTangCallApplication.cs

@@ -62,11 +62,13 @@ namespace Hotline.Application.CallCenter
             ILogger<XingTangCallApplication> logger,
             ICallDomainService callDomainService,
             IOrderVisitDomainService orderVisitDomainService,
-            IOrderVisitRepository orderVisitRepository
+            IOrderVisitRepository orderVisitRepository,
+            ISystemSettingCacheManager systemSettingCacheManager,
+            ICapPublisher capPublisher
         ) : base(telRepository, telGroupRepository, workRepository, telRestRepository, callNativeRepository,
             teloperationRepository, callidRelationRepository, cacheWork, userCacheManager, sessionContext, mapper,
             logger, orderVisitDomainService,callDomainService
-            , orderVisitRepository)
+            , orderVisitRepository, systemSettingCacheManager, capPublisher)
         {
             // _telRepository = telRepository;
             // _telGroupRepository = telGroupRepository;

+ 2 - 2
src/Hotline.Application/Jobs/XingTangCallsSyncJob.cs

@@ -99,11 +99,11 @@ namespace Hotline.Application.Jobs
                         {
                             if (call.EndRingTime != null)
                             {
-                                call.RingDuration = call.BeginRingTime.Value.GetDifferenceSeconds(call.EndRingTime.Value);
+                                call.RingDuration = call.EndRingTime.Value.GetDifferenceSeconds(call.BeginRingTime.Value);
                             }
                             else
                             {
-                                call.RingDuration = call.BeginRingTime.Value.GetDifferenceSeconds(call.EndTime);
+                                call.RingDuration = call.EndTime.GetDifferenceSeconds(call.BeginRingTime.Value);
                             }
                         }
                     }

+ 7 - 1
src/Hotline.Application/Mappers/CallMapperConfigs.cs

@@ -9,6 +9,8 @@ using System.Text;
 using System.Threading.Tasks;
 using Hotline.CallCenter.Tels;
 using XingTang.Sdk;
+using Hotline.Share.Dtos.CallCenter;
+using Hotline.Share.Dtos.Order;
 
 namespace Hotline.Application.Mappers
 {
@@ -72,7 +74,7 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.EndIvrTime, s => s.EnqueueTime)
                 .Map(d => d.BeginQueueTime, s => s.EnqueueTime)
                 .Map(d => d.EndQueueTime, s => s.DequeueTime)
-                .Map(d => d.BeginRingTime, s => s.RingStartTime)
+                .Map(d => d.BeginRingTime, s => s.ReceiveStartTime)
                 .Map(d => d.EndRingTime, s => s.ReceiveEndTime.HasValue ? s.ReceiveEndTime : s.CallEndTime)
                 .Map(d => d.AnsweredTime, s => s.ReceiveEndTime)
                 .Map(d => d.EndTime, s => s.CallEndTime)
@@ -142,6 +144,10 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.AudioFile, s => s.RecordingAbsolutePath)
                 .Map(d => d.BeginIvrTime, s => s.CreatedTime);
 
+            config.ForType<VisitDto, VisitRelevanceCallIdDto>()
+                .Map(d => d.OrderVisitId, s => s.Id)
+                .Map(d => d.CallId, s => s.CallId);
+
         }
 
         private DateTime? FormatDateTime(string? time)

+ 0 - 2
src/Hotline.Application/Mappers/MapperConfigs.cs

@@ -131,8 +131,6 @@ namespace Hotline.Application.Mappers
              .Map(d => d.CenterToOrgTime, x => x.CenterToOrgTime == null ? "" : x.CenterToOrgTime.Value.ToString("yyyy-MM-dd HH:mm:ss"))
              .Map(d => d.ExpiredTime, x => x.ExpiredTime == null ? "" : x.ExpiredTime.Value.ToString("yyyy-MM-dd HH:mm:ss"))
              ;
-
-           
         }
     }
 }

+ 15 - 15
src/Hotline.Repository.SqlSugar/CallCenter/CallNativeRepository.cs

@@ -45,9 +45,9 @@ public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepos
             {
                 DateTimeTo = it.ColumnName,
                 Hour = it.ColumnName.Hour, //小时段
-                EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null, 1, 0)),//有效接通
-                ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null && o.Duration < connectByeTimes, 1, 0)), //接通秒挂
-                NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.RingDuration <= noConnectByeTimes && o.RingDuration > 0, 1, 0)), //未接通秒挂
+                EffectiveCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null && o.Duration >= effectiveTimes, 1, 0)),//有效接通
+                ConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime != null && o.Duration <= connectByeTimes, 1, 0)), //接通秒挂
+                NoConnectByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.AnsweredTime == null && o.RingDuration <= noConnectByeTimes && o.RingDuration > 0, 1, 0)), //未接通秒挂
                 QueueByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallState == ECallState.NotAcceptedHang, 1, 0)), //队列挂断
                 IvrByeCount = SqlFunc.AggregateSum(SqlFunc.IIF(o.CallState == ECallState.IVRNoAccept, 1, 0)), //IVR挂断
             })
@@ -162,7 +162,7 @@ public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepos
                Hour = p.BeginIvrTime.Value.Hour, //小时段
                Total = SqlFunc.AggregateCount(p.Id),
                Answered = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime != null, 1, 0)), //应答数
-               Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime == null && 
+               Hanguped = SqlFunc.AggregateSum(SqlFunc.IIF(p.AnsweredTime == null &&
                (p.CallState == ECallState.Missed || p.CallState == ECallState.NotAcceptedHang || p.CallState == ECallState.IVRNoAccept), 1, 0)),//挂断数
            })
            // .GroupBy(p => p.Hour)
@@ -202,18 +202,18 @@ public class CallNativeRepository : BaseRepository<CallNative>, ICallNativeRepos
             .Where(x => x.BeginIvrTime >= dto.StartTime && x.BeginIvrTime <= dto.EndTime)
             .Where(x => x.Direction == ECallDirection.In && x.CallState != ECallState.Invalid)
             .WhereIF(!string.IsNullOrEmpty(dto.Source), x => x.ToNo == dto.Source)
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("QueueBye".Equals(dto.Type) || "queueByeCount".Equals(dto.Type)), x => x.CallState == ECallState.NotAcceptedHang) //队列挂断
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("IvrBye".Equals(dto.Type) || "ivrByeCount".Equals(dto.Type)), x => x.CallState == ECallState.IVRNoAccept)//IVR挂断
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && ("Effective".Equals(dto.Type) || "effectiveCount".Equals(dto.Type)), x => x.Duration >= effectiveTimes) //有效接通
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && "Invalid".Equals(dto.Type), x => x.Duration > 0 && x.Duration < effectiveTimes)//无效接通
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && "connectByeCount".Equals(dto.Type), x => x.Duration > 0 && x.Duration <= connectByeTimes)  //接通秒挂
-            .WhereIF(!string.IsNullOrEmpty(dto.Type) && "noConnectByeCount".Equals(dto.Type), x => x.Duration == 0 && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0)  //未接通秒挂
+.WhereIF(!string.IsNullOrEmpty(dto.Type) && ("QueueBye".Equals(dto.Type) || "queueByeCount".Equals(dto.Type)), x => x.CallState == ECallState.NotAcceptedHang) //队列挂断
+.WhereIF(!string.IsNullOrEmpty(dto.Type) && ("IvrBye".Equals(dto.Type) || "ivrByeCount".Equals(dto.Type)), x => x.CallState == ECallState.IVRNoAccept)//IVR挂断
+.WhereIF(!string.IsNullOrEmpty(dto.Type) && ("Effective".Equals(dto.Type) || "effectiveCount".Equals(dto.Type)), x => x.AnsweredTime != null && x.Duration >= effectiveTimes) //有效接通
+.WhereIF(!string.IsNullOrEmpty(dto.Type) && "Invalid".Equals(dto.Type), x => x.AnsweredTime != null && x.Duration < effectiveTimes)//无效接通
+            .WhereIF(!string.IsNullOrEmpty(dto.Type) && "connectByeCount".Equals(dto.Type), x => x.AnsweredTime != null && x.Duration <= connectByeTimes)  //接通秒挂
+.WhereIF(!string.IsNullOrEmpty(dto.Type) && "noConnectByeCount".Equals(dto.Type), x => x.AnsweredTime == null && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0)  //未接通秒挂
             .WhereIF(!string.IsNullOrEmpty(dto.Type) && "count".Equals(dto.Type), x =>
-            (x.Duration == 0 && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0)  //未接通秒挂
-            || (x.Duration > 0 && x.Duration <= connectByeTimes)  //接通秒挂
-            || (x.Duration >= effectiveTimes)//有效接通
-            || (x.BeginIvrTime.HasValue && !x.BeginQueueTime.HasValue && !x.BeginRingTime.HasValue && x.AnsweredTime == null) //IVR挂断
-            || (x.WaitDuration > 0 && x.RingDuration == 0))//队列挂断
+            (x.AnsweredTime == null && x.RingDuration <= noConnectByeTimes && x.RingDuration > 0)  //未接通秒挂
+            || (x.AnsweredTime != null && x.Duration <= connectByeTimes)  //接通秒挂
+            || (x.AnsweredTime != null && x.Duration >= effectiveTimes)//有效接通
+            || (x.CallState == ECallState.IVRNoAccept) //IVR挂断
+            || (x.CallState == ECallState.NotAcceptedHang))//队列挂断
             .WhereIF(dto.StartHourTo.HasValue, x => SqlFunc.ToTime(x.BeginIvrTime.Value.ToString("HH:mm:ss")) >= dto.StartHourTo.Value && SqlFunc.ToTime(x.BeginIvrTime.Value.ToString("HH:mm:ss")) < endHourTo)
             .Select(x => new BiSeatSwitchDto
             {

+ 13 - 0
src/Hotline.Share/Dtos/CallCenter/CallDto.cs

@@ -166,4 +166,17 @@ namespace Hotline.Share.Dtos.CallCenter
         /// </summary>
         public string TrunkLine { get; set; }
     }
+
+    public class VisitRelevanceCallIdDto
+    {
+        /// <summary>
+        /// 回访Id
+        /// </summary>
+        public string OrderVisitId { get; set; }
+
+        /// <summary>
+        /// 通话Id
+        /// </summary>
+        public string CallId { get; set; }
+    }
 }