qinchaoyue 7 ay önce
ebeveyn
işleme
8123877997
45 değiştirilmiş dosya ile 1227 ekleme ve 646 silme
  1. 45 13
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  2. 14 0
      src/Hotline.Api/Controllers/CallController.cs
  3. 189 171
      src/Hotline.Api/Controllers/CommonPController.cs
  4. 156 84
      src/Hotline.Api/Controllers/OrderController.cs
  5. 1 0
      src/Hotline.Api/Controllers/SysController.cs
  6. 77 241
      src/Hotline.Api/Controllers/TestController.cs
  7. 2 1
      src/Hotline.Api/Controllers/WebPortalController.cs
  8. 1 1
      src/Hotline.Api/StartupExtensions.cs
  9. 27 2
      src/Hotline.Api/StartupHelper.cs
  10. 1 1
      src/Hotline.Api/config/appsettings.Development.json
  11. 9 9
      src/Hotline.Application/CallCenter/DefaultCallApplication.cs
  12. 0 1
      src/Hotline.Application/CallCenter/ICallApplication.cs
  13. 15 1
      src/Hotline.Application/CallCenter/TianRunCallApplication.cs
  14. 1 0
      src/Hotline.Application/CallCenter/XingTangCallApplication.cs
  15. 1 1
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  16. 5 4
      src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs
  17. 12 6
      src/Hotline.Application/Handlers/FlowEngine/WorkflowStartHandler.cs
  18. 29 0
      src/Hotline.Application/Jobs/CheckAiVisitStateJob.cs
  19. 32 0
      src/Hotline.Application/Jobs/SendOverTimeSmsJob.cs
  20. 8 0
      src/Hotline.Application/Mappers/CallMapperConfigs.cs
  21. 9 7
      src/Hotline.Application/Orders/IOrderApplication.cs
  22. 35 24
      src/Hotline.Application/Orders/OrderApplication.cs
  23. 18 12
      src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs
  24. 3 3
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  25. 1 7
      src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs
  26. 2 30
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  27. 9 4
      src/Hotline.Application/Subscribers/InternalCapSubscriber.cs
  28. 152 3
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  29. 3 1
      src/Hotline.Share/Dtos/CallCenter/CallNativeDto.cs
  30. 6 0
      src/Hotline.Share/Dtos/FlowEngine/PreviousWorkflowDto.cs
  31. 1 1
      src/Hotline.Share/Dtos/Order/HomeOrderDto.cs
  32. 2 2
      src/Hotline.Share/Dtos/Order/OrderBiDto.cs
  33. 9 0
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  34. 8 0
      src/Hotline.Share/Dtos/Order/OrderVisitDto.cs
  35. 83 0
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  36. 10 4
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  37. 19 6
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  38. 67 0
      src/Hotline/Orders/AiVisitDomainService.cs
  39. 13 0
      src/Hotline/Orders/IAiVisitDomainService.cs
  40. 7 0
      src/Hotline/Orders/IOrderDomainService.cs
  41. 22 1
      src/Hotline/Orders/IOrderRepository.cs
  42. 61 1
      src/Hotline/Orders/OrderDomainService.cs
  43. 45 0
      src/Hotline/Permissions/EPermission.cs
  44. 5 0
      src/Hotline/Settings/SettingConstants.cs
  45. 12 4
      src/Hotline/dataview.md

+ 45 - 13
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -1138,11 +1138,11 @@ namespace Hotline.Api.Controllers.Bi
         /// <param name="dto"></param>
         /// <returns></returns>
         [HttpGet("visit-org-satisfaction-detail")]
-        public async Task<PagedDto<OrderVisitDetailDto>> VisitAndOrgSatisfactionDetail([FromQuery] VisitAndOrgSatisfactionDetailDto dto)
+        public async Task<PagedDto<OrgVisitDetailListResp>> VisitAndOrgSatisfactionDetail([FromQuery] VisitAndOrgSatisfactionDetailDto dto)
         {
-            var (total, items) = await _orderApplication.VisitAndOrgSatisfactionDetail(dto)
+            var (total, items) = await _orderRepository.VisitAndOrgSatisfactionDetail(dto)
                 .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-            return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
+            return new PagedDto<OrgVisitDetailListResp>(total, _mapper.Map<IReadOnlyList<OrgVisitDetailListResp>>(items));
         }
 
         /// <summary>
@@ -1153,8 +1153,8 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("visit-org-satisfaction-detail/_export")]
         public async Task<FileStreamResult> VisitAndOrgSatisfactionDetailExport([FromBody] ExportExcelDto<VisitAndOrgSatisfactionDetailDto> dto)
         {
-            var query = _orderApplication.VisitAndOrgSatisfactionDetail(dto.QueryDto);
-            List<OrderVisitDetail> data;
+            var query = _orderRepository.VisitAndOrgSatisfactionDetail(dto.QueryDto);
+            List<OrgVisitDetailListResp> data;
             if (dto.IsExportAll)
             {
                 data = await query.ToListAsync(HttpContext.RequestAborted);
@@ -1165,12 +1165,11 @@ namespace Hotline.Api.Controllers.Bi
                 data = items;
             }
 
-            var dataDtos = _mapper.Map<ICollection<OrderVisitDetailDto>>(data);
 
             dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
 
-            var dtos = dataDtos
-                .Select(stu => _mapper.Map(stu, typeof(OrderVisitDetailDto), dynamicClass))
+            var dtos = data
+                .Select(stu => _mapper.Map(stu, typeof(OrgVisitDetailListResp), dynamicClass))
                 .Cast<object>()
                 .ToList();
 
@@ -2975,7 +2974,7 @@ namespace Hotline.Api.Controllers.Bi
         [HttpGet("org-visitdetail-list")]
         public async Task<PagedDto<OrgVisitDetailListResp>> OrgVisitDetailList([FromQuery] OrgVisitDetailListReq dto)
         {
-            var query = _orderReportApplication.OrgVisitDetailList(dto);
+            var query = _orderRepository.OrgVisitDetailList(dto);
             var (total, items) = await query.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
             return new PagedDto<OrgVisitDetailListResp>(total, _mapper.Map<IReadOnlyList<OrgVisitDetailListResp>>(items));
@@ -3008,9 +3007,9 @@ namespace Hotline.Api.Controllers.Bi
         [HttpPost("org-visitdetail-list-export")]
         public async Task<FileStreamResult> OrgVisitDetailListExport([FromBody] ExportExcelDto<OrgVisitDetailListReq> dto)
         {
-            var query = _orderReportApplication.OrgVisitDetailList(dto.QueryDto);
+            var query = _orderRepository.OrgVisitDetailList(dto.QueryDto);
 
-            List<OrderVisitDetail> orders;
+            List<OrgVisitDetailListResp> orders;
             if (dto.IsExportAll)
             {
                 orders = await query.ToListAsync(HttpContext.RequestAborted);
@@ -3020,9 +3019,9 @@ namespace Hotline.Api.Controllers.Bi
                 var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
                 orders = items;
             }
-            var ordersDtos = _mapper.Map<ICollection<OrgVisitDetailListResp>>(orders);
+            //var ordersDtos = _mapper.Map<ICollection<OrgVisitDetailListResp>>(orders);
             dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-            var dtos = ordersDtos
+            var dtos = orders
                 .Select(stu => _mapper.Map(stu, typeof(OrgVisitDetailListResp), dynamicClass))
                 .Cast<object>()
                 .ToList();
@@ -4023,5 +4022,38 @@ namespace Hotline.Api.Controllers.Bi
 
         }
 
+        /// <summary>
+        /// 扭转信件统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("ordervisit-jude-statistics")]
+        public async Task<List<OrderVisitJudeStatisticsRep>> OrderVisitJudeStatistics([FromQuery] OrderVisitJudeStatisticsReq dto)
+        {
+            var list = await _orderApplication.OrderVisitJudeStatistics(dto).ToListAsync();
+            return list;
+        }
+
+        /// <summary>
+        /// 扭转信件统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("ordervisit-jude-statistics-export")]
+        public async Task<FileStreamResult> OrderVisitJudeStatisticsExport([FromBody]ExportExcelDto<OrderVisitJudeStatisticsReq> dto)
+        {
+            var query = _orderApplication.OrderVisitJudeStatistics(dto.QueryDto);
+            List<OrderVisitJudeStatisticsRep> exportList;
+            exportList = await query.ToListAsync(HttpContext.RequestAborted);
+            var ordersDtos = _mapper.Map<ICollection<OrderVisitJudeStatisticsRep>>(exportList);
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+            var dtos = ordersDtos
+                .Select(stu => _mapper.Map(stu, typeof(OrderVisitJudeStatisticsRep), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+            return ExcelStreamResult(stream, "扭转信件统计");
+        }
     }
 }

+ 14 - 0
src/Hotline.Api/Controllers/CallController.cs

@@ -13,6 +13,7 @@ using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
+using System.Threading;
 using XF.Domain.Exceptions;
 using XF.Utility.EnumExtensions;
 
@@ -97,6 +98,19 @@ namespace Hotline.Api.Controllers
         public Task<IReadOnlyList<CallNativeDto>> QueryCallsFixed([FromQuery] QueryCallsFixedDto dto)
             => _callApplication.QueryCallsFixedAsync(dto, HttpContext.RequestAborted);
 
+        /// <summary>
+        /// 查询通话记录
+        /// </summary>
+        /// <param name="callId"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        [HttpGet("{callId}")]
+        public Task<CallNative?> GetCall(string callId)
+        {
+            if (string.IsNullOrEmpty(callId)) return default;
+            return _callApplication.GetCallAsync(callId, HttpContext.RequestAborted);
+        }
+
         /// <summary>
         /// 通话记录基础数据
         /// </summary>

+ 189 - 171
src/Hotline.Api/Controllers/CommonPController.cs

@@ -24,6 +24,7 @@ using Hotline.Configurations;
 using Hotline.Share.Dtos.Order;
 using System.Runtime.InteropServices;
 using Lucene.Net.Util;
+using NPOI.Util;
 
 namespace Hotline.Api.Controllers
 {
@@ -98,126 +99,118 @@ namespace Hotline.Api.Controllers
 
 		#endregion
 
-		/// <summary>
-		/// 首页基础数据
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("home_data")]
-		public async Task<Object> GetHomeData()
-		{
-			var tadayTime = DateTime.Now.ToString("yyyy-MM-dd");
-			//中心
-			if (_sessionContext.OrgIsCenter)
-			{
-				var orderQuery = _orderRepository.Queryable(false, false, false)
-					.Includes(o => o.Workflow, w => w.Steps);
-				//今日来电
-				//  var tadayCalls = await _trCallRecordRepository.Queryable()
-				//      .Where(x => x.CallDirection == Share.Enums.CallCenter.ECallDirection.In && tadayTime.Equals(x.CreatedTime.ToString("yyyy-MM-dd"))).ToListAsync();
-				//  var callNum = tadayCalls.Count();
-				//  var validCallNum = tadayCalls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
-				//  //今日接通率
-				//  var answeredNum = tadayCalls.Where(x => x.Duration > 0).Count();
-				// var answeredRate = validCallNum > 0 ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%" : "-";
+        /// <summary>
+        /// 首页基础数据
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("home_data")]
+        public async Task<Object> GetHomeData()
+        {
+            var tadayTime = DateTime.Now.ToString("yyyy-MM-dd");
+            //中心
+            if (_sessionContext.OrgIsCenter)
+            {
+                var orderQuery = _orderRepository.Queryable(false, false, false)
+                    .Includes(o => o.Workflow, w => w.Steps);
+                //今日来电
+                //  var tadayCalls = await _trCallRecordRepository.Queryable()
+                //      .Where(x => x.CallDirection == Share.Enums.CallCenter.ECallDirection.In && tadayTime.Equals(x.CreatedTime.ToString("yyyy-MM-dd"))).ToListAsync();
+                //  var callNum = tadayCalls.Count();
+                //  var validCallNum = tadayCalls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
+                //  //今日接通率
+                //  var answeredNum = tadayCalls.Where(x => x.Duration > 0).Count();
+                // var answeredRate = validCallNum > 0 ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%" : "-";
 
-				int callNum = 0, validCallNum = 0, answeredNum = 0;
-				var answeredRate = string.Empty;
-				var today = DateTime.Today.Date;
-				if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
-				{
-					var calls = await _callApplication.QueryTianrunCallsAsync(
-						direction: ECallDirection.In,
-						callStartTimeStart: today,
-						callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
-						cancellationToken: HttpContext.RequestAborted);
-					callNum = calls.Count();
-					validCallNum = calls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
-					//今日接通率
-					answeredNum = calls.Where(x => x.Duration > 0).Count();
-					answeredRate = validCallNum > 0
-						? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
-						: "-";
-				}
-				else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
-				{
-					var calls = await _callApplication.QueryCallsAsync(
-						callStartTimeStart: today,
-						callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
-						cancellationToken: HttpContext.RequestAborted);
-					callNum = calls.Count();
-					validCallNum = calls.Where(x => x.Duration > 0 || x.WaitDuration > 0 || x.RingDuration > 0).Count();
-					//今日接通率
-					answeredNum = calls.Where(x => x.Duration > 0).Count();
-					answeredRate = validCallNum > 0
-						? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
-						: "-";
-				}
+                int callNum = 0, validCallNum = 0, answeredNum = 0;
+                var answeredRate = string.Empty;
+                var today = DateTime.Today.Date;
+                if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
+                {
+                    var calls = await _callApplication.QueryTianrunCallsAsync(
+                        direction: ECallDirection.In,
+                        callStartTimeStart: today,
+                        callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
+                        cancellationToken: HttpContext.RequestAborted);
+                    callNum = calls.Count();
+                    validCallNum = calls.Where(x => x.Duration > 0 || x.QueueTims > 0 || x.RingTimes > 0).Count();
+                    //今日接通率
+                    answeredNum = calls.Where(x => x.Duration > 0).Count();
+                    answeredRate = validCallNum > 0
+                        ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
+                        : "-";
+                }
+                else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
+                {
+                    var calls = await _callApplication.QueryCallsAsync(
+                        callStartTimeStart: today,
+                        callStartTimeEnd: today.AddDays(1).AddSeconds(-1),
+                        cancellationToken: HttpContext.RequestAborted);
+                    callNum = calls.Count();
+                    validCallNum = calls.Where(x => x.Duration > 0 || x.WaitDuration > 0 || x.RingDuration > 0).Count();
+                    //今日接通率
+                    answeredNum = calls.Where(x => x.Duration > 0).Count();
+                    answeredRate = validCallNum > 0
+                        ? Math.Round((double.Parse(answeredNum.ToString()) / double.Parse(validCallNum.ToString())) * 100, 2) + "%"
+                        : "-";
+                }
 
-				//今日受理工单
-				var tadayOrders = await orderQuery
-					.Where(o => tadayTime.Equals(o.CreationTime.ToString("yyyy-MM-dd"))).ToListAsync();
-				var orderNum = tadayOrders.Count();
-				var directlyNum = tadayOrders.Where(o => o.ProcessType == Share.Enums.Order.EProcessType.Zhiban).Count();
-				return new
-				{
-					CallNum = callNum,
-					ValidCallNum = validCallNum,
-					AnsweredNum = answeredNum,
-					AnsweredRate = answeredRate,
-					OrderNum = orderNum,
-					DirectlyNum = directlyNum
-				};
-			}
+                //今日受理工单
+                var tadayOrders = await orderQuery
+                    .Where(o => tadayTime.Equals(o.CreationTime.ToString("yyyy-MM-dd"))).ToListAsync();
+                var orderNum = tadayOrders.Count();
+                var directlyNum = tadayOrders.Where(o => o.ProcessType == Share.Enums.Order.EProcessType.Zhiban).Count();
+                return new
+                {
+                    CallNum = callNum, ValidCallNum = validCallNum, AnsweredNum = answeredNum, AnsweredRate = answeredRate, OrderNum = orderNum,
+                    DirectlyNum = directlyNum
+                };
+            }
 
-			//部门
-			//今日待办 tasksOkNum
-			//var time = DateTime.Parse(tadayTime);
-			//工单
-			var order = await _orderRepository.Queryable(hasHandled: false)
-				.Includes(d => d.OrderSpecials)
-				.Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status != EOrderStatus.HandOverToUnAccept)
+            //部门
+            //今日待办 tasksOkNum
+            //var time = DateTime.Parse(tadayTime);
+            //工单
+            var order = await _orderRepository.Queryable(hasHandled: false)
+	            .Includes(d => d.OrderSpecials)
+	            .Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status !=  EOrderStatus.HandOverToUnAccept)
 				.Where(d => d.Source < ESource.MLSQ || d.Source > ESource.WZSC)
-				.Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed)
-				.Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0))
-				.GroupBy(o => new { o.Id, o.Status })
-				.Select(o => new
-				{
-					aboutExpire = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.NearlyExpiredTime!.Value && DateTime.Now < o.ExpiredTime!.Value,
-						1, 0)),
-					havExpired = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.ExpiredTime!.Value, 1, 0)),
-					countersignHandle = SqlFunc.AggregateSum(SqlFunc.IIF(o.CounterSignType.HasValue, 1, 0)),
-				}).ToListAsync();
-			var aboutExpire = order?.Sum(x => x.aboutExpire) ?? 0;
-			var havExpired = order?.Sum(x => x.havExpired) ?? 0;
-			var countersignHandle = order?.Sum(x => x.countersignHandle) ?? 0;
-			//延期
-			var delay = await _orderDelayRepository.Queryable(hasHandled: false)
-				.Where(d => d.DelayState == EDelayState.Examining).CountAsync();
-			//甄别
-			var screenAudit = await _orderScreenRepository.Queryable(hasHandled: false)
-				.Where(x => x.CreationTime < DateTime.Now && x.CreationTime > DateTime.Now.AddMonths(-2))
-				.Where(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval || (x.Status == EScreenStatus.SendBack && x.SendBackApply == false)))
-				//.Where(d => d.Status == EScreenStatus.Apply)
-				.CountAsync();
-			//var workTime = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
-			var screenHandle = await _orderVisitedDetailRepository.Queryable(false, true)
-				.Includes(x => x.OrderVisit)
-				.Includes(x => x.OrderScreens)
+	            .Where(d => d.Status != EOrderStatus.BackToProvince && d.Status < EOrderStatus.Filed)
+	            .Where(d => d.OrderSpecials.Any() == false || d.OrderSpecials.Any(s => s.State > 0))
+				.GroupBy(o => new { o.Id,o.Status })
+                .Select(o => new
+                {
+                    aboutExpire = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.NearlyExpiredTime!.Value && DateTime.Now < o.ExpiredTime!.Value,
+                        1, 0)),
+                    havExpired = SqlFunc.AggregateSum(SqlFunc.IIF(DateTime.Now > o.ExpiredTime!.Value , 1, 0)),
+                    countersignHandle = SqlFunc.AggregateSum(SqlFunc.IIF(o.CounterSignType.HasValue, 1, 0)),
+                }).ToListAsync();
+            var aboutExpire = order?.Sum(x=>x.aboutExpire) ?? 0;
+            var havExpired = order?.Sum(x=>x.havExpired) ?? 0;
+            var countersignHandle = order?.Sum(x=> x.countersignHandle) ?? 0;
+            //延期
+            var delay = await _orderDelayRepository.Queryable(hasHandled: false)
+                .Where(d => d.DelayState == EDelayState.Examining).CountAsync();
+            //甄别
+            var screenAudit = await _orderScreenRepository.Queryable(hasHandled: false)
+                .Where(x=>x.CreationTime < DateTime.Now && x.CreationTime > DateTime.Now.AddMonths(-2))
+                .Where(x => (x.Status == EScreenStatus.Apply || x.Status == EScreenStatus.Approval || (x.Status == EScreenStatus.SendBack && x.SendBackApply == false)))
+                //.Where(d => d.Status == EScreenStatus.Apply)
+                .CountAsync();
+            //var workTime = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
+            var screenHandle = await _orderVisitedDetailRepository.Queryable(false, true)
+                .Includes(x => x.OrderVisit)
+                .Includes(x => x.OrderScreens)
 				.Where(x => x.OrderScreens.Any(s => s.Status == EScreenStatus.SendBack && s.SendBackApply == true) || x.OrderScreens.Any(s => (s.Status != EScreenStatus.SendBack && s.SendBackApply != true)) == false)
