Procházet zdrojové kódy

Merge branch 'test' into lib/test

libin před 2 měsíci
rodič
revize
7974973986
34 změnil soubory, kde provedl 434 přidání a 386 odebrání
  1. 76 73
      src/Hotline.Api/Controllers/Bi/BiOrderController.cs
  2. 2 2
      src/Hotline.Api/Controllers/KnowledgeController.cs
  3. 46 10
      src/Hotline.Api/Controllers/OrderController.cs
  4. 0 1
      src/Hotline.Application/FlowEngine/WorkflowApplication.cs
  5. 5 84
      src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs
  6. 6 20
      src/Hotline.Application/Orders/OrderApplication.cs
  7. 1 1
      src/Hotline.Application/Snapshot/IInviteCodeApplication.cs
  8. 2 2
      src/Hotline.Application/Snapshot/InviteCodeApplication.cs
  9. 9 6
      src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs
  10. 87 6
      src/Hotline.Application/StatisticalReport/OrderReportApplication.cs
  11. 8 1
      src/Hotline.Repository.SqlSugar/BaseRepository.cs
  12. 14 6
      src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs
  13. 6 1
      src/Hotline.Share/Dtos/Bi/BiOrderDto.cs
  14. 1 1
      src/Hotline.Share/Dtos/Order/OrderBiDto.cs
  15. 6 1
      src/Hotline.Share/Requests/PagedKeywordRequest.cs
  16. 1 10
      src/Hotline/Orders/IOrderDomainService.cs
  17. 2 1
      src/Hotline/Orders/IOrderRepository.cs
  18. 0 130
      src/Hotline/Orders/OrderDomainService.cs
  19. 3 1
      test/Hotline.Tests/Application/DefaultCallApplicationTest.cs
  20. 3 1
      test/Hotline.Tests/Application/IndustryApplicationTest.cs
  21. 28 2
      test/Hotline.Tests/Application/InviteCodeApplicationTest.cs
  22. 11 2
      test/Hotline.Tests/Application/KnowApplicationTest.cs
  23. 46 10
      test/Hotline.Tests/Application/OrderSnapshotApplicationTest.cs
  24. 9 1
      test/Hotline.Tests/Application/RedPackApplicationTest.cs
  25. 4 1
      test/Hotline.Tests/Application/SnapshotApplicationTest.cs
  26. 7 1
      test/Hotline.Tests/Application/SystemSettingCacheManagerTest.cs
  27. 8 1
      test/Hotline.Tests/Controller/IndustryControllerTest.cs
  28. 10 1
      test/Hotline.Tests/Controller/KnowledgeControllerTest.cs
  29. 10 2
      test/Hotline.Tests/Controller/OrderControllerTest.cs
  30. 8 1
      test/Hotline.Tests/Controller/SnapshotControllerTest.cs
  31. 2 1
      test/Hotline.Tests/Domain/OrderVisitDomainServiceTest.cs
  32. 1 0
      test/Hotline.Tests/SqlSuger/CapDbExtensions.cs
  33. 11 4
      test/Hotline.Tests/TestBase.cs
  34. 1 1
      test/Hotline.Tests/appsettings.Development.json

+ 76 - 73
src/Hotline.Api/Controllers/Bi/BiOrderController.cs

@@ -49,6 +49,7 @@ using Hotline.File;
 using Hotline.KnowledgeBase;
 using DocumentFormat.OpenXml.Vml.Spreadsheet;
 using Hotline.Share.Tools;
