Explorar el Código

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

xf hace 8 meses
padre
commit
0f84ad7615
Se han modificado 28 ficheros con 723 adiciones y 499 borrados
  1. 142 146
      src/Hotline.Api/Controllers/CommonPController.cs
  2. 108 60
      src/Hotline.Api/Controllers/OrderController.cs
  3. 77 241
      src/Hotline.Api/Controllers/TestController.cs
  4. 2 1
      src/Hotline.Api/Controllers/WebPortalController.cs
  5. 1 1
      src/Hotline.Api/StartupExtensions.cs
  6. 27 2
      src/Hotline.Api/StartupHelper.cs
  7. 1 1
      src/Hotline.Api/config/appsettings.Development.json
  8. 1 1
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  9. 5 4
      src/Hotline.Application/Handlers/FlowEngine/WorkflowNextHandler.cs
  10. 12 6
      src/Hotline.Application/Handlers/FlowEngine/WorkflowStartHandler.cs
  11. 29 0
      src/Hotline.Application/Jobs/CheckAiVisitStateJob.cs
  12. 32 0
      src/Hotline.Application/Jobs/SendOverTimeSmsJob.cs
  13. 18 12
      src/Hotline.Application/Orders/OrderSecondaryHandlingApplication.cs
  14. 3 3
      src/Hotline.Application/StatisticalReport/CallReportApplication.cs
  15. 1 1
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  16. 9 4
      src/Hotline.Application/Subscribers/InternalCapSubscriber.cs
  17. 6 0
      src/Hotline.Share/Dtos/FlowEngine/PreviousWorkflowDto.cs
  18. 1 1
      src/Hotline.Share/Dtos/Order/HomeOrderDto.cs
  19. 9 0
      src/Hotline.Share/Dtos/Order/OrderDto.cs
  20. 10 4
      src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs
  21. 19 6
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  22. 67 0
      src/Hotline/Orders/AiVisitDomainService.cs
  23. 13 0
      src/Hotline/Orders/IAiVisitDomainService.cs
  24. 7 0
      src/Hotline/Orders/IOrderDomainService.cs
  25. 61 1
      src/Hotline/Orders/OrderDomainService.cs
  26. 45 0
      src/Hotline/Permissions/EPermission.cs
  27. 5 0
      src/Hotline/Settings/SettingConstants.cs
  28. 12 4
      src/Hotline/dataview.md

+ 142 - 146
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;
+				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");
+				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(waitedExpiredList);
+				//allList.AddRange(waitedExpiredDataList);
 				//回访待办
 				var visitDataList = await _orderVisitRepository.Queryable()
 					.Includes(d => d.Order)
@@ -287,11 +282,11 @@ namespace Hotline.Api.Controllers
 				//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");
+				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(signList);
+				//allList.AddRange(signDataList);
 				//延期待审批
 				var delayDataList = await _orderDelayRepository.Queryable(canView: true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -375,12 +370,12 @@ namespace Hotline.Api.Controllers
 				//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();
+				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");
+				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(signList);
+				//allList.AddRange(signDataList);
 				//甄别待审批
 				var screenDataList = await _orderScreenRepository.Queryable(hasHandled: !true, isAdmin: isAdmin)
 					.Includes(d => d.Order)
@@ -508,7 +506,7 @@ namespace Hotline.Api.Controllers
 				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
 					{
@@ -543,8 +541,6 @@ namespace Hotline.Api.Controllers
 						CounterSignType = d.CounterSignType
 					}).Take(40)
 					.ToListAsync();
-				//allNum += nearlyExpiredDataList.Count;
-				//allList.AddRange(nearlyExpiredDataList);
 				return new
 				{
 					//AllNum = allNum,
@@ -552,7 +548,7 @@ namespace Hotline.Api.Controllers
 					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,

+ 108 - 60
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;
@@ -2040,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!)
@@ -2353,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)
                     {
@@ -2597,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)
                     {
                         //发送短信
@@ -3709,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)) //超期 未办
@@ -3822,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)) //超期 未办
@@ -3977,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)) //超期 未办
@@ -4021,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)) //超期 未办
@@ -4099,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;
@@ -4154,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);
@@ -4164,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 })
@@ -4205,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 })
@@ -4565,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,
@@ -4576,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) ||
@@ -4689,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);
@@ -4792,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) ||
@@ -4902,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) ||

+ 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

@@ -175,7 +175,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
       //智能回访

+ 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);
+        }
+    }
+}

+ 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 - 1
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -1911,7 +1911,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))

+ 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; }
 
 	}
-}
+}

+ 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; }
+    }
 }

+ 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);
+
+
     }
 }

+ 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";
 
 
 ### 超期件查询