-				.Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
-				.Where(x => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
-					SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
-					SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2")).CountAsync();
-			return new
-			{
-				AboutExpire = aboutExpire,
-				HavExpired = havExpired,
-				CountersignHandle = countersignHandle,
-				ScreenAudit = screenAudit,
-				Delay = delay,
-				ScreenHandle = screenHandle
-			};
-		}
+                .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
+                .Where(x=> x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
+                    SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" || SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2" ||
+                    SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2")).CountAsync();
+            return new
+            {
+                AboutExpire = aboutExpire, HavExpired = havExpired, CountersignHandle = countersignHandle, ScreenAudit = screenAudit, Delay = delay,
+                ScreenHandle = screenHandle
+            };
+        }
 
 		/// <summary>
 		/// 首页基础数据
@@ -233,7 +226,7 @@ namespace Hotline.Api.Controllers
 			if (_sessionContext.OrgIsCenter)
 			{
 				//待办
-				var waitedList = await _orderRepository
+				var waitedDataList = await _orderRepository
 					.Queryable(hasHandled: false, isAdmin: isAdmin)
 					.Includes(d => d.OrderSpecials)
 					.Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status != EOrderStatus.HandOverToUnAccept)
@@ -250,20 +243,22 @@ namespace Hotline.Api.Controllers
 						HotspotName = d.HotspotName,
 						Type = "Waited",
 						Time = d.ExpiredTime,
-						Status =d.Status,
-						ActualHandleTime =d.ActualHandleTime,
+						Status = d.Status,
+						ActualHandleTime = d.ActualHandleTime,
 						CounterSignType = d.CounterSignType
 					})
 					.ToListAsync();
-				allNum += waitedList.Count > 40 ? 40: waitedList.Count;
-				allList.AddRange(waitedList);
+				var waitedList = waitedDataList.Take(40).ToList();
+				waitedList = waitedList.Count > 0 ? waitedList.Copy() : waitedList;
+				//allNum += waitedList.Count > 40 ? 40 : waitedList.Count;
+				//allList.AddRange(waitedList);
 				// 已超期
-				var waitedExpiredDataList = waitedList.Where(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
-				                                                  (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed)).ToList();
-				var waitedExpiredList = waitedExpiredDataList.Take(40).ToList();
-				waitedExpiredList.ForEach(x => x.Type = "WaitedExpired");
-				allNum += waitedExpiredDataList.Count;
-				allList.AddRange(waitedExpiredList);
+				var waitedExpiredDataList = waitedDataList.Where(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
+				                                                      (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed)).Take(40).ToList();
+				waitedExpiredDataList = waitedExpiredDataList.Count > 0 ? waitedExpiredDataList.Copy() : waitedExpiredDataList;
+				waitedExpiredDataList.ForEach(x => x.Type = "WaitedExpired");
+				//allNum += waitedExpiredDataList.Count;
+				//allList.AddRange(waitedExpiredDataList);
 				//回访待办
 				var visitDataList = await _orderVisitRepository.Queryable()
 					.Includes(d => d.Order)
@@ -284,14 +279,14 @@ namespace Hotline.Api.Controllers
 					})
 					.Take(40)
 					.ToListAsync();
-				allNum += visitDataList.Count;
-				allList.AddRange(visitDataList);
+				//allNum += visitDataList.Count;
+				//allList.AddRange(visitDataList);
 				//会签待办
-				var signDataList = waitedList.Where(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department).ToList();
-				var signList = signDataList.Take(40).ToList();
-				signList.ForEach(x => x.Type = "Sign");
-				allNum += signDataList.Count;
-				allList.AddRange(signList);
+				var signDataList = waitedDataList.Where(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department).Take(40).ToList();
+				signDataList = signDataList.Count > 0 ? signDataList.Copy() : signDataList;
+				signDataList.ForEach(x => x.Type = "Sign");
+				//allNum += signDataList.Count;
+				//allList.AddRange(signDataList);
 				//延期待审批
 				var delayDataList = await _orderDelayRepository.Queryable(canView: true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -310,8 +305,8 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += delayDataList.Count;
-				allList.AddRange(delayDataList);
+				//allNum += delayDataList.Count;
+				//allList.AddRange(delayDataList);
 				//部门即将超期
 				var nearlyExpiredDataList = await _orderRepository.Queryable(canView: !IsCenter)
 					.Includes(d => d.OrderDelays)
@@ -330,8 +325,8 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += nearlyExpiredDataList.Count;
-				allList.AddRange(nearlyExpiredDataList);
+				//allNum += nearlyExpiredDataList.Count;
+				//allList.AddRange(nearlyExpiredDataList);
 				//甄别待审批
 				var screenDataList = await _orderScreenRepository.Queryable(hasHandled: !true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -350,8 +345,8 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += screenDataList.Count;
-				allList.AddRange(screenDataList);
+				//allNum += screenDataList.Count;
+				//allList.AddRange(screenDataList);
 				//退回待审批
 				var sendBackAuditDataList = await _orderSendBackAuditRepository.Queryable()
 					.Includes(d => d.Order)
@@ -371,16 +366,16 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += sendBackAuditDataList.Count;
-				allList.AddRange(sendBackAuditDataList);
+				//allNum += sendBackAuditDataList.Count;
+				//allList.AddRange(sendBackAuditDataList);
 				return new
 				{
-					AllNum = allNum,
-					AllList = allList,
+					//AllNum = allNum,
+					//AllList = allList,
 					WaitedNum = waitedList.Count > 40 ? 40 : waitedList.Count,
 					WaitedList = waitedList.Take(40).ToList(),
 					WaitedExpiredNum = waitedExpiredDataList.Count,
-					WaitedExpiredList = waitedExpiredList,
+					WaitedExpiredList = waitedExpiredDataList,
 					VisitListNum = visitDataList.Count,
 					VisitList = visitDataList,
 					SignDataNum = signDataList.Count,
@@ -398,7 +393,7 @@ namespace Hotline.Api.Controllers
 			else
 			{
 				//待办
-				var waitedList = await _orderRepository
+				var waitedDataList = await _orderRepository
 					.Queryable(hasHandled: false, isAdmin: isAdmin)
 					.Includes(d => d.OrderSpecials)
 					.Where(d => d.Status != EOrderStatus.WaitForAccept && d.Status != EOrderStatus.BackToUnAccept && d.Status != EOrderStatus.SpecialToUnAccept && d.Status != EOrderStatus.HandOverToUnAccept)
@@ -420,21 +415,24 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.CounterSignType
 					})
 					.ToListAsync();
-				allNum += waitedList.Count > 40 ? 40 : waitedList.Count;
-				allList.AddRange(waitedList);
+				var waitedList = waitedDataList.Take(40).ToList();
+				waitedList = waitedList.Count > 0 ? waitedList.Copy() : waitedList;
+				//allNum += waitedList.Count > 40 ? 40 : waitedList.Count;
+				//allList.AddRange(waitedList);
 				//已超期
-				var waitedExpiredDataList = waitedList.Where(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
-				                                                  (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed)).ToList();
-				var waitedExpiredList = waitedExpiredDataList.Take(40).ToList();
-				waitedExpiredList.ForEach(x => x.Type = "WaitedExpired");
-				allNum += waitedExpiredDataList.Count;
-				allList.AddRange(waitedExpiredList);
+				var waitedExpiredDataList = waitedDataList.Where(x => (x.Time < DateTime.Now && x.Status < EOrderStatus.Filed) ||
+				                                                      (x.Time < x.ActualHandleTime && x.Status >= EOrderStatus.Filed)).Take(40).ToList();
+				waitedExpiredDataList = waitedExpiredDataList.Count > 0 ? waitedExpiredDataList.Copy() : waitedExpiredDataList;
+				waitedExpiredDataList.ForEach(x => x.Type = "WaitedExpired");
+				//allNum += waitedExpiredDataList.Count;
+				//allList.AddRange(waitedExpiredDataList);
 				//会签待办
-				var signDataList = waitedList.Where(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department).ToList();
-				var signList = signDataList.Take(40).ToList();
-				signList.ForEach(x => x.Type = "Sign");
-				allNum += signDataList.Count;
-				allList.AddRange(signList);
+				var signDataList = waitedDataList.Where(x => x.CounterSignType == ECounterSignType.Center || x.CounterSignType == ECounterSignType.Department).Take(40).ToList();
+				signDataList = signDataList.Count > 0 ? signDataList.Copy() : signDataList;
+				signDataList.ForEach(x => x.Type = "Sign");
+				
+				//allNum += signDataList.Count;
+				//allList.AddRange(signDataList);
 				//甄别待审批
 				var screenDataList = await _orderScreenRepository.Queryable(hasHandled: !true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -453,8 +451,8 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += screenDataList.Count;
-				allList.AddRange(screenDataList);
+				//allNum += screenDataList.Count;
+				//allList.AddRange(screenDataList);
 				//延期待审批
 				var delayDataList = await _orderDelayRepository.Queryable(canView: true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -473,8 +471,8 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += delayDataList.Count;
-				allList.AddRange(delayDataList);
+				//allNum += delayDataList.Count;
+				//allList.AddRange(delayDataList);
 				//甄别待申请
 				var screenApplyDataList = await _orderVisitedDetailRepository.Queryable(false, true)
 				.Includes(x => x.OrderVisit)
@@ -502,13 +500,13 @@ namespace Hotline.Api.Controllers
 					Status = x.OrderVisit.Order.Status,
 					CounterSignType = x.OrderVisit.Order.CounterSignType
 				}).Take(40).ToListAsync();
-				allNum += screenApplyDataList.Count;
-				allList.AddRange(screenApplyDataList);
+				//allNum += screenApplyDataList.Count;
+				//allList.AddRange(screenApplyDataList);
 				//退回待审批
 				var sendBackAuditDataList = await _orderSendBackAuditRepository.Queryable()
 					.Includes(d => d.Order)
 					.Where(d => d.State == ESendBackAuditState.Apply)
-					.WhereIF(_sessionContext.Roles.Contains("role_sysadmin") == false , x => x.SendBackOrgId == _sessionContext.OrgId) // 123 系统管理员;
+					.WhereIF(_sessionContext.Roles.Contains("role_sysadmin") == false, x => x.SendBackOrgId == _sessionContext.OrgId) // 123 系统管理员;
 					.OrderByDescending(d => d.CreationTime)
 					.Select(d => new HomeOrderDto
 					{
@@ -523,16 +521,34 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.Order.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				allNum += sendBackAuditDataList.Count;
-				allList.AddRange(sendBackAuditDataList);
+				//allNum += sendBackAuditDataList.Count;
+				//allList.AddRange(sendBackAuditDataList);
+				//部门即将超期
+				var nearlyExpiredDataList = await _orderRepository.Queryable(canView: !IsCenter)
+					.Includes(d => d.OrderDelays)
+					.Where(d => d.Status < EOrderStatus.Filed && DateTime.Now > d.NearlyExpiredTime && DateTime.Now < d.ExpiredTime)
+					.OrderByDescending(d => d.CreationTime)
+					.Select(d => new HomeOrderDto
+					{
+						No = d.No,
+						OrderId = d.Id,
+						Title = d.Title,
+						AcceptType = d.AcceptType,
+						HotspotName = d.HotspotName,
+						Type = "NearlyExpired",
+						Time = d.ExpiredTime,
+						Status = d.Status,
+						CounterSignType = d.CounterSignType
+					}).Take(40)
+					.ToListAsync();
 				return new
 				{
-					AllNum = allNum,
-					AllList = allList,
+					//AllNum = allNum,
+					//AllList = allList,
 					WaitedNum = waitedList.Count > 40 ? 40 : waitedList.Count,
 					WaitedList = waitedList.Take(40).ToList(),
 					WaitedExpiredNum = waitedExpiredDataList.Count,
-					WaitedExpiredList = waitedExpiredList,
+					WaitedExpiredList = waitedExpiredDataList,
 					SignDataNum = signDataList.Count,
 					SignDataList = signDataList,
 					ScreenNum = screenDataList.Count,
@@ -542,7 +558,9 @@ namespace Hotline.Api.Controllers
 					ScreenApplyNum = screenApplyDataList.Count,
 					ScreenApplyList = screenApplyDataList,
 					SendBackAuditNum = sendBackAuditDataList.Count,
-					SendBackAuditList = sendBackAuditDataList
+					SendBackAuditList = sendBackAuditDataList,
+					NearlyExpiredNum = nearlyExpiredDataList.Count,
+					NearlyExpiredList = nearlyExpiredDataList,
 				};
 			}
 		}

+ 156 - 84
src/Hotline.Api/Controllers/OrderController.cs

@@ -6,6 +6,7 @@ using Hotline.Application.FlowEngine;
 using Hotline.Application.Orders;
 using Hotline.Application.Quality;
 using Hotline.Caching.Interfaces;
+using Hotline.Caching.Services;
 using Hotline.Configurations;
 using Hotline.ContingencyManagement.Notifies;
 using Hotline.EventBus;
@@ -1193,34 +1194,58 @@ public class OrderController : BaseController
     [HttpGet("visit/judge-query")]
     public async Task<PagedDto<OrderVisitDto>> VisitJudgeQuery([FromQuery] VisitJudgeQueryReq dto)
     {
-        var (total, items) = await _orderVisitRepository.Queryable()
-            .Includes(x => x.Order)
-            .Includes(x => x.Employee)
-            .Where(x => x.VisitState == EVisitState.Visited)
-            .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
-            .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title))
-            .WhereIF(!string.IsNullOrEmpty(dto.VisitUserName), x => x.Employee.Name.Contains(dto.VisitUserName))
-            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)//受理类型
-            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
-            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.Order.CurrentHandleOrgId == dto.OrgId)//接办部门
-            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo),
-                d => d.Order.AcceptorName.Contains(dto.NameOrNo!) || d.Order.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
-            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
-            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-            .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
-            .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.Order.ActualHandleTime <= dto.ActualHandleTimeEnd) //办结时间结束
-            .WhereIF(dto.VisitTimeStart.HasValue, d => d.VisitTime >= dto.VisitTimeStart) //回访开始时间
-            .WhereIF(dto.VisitTimeEnd.HasValue, d => d.VisitTime <= dto.VisitTimeEnd)
-            .WhereIF(dto.IsIng == true, d => d.JudgeState == EJudgeState.Judging)
-            .WhereIF(dto.IsIng == false, d => d.JudgeState != EJudgeState.Judging)
-            .WhereIF(dto.JudgeState != null, d => d.JudgeState == dto.JudgeState)
-            .WhereIF(dto.OrgJudge != null, d => d.OrgJudge == dto.OrgJudge)
-            .WhereIF(dto.SeatJudge != null, d => d.SeatJudge == dto.SeatJudge)
-            .OrderByDescending(x => x.VisitTime)
+        var (total, items) = await _orderRepository.VisitJudgeQuery(dto)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
         return new PagedDto<OrderVisitDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDto>>(items));
     }
 