+using MediatR;
 
 namespace Hotline.Api.Controllers.Bi
 {
@@ -1147,79 +1148,81 @@ namespace Hotline.Api.Controllers.Bi
         public async Task<object> HotPortJoinOrgStatistics([FromQuery] HotPortJoinOrgStatisticsRequest dto)
         {
             var IsCenter = _sessionContext.OrgIsCenter;
-            return await _orderRepository.HotPortJoinOrgStatistics(dto.StartTime, dto.EndTime, IsCenter, _sessionContext.OrgId);
-        }
-
-
-		/// <summary>
-		/// 热点类型部门统计--导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		//[HttpPost("hotport-org-statistics/export")]
-		//public async Task<FileStreamResult> ExportHotPortJoinOrgStatistics([FromBody] ExportHotPortJoinOrgStatisticsRequest dto)
-		//{
-		//	if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
-		//	if (dto.AddColumnName is null || dto.AddColumnName.Count == 0) throw UserFriendlyException.SameMessage("导出字段不能为空");
-		//	if (dto.AddColumnName.FirstOrDefault() != "部门名称") throw UserFriendlyException.SameMessage("导出字段第一个必须是'部门名称'");
-
-		//	var (dissatisfiedReason, list) = await _orderRepository.HotPortJoinOrgStatistics(dto, _sessionContext.OrgIsCenter);
-		//	var dataTable = await _orderReportApplication.ExportQueryVisitNoSatisfiedAsync(dissatisfiedReason, list, dto.AddColumnName);
-
-		//	return ExcelStreamResult(ExcelHelper.CreateStream(dataTable), "回访不满意原因统计");
-		//}
-
-		/// <summary>
-		/// 热点类型部门统计
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("hotport-org-statistics-detail")]
-		public async Task<PagedDto<OrderDto>> HotPortJoinOrgStatisticsDetail([FromQuery] HotPortJoinOrgStatisticsRequestDetail dto)
-		{
-			var (total, items) = await _orderRepository.HotPortJoinOrgStatisticsDetail(dto)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
-		}
-
-		/// <summary>
-		/// 热点类型部门统计明细导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpPost("hotport-org-statistics-detail/export")]
-		public async Task<FileStreamResult> HotPortJoinOrgStatisticsDetailExport([FromBody] ExportExcelDto<HotPortJoinOrgStatisticsRequestDetail> dto)
-		{
-			var query = _orderRepository.HotPortJoinOrgStatisticsDetail(dto.QueryDto);
-			List<Order> data;
-			if (dto.IsExportAll)
-			{
-				data = await query.ToListAsync(HttpContext.RequestAborted);
-			}
-			else
-			{
-				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
-				data = items;
-			}
-			var orderDtos = _mapper.Map<IReadOnlyList<OrderDto>>(data);
-			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
-
-			var dtos = orderDtos
-				.Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
-				.Cast<object>()
-				.ToList();
-
-			var stream = ExcelHelper.CreateStream(dtos);
-
-			return ExcelStreamResult(stream, "热点类型部门统计明细");
-		}
-
-		/// <summary>
-		/// 回访量统计导出
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpPost("visit-measure-statistics-export")]
+            var (hotSpot, data) = await _orderRepository.HotPortJoinOrgStatistics(dto.StartTime, dto.EndTime, IsCenter, _sessionContext.OrgId);
+			return  new { hotSpot, data };
+        }
+
+
+        /// <summary>
+        /// 热点类型部门统计--导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("hotport-org-statistics/export")]
+        public async Task<FileStreamResult> ExportHotPortJoinOrgStatistics([FromBody] ExportHotPortJoinOrgStatisticsRequest dto)
+        {
+            if (!dto.StartTime.HasValue || !dto.EndTime.HasValue) throw UserFriendlyException.SameMessage("请选择时间!");
+            if (dto.AddColumnName is null || dto.AddColumnName.Count == 0) throw UserFriendlyException.SameMessage("导出字段不能为空");
+            if (dto.AddColumnName.FirstOrDefault() != "部门名称") throw UserFriendlyException.SameMessage("导出字段第一个必须是'部门名称'");
+            var IsCenter = _sessionContext.OrgIsCenter;
+
+            var (hotSpot, list) = await _orderRepository.HotPortJoinOrgStatistics(dto.StartTime.Value, dto.EndTime.Value, IsCenter, _sessionContext.OrgId);
+            var dataTable = await _orderReportApplication.ExportHotPortJoinOrgStatisticsAsync(hotSpot, list, dto.AddColumnName);
+
+            return ExcelStreamResult(ExcelHelper.CreateStream(dataTable), "热点类型部门统计");
+        }
+
+        /// <summary>
+        /// 热点类型部门统计明细
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("hotport-org-statistics/detail")]
+        public async Task<PagedDto<OrderDto>> HotPortJoinOrgStatisticsDetail([FromQuery] HotPortJoinOrgStatisticsRequestDetail dto)
+        {
+            var (total, items) = await _orderRepository.HotPortJoinOrgStatisticsDetail(dto)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
+        }
+
+        /// <summary>
+        /// 热点类型部门统计明细导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("hotport-org-statistics/detail/export")]
+        public async Task<FileStreamResult> HotPortJoinOrgStatisticsDetailExport([FromBody] ExportExcelDto<HotPortJoinOrgStatisticsRequestDetail> dto)
+        {
+            var query = _orderRepository.HotPortJoinOrgStatisticsDetail(dto.QueryDto);
+            List<Order> data;
+            if (dto.IsExportAll)
+            {
+                data = await query.ToListAsync(HttpContext.RequestAborted);
+            }
+            else
+            {
+                var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
+                data = items;
+            }
+            var orderDtos = _mapper.Map<IReadOnlyList<OrderDto>>(data);
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
+
+            var dtos = orderDtos
+                .Select(stu => _mapper.Map(stu, typeof(OrderDto), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "热点类型部门统计明细");
+        }
+
+        /// <summary>
+        /// 回访量统计导出
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost("visit-measure-statistics-export")]
         [AllowAnonymous]
         public async Task<FileStreamResult> VisitMeasureStatisticsExport([FromBody] ExportExcelDto<VisitMeasureStatisticsRequest> dto)
         {

+ 2 - 2
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -547,7 +547,7 @@ namespace Hotline.Api.Controllers
             var knowledge = await _knowledgeRepository.GetAsync(dto.Data.Id, HttpContext.RequestAborted);
             if (knowledge == null)
                 throw UserFriendlyException.SameMessage("无效知识库数据");
-            if (knowledge.Status == EKnowledgeStatus.OnShelf || knowledge.Status == EKnowledgeStatus.Auditing)
+            if ((knowledge.Status == EKnowledgeStatus.OnShelf  && knowledge.ExpiredTime >= DateTime.Now) || knowledge.Status == EKnowledgeStatus.Auditing)
                 throw UserFriendlyException.SameMessage("知识库数据不可删除");
             if (knowledge.Status == EKnowledgeStatus.Drafts || knowledge.Status == EKnowledgeStatus.Revert)
             {
@@ -573,7 +573,7 @@ namespace Hotline.Api.Controllers
             var knowledge = await _knowledgeRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
             if (knowledge == null)
                 throw UserFriendlyException.SameMessage("无效知识库数据");
-            if (knowledge.Status == EKnowledgeStatus.OnShelf || knowledge.Status == EKnowledgeStatus.Auditing)
+            if ((knowledge.Status == EKnowledgeStatus.OnShelf && knowledge.ExpiredTime >= DateTime.Now) || knowledge.Status == EKnowledgeStatus.Auditing)
                 throw UserFriendlyException.SameMessage("知识库数据不可删除");
 
             if (knowledge.Status == EKnowledgeStatus.Drafts || knowledge.Status == EKnowledgeStatus.Revert)

+ 46 - 10
src/Hotline.Api/Controllers/OrderController.cs

@@ -2830,12 +2830,47 @@ public class OrderController : BaseController
         return rspModel;
     }
 
-    /// <summary>
-    /// 更新甄别提起截至时限
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <returns></returns>
-    [HttpPut("order_screen_endtime")]
+	/// <summary>
+	/// 甄别详情
+	/// </summary>
+	/// <param name="id"></param>
+	/// <returns></returns>
+	[HttpGet("screen/visitdetail/{id}")]
+	public async Task<OrderScreenListDto> VisitDetailScreenEntity(string id)
+	{
+		var model = await _orderScreenRepository.Queryable(canView: false)
+			.Includes(x => x.Order)
+			.Includes(x => x.Workflow, d => d.Steps)
+			.Includes(x => x.Visit, d => d.Order)
+			.FirstAsync(x => x.VisitDetailId  == id);
+		var rspModel = _mapper.Map<OrderScreenListDto>(model);
+		//rspModel.IsCanHandle = model.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+		rspModel.IsCanHandle = model.Workflow?.IsCanHandle(
+			_sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, _sessionContext.Roles) ?? false;
+		if (model.Status == EScreenStatus.SendBack && model.SendBackApply)
+			rspModel.IsCanHandle = false;
+		rspModel.Handle = false;
+		if (!string.IsNullOrEmpty(rspModel.WorkflowId))
+		{
+			rspModel.Handle = await _workflowDomainService.CheckCurrentIsStartStepAsync(rspModel.WorkflowId, _sessionContext.RequiredUserId,
+				_sessionContext.RequiredOrgId, HttpContext.RequestAborted);
+		}
+
+		if (rspModel.FileJson != null && rspModel.FileJson.Any())
+		{
+			var ids = rspModel.FileJson.Select(x => x.Id).ToList();
+			rspModel.Files = await _fileRepository.GetFilesAsync(ids, HttpContext.RequestAborted);
+		}
+
+		return rspModel;
+	}
+
+	/// <summary>
+	/// 更新甄别提起截至时限
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	[HttpPut("order_screen_endtime")]
     [LogFilter("更新甄别提起截至时限")]
     public async Task Update([FromBody] OrderScreenEndTimeDto dto)
     {
@@ -5855,7 +5890,7 @@ public class OrderController : BaseController
                 NextStepCode = dto.NextStepCode,
                 NextStepName = dto.NextStepName,
                 NextHandlers = dto.NextHandlers,
-                Opinion = dto.Cause,
+                Opinion = "【特提理由】" + dto.Cause,
                 FlowDirection = dto.FlowDirection,
                 HandlerType = dto.HandlerType,
                 BusinessType = dto.BusinessType
@@ -6087,7 +6122,7 @@ public class OrderController : BaseController
                 NextStepCode = dto.NextStepCode,
                 NextStepName = dto.NextStepName,
                 NextHandlers = dto.NextHandlers,
-                Opinion = dto.Reason,
+                Opinion = "【特提理由】" + dto.Reason,
                 FlowDirection = dto.FlowDirection,
                 HandlerType = dto.HandlerType,
                 BusinessType = dto.BusinessType,
@@ -6458,7 +6493,7 @@ public class OrderController : BaseController
                     NextStepCode = special.NextStepCode,
                     NextStepName = special.NextStepName,
                     NextHandlers = special.NextHandlers,
-                    Opinion = dto.Opinion,
+                    Opinion = "【特提理由】" + dto.Opinion,
                     FlowDirection = special.FlowDirection,
                     HandlerType = special.HandlerType.Value,
                     BusinessType = special.BusinessType.Value
@@ -6870,7 +6905,8 @@ public class OrderController : BaseController
 
             if (!order.FileOrgIsCenter.Value)
             {
-                if (step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1).Any())
+				 //&& x.StepType == EStepType.Normal
+				if (step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1).Any())
                 {
                     var stepdDefault = step.Steps.Where(x => x.BusinessType == EBusinessType.Department && x.OrgLevel == 1)
                         .FirstOrDefault();

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

@@ -16,7 +16,6 @@ using Hotline.File;
 using Hotline.Share.Enums.Settings;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
-using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Extensions;
 using XF.Domain.Repository;

+ 5 - 84
src/Hotline.Application/Handlers/FlowEngine/WorkflowEndHandler.cs

@@ -324,100 +324,21 @@ public class WorkflowEndHandler : INotificationHandler<EndWorkflowNotify>
                     //推诿工单
                     // await _enforcementApplication.AddPassTheBuckOrderAsync(order, _sessionContext.OrgId, _sessionContext.OrgName, cancellationToken);
                     break;
-                //case WorkflowModuleConsts.OrderScreen:
-                //    var screen = await _orderScreenRepository.GetAsync(workflow.ExternalId, cancellationToken);
-                //    if (screen != null)
-                //    {
-                //        screen.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
-                //        if (isReviewPass)
-                //        {
-                //            screen.Status = EScreenStatus.End;
-                //            screen.ReplyContent = workflow.ActualOpinion;
-                //            await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
-                //            var visitDetail =
-                //                await _orderVisitedDetailRepository.GetAsync(screen.VisitDetailId, cancellationToken);
-                //            if (visitDetail != null)
-                //            {
-                //                var screenSatisfy = new Kv() { Key = "-1", Value = "视为满意" };
-                //                visitDetail.OrgProcessingResults = screenSatisfy;
-                //                //visitDetail.OrgHandledAttitude = screenSatisfy;
-                //                await _orderVisitedDetailRepository.UpdateAsync(visitDetail, cancellationToken);
-                //                // 修改主表当前评价结果
-                //                await _orderVisitRepository.Updateable().SetColumns(v => new OrderVisit() { NowEvaluate = screenSatisfy }).Where(v => v.Id == visitDetail.VisitId).ExecuteCommandAsync(cancellationToken);
-                //                //获取回访信息
-                //                var visit = await _orderVisitRepository.Queryable().Includes(x => x.Order)
-                //                    .Includes(x => x.OrderVisitDetails)
-                //                    .Where(x => x.Id == screen.VisitId).FirstAsync(cancellationToken);
-                //                if (visit != null)
-                //                {
-                //                    //获取回访明细
-                //                    var visitDe = visit.OrderVisitDetails.First(x => x.Id == screen.VisitDetailId);
-                //                    //推省上
-                //                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderScreenApplyed,
-                //                          new PublishVisitDto()
-                //                          {
-                //                              Order = _mapper.Map<OrderDto>(visit.Order),
-                //                              No = visit.No,
-                //                              VisitType = visit.VisitType,
-                //                              VisitName = visit.CreatorName,
-                //                              VisitTime = visit.VisitTime,
-                //                              VisitRemark = string.IsNullOrEmpty(visitDe.VisitContent) ? screenSatisfy.Value : visitDe.VisitContent,
-                //                              AreaCode = visit.Order.AreaCode!,
-                //                              SubjectResultSatifyCode = visitDe.OrgProcessingResults?.Key,
-                //                              FirstSatisfactionCode = visit.Order.FirstVisitResultCode!,
-                //                              ClientGuid = ""
-                //                          });
-
-                //                    //推门户
-                //                    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisitedWeb, new PublishVisitAllDto()
-                //                    {
-                //                        Id = visit.Id,
-                //                        Order = _mapper.Map<OrderDto>(visit.Order),
-                //                        OrderVisitDetails = _mapper.Map<List<VisitDetailDto>>(visit.OrderVisitDetails),
-                //                        VisitName = visit.CreatorName,
-                //                        VisitTime = visit.VisitTime,
-                //                        VisitType = visit.VisitType,
-                //                        VisitState = visit.VisitState,
-                //                        PublishTime = visit.PublishTime,
-                //                    }, cancellationToken: cancellationToken);
-                //                }
-                //            }
-                //        }
-                //      else
-                //               {
-                //                   await _orderRepository.OrderScreenRevisionVisit(screen.VisitId, true, cancellationToken);
-                //                   screen.Status = EScreenStatus.Refuse;
-                //                   screen.ReplyContent = workflow.ActualOpinion;
-                //               }
-                //               screen.NewestAuditTime = DateTime.Now;
-                //await _orderScreenRepository.UpdateAsync(screen, cancellationToken);
-                //OrderScreenDetail detail = new OrderScreenDetail
-                //{
-                //	ScreenId = screen.Id
-                //};
-                //detail.Audit(_sessionContext.UserId, _sessionContext.UserName, _sessionContext.OrgId, _sessionContext.OrgName, 1);
-                //               await _orderScreenDetailRepository.AddAsync(detail, cancellationToken);
-                //    }
-                //    break;
                 case WorkflowModuleConsts.OrderDelay:
                     var delay = await _orderDelayRepository.GetAsync(workflow.ExternalId, cancellationToken);
                     if (delay != null)
                     {
-                        delay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
+                        //delay.Flowed(workflow.FlowedUserIds, workflow.FlowedOrgIds, workflow.HandlerUsers, workflow.HandlerOrgs);
+                        delay.DelayState = isReviewPass ? EDelayState.Pass : EDelayState.NoPass;
+                        await _orderDelayRepository.Updateable(delay)
+                            .UpdateColumns(d => d.DelayState)
+                            .ExecuteCommandAsync(cancellationToken);
                         if (isReviewPass)
                         {
-                            delay.DelayState = isReviewPass ? EDelayState.Pass : EDelayState.NoPass;
-                            await _orderDelayRepository.UpdateAsync(delay, cancellationToken);
-
                             //处理工单延期
                             await _orderApplication.DelayOrderExpiredTimeAsync(delay.OrderId, delay.DelayNum,
                                 delay.DelayUnit, delay.IsProDelay, cancellationToken);
                         }
-                        else
-                        {
-                            delay.DelayState = EDelayState.NoPass;
-                            await _orderDelayRepository.UpdateAsync(delay, cancellationToken);
-                        }
                     }
                     break;
                 case WorkflowModuleConsts.OrderTerminate:

+ 6 - 20
src/Hotline.Application/Orders/OrderApplication.cs

@@ -3572,11 +3572,9 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         // 6、班长特提至话务部,办理对象非必选,没选择则所有坐席都可以查看和办理
         //泸州需求:
         /* 1、特提(仅针对特提到热线中心节点)
-           1.1、工单特提回话务部,办理对象需调整所有坐席都可以查看和办理
-           1.2、工单特提到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
+           1.1、工单特提到话务部、派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
            2、退回功能(仅针对退回到热线中心节点)
-           2.1、退回到话务部节点,只有之前受理人才能办理;
-           2.2、退回到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
+           2.1、退回到热线中心各节点,只有之前办理人才能办理;
          */
 
         if (workflow.FlowType is not EFlowType.Handle) return null;
@@ -3730,12 +3728,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         // 6、班长特提至话务部,办理对象非必选,没选择则所有坐席都可以查看和办理
         //泸州需求:
         /* 1、特提(仅针对特提到热线中心节点)
-           1.1、工单特提回话务部,办理对象需调整所有坐席都可以查看和办理
-           1.2、工单特提到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
-           2、退回功能(仅针对退回到热线中心节点)
-           2.1、退回到话务部节点,只有之前受理人才能办理;
-           2.2、退回到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
-         */
+             1.1、工单特提到话务部、派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
+             2、退回功能(仅针对退回到热线中心节点)
+             2.1、退回到热线中心各节点,只有之前办理人才能办理;
+        */
 
         if (workflow.FlowType is not EFlowType.Handle) return null;
 
@@ -3850,16 +3846,6 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 switch (prevStepDefine.BusinessType)
                 {
                     case EBusinessType.Seat:
-                        var define = prevStepDefine.HandlerTypeItems.First();
-                        rsp = new StepAssignInfo
-                        {
-                            FlowAssignType = EFlowAssignType.Role,
-                            RoleId = define.Key,
-                            RoleName = define.Value,
-                            Key = define.Key,
-                            Value = define.Value,
-                        };
-                        break;
                     case EBusinessType.Send:
                     case EBusinessType.CenterMonitor:
                     case EBusinessType.CenterLeader:

+ 1 - 1
src/Hotline.Application/Snapshot/IInviteCodeApplication.cs

@@ -11,7 +11,7 @@ using System.Threading.Tasks;
 namespace Hotline.Application.Snapshot;
 public interface IInviteCodeApplication
 {
-    Task AddInviteCodeAsync(AddInviteCodeInDto dto);
+    Task<string> AddInviteCodeAsync(AddInviteCodeInDto dto);
 
     /// <summary>
     /// 删除邀请码

+ 2 - 2
src/Hotline.Application/Snapshot/InviteCodeApplication.cs

@@ -26,7 +26,7 @@ public class InviteCodeApplication : IInviteCodeApplication, IScopeDependency
         _inviteCodeRecordRepository = inviteCodeRecordRepository;
     }
 
-    public async Task AddInviteCodeAsync(AddInviteCodeInDto dto)
+    public async Task<string> AddInviteCodeAsync(AddInviteCodeInDto dto)
     {
         if (_inviteCodeRepository.Queryable().Where(m => m.OrgName == dto.OrgName).Any())
         {
@@ -37,7 +37,7 @@ public class InviteCodeApplication : IInviteCodeApplication, IScopeDependency
         {
             throw UserFriendlyException.SameMessage("开始邀请码不能大于结束邀请码");
         }
-        await _inviteCodeRepository.AddAsync(entity);
+        return await _inviteCodeRepository.AddAsync(entity);
     }
 
     /// <summary>

+ 9 - 6
src/Hotline.Application/StatisticalReport/IOrderReportApplication.cs

@@ -1,5 +1,6 @@
 using Hotline.Orders;
 using Hotline.Settings;
+using Hotline.Settings.Hotspots;
 using Hotline.Share.Dtos.Bi;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Requests;
@@ -149,12 +150,14 @@ namespace Hotline.Application.StatisticalReport
         /// <returns></returns>
         Task<DataTable> ExportQueryVisitNoSatisfiedAsync(IReadOnlyList<SystemDicData> dissatisfiedReason, List<dynamic>? list, List<string> addColumnName);
 
-        /// <summary>
-        /// 部门不满意统计明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        ISugarQueryable<OrderVisitDetail> BiQueryVisitNoSatisfiedDetail(BiQueryVisitNoSatisfiedDetailDto dto);
+        Task<DataTable> ExportHotPortJoinOrgStatisticsAsync(IReadOnlyList<Hotspot> dissatisfiedReason, List<dynamic>? list, List<string> addColumnName);
+
+		/// <summary>
+		/// 部门不满意统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		ISugarQueryable<OrderVisitDetail> BiQueryVisitNoSatisfiedDetail(BiQueryVisitNoSatisfiedDetailDto dto);
 
         /// <summary>
         /// 未签收统计

+ 87 - 6
src/Hotline.Application/StatisticalReport/OrderReportApplication.cs

@@ -7,6 +7,7 @@ using Hotline.Identity.Accounts;
 using Hotline.Orders;
 using Hotline.SeedData;
 using Hotline.Settings;
+using Hotline.Settings.Hotspots;
 using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos.Bi;
 using Hotline.Share.Dtos.CallCenter;
@@ -2436,12 +2437,92 @@ namespace Hotline.Application.StatisticalReport
             return dataTable;
         }
 
-        /// <summary>
-        /// 部门不满意统计明细
-        /// </summary>
-        /// <param name="dto"></param>
-        /// <returns></returns>
-        [HttpGet("visit-nosatisfied-detail")]
+
+		public async Task<DataTable> ExportHotPortJoinOrgStatisticsAsync(IReadOnlyList<Hotspot> dissatisfiedReason, List<dynamic>? list, List<string> addColumnName)
+		{
+			var dataTable = new DataTable();
+			foreach (var item in addColumnName)
+			{
+				dataTable.Columns.Add(item);
+			}
+
+			Dictionary<string, DataRow> dicRow = new();
+
+			// 先拿部门名称
+			// bug 部门名称重复时有问题
+			// 循环填充 首列 数据
+			foreach (var item in list)
+			{
+				foreach (var property in (IDictionary<string, object>)item)
+				{
+					if (property.Key == "OrgName")
+					{
+						var name = property.Value.ToString();
+						if (string.IsNullOrEmpty(name)) continue;
+						if (dicRow.Any(m => m.Key == name)) continue;
+						var dr = dataTable.NewRow();
+						dr[0] = name;
+						dicRow.Add(name, dr);
+					}
+				}
+			}
+
+			var drCount = dataTable.NewRow();
+			drCount[0] = "合计";
+			dicRow.Add("合计", drCount);
+
+			for (int i = 0; i < dissatisfiedReason.Count; i++)
+			{ // 循环填充列数据
+
+				var total = 0;
+				for (int l = 0; l < list.Count; l++)
+				{
+					var columnIndex = i + 2;
+					var value = string.Empty;
+					var orgName = string.Empty;
+					foreach (var property in (IDictionary<string, object>)list[l])
+					{
+						if (property.Key.ToLower().Equals("orgname")) orgName = property.Value.ToString();
+						if (property.Key.ToLower().Equals(dissatisfiedReason[i].Id))
+						{
+							value = property.Value.ToString();
+							total += int.Parse(value!);
+						}
+					}
+					if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(orgName))
+					{
+						dicRow[orgName!][columnIndex] = value;
+					}
+					if (l + 1 == list.Count)
+						dicRow["合计"][columnIndex] = total;
+				}
+			}
+
+			foreach (var item in dicRow)
+			{
+                //小计
+                var index = 0;
+                var subtotal = 0;
+				foreach (var item2 in item.Value.ItemArray)
+				{
+                    if (index >1)
+                    {
+                        subtotal += int.Parse(item2.ToString());
+					}
+                    index++;
+				}
+                item.Value[1] = subtotal.ToString();
+				dataTable.Rows.Add(item.Value);
+			}
+			return dataTable;
+		}
+
+		/// <summary>
+		/// 部门不满意统计明细
+		/// </summary>
+		/// <param name="dto"></param>
+		/// <returns></returns>
+		[HttpGet("visit-nosatisfied-detail")]
         public ISugarQueryable<OrderVisitDetail> BiQueryVisitNoSatisfiedDetail(BiQueryVisitNoSatisfiedDetailDto dto)
         {
             var IsCenter = _sessionContext.OrgIsCenter;

+ 8 - 1
src/Hotline.Repository.SqlSugar/BaseRepository.cs

@@ -368,7 +368,14 @@ namespace Hotline.Repository.SqlSugar
 
         public async Task UpdateAsync(TEntity entity, bool ignoreNullColumns = true, CancellationToken cancellationToken = default)
         {
-            _serviceProvider.GetService<DatabaseEventDispatcher>()?.Dispatch(entity, DataFilterType.UpdateByObject, true);
+            try
+            {
+                _serviceProvider.GetService<DatabaseEventDispatcher>()?.Dispatch(entity, DataFilterType.UpdateByObject, true);
+            }
+            catch (Exception e)
+            {
+                var msg = e.Message;
+            }
             await Db.Updateable(entity)
                 .IgnoreColumns(ignoreAllNullColumns: ignoreNullColumns)
                 .IgnoreColumns(d => d.CreationTime)

+ 14 - 6
src/Hotline.Repository.SqlSugar/Orders/OrderRepository.cs

@@ -133,7 +133,7 @@ namespace Hotline.Repository.SqlSugar.Orders
             return propertyInfo.GetValue(obj, null);
         }
 
-        public async Task<object> HotPortJoinOrgStatistics(DateTime StartTime, DateTime EndTime, bool IsCenter, string? OrgCode)
+        public async Task<(IReadOnlyList<Hotspot> hotSpotList, List<dynamic>? list)> HotPortJoinOrgStatistics(DateTime StartTime, DateTime EndTime, bool IsCenter, string? OrgCode)
         {
             //查询一级热点
             var hotSpotList = await Db.Queryable<Hotspot>().Where(x => string.IsNullOrEmpty(x.ParentId)).ToListAsync();
@@ -159,7 +159,7 @@ namespace Hotline.Repository.SqlSugar.Orders
                     }).ToPivotListAsync(x => x.Key, x => new { x.OrgCode, x.OrgName, x.HotSorpName }, x => x.Sum(x => x.Count));
                 listReturn.AddRange(table);
             }