+    /// <summary>
+    /// 扭转列表查询基础数据
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("visit/judge-query-basedata")]
+    public async Task<object> VisitJudgeQueryBaseData()
+    {
+        return new
+        {
+            FiledTypeOptions = EnumExts.GetDescriptions<FiledType>(),
+            AcceptTypeOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
+            OrgsOptions = await _organizeRepository.GetOrgJson(),
+            CallForwardingOptions = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.CallForwardingSource)
+        };
+    }
+
+    /// <summary>
+    /// 扭转列表导出
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("visit/judge-query-export")]
+    public async Task<FileStreamResult> VisitJudgeQueryExport([FromBody]ExportExcelDto<VisitJudgeQueryReq> dto)
+    {
+        var query = _orderRepository.VisitJudgeQuery(dto.QueryDto);
+
+        List<OrderVisit> datas;
+        if (dto.IsExportAll)
+        {
+            datas = await query.ToListAsync(HttpContext.RequestAborted);
+        }
+        else
+        {
+            var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+            datas = items;
+        }
+        var orderDtos = _mapper.Map<ICollection<OrderVisitDto>>(datas);
+        dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+        var dtos = orderDtos
+            .Select(stu => _mapper.Map(stu, typeof(OrderVisitDto), dynamicClass))
+            .Cast<object>()
+            .ToList();
+
+        var stream = ExcelHelper.CreateStream(dtos);
+        return ExcelStreamResult(stream, "扭转明细");
+    }
+
     /// <summary>
     /// 扭转满意度
     /// </summary>
@@ -2016,7 +2041,7 @@ public class OrderController : BaseController
 
         var (total, items) = await query
             .WhereIF(dto.DataScope is 1, x => x.CreatorId == _sessionContext.RequiredUserId)
-            //.WhereIF(dto.Status.HasValue, x => x.Status == dto.Status)
+            .WhereIF(dto.Status.HasValue, x => x.Status == dto.Status)
             .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.Order!.AcceptTypeCode! == dto.AcceptType!)
             .WhereIF(!string.IsNullOrEmpty(dto.HotspotSpliceName), x => x.Order!.Hotspot.HotSpotFullName!.StartsWith(dto.HotspotSpliceName!))
             .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.Order!.SourceChannelCode! == dto.SourceChannel!)
@@ -2329,10 +2354,11 @@ public class OrderController : BaseController
                 //发送短信
                 try
                 {
+                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                     //查询部门所有账号
                     var userlist = await _userRepository.Queryable().Where(x =>
                         x.OrgId == model.OrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
-                        x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                        x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
                     //发送短信
                     foreach (var user in userlist)
                     {
@@ -2573,10 +2599,11 @@ public class OrderController : BaseController
             {
                 try
                 {
+                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                     //查询部门所有账号
                     var userlist = await _userRepository.Queryable().Where(x =>
                         x.OrgId == model.OrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
-                        x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                        x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
                     foreach (var user in userlist)
                     {
                         //发送短信
@@ -3685,7 +3712,7 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)
             .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
-            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
+            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => d.CounterSignType == null)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
                 d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) ||
                      (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办
@@ -3798,7 +3825,7 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)
             .WhereIF(!string.IsNullOrEmpty(dto.AreaCode), d => d.AreaCode == dto.AreaCode)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
-            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
+            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => d.CounterSignType == null)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
                 d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) ||
                      (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办
@@ -3953,7 +3980,7 @@ public class OrderController : BaseController
             .WhereIF(dto.IsProvince.HasValue, d => d.IsProvince == dto.IsProvince)
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.No.Contains(dto.Keyword) || d.Title.Contains(dto.Keyword))
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
-            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
+            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => d.CounterSignType == null)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
                 d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) ||
                      (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办
@@ -3997,7 +4024,7 @@ public class OrderController : BaseController
             .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.StartsWith(dto.Keyword!))
             .WhereIF(!string.IsNullOrEmpty(dto.No), d => d.No == dto.No)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
-            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
+            .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => d.CounterSignType == null)
             .WhereIF(dto.ExpiredOrAlmostOverdue.HasValue && dto.ExpiredOrAlmostOverdue == true,
                 d => (d.ExpiredTime < DateTime.Now && d.Status < EOrderStatus.Filed) ||
                      (d.ExpiredTime < d.ActualHandleTime && d.Status >= EOrderStatus.Filed)) //超期 未办
@@ -4075,7 +4102,8 @@ public class OrderController : BaseController
                 audit.State = ESendBackAuditState.End;
                 audit.AuditUser = "默认通过";
                 audit.AuditTime = DateTime.Now;
-                var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+                dto.ExpiredTime = order.ExpiredTime;
+				var flowDirection = await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
                 var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter
                     ? EProcessType.Zhiban
                     : EProcessType.Jiaoban;
@@ -4130,9 +4158,11 @@ public class OrderController : BaseController
         //执行退回
         if (sendBack.State == ESendBackAuditState.End)
         {
-            //string applicantId, string applicantOrgId, string[] applicantRoleIds,
-            //    ISessionContext current, CancellationToken cancellationToken);
-            var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId,
+	        var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.Id == sendBack.OrderId);
+			//string applicantId, string applicantOrgId, string[] applicantRoleIds,
+			//    ISessionContext current, CancellationToken cancellationToken);
+			sendBack.SendBackData.ExpiredTime = order.ExpiredTime;
+			var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId,
                 sendBack.WorkflowOrgId, sendBack.WorkflowRoleIds.ToArray(), _sessionContext,
                 HttpContext.RequestAborted);
             //var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, HttpContext.RequestAborted);
@@ -4140,7 +4170,6 @@ public class OrderController : BaseController
                               flowDirection == EFlowDirection.CenterToCenter
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
-            var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.Id == sendBack.OrderId);
 			if (sendBack.ApplyOrgId != OrgSeedData.CenterId && sendBack.SendBackOrgId == OrgSeedData.CenterId)
 				order.SendBackNum = order.SendBackNum.HasValue ? order.SendBackNum.Value + 1 : 1;
 			await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType,SendBackNum = order.SendBackNum })
@@ -4181,14 +4210,15 @@ public class OrderController : BaseController
             //执行退回
             if (sendBack.State == ESendBackAuditState.End)
             {
-                var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData,
+	            var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.Id == sendBack.OrderId);
+	            sendBack.SendBackData.ExpiredTime = order.ExpiredTime;
+				var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData,
                     sendBack.WorkflowUserId, sendBack.WorkflowOrgId, sendBack.WorkflowRoleIds.ToArray(),
                     _sessionContext, HttpContext.RequestAborted);
                 //var flowDirection = await _workflowApplication.PreviousAsync(sendBack.SendBackData, sendBack.WorkflowUserId, HttpContext.RequestAborted);
                 var processType = flowDirection == EFlowDirection.OrgToCenter || flowDirection == EFlowDirection.CenterToCenter
                     ? EProcessType.Zhiban
                     : EProcessType.Jiaoban;
-                var order = await _orderRepository.Queryable().Includes(d => d.Workflow).FirstAsync(d => d.Id == sendBack.OrderId);
                 if (sendBack.ApplyOrgId != OrgSeedData.CenterId && sendBack.SendBackOrgId == OrgSeedData.CenterId)
 	                order.SendBackNum = order.SendBackNum.HasValue ? order.SendBackNum.Value + 1 : 1;
 				await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ProcessType = processType, SendBackNum = order.SendBackNum })
@@ -4541,10 +4571,16 @@ public class OrderController : BaseController
             var processType = dto.FlowDirection is EFlowDirection.OrgToCenter or EFlowDirection.CenterToCenter or EFlowDirection.FiledToCenter
                 ? EProcessType.Zhiban
                 : EProcessType.Jiaoban;
-            //var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
-            //	ETimeType.WorkDay,
-            //	dto.TimeLimit.Value, order.AcceptTypeCode);
-            await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType, Status = EOrderStatus.Special })
+            if (expiredTime.ExpiredTime < order.ExpiredTime)
+            {
+                expiredTime.ExpiredTime = order.ExpiredTime.Value;
+                expiredTime.NearlyExpiredTime = order.NearlyExpiredTime.Value;
+                expiredTime.NearlyExpiredTimeOne = order.NearlyExpiredTimeOne.Value;
+			}
+			//var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now,
+			//	ETimeType.WorkDay,
+			//	dto.TimeLimit.Value, order.AcceptTypeCode);
+			await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ProcessType = processType, Status = EOrderStatus.Special })
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
             var orderDto = _mapper.Map<OrderDto>(order);
             await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto,
@@ -4552,6 +4588,30 @@ public class OrderController : BaseController
             //}
             await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, EWorkflowTraceType.Recall, HttpContext.RequestAborted);
 
+            if (order.Status  >= EOrderStatus.Filed)
+            {
+				var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == dto.OrderId);
+				if (publish != null)
+				{
+					var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+					publishHistory.OrderPublishId = publish.Id;
+					publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+					publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+					publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+					publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+					publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+					publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+					await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
+					await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
+				}
+
+				var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == dto.OrderId && x.VisitState != EVisitState.None);
+				if (visit != null)
+				{
+					visit.VisitState = EVisitState.None;
+					await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
+				}
+			}
 
             if (order != null && ("001171".Equals(model.OrgId) ||
                                   "001178".Equals(model.OrgId) ||
@@ -4665,7 +4725,13 @@ public class OrderController : BaseController
                     DateTime.Now,
                     ETimeType.WorkDay,
                     dto.TimeLimit.Value, order.AcceptTypeCode);
-                endTime = expiredTime.EndTime;
+                if (expiredTime.EndTime < order.ExpiredTime.Value)
+                {
+	                expiredTime.EndTime = order.ExpiredTime.Value;
+	                expiredTime.NearlyExpiredTime = order.NearlyExpiredTime.Value;
+	                expiredTime.NearlyExpiredTimeOne = order.NearlyExpiredTimeOne.Value;
+                }
+				endTime = expiredTime.EndTime;
                 await _orderRepository.Updateable().SetColumns(o => new Orders.Order() { ExpiredTime = expiredTime.EndTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne })
                     .Where(o => o.Id == order.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
                 var orderDto = _mapper.Map<OrderDto>(order);
@@ -4768,27 +4834,30 @@ public class OrderController : BaseController
             //todo 特提重办,按审批通过时间依据中心派至部门的规则计算期满时间,更新order
 
             await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, EWorkflowTraceType.Recall, HttpContext.RequestAborted);
-            //var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
-            //if (publish != null)
-            //{
-            //    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-            //    publishHistory.OrderPublishId = publish.Id;
-            //    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-            //    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-            //    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-            //    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-            //    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-            //    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-            //    await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
-            //    await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
-            //}
-
-            //var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
-            //if (visit != null)
-            //{
-            //    visit.VisitState = EVisitState.None;
-            //    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
-            //}
+            if (order.Status >= EOrderStatus.Filed)
+            {
+				var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
+				if (publish != null)
+				{
+					var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+					publishHistory.OrderPublishId = publish.Id;
+					publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+					publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+					publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+					publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+					publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+					publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+					await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
+					await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
+				}
+
+				var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
+				if (visit != null)
+				{
+					visit.VisitState = EVisitState.None;
+					await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
+				}
+			}
 
             if (order != null && ("001171".Equals(special.OrgId) ||
                                   "001178".Equals(special.OrgId) ||
@@ -4878,27 +4947,30 @@ public class OrderController : BaseController
                 //todo 特提重办,按审批通过时间依据中心派至部门的规则计算期满时间,更新order
 
                 await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, order.Status >= EOrderStatus.Filed, EWorkflowTraceType.Recall, HttpContext.RequestAborted);
-                var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
-                if (publish != null)
+                if (order.Status >= EOrderStatus.Filed)
                 {
-                    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
-                    publishHistory.OrderPublishId = publish.Id;
-                    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
-                    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
-                    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
-                    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
-                    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
-                    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
-                    await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
-                    await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
-                }
-
-                var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
-                if (visit != null)
-                {
-                    visit.VisitState = EVisitState.None;
-                    await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
-                }
+					var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == special.OrderId);
+					if (publish != null)
+					{
+						var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
+						publishHistory.OrderPublishId = publish.Id;
+						publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
+						publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
+						publishHistory.ArrangeContentAfter = publish.ArrangeContent;
+						publishHistory.ArrangeContentBefor = publish.ArrangeContent;
+						publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
+						publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
+						await _orderPublishHistoryRepository.AddAsync(publishHistory, HttpContext.RequestAborted);
+						await _orderPublishRepository.RemoveAsync(publish, false, HttpContext.RequestAborted);
+					}
+
+					var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == special.OrderId && x.VisitState != EVisitState.None);
+					if (visit != null)
+					{
+						visit.VisitState = EVisitState.None;
+						await _orderVisitRepository.UpdateAsync(visit, HttpContext.RequestAborted);
+					}
+				}
 
                 if (order != null && ("001171".Equals(special.OrgId) ||
                                       "001178".Equals(special.OrgId) ||

+ 1 - 0
src/Hotline.Api/Controllers/SysController.cs

@@ -318,6 +318,7 @@ namespace Hotline.Api.Controllers
                 throw UserFriendlyException.SameMessage("无效字典类型");
             var dicData = _mapper.Map<SystemDicData>(dto);
             dicData.DicTypeCode = dicType.DicTypeCode;
+            dicData.IsShow = true;
             _systemDicDataCacheManager.RemoveSysDicDataCache(dicType.DicTypeCode);
             await _sysDicDataRepository.AddAsync(dicData);
         }

+ 77 - 241
src/Hotline.Api/Controllers/TestController.cs

@@ -8,6 +8,7 @@ using Hotline.Application.Orders;
 using Hotline.Application.Quality;
 using Hotline.Application.StatisticalReport;
 using Hotline.Authentications;
+using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.BlackLists;
 using Hotline.CallCenter.Calls;
 using Hotline.CallCenter.Configs;
@@ -116,6 +117,8 @@ public class TestController : BaseController
     private readonly IRepository<Tel> _telRepository;
     private readonly IOrderDomainService _orderDomainService;
     private readonly ICallApplication _callApplication;
+
+    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     //private readonly ITypedCache<List<User>> _cache;
     //private readonly ICacheManager<User> _cache;
     private readonly ICalcExpireTime _expireTime;
@@ -219,6 +222,62 @@ ICalcExpireTime expireTime)
     }
 
 
+    [HttpGet("time")]
+    [AllowAnonymous]
+    public async Task<OpenResponse> GetTime(string batchId, string taskId)
+    {
+        //await _repositoryts.AddVectorAsync("f595e730-909a-45e4-9138-a84bf15f4662", DateTime.Now,
+        //    new List<string> { "xx", "bb" }, HttpContext.RequestAborted);
+
+        //await _repositoryts.AddVectorAsync("f595e730-909a-45e4-9138-a84bf15f4663", DateTime.Now,
+        //    new List<string> { "aa", "bb", "cc" }, HttpContext.RequestAborted);
+
+        var result0 = await _repositoryts.SearchAsync(new List<string> { "xx", "aa" }, HttpContext.RequestAborted);
+        var result = await _repositoryts.SearchAsync(new List<string> { "bb" }, HttpContext.RequestAborted);
+        var result1 = await _repositoryts.SearchAsync(new List<string> { "cc", "bb" }, HttpContext.RequestAborted);
+        var result2 = await _repositoryts.SearchAsync(new List<string> { "cc", "xx" }, HttpContext.RequestAborted);
+        var result3 = await _repositoryts.SearchAsync(new List<string> { "aa", "bb", "ss" }, HttpContext.RequestAborted);
+
+
+        //await _orderDomainService.SendOverTimeSms(HttpContext.RequestAborted);
+        //await _repositoryts.UpdateVectorAsync("f595e730-909a-45e4-9138-a84bf15f4662",
+        //    new List<string> { "ss", "bb" }, HttpContext.RequestAborted);
+
+        //_uow.Db.Ado.SqlQueryAsync<OrderUrge>("SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat')")
+
+        //var tests = _uowWex.Db.Ado.SqlQuery<Test>("select * from view_telinfo_full where IsSynch=@IsSynch", new { IsSynch = 0 });
+        //var a = _uowWex.Db.Ado.ExecuteCommand("update telinfo set IsSynch=1 where GUID=@CallId", new { CallId = "b1f97f3c-88b6-4f42-b8de-83ed448854b0" });
+        //var rsp = await _wexClient.QueryTelsAsync(new QueryTelRequest {  }, HttpContext.RequestAborted);
+
+        //int a = _timeLimitDomainService.CalcWorkTime(DateTime.Now, DateTime.Parse("2023-09-11 16:21:00"));
+        //int m = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2023-09-19 12:00:00"), DateTime.Parse("2023-09-20 18:00:00"), false);
+        //var r = _timeLimitDomainService.CalcEndTime(DateTime.Parse("2024-6-06 14:32:47"),"40");
+        //var r = _timeLimitDomainService.CalcExpiredTime(DateTime.Parse("2024-02-29 10:12:33"), Share.Enums.FlowEngine.EFlowDirection.OrgToCenter, "10");
+        //await _wfModuleDomainService.PersistenceModulesAsync(HttpContext.RequestAborted);
+
+        //var rsp = await _daprClient.InvokeMethodAsync<ApiResponse<string>>(HttpMethod.Get, "identity", "api/v1/Test/time", HttpContext.RequestAborted);
+        //var rsp1 = await _daprClient.InvokeMethodAsync<int, ApiResponse<string>>(HttpMethod.Post, "identity", "api/v1/Test/time1", 222, HttpContext.RequestAborted);
+        //var a = await _trClient.QueryTelsAsync(new Tr.Sdk.Tels.QueryTelRequest() { }, HttpContext.RequestAborted);
+        //await _daySettingRepository.IsWorkDay(DateTime.Now);
+
+        //var r = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2024-6-06 14:32:47"), DateTime.Parse("2024-3-22 06:00:00"), false);
+        //var r = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2024-3-24 17:20:00"), DateTime.Parse("2024-3-24 17:21:00"), false);
+        //await _aiVisitService.QueryAiVisitTask(batchId, taskId, HttpContext.RequestAborted);
+        //var r = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
+        //var r = _timeLimitDomainService.CalcWorkTimeToDecimal(DateTime.Parse("2024-07-09 14:57:51"), DateTime.Parse("2024-07-10 14:20:42"), false);
+        //var endTime = _timeLimitDomainService
+        //.CalcEndTime(DateTime.Parse("2024-07-09 14:57:51"), ETimeType.WorkDay, -3, 0, 0);///.EndTime;
+        //var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 3, 80, 50);
+        //var t = _timeLimitDomainService.CalcWorkTimeEx(DateTime.Parse("2024-07-22 11:30:00"), DateTime.Parse("2024-07-23 14:00:00"), false);
+        //var r = await _aiVisitService.QueryAiVisitTaskEx("MTAwMDAx173ASS0kSUAqK2rl2sFGME", "", HttpContext.RequestAborted);
+        //var r = await _aiVisitService.QueryAiVisitTaskResult(batchId, DateTime.Parse("2024-07-28"), DateTime.Parse("2024-08-01"), HttpContext.RequestAborted);
+
+        //var r = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, batchId);
+
+        return OpenResponse.Ok(DateTime.Now.ToString("F"));
+    }
+
+
     /// <summary>
     /// 推送回访到省上
     /// </summary>
@@ -516,63 +575,6 @@ ICalcExpireTime expireTime)
         return _exportApplication.ExportData<ExcelContent>(list, "demo.xlsx");
     }
 
-
-
-    [HttpGet("time")]
-    [AllowAnonymous]
-    public async Task<OpenResponse> GetTime(string batchId, string taskId)
-    {
-        //await _repositoryts.AddVectorAsync("f595e730-909a-45e4-9138-a84bf15f4662", DateTime.Now,
-        //    new List<string> { "xx", "bb" }, HttpContext.RequestAborted);
-
-        //await _repositoryts.AddVectorAsync("f595e730-909a-45e4-9138-a84bf15f4663", DateTime.Now,
-        //    new List<string> { "aa", "bb", "cc" }, HttpContext.RequestAborted);
-
-        var result0 = await _repositoryts.SearchAsync(new List<string> { "xx", "aa" }, HttpContext.RequestAborted);
-        var result = await _repositoryts.SearchAsync(new List<string> { "bb" }, HttpContext.RequestAborted);
-        var result1 = await _repositoryts.SearchAsync(new List<string> { "cc", "bb" }, HttpContext.RequestAborted);
-        var result2 = await _repositoryts.SearchAsync(new List<string> { "cc", "xx" }, HttpContext.RequestAborted);
-        var result3 = await _repositoryts.SearchAsync(new List<string> { "aa", "bb", "ss" }, HttpContext.RequestAborted);
-
-        //await _repositoryts.UpdateVectorAsync("f595e730-909a-45e4-9138-a84bf15f4662",
-        //    new List<string> { "ss", "bb" }, HttpContext.RequestAborted);
-
-        //_uow.Db.Ado.SqlQueryAsync<OrderUrge>("SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat')")
-
-        //var tests = _uowWex.Db.Ado.SqlQuery<Test>("select * from view_telinfo_full where IsSynch=@IsSynch", new { IsSynch = 0 });
-        //var a = _uowWex.Db.Ado.ExecuteCommand("update telinfo set IsSynch=1 where GUID=@CallId", new { CallId = "b1f97f3c-88b6-4f42-b8de-83ed448854b0" });
-        //var rsp = await _wexClient.QueryTelsAsync(new QueryTelRequest {  }, HttpContext.RequestAborted);
-
-        //int a = _timeLimitDomainService.CalcWorkTime(DateTime.Now, DateTime.Parse("2023-09-11 16:21:00"));
-        //int m = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2023-09-19 12:00:00"), DateTime.Parse("2023-09-20 18:00:00"), false);
-        //var r = _timeLimitDomainService.CalcEndTime(DateTime.Parse("2024-6-06 14:32:47"),"40");
-        //var r = _timeLimitDomainService.CalcExpiredTime(DateTime.Parse("2024-02-29 10:12:33"), Share.Enums.FlowEngine.EFlowDirection.OrgToCenter, "10");
-        //await _wfModuleDomainService.PersistenceModulesAsync(HttpContext.RequestAborted);
-
-        //var rsp = await _daprClient.InvokeMethodAsync<ApiResponse<string>>(HttpMethod.Get, "identity", "api/v1/Test/time", HttpContext.RequestAborted);
-        //var rsp1 = await _daprClient.InvokeMethodAsync<int, ApiResponse<string>>(HttpMethod.Post, "identity", "api/v1/Test/time1", 222, HttpContext.RequestAborted);
-        //var a = await _trClient.QueryTelsAsync(new Tr.Sdk.Tels.QueryTelRequest() { }, HttpContext.RequestAborted);
-        //await _daySettingRepository.IsWorkDay(DateTime.Now);
-
-        //var r = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2024-6-06 14:32:47"), DateTime.Parse("2024-3-22 06:00:00"), false);
-        //var r = _timeLimitDomainService.CalcWorkTime(DateTime.Parse("2024-3-24 17:20:00"), DateTime.Parse("2024-3-24 17:21:00"), false);
-        //await _aiVisitService.QueryAiVisitTask(batchId, taskId, HttpContext.RequestAborted);
-        //var r = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
-        //var r = _timeLimitDomainService.CalcWorkTimeToDecimal(DateTime.Parse("2024-07-09 14:57:51"), DateTime.Parse("2024-07-10 14:20:42"), false);
-        //var endTime = _timeLimitDomainService
-        //.CalcEndTime(DateTime.Parse("2024-07-09 14:57:51"), ETimeType.WorkDay, -3, 0, 0);///.EndTime;
-        //var timeResult = _timeLimitDomainService.CalcEndTime(DateTime.Now, ETimeType.WorkDay, 3, 80, 50);
-        // var t = _timeLimitDomainService.CalcWorkTimeEx(DateTime.Parse(batchId), DateTime.Parse(taskId), false);
-        var t = await _expireTime.CalcWorkTimeEx(DateTime.Parse(batchId), DateTime.Parse(taskId), false);
-        //var r = await _aiVisitService.QueryAiVisitTaskEx("MTAwMDAx173ASS0kSUAqK2rl2sFGME", "", HttpContext.RequestAborted);
-        //var r = await _aiVisitService.QueryAiVisitTaskResult(batchId, DateTime.Parse("2024-07-28"), DateTime.Parse("2024-08-01"), HttpContext.RequestAborted);
-
-        //var r = _timeLimitDomainService.CalcExpiredTime(DateTime.Now, EFlowDirection.CenterToCenter, batchId);
-        //_capPublisher.PublishDelay(DateTime.Now.AddSeconds(10) - DateTime.Now, EventNames.HotlineBatchSmsTask, new PublishBatchSmsTaskDto() { TaskId = "123123" });
-
-        return OpenResponse.Ok(DateTime.Now.ToString("F"));
-    }
-
     [HttpGet("pgsql")]
     public async Task<string> Pgsql()
     {
@@ -653,89 +655,21 @@ ICalcExpireTime expireTime)
             HttpContext.RequestAborted);
     }
 
-    /// <summary>
-    /// 
-    /// </summary>
-    /// <returns></returns>
     [AllowAnonymous]
     [HttpGet("t2")]
-    public async Task GetVoiceEndAnswerAsyncTest()
+    public async Task<string> GetCacheAllowAnonymous()
     {
-        //var answer = await _ivrDomainService.GetVoiceEndAnswerAsync("3", HttpContext.RequestAborted);
-        //Console.WriteLine(answer.Content);
-        throw new UserFriendlyException(2001, "test");
+        var systemAdministrator = _systemSettingCacheManager.GetSetting(SettingConstants.SystemAdministrator)?.SettingValue[0]; 
+        return systemAdministrator;
     }
 
-    [HttpGet("wfdefine")]
-    public async Task GetWorkflowDefine([FromQuery] string id)
+    [HttpGet("t3")]
+    public async Task<string> GetCacheWithAuth()
     {
-        //var query = _workflowTraceRepository.Queryable()
-        //    .LeftJoin<Workflow>((t, w) => t.WorkflowId == w.Id)
-        //    .LeftJoin<Order>((t, w, o) => w.ExternalId == o.Id)
-        //    .Where((t, w, o) => o.No.Length == 14);
-
-        //if (!string.IsNullOrEmpty(id))
-        //    query = query.Where(d => d.WorkflowId == id);
-        //var list = await query
-        //    .Select((t, w, o) => new { t, w, o })
-        //    .ToListAsync(HttpContext.RequestAborted);
-
-        //var toUsers = list.Where(d => d.t.FlowAssignType == EFlowAssignType.User).ToList();
-        //var userIds = toUsers.SelectMany(d => d.t.Handlers).Select(d => d.Key).Distinct().ToList();
-        //var users = await _userRepository.Queryable()
-        //    .Includes(d => d.Organization)
-        //    .Where(d => userIds.Contains(d.Id))
-        //    .ToListAsync(HttpContext.RequestAborted);
-        ////var orgTraces = list.Where(d => d.FlowAssignType == EFlowAssignType.Org).ToList();
-        //var stepHandlers = new List<WorkflowStepHandler>();
-        //foreach (var toUser in toUsers)
-        //{
-        //    foreach (var traceHandler in toUser.t.Handlers)
-        //    {
-        //        var user = users.FirstOrDefault(d => d.Id == traceHandler.Key);
-        //        if (user != null)
-        //            stepHandlers.Add(new WorkflowStepHandler
-        //            {
-        //                WorkflowId = toUser.w.Id,
-        //                ExternalId = toUser.w.ExternalId,
-        //                WorkflowStepId = toUser.t.StepId,
-        //                FlowAssignType = toUser.t.FlowAssignType.Value,
-        //                UserId = user.Id,
-        //                Username = user.Name,
-        //                OrgId = user.OrgId,
-        //                OrgName = user.Organization.Name,
-        //                IsActualHandler = user.Id == toUser.t.HandlerId
-        //            });
-        //    }
-        //}
-
-        //var toOrgs = list.Where(d => d.t.FlowAssignType == EFlowAssignType.Org).ToList();
-        //foreach (var toOrg in toOrgs)
-        //{
-        //    foreach (var handler in toOrg.t.Handlers)
-        //    {
-        //        stepHandlers.Add(new WorkflowStepHandler
-        //        {
-        //            WorkflowId = toOrg.w.Id,
-        //            ExternalId = toOrg.w.ExternalId,
-        //            WorkflowStepId = toOrg.t.StepId,
-        //            FlowAssignType = toOrg.t.FlowAssignType.Value,
-        //            OrgId = handler.Key,
-        //            OrgName = handler.Value,
-        //            IsActualHandler = handler.Key == toOrg.t.HandlerOrgId
-        //        });
-        //    }
-        //}
-
-        //_logger.LogInformation($"生成handlers: {stepHandlers.Count} 条");
-
-        //await _workflowStepHandleRepository.AddRangeAsync(stepHandlers, HttpContext.RequestAborted);
+        var systemAdministrator = _systemSettingCacheManager.GetSetting(SettingConstants.SystemAdministrator)?.SettingValue[0];
+        return systemAdministrator;
     }
 
-    /// <summary>
-    /// 处理FlowAssignType
-    /// </summary>
-    /// <returns></returns>
     [AllowAnonymous]
     [HttpPost("t3")]
     public async Task TestExportExcel()
@@ -795,7 +729,6 @@ ICalcExpireTime expireTime)
         await _orderRepository.UpdateRangeAsync(updateOrders, HttpContext.RequestAborted);
     }
 
-
     [AllowAnonymous]
     [HttpPost("t4")]
     public async Task TestExportExcel1()
@@ -940,116 +873,19 @@ ICalcExpireTime expireTime)
 
     [AllowAnonymous]
     [HttpGet("t5")]