-            return new { HotSpot = hotSpotList, Data = listReturn };
+            return (hotSpotList, listReturn);
         }
 
 
@@ -1843,7 +1843,9 @@ namespace Hotline.Repository.SqlSugar.Orders
                 .WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval), x => x.VisitContent.Contains(dto.ContentRetrieval!))
                 .WhereIF(!string.IsNullOrEmpty(dto.LevelOneOrg), x => x.OrderVisit.Order.OrgLevelOneName.Contains(dto.LevelOneOrg))//一级部门名称
                 .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName))// 接办部门
-                .Select(x => new OrgVisitDetailListResp()
+                .WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value ,x=> SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId && q.VisitDetailId == x.Id).Any())
+				.WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value == false, x => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId && q.VisitDetailId == x.Id).NotAny())
+				.Select(x => new OrgVisitDetailListResp()
                 {
                     Id = x.Id,
                     OrderId = x.OrderVisit.Order.Id,
@@ -1869,7 +1871,9 @@ namespace Hotline.Repository.SqlSugar.Orders
                     ActualHandleOrgName = x.OrderVisit.Order.ActualHandleOrgName,
                     IsProvinceOrder = x.OrderVisit.Order.Source == ESource.ProvinceStraight ? true : false
                 }).MergeTable().OrderByIF(string.IsNullOrEmpty(dto.SortField), x => x.VisitTime, OrderByType.Desc)