-    public async Task Test5()
+    public async Task<string> GetUserAllowAnonymous()
     {
-        var query = _orderRepository.Queryable()
-            .Includes(d => d.Workflow, x => x.Steps)
-            .Where(d => d.Status >= EOrderStatus.Filed &&
-                        d.CurrentStepId == null)
-            .OrderBy(d => d.Id);
-
-        var size = 1000;
-        var count = await query.CountAsync(HttpContext.RequestAborted);
-        _logger.LogWarning($"共计 {count} 条");
-        var batchs = (int)Math.Ceiling(Convert.ToDouble(count) / size);
-        for (int i = 0; i < batchs; i++)
-        {
-            _logger.LogWarning($"第 {i} 批次开始");
-            var orders = await query
-                .Skip(i * size)
-                .Take(size)
-                .ToListAsync(HttpContext.RequestAborted);
-            foreach (var order in orders)
-            {
-                if (order.No.Trim().Length != 14)
-                {
-                    order.CurrentStepId = order.ActualHandleStepId;
-                    order.CurrentStepCode = order.ActualHandleStepCode;
-                    order.CurrentStepName = order.ActualHandleStepName;
-                    order.CurrentStepCreateTime = order.ActualHandleStepCreateTime;
-                    order.CurrentStepAcceptTime = order.ActualHandleStepAcceptTime;
-                    order.CurrentHandleTime = order.ActualHandleTime;
-                    order.CurrentHandlerId = order.ActualHandlerId;
-                    order.CurrentHandlerName = order.ActualHandlerName;
-                    order.CurrentHandleOrgName = order.ActualHandleOrgName;
-                    order.CurrentHandleOrgId = order.ActualHandleOrgCode;
-                    order.CurrentHandleOrgAreaCode = order.ActualHandleOrgAreaCode;
-                    order.CurrentHandleOrgAreaName = order.ActualHandleOrgAreaName;
-                }
-                else
-                {
-                    if (order.CounterSignType != null)
-                    {
-                        order.Workflow.CurrentStepId = order.Workflow.ActualHandleStepId;
-                        order.Workflow.CurrentStepCode = order.Workflow.ActualHandleStepCode;
-                        order.Workflow.CurrentStepName = order.Workflow.ActualHandleStepName;
-                        order.Workflow.CurrentStepCreateTime = order.Workflow.ActualHandleStepCreateTime;
-                        order.Workflow.CurrentStepAcceptTime = order.Workflow.ActualHandleStepAcceptTime;
-                        order.Workflow.CurrentHandleTime = order.Workflow.ActualHandleTime;
-                        order.Workflow.CurrentHandlerId = order.Workflow.ActualHandlerId;
-                        order.Workflow.CurrentHandlerName = order.Workflow.ActualHandlerName;
-                        order.Workflow.CurrentHandleOrgName = order.Workflow.ActualHandleOrgName;
-                        order.Workflow.CurrentHandleOrgId = order.Workflow.ActualHandleOrgCode;
-                        order.Workflow.CurrentHandleOrgAreaCode = order.Workflow.ActualHandleOrgAreaCode;
-                        order.Workflow.CurrentHandleOrgAreaName = order.Workflow.ActualHandleOrgAreaName;
-
-                        order.CurrentStepId = order.Workflow.ActualHandleStepId;
-                        order.CurrentStepCode = order.Workflow.ActualHandleStepCode;
-                        order.CurrentStepName = order.Workflow.ActualHandleStepName;
-                        order.CurrentStepCreateTime = order.Workflow.ActualHandleStepCreateTime;
-                        order.CurrentStepAcceptTime = order.Workflow.ActualHandleStepAcceptTime;
-                        order.CurrentHandleTime = order.Workflow.ActualHandleTime;
-                        order.CurrentHandlerId = order.Workflow.ActualHandlerId;
-                        order.CurrentHandlerName = order.Workflow.ActualHandlerName;
-                        order.CurrentHandleOrgName = order.Workflow.ActualHandleOrgName;
-                        order.CurrentHandleOrgId = order.Workflow.ActualHandleOrgCode;
-                        order.CurrentHandleOrgAreaCode = order.Workflow.ActualHandleOrgAreaCode;
-                        order.CurrentHandleOrgAreaName = order.Workflow.ActualHandleOrgAreaName;
-                    }
-                    else
-                    {
-                        var endStep = order.Workflow.Steps.FirstOrDefault(d => d.StepType == EStepType.End);
-                        if (endStep is null) continue;
-                        var preStep = order.Workflow.Steps.FirstOrDefault(d => d.Id == endStep.PrevStepId);
-                        if (preStep is null) continue;
-
-                        order.Workflow.CurrentStepId = preStep.Id;
-                        order.Workflow.CurrentStepCode = preStep.Code;
-                        order.Workflow.CurrentStepName = preStep.Name;
-                        order.Workflow.CurrentStepCreateTime = preStep.CreationTime;
-                        order.Workflow.CurrentStepAcceptTime = preStep.AcceptTime;
-                        order.Workflow.CurrentHandleTime = preStep.HandleTime;
-                        order.Workflow.CurrentHandlerId = preStep.HandlerId;
-                        order.Workflow.CurrentHandlerName = preStep.HandlerName;
-                        order.Workflow.CurrentHandleOrgName = preStep.HandlerOrgName;
-                        order.Workflow.CurrentHandleOrgId = preStep.HandlerOrgId;
-                        order.Workflow.CurrentHandleOrgAreaCode = preStep.HandlerOrgAreaCode;
-                        order.Workflow.CurrentHandleOrgAreaName = preStep.HandlerOrgAreaName;
-
-                        order.CurrentStepId = order.Workflow.ActualHandleStepId;
-                        order.CurrentStepCode = order.Workflow.ActualHandleStepCode;
-                        order.CurrentStepName = order.Workflow.ActualHandleStepName;
-                        order.CurrentStepCreateTime = order.Workflow.ActualHandleStepCreateTime;
-                        order.CurrentStepAcceptTime = order.Workflow.ActualHandleStepAcceptTime;
-                        order.CurrentHandleTime = order.Workflow.ActualHandleTime;
-                        order.CurrentHandlerId = order.Workflow.ActualHandlerId;
-                        order.CurrentHandlerName = order.Workflow.ActualHandlerName;
-                        order.CurrentHandleOrgName = order.Workflow.ActualHandleOrgName;
-                        order.CurrentHandleOrgId = order.Workflow.ActualHandleOrgCode;
-                        order.CurrentHandleOrgAreaCode = order.Workflow.ActualHandleOrgAreaCode;
-                        order.CurrentHandleOrgAreaName = order.Workflow.ActualHandleOrgAreaName;
-                    }
-                }
-            }
-
-            _logger.LogWarning($"更新数据:{orders.Count} 条");
-            await _orderRepository.UpdateNav(orders)
-                .Include(d => d.Workflow)
-                .ExecuteCommandAsync();
-        }
-
+        var users = await _userRepository.Queryable()
+            .FirstAsync(d => d.Name == "xf", HttpContext.RequestAborted);
+        return users.Id;
+    }
 
-        //await _workflowTraceRepository.UpdateRangeAsync(updateSteps, HttpContext.RequestAborted);
+    [HttpGet("t6")]
+    public async Task<string> GetUserWithAuth()
+    {
+        var users = await _userRepository.Queryable()
+            .FirstAsync(d => d.Name == "xf", HttpContext.RequestAborted);
+        return users.Id;
     }
 
     [HttpGet("rsa")]

+ 2 - 1
src/Hotline.Api/Controllers/WebPortalController.cs

@@ -138,7 +138,8 @@ namespace Hotline.Api.Controllers
                 .Where(p => p.LoseEfficacyTime >= DateTime.Now)
                 .Where(p => p.IsArrive == true)
                 .Where(p => SqlFunc.JsonListObjectAny(p.PushRanges, "Key", "2"))
-                 .Where(p => p.BulletinTypeId == dto.BulletinTypeId)
+               //  .Where(p => p.BulletinTypeId == dto.BulletinTypeId)
+               .WhereIF(!string.IsNullOrEmpty(dto.BulletinTypeId), p => p.BulletinTypeId == dto.BulletinTypeId)
                  .WhereIF(!string.IsNullOrEmpty(dto.CheckChar), p => p.Content.Contains(dto.CheckChar))
                  .OrderByDescending(p => p.BulletinTime)
                  .Select(it => new

+ 1 - 1
src/Hotline.Api/StartupExtensions.cs

@@ -182,7 +182,7 @@ internal static class StartupExtensions
         services.AddMq(configuration);
 
         //job
-        services.RegisterJob(callcenterType);
+        services.RegisterJob(appConfiguration);
 
         services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
         services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

+ 27 - 2
src/Hotline.Api/StartupHelper.cs

@@ -246,7 +246,7 @@ namespace Hotline.Api
             return services;
         }
 
-        public static IServiceCollection RegisterJob(this IServiceCollection services, string callcenterType)
+        public static IServiceCollection RegisterJob(this IServiceCollection services,AppConfiguration appConfiguration )
         {
             services.AddQuartz(d =>
             {
@@ -265,7 +265,32 @@ namespace Hotline.Api
                     .WithCronSchedule("0 10 9 * * ?")
                 );
 
-                switch (callcenterType)
+                //即将超期和超期短信
+                var autoSendOverTimeSmsKey = new JobKey(nameof(SendOverTimeSmsJob), "send overtime order task");
+                d.AddJob<SendOverTimeSmsJob>(autoSendOverTimeSmsKey);
+                d.AddTrigger(t => t
+                    .WithIdentity("task-send-overtime-order-trigger")
+                    .ForJob(autoSendOverTimeSmsKey)
+                    .StartNow()
+                    .WithCronSchedule("0 30 09,14 * * ?"));
+
+                switch (appConfiguration.AppScope)
+                {
+                    //智能化任务
+                    case AppDefaults.AppScope.YiBin:
+                        var aiVisitStatusKey = new JobKey(nameof(CheckAiVisitStateJob), "check aivisit state task");
+                        d.AddJob<CheckAiVisitStateJob>(aiVisitStatusKey);
+                        d.AddTrigger(t => t
+                        .WithIdentity("task-check-aivisit-state-trigger")
+                        .ForJob(aiVisitStatusKey)
+                        .StartNow()
+                        .WithCronSchedule("0 0/5 * * * ? *"));
+                        break;
+                    default:
+                        break;
+                }
+
+                switch (appConfiguration.GetDefaultAppScopeConfiguration().CallCenterType)
                 {
                     case AppDefaults.CallCenterType.XingTang:
                         var getCallsJobKey = new JobKey(nameof(XingTangCallsSyncJob));

+ 1 - 1
src/Hotline.Api/config/appsettings.Development.json

@@ -1,7 +1,7 @@
 {
   "AllowedHosts": "*",
   "AppConfiguration": {
-    "AppScope": "ZiGong",
+    "AppScope": "YiBin",
     "YiBin": {
       "CallCenterType": "TianRun", //XunShi、WeiErXin、TianRun、XingTang
       //智能回访

+ 9 - 9
src/Hotline.Application/CallCenter/DefaultCallApplication.cs

@@ -329,18 +329,18 @@ public abstract class DefaultCallApplication : ICallApplication
     /// <returns></returns>
     public virtual async Task<TrCallRecord?> GetTianrunCallTransliterationAsync(string transliterationId, CancellationToken cancellationToken)
     {
-		throw new NotImplementedException();
-	}
+        throw new NotImplementedException();
+    }
 
-	public virtual async Task EditTransliterationStateAsync(string callId, ECallTransliterationState state, string transliterationId, CancellationToken cancellationToken)
+    public virtual async Task EditTransliterationStateAsync(string callId, ECallTransliterationState state, string transliterationId, CancellationToken cancellationToken)
     {
-		throw new NotImplementedException();
-	}
+        throw new NotImplementedException();
+    }
 
-	/// <summary>
-	/// 关联通话记录与order(添润)
-	/// </summary>
-	public virtual Task RelateTianrunCallWithOrderAsync(string callId, string orderId,
+    /// <summary>
+    /// 关联通话记录与order(添润)
+    /// </summary>
+    public virtual Task RelateTianrunCallWithOrderAsync(string callId, string orderId,
         CancellationToken cancellationToken)
     {
         throw new NotImplementedException();

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

@@ -138,6 +138,5 @@ namespace Hotline.Application.CallCenter
         /// </summary>
         /// <returns></returns>
         List<Kv> GetTelOperationOptions();
-
     }
 }

+ 15 - 1
src/Hotline.Application/CallCenter/TianRunCallApplication.cs

@@ -14,6 +14,7 @@ using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.TrCallCenter;
 using Hotline.Share.Enums.CallCenter;
+using MapsterMapper;
 using Microsoft.AspNetCore.Http;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
@@ -28,13 +29,15 @@ namespace Hotline.Application.CallCenter
         private readonly ITrApplication _trApplication;
         private readonly ITelApplication _telApplication;
         private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+        private readonly IMapper _mapper;
 
         public TianRunCallApplication(
             ISessionContext sessionContext,
             IRepository<TrCallRecord> trCallRecordRepository,
             ITrApplication trApplication,
             ITelApplication telApplication,
-            ISystemSettingCacheManager systemSettingCacheManager
+            ISystemSettingCacheManager systemSettingCacheManager,
+            IMapper mapper
         )
         {
             _sessionContext = sessionContext;
@@ -42,6 +45,7 @@ namespace Hotline.Application.CallCenter
             _trApplication = trApplication;
             _telApplication = telApplication;
             _systemSettingCacheManager = systemSettingCacheManager;
+            _mapper = mapper;
         }
 
         /// <summary>
@@ -169,5 +173,15 @@ namespace Hotline.Application.CallCenter
         {
             throw new NotImplementedException();
         }
+
+        /// <summary>
+        /// 查询通话记录
+        /// </summary>
+        public override async Task<CallNative?> GetCallAsync(string callId, CancellationToken cancellationToken)
+        {
+            var call = await _trCallRecordRepository.Queryable()
+                .FirstAsync(d => d.OtherAccept == callId, cancellationToken);
+            return _mapper.Map<CallNative>(call);
+        }
     }
 }

+ 1 - 0
src/Hotline.Application/CallCenter/XingTangCallApplication.cs

@@ -31,6 +31,7 @@ using XingTang.Sdk;
 
 namespace Hotline.Application.CallCenter
 {
+    //临时方案,后续需重构为:业务内部统一采用CallNative
     public class XingTangCallApplication : DefaultCallApplication
     {
         // private readonly IRepository<Tel> _telRepository;

+ 1 - 1
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -292,7 +292,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// 工单退回(返回前一节点)
     /// </summary>
     public async Task<EFlowDirection> PreviousAsync(PreviousWorkflowDto dto, string applicantId, string applicantOrgId, string[] applicantRoleIds,
-        ISessionContext current, CancellationToken cancellationToken)
+		ISessionContext current, CancellationToken cancellationToken)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
             withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);

+ 5 - 4
src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs

@@ -155,9 +155,10 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                             switch (notification.FlowAssignInfo.FlowAssignType)
                             {
                                 case EFlowAssignType.Org:
-                                    var orgCodes = notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                    var orgCodes = notification.Trace.NextHandlers.Select(x => x.OrgId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                                     var orgList = await _userRepository.Queryable()
-                                        .Where(x => orgCodes.Contains(x.OrgId) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e"))
+                                        .Where(x => orgCodes.Contains(x.OrgId) && x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id)))
                                         .ToListAsync(cancellationToken);
                                     foreach (var item in orgList)
                                     {
@@ -181,9 +182,9 @@ public class WorkflowNextHandler : INotificationHandler<NextStepNotify>
                                     }
                                     break;
                                 case EFlowAssignType.User:
-                                    var userCodes = notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                    var userCodes = notification.Trace.NextHandlers.Select(x=>x.UserId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
                                     var userList = await _userRepository.Queryable()
-                                        .Where(x => userCodes.Contains(x.Id) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e"))
+                                        .Where(x => userCodes.Contains(x.Id) && !string.IsNullOrEmpty(x.PhoneNo))
                                         .ToListAsync(cancellationToken);
                                     foreach (var item in userList)
                                     {

+ 12 - 6
src/Hotline.Application/Handlers/FlowEngine/WorkflowStartHandler.cs

@@ -1,6 +1,7 @@
 using DotNetCore.CAP;
 using Hotline.Application.CallCenter;
 using Hotline.Application.Quality;
+using Hotline.Caching.Interfaces;
 using Hotline.CallCenter.Configs;
 using Hotline.Configurations;
 using Hotline.FlowEngine.Notifications;
@@ -8,6 +9,7 @@ using Hotline.FlowEngine.WorkflowModules;
 using Hotline.KnowledgeBase;
 using Hotline.Orders;
 using Hotline.Push.Notifies;
+using Hotline.Settings;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.TrCallCenter;
@@ -39,6 +41,7 @@ namespace Hotline.Application.Handlers.FlowEngine
         private readonly ICallApplication _callApplication;
         private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
         private readonly IMediator _mediator;
+        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
 
         public WorkflowStartHandler(
             IOrderDomainService orderDomainService,
@@ -52,8 +55,9 @@ namespace Hotline.Application.Handlers.FlowEngine
             IRepository<User> userRepository,
             ICallApplication callApplication,
             IOptionsSnapshot<AppConfiguration> appOptions,
-            IMediator mediator
-		)
+            IMediator mediator,
+            ISystemSettingCacheManager systemSettingCacheManager
+        )
         {
             _orderDomainService = orderDomainService;
             _knowledgeDomainService = knowledgeDomainService;
@@ -68,6 +72,7 @@ namespace Hotline.Application.Handlers.FlowEngine
             _callApplication = callApplication;
             _appOptions = appOptions;
             _mediator = mediator;
+            _systemSettingCacheManager = systemSettingCacheManager;
         }
 
         /// <summary>Handles a notification</summary>
@@ -138,9 +143,10 @@ namespace Hotline.Application.Handlers.FlowEngine
                                 switch (notification.FlowAssignInfo.FlowAssignType)
                                 {
                                     case EFlowAssignType.Org:
-                                        var orgCodes = notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                        var orgCodes = notification.Trace.NextHandlers.Select(x => x.OrgId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                        var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                                         var orgList = await _userRepository.Queryable().Where(x =>
-                                            orgCodes.Contains(x.OrgId) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                                            orgCodes.Contains(x.OrgId) && x.Roles.Any(d => orgCodes.Contains(d.Id))).ToListAsync();
                                         foreach (var item in orgList)
                                         {
                                             if (!string.IsNullOrEmpty(item.PhoneNo))
@@ -163,9 +169,9 @@ namespace Hotline.Application.Handlers.FlowEngine
 
                                         break;
                                     case EFlowAssignType.User:
-                                        var userCodes = notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
+                                        var userCodes = notification.Trace.NextHandlers.Select(x => x.UserId); //notification.FlowAssignInfo.HandlerObjects.Select(x => x.Key);
                                         var userList = await _userRepository.Queryable().Where(x =>
-                                            userCodes.Contains(x.Id) && x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                                            userCodes.Contains(x.Id) && !string.IsNullOrEmpty(x.PhoneNo)).ToListAsync();
                                         foreach (var item in userList)
                                         {
                                             var messageDto = new Share.Dtos.Push.MessageDto

+ 29 - 0
src/Hotline.Application/Jobs/CheckAiVisitStateJob.cs

@@ -0,0 +1,29 @@
+using Hotline.Orders;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Jobs
+{
+    public class CheckAiVisitStateJob : IJob, IDisposable
+    {
+        private readonly IAiVisitDomainService _aiVisitDomainService;
+        public CheckAiVisitStateJob(IAiVisitDomainService aiVisitDomainService)
+        {
+                _aiVisitDomainService = aiVisitDomainService;
+        }
+        public void Dispose()
+        {
+            
+        }
+
+        public async Task Execute(IJobExecutionContext context)
+        {
+            Console.WriteLine($"{nameof(SendOrderJob)} 执行, {DateTime.Now}");
+            await _aiVisitDomainService.OrderVisitStatusService(context.CancellationToken);
+        }
+    }
+}

+ 32 - 0
src/Hotline.Application/Jobs/SendOverTimeSmsJob.cs

@@ -0,0 +1,32 @@
+using Hotline.Orders;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Jobs
+{
+    public class SendOverTimeSmsJob : IJob, IDisposable
+    {
+        private readonly IOrderDomainService _orderDomainService;
+
+        public SendOverTimeSmsJob(IOrderDomainService orderDomainService)
+        {
+            _orderDomainService = orderDomainService;
+        }
+
+
+        public void Dispose()
+        {
+            
+        }
+
+        public async Task Execute(IJobExecutionContext context)
+        {
+            Console.WriteLine($"{nameof(SendOrderJob)} 执行, {DateTime.Now}");
+            await _orderDomainService.SendOverTimeSms(context.CancellationToken);
+        }
+    }
+}

+ 8 - 0
src/Hotline.Application/Mappers/CallMapperConfigs.cs

@@ -117,6 +117,14 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.Cpn, s => s.CPN)
                 .Map(d => d.Cdpn, s => s.CDPN)
                 ;
+
+            config.ForType<TrCallRecord, CallNative>()
+                .Map(d => d.CallNo, s => s.OtherAccept)
+                .Map(d => d.FromNo, s => s.CPN)
+                .Map(d => d.ToNo, s => s.CDPN)
+                .Map(d => d.EndRingTime, s => s.EndRingTimg)
+                .Map(d => d.AudioFile, s => s.RecordingAbsolutePath);
+
         }
 
         private DateTime? FormatDateTime(string? time)

+ 9 - 7
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -171,12 +171,6 @@ namespace Hotline.Application.Orders
         /// <returns></returns>
         Task<List<VisitAndOrgSatisfactionStatisticsDto>> VisitAndOrgStatisfactionOrgDetail(PagedKeywordSonRequest dto);
 
-        /// <summary>
-        /// 部门满意度明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        ISugarQueryable<OrderVisitDetail> VisitAndOrgSatisfactionDetail(VisitAndOrgSatisfactionDetailDto dto);
 
         /// <summary>
         /// 热点-区域统计
@@ -273,5 +267,13 @@ namespace Hotline.Application.Orders
         /// </summary>
         /// <returns></returns>
 		ISugarQueryable<OrderCenterAcceptUserVo> OrderCenterAcceptUser(OrderCenterAcceptPagedRequest dto);
-	}
+
+        /// <summary>
+        /// 扭转信件统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrderVisitJudeStatisticsRep> OrderVisitJudeStatistics(OrderVisitJudeStatisticsReq dto);
+
+    }
 }

+ 35 - 24
src/Hotline.Application/Orders/OrderApplication.cs

@@ -1108,30 +1108,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         return list;
     }
 
-    /// <summary>
-    /// 部门满意度明细统计
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <returns></returns>
-    public ISugarQueryable<OrderVisitDetail> VisitAndOrgSatisfactionDetail(VisitAndOrgSatisfactionDetailDto dto)
-    {
-        dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
-        bool IsCenter = _sessionContext.OrgIsCenter;
-        return _orderVisitDetailRepository.Queryable()
-            .Includes(x => x.OrderVisit, o => o.Order, d => d.CallRecord)
-            .Where(x => x.OrderVisit.VisitTime >= dto.StartTime && x.OrderVisit.VisitTime <= dto.EndTime && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
-            .WhereIF(dto.OrgCode == "001", x => x.VisitOrgCode == dto.OrgCode)
-            .WhereIF(dto.TypeCode != null && dto.TypeCode == 1, x => x.OrderVisit.Order.IdentityType == EIdentityType.Citizen)
-            .WhereIF(dto.TypeCode != null && dto.TypeCode == 2, x => x.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
-            //.WhereIF(dto.OrgCode != "001", x => x.VisitOrgCode == dto.OrgCode).
-            .WhereIF(dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
-            .WhereIF(IsCenter == true && dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
-            .WhereIF(IsCenter == true && dto.IsOnlyMy == null, x => x.VisitOrgCode.StartsWith(dto.OrgCode))
-            .WhereIF(IsCenter == false, x => x.VisitOrgCode == dto.OrgCode)
-            .WhereIF(dto.TypeId is 1, x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.DateValue)
-            .WhereIF(dto.TypeId is 2, x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == dto.DateValue)
-            .WhereIF(!string.IsNullOrEmpty(dto.LineNum), x => x.OrderVisit.Order.CallRecord.Gateway == dto.LineNum);
-    }
+    
 
     /// <summary>
     /// 热点区域统计
@@ -2015,5 +1992,39 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     }
 
 
+    /// <summary>
+    /// 扭转信件统计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public ISugarQueryable<OrderVisitJudeStatisticsRep> OrderVisitJudeStatistics(OrderVisitJudeStatisticsReq dto)
+    {
+        if (!dto.EndTime.HasValue)
+        {
+            dto.EndTime = dto.StartTime?.AddDays(1).AddSeconds(-1);
+        }
+        else
+        {
+            dto.EndTime = dto.EndTime?.AddDays(1).AddSeconds(-1);
+        }
+       return _orderVisitRepository.Queryable()
+            .WhereIF(dto.StartTime.HasValue, x => x.VisitTime >= dto.StartTime)
+            .WhereIF(dto.EndTime.HasValue, x => x.VisitTime <= dto.EndTime)
+            .GroupBy(x => new { EmployeeId = x.EmployeeId, Name = x.Employee.Name })
+            .Select(x => new OrderVisitJudeStatisticsRep()
+            {
+                EmpId = x.EmployeeId,
+                EmpName = x.Employee.Name,
+                OrgJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue, 1, 0)), //部门扭转总件
+                OrgJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.JudgeState == EJudgeState.Judging, 1, 0)),
+                OrgJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.JudgeState == EJudgeState.Agreed, 1, 0)),
+                OrgJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.OrgJudge.HasValue && x.JudgeState == EJudgeState.UnAgreed, 1, 0)),
+                SeatJudeCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue, 1, 0)),
+                SeatJudeApprovalingCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.JudgeState == EJudgeState.Judging, 1, 0)),
+                SeatJudeSuccessCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.JudgeState == EJudgeState.Agreed, 1, 0)),
+                SeatJudeFailCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.SeatJudge.HasValue && x.JudgeState == EJudgeState.UnAgreed, 1, 0))
+            });
+    }
+
     #endregion
 }

+ 18 - 12
src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs

@@ -107,7 +107,8 @@ namespace Hotline.Application.Orders
             if (visit != null)
             {
                 model.VisitState = visit.VisitState;
-                visit.VisitState = EVisitState.None;
+                //visit.VisitState = EVisitState.None;
+                visit.IsCanHandle = false;
                 await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
             }
 
@@ -133,8 +134,9 @@ namespace Hotline.Application.Orders
             var visit = await _orderVisitRepository.GetAsync(x => x.Id == model.VisitId, cancellationToken);
             if (visit != null)
             {
-                visit.VisitState = model.VisitState;
-                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+				//visit.VisitState = model.VisitState;
+				visit.IsCanHandle = true;
+				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
             }
         }
 
@@ -150,12 +152,14 @@ namespace Hotline.Application.Orders
             model.AuditId = _sessionContext.UserId;
             model.AuditUser = _sessionContext.UserName;
             model.AuditTime = DateTime.Now;
-            if (model.State == ESecondaryHandlingState.End)
+            var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId, cancellationToken);
+			if (model.State == ESecondaryHandlingState.End)
             {
                 var order = await _orderRepository.GetAsync(x => x.Id == model.OrderId, cancellationToken);
                 if (string.IsNullOrEmpty(order.WorkflowId))
                     throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程信息!");
-                var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, model.ApplyOrgId, cancellationToken);
+                var step = order.CounterSignType == ECounterSignType.Department ?
+                    await _workflowDomainService.FindTopHandleStepAsync(order.WorkflowId, cancellationToken) : await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, model.ApplyOrgId, cancellationToken);
                 if (step == null)
                     throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程节点!");
                 var recall = new RecallDto
@@ -194,12 +198,13 @@ namespace Hotline.Application.Orders
                     await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
                 }
                 await _workflowApplication.RecallAsync(recall, expiredTime.ExpiredTime, isOrderFiled, EWorkflowTraceType.SecondHandle, cancellationToken);
-            }
+                visit.VisitState = EVisitState.None;
+                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+			}
             else
             {
-                var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId, cancellationToken);
-                visit.VisitState = model.VisitState;
-                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
+                visit.IsCanHandle = true;
+				await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
             }
             await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
         }
@@ -241,14 +246,14 @@ namespace Hotline.Application.Orders
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude), x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
                 .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
                 .Where((x, s) => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
-                .WhereIF(!isAdmin, (x, s) => x.OrderVisit.Order.CounterSignType !=  ECounterSignType.Center && x.OrderVisit.Order.ActualHandleOrgCode == _sessionContext.OrgId)
+                .WhereIF(!isAdmin, (x, s) => (x.OrderVisit.Order.CounterSignType ==  ECounterSignType.Department || x.OrderVisit.Order.CounterSignType == null) && x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
                 ;
             if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
             {
                 query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                         (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
                                   x.OrderVisit.Order.No.Contains(dto.Keyword!))
-                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode == _sessionContext.OrgId && (
+                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && (
                         SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                         SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
                         || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
@@ -284,7 +289,8 @@ namespace Hotline.Application.Orders
                 .Includes(x => x.VisitDetail)
                 .Includes(x => x.Visit, d => d.Order)
                 .Where(x => x.State > ESecondaryHandlingState.NotApply)
-                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Visit.Order.Title.Contains(dto.Title!))
+                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Visit.Order.Title.Contains(dto.Keyword!) || x.Visit.Order.No.Contains(dto.Keyword!))
+				.WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Visit.Order.Title.Contains(dto.Title!))
                 .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Visit.Order.No.Contains(dto.No!))
                 .WhereIF(dto.Status is ESecondaryHandlingState.Apply, x => x.State == ESecondaryHandlingState.Apply)
                 .WhereIF(dto.Status is ESecondaryHandlingState.Handled, x => x.State != ESecondaryHandlingState.Apply)

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

@@ -58,7 +58,7 @@ namespace Hotline.Application.StatisticalReport
 
             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)
+                     // .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
@@ -66,7 +66,7 @@ namespace Hotline.Application.StatisticalReport
                         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, 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)), //呼入接通秒挂
@@ -98,7 +98,7 @@ namespace Hotline.Application.StatisticalReport
                      .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)
+                     // .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();

+ 1 - 7
src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs

@@ -88,13 +88,7 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         ISugarQueryable<Order> DepartmentAcceptanceTypeOrderList(DepartmentKeyWordRequest dto);
 
-        /// <summary>
-        /// 满意度明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        ISugarQueryable<OrderVisitDetail> OrgVisitDetailList(OrgVisitDetailListReq dto);
-
+        
         /// <summary>
         /// 受理类型统计
         /// </summary>

+ 2 - 30
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1591,35 +1591,7 @@ namespace Hotline.Application.StatisticalReport
                  .MergeTable();
         }
 
-        /// <summary>
-        /// 满意度明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        public ISugarQueryable<OrderVisitDetail> OrgVisitDetailList(OrgVisitDetailListReq dto)
-        {
-            var IsCenter = _sessionContext.OrgIsCenter;
-
-            return _orderVisitDetailRepository.Queryable()
-                .Includes(x => x.OrderVisit, x => x.Order, x => x.OrderScreens)
-                .Includes(x => x.OrderVisit, x => x.Employee)
-                .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.VisitTarget == EVisitTarget.Org)
-                .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.RequiredOrgId))
-                .WhereIF(dto.OrgVisitStatisticsType.HasValue, x => x.OrderVisit.Order.ProcessType == (EProcessType)((int)dto.OrgVisitStatisticsType))
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
-                .WhereIF(!string.IsNullOrEmpty(dto.VisitUser), x => x.OrderVisit.Employee.Name.Contains(dto.VisitUser))
-                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order.No == dto.No)
-                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order.Title.Contains(dto.Title))
-                .WhereIF(!string.IsNullOrEmpty(dto.OrgId), x => x.VisitOrgCode == dto.OrgId)//接办部门
-                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.OrderVisit.Order.HotspotSpliceName != null && x.OrderVisit.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
-                .WhereIF(!string.IsNullOrEmpty(dto.Channel), x => x.OrderVisit.Order.SourceChannelCode == dto.Channel)//受理类型
-                .WhereIF(dto.CreationTimeStart.HasValue, x => x.OrderVisit.Order.CreationTime >= dto.CreationTimeStart) //受理时间开始
-                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.OrderVisit.Order.CreationTime <= dto.CreationTimeEnd) //受理时间结束
-                .WhereIF(dto.ActualHandleTimeStart.HasValue, x => x.OrderVisit.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
-                .WhereIF(dto.ActualHandleTimeEnd.HasValue, x => x.OrderVisit.Order.ActualHandleTime <= dto.ActualHandleTimeEnd)
-                .OrderBy(x => x.OrderVisit.VisitTime); //办结时间结束
-
-        }
+        
 
         /// <summary>
         /// 受理类型统计
@@ -1911,7 +1883,7 @@ namespace Hotline.Application.StatisticalReport
 
             //查询通话
             var queryCall = _trCallRecordRepository.Queryable()
-                .Where(t => t.CreatedTime >= dto.StartTime && t.CreatedTime <= dto.EndTime)
+                .Where(t => t.CreatedTime >= dto.StartTime && t.CreatedTime <= dto.EndTime && t.OnState == EOnState.On)
                 .Where(t => userData.Contains(t.UserId))
                 .WhereIF(!string.IsNullOrEmpty(dto.UserName), t => t.UserName.Contains(dto.UserName))
                 .GroupBy(t => new { t.UserId })

+ 9 - 4
src/Hotline.Application/Subscribers/InternalCapSubscriber.cs

@@ -1,7 +1,9 @@
 using DotNetCore.CAP;
+using Hotline.Caching.Interfaces;
 using Hotline.Orders;
 using Hotline.Push;
 using Hotline.Push.Notifies;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Push;
 using Hotline.Share.Enums.Push;
@@ -22,14 +24,15 @@ namespace Hotline.Application.Subscribers
         private readonly IRepository<User> _userRepository;
         private readonly ICapPublisher _capPublisher;
         private readonly IRepository<BatchSmsTask> _batchSmsTaskRepository;
-
-        public InternalCapSubscriber(IOrderRepository orderRepository,IMediator mediator,IRepository<User> userRepository,ICapPublisher capPublisher,IRepository<BatchSmsTask> batchSmsTaskRepository)
+        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
+        public InternalCapSubscriber(IOrderRepository orderRepository,IMediator mediator,IRepository<User> userRepository,ICapPublisher capPublisher,IRepository<BatchSmsTask> batchSmsTaskRepository,ISystemSettingCacheManager systemSettingCacheManager)
         {
             _orderRepository = orderRepository;
             _mediator = mediator;
             _userRepository = userRepository;
             _capPublisher = capPublisher;
             _batchSmsTaskRepository = batchSmsTaskRepository;
+            _systemSettingCacheManager = systemSettingCacheManager;
         }
 
         /// <summary>