-                .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc) //受理时间升序
+				.OrderByIF(dto is { SortField: "orderScreenStatusText", SortRule: 0 }, x => x.OrderScreenStatus, OrderByType.Asc)
+				.OrderByIF(dto is { SortField: "orderScreenStatusText", SortRule: 1 }, x => x.OrderScreenStatus, OrderByType.Desc) 
+				.OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc) //受理时间升序
                 .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, x => x.CreationTime, OrderByType.Desc) //受理时间降序
                 .OrderByIF(dto is { SortField: "visitTime", SortRule: 0 }, x => x.VisitTime, OrderByType.Asc) //回访时间升序
                 .OrderByIF(dto is { SortField: "visitTime", SortRule: 1 }, x => x.VisitTime, OrderByType.Desc) //回访时间降序
@@ -1911,7 +1915,9 @@ namespace Hotline.Repository.SqlSugar.Orders
                 .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.OrderVisit.Order.Source != ESource.ProvinceStraight)
                 .WhereIF(!string.IsNullOrEmpty(dto.ContentRetrieval), x => x.VisitContent.Contains(dto.ContentRetrieval!))
                 .WhereIF(!string.IsNullOrEmpty(dto.ActualHandleOrgName), x => x.OrderVisit.Order.ActualHandleOrgName.Contains(dto.ActualHandleOrgName!))
-                .Select(x => new OrgVisitDetailListResp
+				.WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value, x => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId && q.VisitDetailId == x.Id).Any())
+				.WhereIF(dto.IsScreen.HasValue && dto.IsScreen.Value == false, x => SqlFunc.Subqueryable<OrderScreen>().Where(q => q.OrderId == x.OrderVisit.OrderId && q.VisitDetailId == x.Id).NotAny())
+				.Select(x => new OrgVisitDetailListResp
                 {
                     Id = x.Id,
                     OrderId = x.OrderVisit.Order.Id,
@@ -1937,7 +1943,9 @@ namespace Hotline.Repository.SqlSugar.Orders
                     ActualHandleOrgName = x.OrderVisit.Order.ActualHandleOrgName
                 }).MergeTable()
                 .OrderByIF(string.IsNullOrEmpty(dto.SortField), x => x.VisitTime, OrderByType.Desc)
-                .OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc) //受理时间升序
+				.OrderByIF(dto is { SortField: "orderScreenStatusText", SortRule: 0 }, x => x.OrderScreenStatus, OrderByType.Asc)
+				.OrderByIF(dto is { SortField: "orderScreenStatusText", SortRule: 1 }, x => x.OrderScreenStatus, OrderByType.Desc)
+				.OrderByIF(dto is { SortField: "creationTime", SortRule: 0 }, x => x.CreationTime, OrderByType.Asc) //受理时间升序
                 .OrderByIF(dto is { SortField: "creationTime", SortRule: 1 }, x => x.CreationTime, OrderByType.Desc) //受理时间降序
                 .OrderByIF(dto is { SortField: "visitTime", SortRule: 0 }, x => x.VisitTime, OrderByType.Asc) //回访时间升序
                 .OrderByIF(dto is { SortField: "visitTime", SortRule: 1 }, x => x.VisitTime, OrderByType.Desc) //回访时间降序

+ 6 - 1
src/Hotline.Share/Dtos/Bi/BiOrderDto.cs

@@ -76,7 +76,12 @@ namespace Hotline.Share.Dtos.Bi
         /// 接办部门
         /// </summary>
         public string? ActualHandleOrgName { get; set; }
-    }
+
+		/// <summary>
+		/// 是否甄别
+		/// </summary>
+		public bool? IsScreen { get; set; }
+	}
 
     public record HighFrequencyCallStatisticsRequest : PagedRequest
     {

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

@@ -451,7 +451,7 @@ namespace Hotline.Share.Dtos.Order
         /// 甄别状态
         /// </summary>
         public EScreenStatus? OrderScreenStatus { get; set; }
-        public string? OrderScreenStatusText => OrderScreenStatus?.GetDescription();
+        public string? OrderScreenStatusText => OrderScreenStatus.HasValue && OrderScreenStatus != null ? OrderScreenStatus?.GetDescription() : "未甄别";
 
         /// <summary>
         /// 回访内容

+ 6 - 1
src/Hotline.Share/Requests/PagedKeywordRequest.cs

@@ -352,7 +352,7 @@ public record ExportHotPortJoinOrgStatisticsRequest
 	public List<string> AddColumnName { get; set; } = new();
 }
 
-public record  HotPortJoinOrgStatisticsRequestDetail: PagedKeywordRequest
+public record  HotPortJoinOrgStatisticsRequestDetail: PagedRequest
 {
 	public DateTime StartTime { get; set; }
 
@@ -678,6 +678,11 @@ public record OrgVisitDetailListReq : PagedKeywordRequest
     /// 内容检索(回访内容)
     /// </summary>
     public string? ContentRetrieval { get; set; }
+
+    /// <summary>
+    /// 是否甄别
+    /// </summary>
+    public bool? IsScreen { get; set; }
 }
 
 

+ 1 - 10
src/Hotline/Orders/IOrderDomainService.cs

@@ -115,15 +115,6 @@ namespace Hotline.Orders
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         Task VisitNoneByCancelPublishAsync(string orderId, CancellationToken cancellationToken);
-
-        /// <summary>
-        /// 查询退回操作目标节点的指派方式
-        /// </summary>
-        ReverseFlowStepAssignInfo GetOrderPreviousAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler);
-
-        /// <summary>
-        /// 查询特提操作目标节点的指派方式
-        /// </summary>
-        ReverseFlowStepAssignInfo GetOrderRecallAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler);
+        
     }
 }

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

@@ -6,6 +6,7 @@ using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Order;
 using XF.Domain.Repository;
 using Hotline.Share.Dtos.Bi;
+using Hotline.Settings.Hotspots;
 
 namespace Hotline.Orders
 {
@@ -18,7 +19,7 @@ namespace Hotline.Orders
         Task OrderScreenRevisionVisit(string VisitId, bool canHandle, CancellationToken cancellationToken);
         Task FileAsync(Order order, CancellationToken cancellationToken);
 
-        Task<object> HotPortJoinOrgStatistics(DateTime StartTime, DateTime EndTime, bool IsCenter, string? OrgCode);
+        Task<(IReadOnlyList<Hotspot> hotSpotList, List<dynamic>? list)> HotPortJoinOrgStatistics(DateTime StartTime, DateTime EndTime, bool IsCenter, string? OrgCode);
         ISugarQueryable<Order> HotPortJoinOrgStatisticsDetail(HotPortJoinOrgStatisticsRequestDetail dto);
 
 

+ 0 - 130
src/Hotline/Orders/OrderDomainService.cs

@@ -411,136 +411,6 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         }
     }
 