@@ -70,10 +73,11 @@ namespace Hotline.Application.Subscribers
                 //当前办理部门不为空,发短信给部门经办人
                 else if(!string.IsNullOrEmpty(order.CurrentHandleOrgId))
                 {
+                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                     //查询部门经办人
                     var userlist = await _userRepository.Queryable().Where(x =>
                         x.OrgId == order.CurrentHandleOrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
-                        x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                        x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
                     foreach (var user in userlist)
                     {
                         if (!string.IsNullOrEmpty(user.PhoneNo))
@@ -138,10 +142,11 @@ namespace Hotline.Application.Subscribers
                 //当前办理部门不为空,发短信给部门经办人
                 else if (!string.IsNullOrEmpty(order.CurrentHandleOrgId))
                 {
+                    var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
                     //查询部门经办人
                     var userlist = await _userRepository.Queryable().Where(x =>
                         x.OrgId == order.CurrentHandleOrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
-                        x.Roles.Any(d => d.Id == "08dae71e-0eca-4bc4-89fe-7eaefae8a98e")).ToListAsync();
+                        x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
                     foreach (var user in userlist)
                     {
                         if (!string.IsNullOrEmpty(user.PhoneNo))

+ 152 - 3
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -4,6 +4,7 @@ using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Settings.Hotspots;
+using Hotline.Share.Dtos.Bi;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.CallCenter;
@@ -27,16 +28,25 @@ namespace Hotline.Repository.SqlSugar.Orders
     {
         private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
         private readonly IRepository<OrderSendBackAudit> _orderSendBackAuditRepository;
+        private readonly IRepository<OrderVisit> _orderVisitRepository;
+        private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
+        private readonly ISessionContext _sessionContext;
 
 		public OrderRepository(ISugarUnitOfWork<HotlineDbContext> uow,
             IDataPermissionFilterBuilder dataPermissionFilterBuilder,
-            IRepository<OrderSendBackAudit> orderSendBackAuditRepository
-			) : base(uow, dataPermissionFilterBuilder)
+            IRepository<OrderSendBackAudit> orderSendBackAuditRepository,
+            IRepository<OrderVisit> orderVisitRepository,
+            ISessionContext sessionContext,
+            IRepository<OrderVisitDetail> orderVisitDetailRepository
+            ) : base(uow, dataPermissionFilterBuilder)
         {
             _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
             _orderSendBackAuditRepository = orderSendBackAuditRepository;
+            _orderVisitRepository = orderVisitRepository;
+            _sessionContext = sessionContext;
+            _orderVisitDetailRepository = orderVisitDetailRepository;
 
-		}
+        }
 
         public async Task<string> AddOrderNavAsync(Order order, CancellationToken cancellationToken)
         {
@@ -1200,6 +1210,145 @@ namespace Hotline.Repository.SqlSugar.Orders
                 }).OrderByDescending(x => x.CreationTime);
             return result;
         }
+
+        /// <summary>
+        /// 扭转列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrderVisit> VisitJudgeQuery(VisitJudgeQueryReq dto)
+        {
+            return _orderVisitRepository.Queryable()
+            .Includes(x => x.Order)
+            .Includes(x => x.Employee)
+            .Where(x => x.VisitState == EVisitState.Visited)
+            .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.No == dto.No)
+            .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title))
+            .WhereIF(!string.IsNullOrEmpty(dto.VisitUserName), x => x.Employee.Name.Contains(dto.VisitUserName))
+            .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), d => d.Order.AcceptTypeCode == dto.AcceptType)//受理类型
+            .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), d => d.Order.HotspotSpliceName != null && d.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgId), d => d.Order.CurrentHandleOrgId == dto.OrgId)//接办部门
+            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo),
+                d => d.Order.AcceptorName.Contains(dto.NameOrNo!) || d.Order.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
+            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+            .WhereIF(dto.ActualHandleTimeStart.HasValue, d => d.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
+            .WhereIF(dto.ActualHandleTimeEnd.HasValue, d => d.Order.ActualHandleTime <= dto.ActualHandleTimeEnd) //办结时间结束
+            .WhereIF(dto.VisitTimeStart.HasValue, d => d.VisitTime >= dto.VisitTimeStart) //回访开始时间
+            .WhereIF(dto.VisitTimeEnd.HasValue, d => d.VisitTime <= dto.VisitTimeEnd)
+            .WhereIF(dto.IsIng == true, d => d.JudgeState == EJudgeState.Judging)
+            .WhereIF(dto.IsIng == false, d => d.JudgeState != EJudgeState.Judging)
+            .WhereIF(dto.JudgeState != null, d => d.JudgeState == dto.JudgeState)
+            .WhereIF(dto.OrgJudge != null, d => d.OrgJudge == dto.OrgJudge)
+            .WhereIF(dto.SeatJudge != null, d => d.SeatJudge == dto.SeatJudge)
+            .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.CenterFiled, d => d.Order.ProcessType == EProcessType.Zhiban)
+            .WhereIF(dto.FiledType != null && dto.FiledType == FiledType.OrgFiled, d => d.Order.ProcessType == EProcessType.Jiaoban)
+            .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), x => x.Order.TransferPhone == dto.TransferPhone)
+            .OrderByDescending(x => x.VisitTime);
+        }
+
+        /// <summary>
+        /// 满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrgVisitDetailListResp> OrgVisitDetailList(OrgVisitDetailListReq dto)
+        {
+            var IsCenter = _sessionContext.OrgIsCenter;
+
+            return _orderVisitDetailRepository.Queryable()
+                .Includes(x => x.OrderVisit, x => x.Order)
+                .Includes(x => x.OrderVisit, x => x.Employee)
+                .Where(x => x.OrderVisit.VisitState == EVisitState.Visited && x.VisitTarget == EVisitTarget.Org)
+                .WhereIF(IsCenter == false, x => x.VisitOrgCode.StartsWith(_sessionContext.RequiredOrgId))
+                .WhereIF(dto.OrgVisitStatisticsType.HasValue, x => x.OrderVisit.Order.ProcessType == (EProcessType)((int)dto.OrgVisitStatisticsType))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
+                .WhereIF(!string.IsNullOrEmpty(dto.VisitUser), x => x.OrderVisit.Employee.Name.Contains(dto.VisitUser))
+                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order.No == dto.No)
+                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order.Title.Contains(dto.Title))
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgId), x => x.VisitOrgCode == dto.OrgId)//接办部门
+                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.OrderVisit.Order.HotspotSpliceName != null && x.OrderVisit.Order.HotspotSpliceName.Contains(dto.Hotspot))//热点类型
+                .WhereIF(!string.IsNullOrEmpty(dto.Channel), x => x.OrderVisit.Order.SourceChannelCode == dto.Channel)//受理类型
+                .WhereIF(dto.CreationTimeStart.HasValue, x => x.OrderVisit.Order.CreationTime >= dto.CreationTimeStart) //受理时间开始
+                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.OrderVisit.Order.CreationTime <= dto.CreationTimeEnd) //受理时间结束
+                .WhereIF(dto.ActualHandleTimeStart.HasValue, x => x.OrderVisit.Order.ActualHandleTime >= dto.ActualHandleTimeStart) //办结时间开始
+                .WhereIF(dto.ActualHandleTimeEnd.HasValue, x => x.OrderVisit.Order.ActualHandleTime <= dto.ActualHandleTimeEnd)//办结时间结束
+                .WhereIF(dto.VisitTimeStart.HasValue,x=>x.OrderVisit.VisitTime>= dto.VisitTimeStart) //回访时间
+                .WhereIF(dto.VisitTimeEnd.HasValue,x=>x.OrderVisit.VisitTime<dto.VisitTimeEnd) //回访时间
+                .OrderByDescending(x => x.OrderVisit.VisitTime)
+                .Select(x => new OrgVisitDetailListResp()
+                {
+                    Id = x.OrderVisit.Order.Id,
+                    VisitId = x.OrderVisit.Id,
+                    No =  x.OrderVisit.No,
+                    ReTransactNum = x.OrderVisit.Order.ReTransactNum,
+                    OrderScreenStatus = SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId).OrderByDesc(q => q.CreationTime).Select(q => q.Status),
+                    VisitContent = x.VisitContent,
+                    HotspotSpliceName = x.OrderVisit.Order.HotspotSpliceName,
+                    OrgLevelOneName = x.OrderVisit.Order.OrgLevelOneName,
+                    ActualHandleOrgName = x.OrderVisit.Order.ActualHandleOrgName,
+                    CreationTime = x.CreationTime,
+                    Title = x.OrderVisit.Order.Title,
+                    VisitUser = x.OrderVisit.Employee.Name,
+                    VisitType = x.OrderVisit.VisitType,
+                    VisitTime = x.OrderVisit.VisitTime,
+                    OrgProcessingResults = SqlFunc.JsonField(x.OrgProcessingResults,"Value"),
+                    Content = x.OrderVisit.Order.Content,
+                    FileOpinion = x.OrderVisit.Order.FileOpinion,
+                    FiledTime = x.OrderVisit.Order.FiledTime,
+                    VisitOrgName = x.VisitOrgName
+                }); 
+
+        }
+
+
+        /// <summary>
+        /// 部门满意度明细统计
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        public ISugarQueryable<OrgVisitDetailListResp> VisitAndOrgSatisfactionDetail(VisitAndOrgSatisfactionDetailDto dto)
+        {
+            dto.EndTime = dto.EndTime.AddDays(1).AddSeconds(-1);
+            bool IsCenter = _sessionContext.OrgIsCenter;
+            return _orderVisitDetailRepository.Queryable()
+                .Includes(x => x.OrderVisit, o => o.Order, d => d.CallRecord)
+                .Where(x => x.OrderVisit.VisitTime >= dto.StartTime && x.OrderVisit.VisitTime <= dto.EndTime && x.VisitTarget == EVisitTarget.Org && x.OrderVisit.VisitState == EVisitState.Visited)
+                .WhereIF(dto.OrgCode == "001", x => x.VisitOrgCode == dto.OrgCode)
+                .WhereIF(dto.TypeCode != null && dto.TypeCode == 1, x => x.OrderVisit.Order.IdentityType == EIdentityType.Citizen)
+                .WhereIF(dto.TypeCode != null && dto.TypeCode == 2, x => x.OrderVisit.Order.IdentityType == EIdentityType.Enterprise)
+                //.WhereIF(dto.OrgCode != "001", x => x.VisitOrgCode == dto.OrgCode).
+                .WhereIF(dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
+                .WhereIF(IsCenter == true && dto.IsOnlyMy == true, x => x.VisitOrgCode == dto.OrgCode)
+                .WhereIF(IsCenter == true && dto.IsOnlyMy == null, x => x.VisitOrgCode.StartsWith(dto.OrgCode))
+                .WhereIF(IsCenter == false, x => x.VisitOrgCode == dto.OrgCode)
+                .WhereIF(dto.TypeId is 1, x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.DateValue)
+                .WhereIF(dto.TypeId is 2, x => SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == dto.DateValue)
+                .WhereIF(!string.IsNullOrEmpty(dto.LineNum), x => x.OrderVisit.Order.CallRecord.Gateway == dto.LineNum)
+                .OrderByDescending(x => x.OrderVisit.VisitTime)
+                .Select(x => new OrgVisitDetailListResp
+                {
+                    Id = x.OrderVisit.Order.Id,
+                    VisitId = x.OrderVisit.Id,
+                    No = x.OrderVisit.No,
+                    ReTransactNum = x.OrderVisit.Order.ReTransactNum,
+                    OrderScreenStatus = SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId).OrderByDesc(q => q.CreationTime).Select(q => q.Status),
+                    VisitContent = x.VisitContent,
+                    HotspotSpliceName = x.OrderVisit.Order.HotspotSpliceName,
+                    OrgLevelOneName = x.OrderVisit.Order.OrgLevelOneName,
+                    ActualHandleOrgName = x.OrderVisit.Order.ActualHandleOrgName,
+                    CreationTime = x.CreationTime,
+                    Title = x.OrderVisit.Order.Title,
+                    VisitUser = x.OrderVisit.Employee.Name,
+                    VisitType = x.OrderVisit.VisitType,
+                    VisitTime = x.OrderVisit.VisitTime,
+                    OrgProcessingResults = SqlFunc.JsonField(x.OrgProcessingResults, "Value"),
+                    Content = x.OrderVisit.Order.Content,
+                    FileOpinion = x.OrderVisit.Order.FileOpinion,
+                    FiledTime = x.OrderVisit.Order.FiledTime,
+                    VisitOrgName = x.VisitOrgName
+                });
+        }
     }
 
     public class OrderScreenRepository : BaseRepositoryWorkflow<OrderScreen>, IOrderScreenRepository, IScopeDependency

+ 3 - 1
src/Hotline.Share/Dtos/CallCenter/CallNativeDto.cs

@@ -10,8 +10,10 @@ namespace Hotline.Share.Dtos.CallCenter
 {
     public class CallNativeDto
     {
+        public string Id { get; set; }
+
         /// <summary>
-        /// 通话记录编号
+        /// 通话记录编号(呼叫中心)
         /// </summary>
         public string CallNo { get; set; }
 

+ 6 - 0
src/Hotline.Share/Dtos/FlowEngine/PreviousWorkflowDto.cs

@@ -6,4 +6,10 @@ public class PreviousWorkflowDto : EndWorkflowIdDto
     /// 是否短信通知
     /// </summary>
     public bool AcceptSms { get; set; }
+
+    /// <summary>
+    /// 期满时间
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
 }

+ 1 - 1
src/Hotline.Share/Dtos/Order/HomeOrderDto.cs

@@ -61,4 +61,4 @@ namespace Hotline.Share.Dtos.Order
 		public DateTime? ActualHandleTime { get; set; }
 
 	}
-}
+}

+ 2 - 2
src/Hotline.Share/Dtos/Order/OrderBiDto.cs

@@ -290,7 +290,7 @@ namespace Hotline.Share.Dtos.Order
 		/// <summary>
 		/// 重办次数
 		/// </summary>
-		public string ReTransactNum { get; set; }
+		public int? ReTransactNum { get; set; }
 
 		/// <summary>
 		/// 甄别状态
@@ -348,7 +348,7 @@ namespace Hotline.Share.Dtos.Order
 		/// <summary>
 		/// 回访时间
 		/// </summary>
-		public DateTime VisitTime { get; set; }
+		public DateTime? VisitTime { get; set; }
 
 		/// <summary>
 		/// 满意度

+ 9 - 0
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -1067,4 +1067,13 @@ namespace Hotline.Share.Dtos.Order
     {
         public string OrderId { get; set; }
     }
+
+    public class OverTimeOrderDto
+    {
+        public string OrgId { get; set; }
+
+        public int NearlyOrderCount { get; set; }
+
+        public int ExpiredTimeOrderCount { get; set; }
+    }
 }

+ 8 - 0
src/Hotline.Share/Dtos/Order/OrderVisitDto.cs

@@ -115,6 +115,14 @@ namespace Hotline.Share.Dtos.Order
 
     public record VisitJudgeQueryReq : PagedKeywordRequest
     {
+        /// <summary>
+        /// 转接号码
+        /// </summary>
+        public string? TransferPhone { get; set; }
+        /// <summary>
+        /// 归档类型
+        /// </summary>
+        public FiledType? FiledType { get; set; }
         /// <summary>
         /// 工单编号
         /// </summary>

+ 83 - 0
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -424,6 +424,13 @@ public record OrgVisitDetailListReq: PagedKeywordRequest
     /// </summary>
     public DateTime? ActualHandleTimeStart { get; set; }
     public DateTime? ActualHandleTimeEnd { get; set; }
+
+    /// <summary>
+    /// 回访时间
+    /// </summary>
+    public DateTime? VisitTimeStart { get; set; }
+
+    public DateTime? VisitTimeEnd { get; set; }
 }
 
 
@@ -1121,3 +1128,79 @@ public class OrderDataInventoryRep
     public string? FileOpinion { get; set; }
 }
 
+public class OrderVisitJudeStatisticsReq
+{
+    /// <summary>
+    /// 开始时间
+    /// </summary>
+    public DateTime? StartTime { get; set; }
+    /// <summary>
+    /// 结束时间
+    /// </summary>
+    public DateTime? EndTime { get; set; }
+
+
+}
+
+public class OrderVisitJudeStatisticsRep
+{
+    /// <summary>
+    /// 回访员
+    /// </summary>
+    public string EmpName { get; set; }
+
+    public string EmpId { get; set; }
+
+    /// <summary>
+    /// 部门扭转总件
+    /// </summary>
+    public int OrgJudeCount { get; set; }
+
+    /// <summary>
+    /// 部门扭转待审批件
+    /// </summary>
+    public int OrgJudeApprovalingCount { get; set; }
+
+    /// <summary>
+    /// 部门扭转审批成功件
+    /// </summary>
+    public int OrgJudeSuccessCount { get; set; }
+
+    /// <summary>
+    /// 部门扭转审批失败件
+    /// </summary>
+    public int OrgJudeFailCount { get;set; }
+
+    /// <summary>
+    /// 坐席扭转总件
+    /// </summary>
+    public int SeatJudeCount { get; set; }
+
+    /// <summary>
+    /// 坐席扭转待审批件
+    /// </summary>
+    public int SeatJudeApprovalingCount { get; set; }
+
+    /// <summary>
+    /// 坐席扭转审批成功件
+    /// </summary>
+    public int SeatJudeSuccessCount { get; set; }
+
+    /// <summary>
+    /// 坐席扭转审批失败件
+    /// </summary>
+    public int SeatJudeFailCount { get; set; }
+
+}
+
+
+public record OrderVisitJudeDetailReq: PagedRequest
+{
+
+}
+
+
+public class OrderVisitJudeDetailRep
+{
+
+}

+ 10 - 4
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -250,10 +250,16 @@ namespace Hotline.FlowEngine.Workflows
         /// <returns></returns>
         Task<WorkflowStep> FindLastHandleStepAsync(string workflowId, string orgId, CancellationToken cancellation);
 
-        /// <summary>
-        /// 查询流转方向
-        /// </summary>
-        EFlowDirection GetFlowDirection(EBusinessType sourceStepBusinessType, EBusinessType directionStepBusinessType);
+		/// <summary>
+		/// 部门会签工单获取流程最顶级办理节点
+		/// </summary>
+		/// <returns></returns>
+		Task<WorkflowStep> FindTopHandleStepAsync(string workflowId, CancellationToken cancellation);
+
+		/// <summary>
+		/// 查询流转方向
+		/// </summary>
+		EFlowDirection GetFlowDirection(EBusinessType sourceStepBusinessType, EBusinessType directionStepBusinessType);
 
         /// <summary>
         /// 流程被签收至某个用户(更新流转对象,办理对象,节点办理对象以及stepHandlers)

+ 19 - 6
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -632,10 +632,13 @@ namespace Hotline.FlowEngine.Workflows
                 applicantOrgAreaCode, applicantOrgAreaName,
                 applicantIsCenter, dto.Opinion);
 
-            //await _workflowTraceRepository.UpdateAsync(trace, cancellationToken);
+			//await _workflowTraceRepository.UpdateAsync(trace, cancellationToken);
 
-            //复制上一个节点为待接办
-            var newPrevStep =
+			//如果有传入期满时间 新节点为传入的期满时间
+			if (dto.ExpiredTime.HasValue)
+                prevStep.StepExpiredTime = dto.ExpiredTime;
+			//复制上一个节点为待接办
+			var newPrevStep =
                 await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceType.Previous, cancellationToken);
 
             //remove workflow.steps
@@ -919,16 +922,26 @@ namespace Hotline.FlowEngine.Workflows
             CancellationToken cancellation)
         {
             return await _workflowStepRepository.Queryable()
-                .Where(d => d.WorkflowId == workflowId && d.HandlerOrgId == orgId && d.StepType != EStepType.End)
+                .Where(d => d.WorkflowId == workflowId && d.HandlerOrgId == orgId && d.StepType != EStepType.End && d.StepType !=  EStepType.Summary)
                 //.Where(d => d.StepHandlers.Any(sh => sh.OrgId == orgId) && d.WorkflowId == workflowId)
                 .OrderByDescending(d => d.HandleTime)
                 .FirstAsync(cancellation);
         }
 
         /// <summary>
-        /// 查询流转方向
+        /// 部门会签工单获取流程最顶级办理节点
         /// </summary>
-        public EFlowDirection GetFlowDirection(EBusinessType sourceStepBusinessType,
+        /// <returns></returns>
+        public async Task<WorkflowStep> FindTopHandleStepAsync(string workflowId, CancellationToken cancellation)
+        {
+            var workflow = await GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: cancellation);
+			return workflow.Steps.FirstOrDefault(x => x.Id == workflow.TopCountersignStepId);
+        }
+
+		/// <summary>
+		/// 查询流转方向
+		/// </summary>
+		public EFlowDirection GetFlowDirection(EBusinessType sourceStepBusinessType,
             EBusinessType directionStepBusinessType)
         {
             switch (sourceStepBusinessType)

+ 67 - 0
src/Hotline/Orders/AiVisitDomainService.cs

@@ -0,0 +1,67 @@
+using Hotline.Ai.Visit;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+using XF.Domain.Repository;
+
+namespace Hotline.Orders
+{
+    public class AiVisitDomainService : IAiVisitDomainService, IScopeDependency
+    {
+        private readonly IAiVisitService _aiVisitService;
+        private readonly IRepository<AiOrderVisit> _aiOrderVisitRepository;
+        private readonly IRepository<AiOrderVisitDetail> _aiOrderVisitDetailRepository;
+        private readonly IRepository<OrderVisit> _orderVisitRepository;
+
+        public AiVisitDomainService(IAiVisitService aiVisitService,IRepository<AiOrderVisit> aiOrderVisitRepository, IRepository<AiOrderVisitDetail> aiOrderVisitDetailRepository, IRepository<OrderVisit> orderVisitRepository)
+        {
+            _aiVisitService = aiVisitService;
+            _aiOrderVisitRepository = aiOrderVisitRepository;
+            _aiOrderVisitDetailRepository = aiOrderVisitDetailRepository;
+            _orderVisitRepository = orderVisitRepository;
+        }
+
+
+        public async Task OrderVisitStatusService(CancellationToken cancellationToken)
+        {
+            try
+            {
+                var aivisitList = await _aiOrderVisitRepository.Queryable()
+                .Includes(x => x.AiOrderVisitDetails, d => d.OrderVisit).Where(x => x.TaskState == Share.Enums.Ai.EAiOrderVisitTaskState.InProgress).ToListAsync();
+                if (aivisitList != null)
+                {
+                    foreach (var aivisit in aivisitList)
+                    {
+                        foreach (var aivisitDetail in aivisit.AiOrderVisitDetails)
+                        {
+                            if (!string.IsNullOrEmpty(aivisit.BatchUid) && !string.IsNullOrEmpty(aivisitDetail.TaskUid))
+                            {
+                                var res = await _aiVisitService.QueryAiVisitTask(aivisit.BatchUid, aivisitDetail.TaskUid, cancellationToken);
+                                if (res != null && res.Status == 4)
+                                {
+                                    aivisitDetail.AiOrderVisitState = Share.Enums.Ai.EAiOrderVisitState.LoseEfficacy;
+                                    await _aiOrderVisitDetailRepository.UpdateAsync(aivisitDetail, cancellationToken);
+                                    aivisitDetail.OrderVisit.VisitState = Share.Enums.Order.EVisitState.WaitForVisit;
+                                    aivisitDetail.OrderVisit.IsCanAiVisit = true;
+                                    await _orderVisitRepository.UpdateAsync(aivisitDetail.OrderVisit, cancellationToken);
+                                    aivisit.VisitedFailCount++;
+                                    if ((aivisit.VisitedFailCount + aivisit.VisitedCount) == aivisit.HasVisitCount)
+                                    {
+                                        aivisit.TaskState = Share.Enums.Ai.EAiOrderVisitTaskState.Ended;
+                                    }
+                                    await _aiOrderVisitRepository.UpdateAsync(aivisit, cancellationToken);
+                                }
+                            }
+
+                        }
+                    }
+                }
+
+            }
+            catch { }
+        }
+    }
+}

+ 13 - 0
src/Hotline/Orders/IAiVisitDomainService.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Orders
+{
+    public interface IAiVisitDomainService
+    {
+        Task OrderVisitStatusService(CancellationToken cancellationToken);
+    }
+}

+ 7 - 0
src/Hotline/Orders/IOrderDomainService.cs

@@ -97,5 +97,12 @@ namespace Hotline.Orders
         /// <returns></returns>
         bool IsCheckAdmin();
 
+        /// <summary>
+        /// 推送即将超期和超期短信
+        /// </summary>
+        /// <returns></returns>
+        Task SendOverTimeSms(CancellationToken cancellationToken);
+
+
     }
 }

+ 22 - 1
src/Hotline/Orders/IOrderRepository.cs

@@ -4,6 +4,7 @@ using SqlSugar;
 using System.Data;
 using Hotline.Share.Dtos.Order;
 using XF.Domain.Repository;
+using Hotline.Share.Dtos.Bi;
 
 namespace Hotline.Orders
 {
@@ -156,7 +157,27 @@ namespace Hotline.Orders
         /// <param name="dto"></param>
         /// <returns></returns>
         ISugarQueryable<OrderDataInventoryRep> OrderDataInventory(OrderDataInventoryReq dto);
-               
+
+        /// <summary>
+        /// 扭转列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrderVisit> VisitJudgeQuery(VisitJudgeQueryReq dto);
+
+        /// <summary>
+        /// 满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrgVisitDetailListResp> OrgVisitDetailList(OrgVisitDetailListReq dto);
+
+        /// <summary>
+        /// 部门满意度明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        ISugarQueryable<OrgVisitDetailListResp> VisitAndOrgSatisfactionDetail(VisitAndOrgSatisfactionDetailDto dto);
     }
 
     public interface IOrderScreenRepository : IRepositoryWorkflow<OrderScreen>

+ 61 - 1
src/Hotline/Orders/OrderDomainService.cs

@@ -20,6 +20,10 @@ using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos.FlowEngine;
 using Microsoft.AspNetCore.Http;
 using Hotline.Settings;
+using SqlSugar;
+using Hotline.Push.Notifies;
+using Hotline.Share.Enums.Push;
+using MediatR;
 
 namespace Hotline.Orders;
 
@@ -42,6 +46,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     private readonly ISystemSettingCacheManager _systemSettingCacheManager;
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IRepository<Hotspot> _hotspotRepository;
+    private readonly IMediator _mediator;
 
 
     public OrderDomainService(
@@ -62,7 +67,8 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         ISystemSettingCacheManager systemSettingCacheManager,
         IRepository<Scheduling> schedulingRepository,
         IWorkflowDomainService workflowDomainService,
-        IRepository<Hotspot> hotspotRepository)
+        IRepository<Hotspot> hotspotRepository,
+        IMediator mediator)
     {
         _orderRepository = orderRepository;
         _orderRedoRepository = orderRedoRepository;
@@ -81,6 +87,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         _systemSettingCacheManager = systemSettingCacheManager;
         _workflowDomainService = workflowDomainService;
         _hotspotRepository = hotspotRepository;
+        _mediator = mediator;
     }
 
     public async Task<Order> GetOrderAsync(string? orderId, bool withHotspot = false, bool withAcceptor = false,
@@ -400,6 +407,59 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     }
     #endregion
 
+
+    #region 即将超期和超期短信
+
+    /// <summary>
+    ///  即将超期和超期短信
+    /// </summary>
+    /// <returns></returns>
+    public async Task SendOverTimeSms(CancellationToken cancellationToken)
+    {
+        var now = DateTime.Now;
+        //查询即将超期和超期工单
+        var orderList = await _orderRepository.Queryable()
+            .Where(x=> x.Status< EOrderStatus.Filed && !string.IsNullOrEmpty(x.CurrentHandleOrgId))
+            .GroupBy(x=>x.CurrentHandleOrgId)
+            .Select(x => new OverTimeOrderDto
+            { 
+                 OrgId = x.CurrentHandleOrgId,
+                 NearlyOrderCount = SqlFunc.AggregateSum(SqlFunc.IIF(now >= x.NearlyExpiredTime  && now < x.ExpiredTime ,1,0)),
+                 ExpiredTimeOrderCount = SqlFunc.AggregateSum(SqlFunc.IIF(x.ExpiredTime<now,1,0))
+            })
+            .ToListAsync(cancellationToken);
+
+        foreach (var item in orderList)
+        {
+            if (item.NearlyOrderCount==0 && item.ExpiredTimeOrderCount==0)
+            {
+                continue;
+            }
+            var acceptSmsRoleIds = _systemSettingCacheManager.GetSetting(SettingConstants.AcceptSmsRoleIds)?.SettingValue;
+            //查询部门所有账号
+            var userlist = await _userRepository.Queryable().Where(x =>
+                x.OrgId == item.OrgId && !string.IsNullOrEmpty(x.PhoneNo) &&
+                x.Roles.Any(d => acceptSmsRoleIds.Contains(d.Id))).ToListAsync();
+            //发送短信
+            foreach (var user in userlist)
+            {
+                var messageDto = new Share.Dtos.Push.MessageDto
+                {
+                    PushBusiness = EPushBusiness.OrderExpire,
+                    PushPlatform = EPushPlatform.Sms,
+                    Name = user.Name,
+                    TemplateCode = "1009",
+                    Params = new List<string>() { item.NearlyOrderCount.ToString(), item.ExpiredTimeOrderCount.ToString() },
+                    TelNumber = user.PhoneNo,
+                };
+                await _mediator.Publish(new PushMessageNotify(messageDto), cancellationToken);
+            }
+        }
+    }
+
+    #endregion
+
+
     #region private
 
     private async Task<Order> GetOrderByFlowIdAsync(string workflowId, CancellationToken cancellationToken)

+ 45 - 0
src/Hotline/Permissions/EPermission.cs

@@ -2378,6 +2378,51 @@ namespace Hotline.Permissions
         /// </summary>
         [Display(GroupName = "中心办件统计", Name = "应急清单", Description = "应急清单")]
         EmergencyList = 110506,
+        /// <summary>
+        /// 中心受理统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="中心受理统计",Description ="中心受理统计")]
+        CenterAcceptStatistics = 110507,
+        /// <summary>
+        /// 报告管理
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="报告管理",Description ="报告管理")]
+        ReportManage = 110508,
+        /// <summary>
+        /// 数据清单
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="数据清单",Description ="数据清单")]
+        OrderDataList = 110509,
+        /// <summary>
+        /// 提起甄别统计
+        /// </summary>
+        [Display(GroupName ="中心办结统计",Name ="提起甄别统计",Description ="提起甄别统计")]
+        AddOrderScreenStatistics = 110510,
+        /// <summary>
+        /// 提起甄别审核统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="提起甄别审核统计",Description ="提起甄别审核统计")]
+        AddOrderScreenApproveStatistics = 110511,
+        /// <summary>
+        /// 未签收统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="未签收统计",Description ="未签收统计")]
+        NoSignStatistics = 110512,
+        /// <summary>
+        /// 回访来源统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="回访来源统计",Description ="回访来源统计")]
+        VisitSourceStatistics = 110513,
+        /// <summary>
+        /// 企业专席信件统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="企业专席信件统计",Description ="企业专席信件统计")]
+        EnterpriseSeatOrderStatistics = 110514,
+        /// <summary>
+        /// 发布量统计
+        /// </summary>
+        [Display(GroupName ="中心办件统计",Name ="发布量统计",Description ="发布量统计")]
+        PublishCountStatistics = 110515,
         #endregion
 
         #region 部门办件统计(11,06,00)

+ 5 - 0
src/Hotline/Settings/SettingConstants.cs

@@ -460,6 +460,11 @@ namespace Hotline.Settings
         /// </summary>
         public const string RecordDownLoadPrefix = "RecordDownLoadPrefix";
 
+        /// <summary>
+        /// 接受短信的角色ID
+        /// </summary>
+        public const string AcceptSmsRoleIds = "AcceptSmsRoleIds";
+
         /// <summary>
         /// 企业专席配置	
         /// </summary>

+ 12 - 4
src/Hotline/dataview.md

@@ -1,5 +1,5 @@
 ### 信件数据查询
-select aaa.*,bbb."SeatVisitResult" from 
+select aaa.*,bbb."SeatVisitResult",ccc."OrgProcessingResults" from 
 (select 
 CASE "ordertemp"."Status"
 	WHEN 500 THEN '已回访'
@@ -83,12 +83,12 @@ CASE "FromGender"
 	ELSE '未知'
 END AS "FromGender" , 
 '-' AS "SeatVisitResult",
-"FirstVisitResult" AS "FirstVisitResult" , 
+'-' AS "NowEvaluate",
 "PushType" AS "PushType" , 
 "Content" AS "Content" , 
 "ActualOpinion" AS "ActualOpinion" ,
 "FileOpinion" AS "FileOpinion" ,
-"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-07-17' ) AND ( "CreationTime" < '2024-07-24' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
+"Id" AS "SugarNav_Id" FROM "order" ordertemp  WHERE (( "CreationTime" >= '2024-07-29' ) AND ( "CreationTime" < '2024-08-10' ))  AND ( "IsDeleted" = FALSE )ORDER BY "CreationTime" ASC) aaa
 left join 
 (select DISTINCT CASE visitdetailtemp."SeatEvaluate"
 	WHEN 0 THEN '默认满意'
@@ -102,7 +102,15 @@ left join
 END AS "SeatVisitResult",visittemp."OrderId" as "OrderId"
  from order_visit visittemp
 left join order_visit_detail visitdetailtemp on visittemp."Id"= visitdetailtemp."VisitId"  
-where visittemp."CreationTime">='2024-07-17' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb on aaa."SugarNav_Id"=bbb."OrderId";
+where visittemp."CreationTime">='2024-07-29' and visitdetailtemp."VisitTarget"=10 AND visittemp."VisitState"=30 ) bbb
+on aaa."SugarNav_Id"=bbb."OrderId"
+left join 
+(select DISTINCT
+visitdetailtemptwo."OrgProcessingResults"::JSON->>'Value' as "OrgProcessingResults",visittemptwo."OrderId"
+from order_visit visittemptwo
+left join order_visit_detail visitdetailtemptwo on visittemptwo."Id" = visitdetailtemptwo."VisitId"
+where visittemptwo."CreationTime">='2024-07-29' and visitdetailtemptwo."VisitTarget"=20 AND visittemptwo."VisitState"=30) ccc
+on aaa."SugarNav_Id"=ccc."OrderId";
 
 
 ### 超期件查询