-    /// <summary>
-    /// 查询退回操作目标节点的指派方式
-    /// </summary>
-    public ReverseFlowStepAssignInfo GetOrderPreviousAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler)
-    {
-        //自贡需求:
-        // 1. 工单退回、特提、重办到话务部节点时,所有坐席都可以查看和办理
-        // 2. 退回到派单组时需执行平均分配逻辑
-        //宜宾需求:
-        // 1、退回至话务部:所有坐席都可以查看和办理(除某些场景下本来就需指定办理对象,如:发布时退回……)
-        // 2、退回至派单组:默认退给之前的派单员(除某些场景下本来就需指定办理对象,如:发布时退回……)
-        // 3、话务员特提至话务部:根据特提申请时候选择来,指定的办理对象才能查看和办理
-        // 4、派单员特提至派单组:根据特提申请时候选择来,指定的办理对象才能查看和办理
-        // 5、班长特提至派单组,办理对象必选(已实现)
-        // 6、班长特提至话务部,办理对象非必选,没选择则所有坐席都可以查看和办理
-        //泸州需求:
-        /* 1、特提(仅针对特提到热线中心节点)
-           1.1、工单特提回话务部,办理对象需调整所有坐席都可以查看和办理
-           1.2、工单特提到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
-           2、退回功能(仅针对退回到热线中心节点)
-           2.1、退回到话务部节点,只有之前受理人才能办理;
-           2.2、退回到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理  
-         */
-
-        var rsp = new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
-
-        switch (targetStepBusinessType)
-        {
-            case EBusinessType.Seat:
-                if (_appOptions.Value.IsZiGong || _appOptions.Value.IsYiBin)
-                {
-                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginDefinition;
-                }
-                break;
-            case EBusinessType.Send:
-                if (_appOptions.Value.IsZiGong)
-                {
-                    if (handler is null)
-                        throw new UserFriendlyException("参数异常,退回派单组需要通过平均派单指定办理人");
-
-                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.AssignHandler;
-                    rsp.StepAssignInfo = handler;
-                }
-                break;
-            case EBusinessType.Department:
-                rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStepOrg;
-                break;
-            case EBusinessType.DepartmentLeader:
-                break;
-            case EBusinessType.CenterMonitor:
-                break;
-            case EBusinessType.CenterLeader:
-                break;
-            case EBusinessType.Unknown:
-                break;
-            case EBusinessType.File:
-            default:
-                throw new ArgumentOutOfRangeException(nameof(targetStepBusinessType), targetStepBusinessType, null);
-        }
-
-        return rsp;
-    }
-
-    /// <summary>
-    /// 查询特提操作目标节点的指派方式
-    /// </summary>
-    public ReverseFlowStepAssignInfo GetOrderRecallAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler)
-    {
-        //自贡需求:
-        // 1. 工单退回、特提、重办到话务部节点时,所有坐席都可以查看和办理
-        // 2. 退回到派单组时需执行平均分配逻辑
-        //宜宾需求:
-        // 1、退回至话务部:所有坐席都可以查看和办理(除某些场景下本来就需指定办理对象,如:发布时退回……)
-        // 2、退回至派单组:默认退给之前的派单员(除某些场景下本来就需指定办理对象,如:发布时退回……)
-        // 3、话务员特提至话务部:根据特提申请时候选择来,指定的办理对象才能查看和办理
-        // 4、派单员特提至派单组:根据特提申请时候选择来,指定的办理对象才能查看和办理
-        // 5、班长特提至派单组,办理对象必选(已实现)
-        // 6、班长特提至话务部,办理对象非必选,没选择则所有坐席都可以查看和办理
-        //泸州需求:
-        /* 1、特提(仅针对特提到热线中心节点)
-           1.1、工单特提回话务部,办理对象需调整所有坐席都可以查看和办理
-           1.2、工单特提到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
-           2、退回功能(仅针对退回到热线中心节点)
-           2.1、退回到话务部节点,只有之前受理人才能办理;
-           2.2、退回到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
-         */
-
-        var rsp = new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
-
-        switch (targetStepBusinessType)
-        {
-            case EBusinessType.Seat:
-                if (_appOptions.Value.IsYiBin && handler is not null)
-                {
-                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.AssignHandler;
-                    rsp.StepAssignInfo = handler;
-                }
-                else
-                {
-                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginDefinition;
-                }
-                break;
-            case EBusinessType.Send:
-                if (_appOptions.Value.IsZiGong || _appOptions.Value.IsYiBin)
-                {
-                    if(handler is null)
-                        throw new UserFriendlyException("参数异常,特提派单组需要指定办理人");
-                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.AssignHandler;
-                    rsp.StepAssignInfo = handler;
-                }
-                break;
-            case EBusinessType.Department:
-                rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStepOrg;
-                break;
-            case EBusinessType.DepartmentLeader:
-                break;
-            case EBusinessType.CenterMonitor:
-                break;
-            case EBusinessType.CenterLeader:
-                break;
-            case EBusinessType.Unknown:
-                break;
-            case EBusinessType.File:
-            default:
-                throw new ArgumentOutOfRangeException(nameof(targetStepBusinessType), targetStepBusinessType, null);
-        }
-
-        return rsp;
-    }
-
     public async Task<Order> GetOrderAsync(string? orderId, bool withHotspot = false, bool withAcceptor = false,
         bool withExtension = false, CancellationToken cancellationToken = default)
     {

+ 3 - 1
test/Hotline.Tests/Application/DefaultCallApplicationTest.cs

@@ -5,6 +5,7 @@ using Hotline.CallCenter.Calls;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
 using Hotline.Orders;
+using Hotline.Settings;
 using Hotline.Share.Dtos.CallCenter;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.CallCenter;
@@ -14,6 +15,7 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
 using SqlSugar.Extensions;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
@@ -25,7 +27,7 @@ public class DefaultCallApplicationTest : TestBase
     public readonly IFixture _fixture;
     private readonly IOrderRepository _orderRepository;
 
-    public DefaultCallApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, XingTangCallApplication defaultCallApplication, IOrderVisitRepository orderVisitRepository, IRepository<CallNative> callNativeRepository, IOrderRepository orderRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public DefaultCallApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, XingTangCallApplication defaultCallApplication, IOrderVisitRepository orderVisitRepository, IRepository<CallNative> callNativeRepository, IOrderRepository orderRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _fixture = new Fixture();
         _defaultCallApplication = defaultCallApplication;

+ 3 - 1
test/Hotline.Tests/Application/IndustryApplicationTest.cs

@@ -13,6 +13,8 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
 using XF.Domain.Repository;
+using Hotline.Settings;
+using XF.Domain.Cache;
 
 namespace Hotline.Tests.Application;
 public class IndustryApplicationTest : TestBase
@@ -21,7 +23,7 @@ public class IndustryApplicationTest : TestBase
     private readonly IIndustryRepository _industryRepository;
     private readonly ISystemOrganizeRepository _systemOrganizeRepository;
 
-    public IndustryApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, ISystemOrganizeRepository systemOrganizeRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    public IndustryApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, ISystemOrganizeRepository systemOrganizeRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _industryApplication = industryApplication;
         _industryRepository = industryRepository;

+ 28 - 2
test/Hotline.Tests/Application/InviteCodeApplicationTest.cs

@@ -2,22 +2,39 @@
 using Hotline.Application.Snapshot;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.Repository.SqlSugar.Snapshot;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
 public class InviteCodeApplicationTest : TestBase
 {
     private readonly IInviteCodeApplication _inviteCodeApplication;
+    private readonly ISnapshotApplication _snapshotApplication;
+    private readonly IInviteCodeRepository _inviteCodeRepository;
+    private readonly ISessionContext _sessionContext;
+    private readonly IInviteCodeRecordRepository _inviteCodeRecordRepository;
 
-    public InviteCodeApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IInviteCodeApplication inviteCodeApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    public InviteCodeApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IInviteCodeApplication inviteCodeApplication, ISnapshotApplication snapshotApplication, IInviteCodeRepository inviteCodeRepository, ISessionContext sessionContext, IInviteCodeRecordRepository inviteCodeRecordRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _inviteCodeApplication = inviteCodeApplication;
+        _snapshotApplication = snapshotApplication;
+        this._inviteCodeRepository = inviteCodeRepository;
+        _sessionContext = sessionContext;
+        _inviteCodeRecordRepository = inviteCodeRecordRepository;
     }
 
     [Fact]
@@ -30,10 +47,19 @@ public class InviteCodeApplicationTest : TestBase
             EndCode = 200,
         };
 
-        await _inviteCodeApplication.AddInviteCodeAsync(inDto);
+        var id = await _inviteCodeApplication.AddInviteCodeAsync(inDto);
 
         var items = _inviteCodeApplication.GetInviteCodeItems().ToList();
         items.Count.ShouldNotBe(0);
+        await _inviteCodeRepository.RemoveAsync(id);
+
+        SetWeiXin();
+        await _thirdAccountRepository.Updateable()
+            .SetColumns(m => m.InvitationCode, null)
+            .Where(m => m.OpenId == _sessionContext.OpenId)
+            .ExecuteCommandAsync();
+        await _inviteCodeRecordRepository.Removeable().Where(m => m.InviteCode == "110").ExecuteCommandAsync();
+        await _snapshotApplication.SaveInvitationCodeAsync(new SaveInvitationCodeInDto { InvitationCode = "110"});
 
         var statics = await _inviteCodeApplication.GetInviteCodeStatisticAsync(new GetInviteCodeStatisticInDto 
         {

+ 11 - 2
test/Hotline.Tests/Application/KnowApplicationTest.cs

@@ -3,6 +3,8 @@ using Hotline.Application.Knowledge;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
 using Hotline.KnowledgeBase;
+using Hotline.KnowledgeBase.Notifies;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Knowledge;
 using Hotline.Share.Tools;
 using Hotline.Snapshot.Interfaces;
@@ -12,6 +14,13 @@ using MediatR;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
@@ -29,8 +38,8 @@ public class KnowApplicationTest : TestBase
         IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor,
         IKnowApplication knowApplication, IMediator mediator, IRepository<KnowledgeBase.Knowledge> knowledgeRepository,
         IKnowledgeDomainService knowledgeDomainService, IRepository<KnowledgeWord> knowledgeWordRepository,
-        IRepository<KnowledgeHotWord> knowledgeHotWordRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount)
-        : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+        IRepository<KnowledgeHotWord> knowledgeHotWordRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ITypedCache<SystemSetting> cacheSettingData)
+        : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _knowApplication = knowApplication;
         _mediator = mediator;

+ 46 - 10
test/Hotline.Tests/Application/OrderSnapshotApplicationTest.cs

@@ -5,6 +5,7 @@ using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Repository.SqlSugar.Snapshot;
+using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
@@ -15,7 +16,14 @@ using Hotline.Tests.Mock;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
+using NPOI.SS.Formula.Functions;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
@@ -32,7 +40,7 @@ public class OrderSnapshotApplicationTest : TestBase
     private readonly IRedPackRecordRepository _redPackRecordRepository;
     private readonly ISnapshotLabelLogRepository _snapshotLabelLogRepository;
 
-    public OrderSnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, OrderServiceMock orderServiceMock, ISystemDicDataCacheManager systemDicDataCacheManager, IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISnapshotApplication snapshotApplication, IIndustryLogRepository industryLogRepository, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, ISnapshotLabelLogRepository snapshotLabelLogRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    public OrderSnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, OrderServiceMock orderServiceMock, ISystemDicDataCacheManager systemDicDataCacheManager, IOrderSnapshotRepository orderSnapshotRepository, IOrderSnapshotApplication orderSnapshotApplication, ISnapshotApplication snapshotApplication, IIndustryLogRepository industryLogRepository, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, ISnapshotLabelLogRepository snapshotLabelLogRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _orderServiceMock = orderServiceMock;
         _systemDicDataCacheManager = systemDicDataCacheManager;
@@ -46,9 +54,35 @@ public class OrderSnapshotApplicationTest : TestBase
         _snapshotLabelLogRepository = snapshotLabelLogRepository;
     }
 
+    /// <summary>
+    /// 随手拍网格员超时:
+    /// </summary>
+    /// <returns></returns>
+    [Fact]
+    public async Task SnapshotWorkflow_Guider_Timeout_Test()
+    {
+        SetSettingCache(SettingConstants.OvertimeBack, "0.00027778");
+        var order = _orderServiceMock.CreateSnapshotOrder(SetWeiXin)
+            .办理到网格员(SetZuoXi)
+            .StepHandle(async order =>
+            {
+                Thread.Sleep(30 * 1000);
+            }
+            ).GetCreateResult();
+        order.Id.ShouldNotBeNull();
+    }
+
     /// <summary>
     /// 随手拍办理流程:
-    ///     到网格员
+    ///     坐席
+    ///     网格员
+    ///     派单员
+    ///     一级部门
+    ///     归档
+    ///     发布工单
+    ///     政法委部门审核网格红包
+    ///     应急局部门审核网格员红包
+    ///     部门审核市民红包
     /// </summary>
     /// <returns></returns>
     [Fact]
@@ -114,15 +148,16 @@ public class OrderSnapshotApplicationTest : TestBase
             .办理到一级部门(SetPaiDanYuan)
             .办理到归档(Set一级部门)
             .发布工单(SetZuoXi, inputLable.Select(m => new Kv(m.DicDataName, m.DicDataName)).ToList())
-            .StepHandle(async order => {
-                    var log = _snapshotLabelLogRepository.Queryable().Where(m => m.OrderId == order.Id).First();
-                    log.ShouldNotBeNull();
-                    var snapshot = _orderSnapshotRepository.Get(order.Id);
-                    snapshot.LabelName.ShouldBe(string.Join(',', inputLable.Select(m => m.DicDataName)),"label异常");
-                    })
+            .StepHandle(async order =>
+            {
+                var log = _snapshotLabelLogRepository.Queryable().Where(m => m.OrderId == order.Id).First();
+                log.ShouldNotBeNull();
+                var snapshot = _orderSnapshotRepository.Get(order.Id);
+                snapshot.LabelName.ShouldBe(string.Join(',', inputLable.Select(m => m.DicDataName)), "label异常");
+            })
             .部门审核网格员红包(Set政法委)
             .部门审核网格员红包(Set应急管理局)
-            .StepHandle(async order => 
+            .StepHandle(async order =>
             {
                 var redPackRecord = _redPackRecordRepository.Queryable()
                 .Where(m => m.OrderId == order.Id && m.PeopleType == EReadPackUserType.Guider)
@@ -130,7 +165,8 @@ public class OrderSnapshotApplicationTest : TestBase
                 redPackRecord.Amount.ShouldNotBe(0);
             })
             .部门审核市民红包(Set应急管理局)
-            .StepHandle(async order => {
+            .StepHandle(async order =>
+            {
                 var redPackAudit = _redPackAuditRepository.Queryable().Where(m => m.OrderId == order.Id).First();
                 redPackAudit.Status.ShouldBe(ERedPackAuditStatus.Agree);
                 var redPackRecord = _redPackRecordRepository.Queryable().Where(m => m.OrderId == order.Id).First();

+ 9 - 1
test/Hotline.Tests/Application/RedPackApplicationTest.cs

@@ -2,6 +2,7 @@
 using Hotline.Application.Snapshot;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Snapshot.Interfaces;
@@ -9,6 +10,13 @@ using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
@@ -17,7 +25,7 @@ public class RedPackApplicationTest : TestBase
     private readonly IRedPackApplication _redPackApplication;
     private readonly IRedPackRecordRepository _redPackRecordRepository;
 
-    public RedPackApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IRedPackApplication redPackApplication, IRedPackRecordRepository redPackRecordRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    public RedPackApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IRedPackApplication redPackApplication, IRedPackRecordRepository redPackRecordRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _redPackApplication = redPackApplication;
         _redPackRecordRepository = redPackRecordRepository;

+ 4 - 1
test/Hotline.Tests/Application/SnapshotApplicationTest.cs

@@ -7,6 +7,8 @@ using Hotline.File;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
 using Hotline.Orders;
+using Hotline.Repository.SqlSugar.Extensions;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Article;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums;
@@ -21,6 +23,7 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
 using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
 
@@ -44,7 +47,7 @@ public class SnapshotApplicationTest : TestBase
     private readonly IRedPackApplication _redPackApplication;
     private readonly IOrderSnapshotApplication _orderSnapshotApplication;
 
-    public SnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISnapshotApplication snapshotApplication, IIdentityAppService identityAppService, IRepository<RedPackRecord> redPackRecordRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, IFileRepository fileRepository, OrderServiceMock orderServiceMock, IOrderRepository orderRepository, IOrderSnapshotRepository orderSnapshotRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISessionContext sessionContext, IGuiderSystemService guiderSystemService, ISystemSettingCacheManager systemSettingCacheManager, ICommunityInfoRepository communityInfoRepository, IIndustryLogRepository industryLogRepository, IRedPackApplication redPackApplication, IOrderSnapshotApplication orderSnapshotApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public SnapshotApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISnapshotApplication snapshotApplication, IIdentityAppService identityAppService, IRepository<RedPackRecord> redPackRecordRepository, IIndustryApplication industryApplication, IIndustryRepository industryRepository, IFileRepository fileRepository, OrderServiceMock orderServiceMock, IOrderRepository orderRepository, IOrderSnapshotRepository orderSnapshotRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISessionContext sessionContext, IGuiderSystemService guiderSystemService, ISystemSettingCacheManager systemSettingCacheManager, ICommunityInfoRepository communityInfoRepository, IIndustryLogRepository industryLogRepository, IRedPackApplication redPackApplication, IOrderSnapshotApplication orderSnapshotApplication, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _snapshotApplication = snapshotApplication;
         _identityAppService = identityAppService;

+ 7 - 1
test/Hotline.Tests/Application/SystemSettingCacheManagerTest.cs

@@ -8,6 +8,12 @@ using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Application;
@@ -17,7 +23,7 @@ public class SystemSettingCacheManagerTest : TestBase
     private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
     private readonly IRepository<SystemSetting> _systemSettingRepository;
 
-    public SystemSettingCacheManagerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISystemSettingCacheManager systemSettingCacheManager, ISystemDicDataCacheManager systemDicDataCacheManager, IRepository<SystemSetting> systemSettingRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public SystemSettingCacheManagerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, ISystemSettingCacheManager systemSettingCacheManager, ISystemDicDataCacheManager systemDicDataCacheManager, IRepository<SystemSetting> systemSettingRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _systemSettingCacheManager = systemSettingCacheManager;
         _systemDicDataCacheManager = systemDicDataCacheManager;

+ 8 - 1
test/Hotline.Tests/Controller/IndustryControllerTest.cs

@@ -2,19 +2,26 @@
 using Hotline.Api.Controllers.Snapshot;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.Settings;
 using Hotline.Snapshot.Interfaces;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Controller;
 public class IndustryControllerTest : TestBase
 {
     private readonly IndustryController _industryController;
-    public IndustryControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IndustryController industryController) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository)
+    public IndustryControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IndustryController industryController, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _industryController = industryController;
         _industryController.ControllerContext = new ControllerContext

+ 10 - 1
test/Hotline.Tests/Controller/KnowledgeControllerTest.cs

@@ -1,6 +1,9 @@
 using Hotline.Api.Controllers;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.KnowledgeBase;
+using Hotline.Settings;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Knowledge;
 using Hotline.Share.Enums.KnowledgeBase;
 using Hotline.Snapshot.Interfaces;
@@ -10,6 +13,12 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Controller;
@@ -19,7 +28,7 @@ public class KnowledgeControllerTest : TestBase
     private readonly KnowledgeController _knowledgeController;
     private readonly IRepository<KnowledgeBase.Knowledge> _knowledgeRepository;
 
-    public KnowledgeControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, KnowledgeServiceMock knowledgeServiceMock, KnowledgeController knowledgeController, IRepository<KnowledgeBase.Knowledge> knowledgeRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public KnowledgeControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, KnowledgeServiceMock knowledgeServiceMock, KnowledgeController knowledgeController, IRepository<KnowledgeBase.Knowledge> knowledgeRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _knowledgeServiceMock = knowledgeServiceMock;
         _knowledgeController = knowledgeController;

+ 10 - 2
test/Hotline.Tests/Controller/OrderControllerTest.cs

@@ -31,6 +31,14 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
 using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
@@ -67,8 +75,8 @@ public class OrderControllerTest : TestBase
         IRepository<CallidRelation> callIdRelationRepository, XingTangCallApplication defaultCallApplication,
         ISugarUnitOfWork<CapDbContext> capDbContext, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService,
         IThirdAccountRepository thirdAccount, IIndustryRepository industryRepository, IOrderSnapshotRepository orderSnapshotRepository,
-        ISystemLogRepository systemLogRepository, IOrderVisitDomainService orderVisitDomainService, IRepository<OrderVisitDetail> orderVisitDetailRepository, ISystemDicDataCacheManager systemDicDataCacheManager)
-        : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+        ISystemLogRepository systemLogRepository, IOrderVisitDomainService orderVisitDomainService, IRepository<OrderVisitDetail> orderVisitDetailRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ITypedCache<SystemSetting> cacheSettingData)
+        : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _hotspotRepository = hotspotRepository;
         _orderController = orderController;

+ 8 - 1
test/Hotline.Tests/Controller/SnapshotControllerTest.cs

@@ -5,6 +5,7 @@ using Hotline.Api.Controllers.Snapshot;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
 using Hotline.Orders;
+using Hotline.Settings;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Share.Tools;
@@ -14,6 +15,12 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Controller;
@@ -26,7 +33,7 @@ public class SnapshotControllerTest : TestBase
     private readonly IEasyCachingProvider _easyCaching;
     private readonly IRedisCachingProvider _redisCaching;
 
-    public SnapshotControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, SnapshotController snapshotController, IOrderRepository orderRepository, IOrderSnapshotRepository orderSnapshotRepository, IIndustryRepository industryRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, IEasyCachingProvider easyCaching, IRedisCachingProvider redisCaching) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public SnapshotControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, SnapshotController snapshotController, IOrderRepository orderRepository, IOrderSnapshotRepository orderSnapshotRepository, IIndustryRepository industryRepository, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, IEasyCachingProvider easyCaching, IRedisCachingProvider redisCaching, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _snapshotController = snapshotController;
         _snapshotController.ControllerContext = new ControllerContext

+ 2 - 1
test/Hotline.Tests/Domain/OrderVisitDomainServiceTest.cs

@@ -21,6 +21,7 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Options;
 using Shouldly;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests.Domain;
@@ -37,7 +38,7 @@ public class OrderVisitDomainServiceTest : TestBase
     private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
     private readonly ISystemLogRepository _logRepository;
 
-    public OrderVisitDomainServiceTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IOrderVisitDomainService orderVisitDomainService, IOrderVisitRepository orderVisitRepository, IRepository<OrderVisitDetail> orderVisitDetailRepository, Publisher publisher, IOrderRepository orderRepository, OrderServiceMock orderServiceMock, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISettingOrderVisitSmsReplyRuleRepository settingOrderVisitSmsReplyRuleRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IOptionsSnapshot<AppConfiguration> appOptions, ISystemLogRepository logRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
+    public OrderVisitDomainServiceTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IOrderVisitDomainService orderVisitDomainService, IOrderVisitRepository orderVisitRepository, IRepository<OrderVisitDetail> orderVisitDetailRepository, Publisher publisher, IOrderRepository orderRepository, OrderServiceMock orderServiceMock, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISettingOrderVisitSmsReplyRuleRepository settingOrderVisitSmsReplyRuleRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IOptionsSnapshot<AppConfiguration> appOptions, ISystemLogRepository logRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount, cacheSettingData)
     {
         _orderVisitDomainService = orderVisitDomainService;
         _orderVisitRepository = orderVisitRepository;

+ 1 - 0
test/Hotline.Tests/SqlSuger/CapDbExtensions.cs

@@ -7,6 +7,7 @@ public static class CAPDbExtensions
 {
     public static IServiceCollection AddCAPDb(this IServiceCollection services, IConfiguration configuration)
     {
+        var config = configuration.GetConnectionString("CAP");
         SqlSugarScope sqlSugar = new(new ConnectionConfig() 
         { 
             DbType = DbType.PostgreSQL,

+ 11 - 4
test/Hotline.Tests/TestBase.cs

@@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Repository;
 
 namespace Hotline.Tests;
@@ -29,11 +30,9 @@ public class TestBase
     public readonly IHttpContextAccessor _httpContextAccessor;
     public readonly IThirdIdentiyService _thirdIdentiyService;
     public readonly IThirdAccountRepository _thirdAccountRepository;
+    private readonly ITypedCache<SystemSetting> _cacheSettingData;
 
-
-    public TestBase(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController,
-        IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor,
-        IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository)
+    public TestBase(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData)
     {
         _thirdAccountRepository = thirdAccountRepository;
         _thirdIdentiyService = thirdIdentiyService;
@@ -55,6 +54,14 @@ public class TestBase
             SetZuoXi();
         }
 
+        _cacheSettingData = cacheSettingData;
+    }
+
+    public void SetSettingCache(string code, string value)
+    {
+        _cacheSettingData.Remove(code);
+        var a = new SystemSetting { SettingValue = new List<string> { value } };
+        _cacheSettingData.Set(code, a);
     }
 
     public void ChangeAppScopeYiBin()

+ 1 - 1
test/Hotline.Tests/appsettings.Development.json

@@ -120,7 +120,7 @@
             "UserName": "dev",
             "Password": "123456",
             "HostName": "110.188.24.182",
-            "VirtualHost": "fwt-dev"
+            "VirtualHost": "fwt-unittest"
         }
     },
     //"SmsAccountInfo": {