Переглянути джерело

Merge branch 'test' into lib/test

libin 1 місяць тому
батько
коміт
36a8a7d639
34 змінених файлів з 326 додано та 115 видалено
  1. 42 28
      src/Hotline.Api/Controllers/OrderController.cs
  2. 3 12
      src/Hotline.Api/Controllers/OrderControllers/OrderCarbonCopyController.cs
  3. 1 1
      src/Hotline.Api/Controllers/OrderControllers/OrderComplementController.cs
  4. 12 0
      src/Hotline.Api/Controllers/TestController.cs
  5. 1 1
      src/Hotline.Application/Orders/Handlers/OrderHandler/AddOrderPushMessageNotifyHandler.cs
  6. 2 7
      src/Hotline.Application/Orders/Handlers/OrderHandler/GetOrderDetailNotifyHandler.cs
  7. 1 9
      src/Hotline.Application/Orders/Handlers/OrderHandler/OrderRelateCallHandler.cs
  8. 2 10
      src/Hotline.Application/Orders/Handlers/OrderHandler/OrderVisitSmsHandler.cs
  9. 1 5
      src/Hotline.Application/Orders/Handlers/OrderHandler/TranspondCityNotifyHandler.cs
  10. 1 1
      src/Hotline.Application/Orders/Handlers/OrderHandler/UpdateOrderPushMessageNotifyHandler.cs
  11. 1 1
      src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs
  12. 1 1
      src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs
  13. 1 1
      src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenStartWorkflowHandler.cs
  14. 2 16
      src/Hotline.Application/Orders/Handlers/SnapshotHandler/GuiderSystemTimeoutHandler.cs
  15. 5 1
      src/Hotline.Application/Orders/IOrderApplication.cs
  16. 123 8
      src/Hotline.Application/Orders/OrderApplication.cs
  17. 2 2
      src/Hotline.Application/StatisticalReport/CallReport/YiBinCallReportApplication.cs
  18. 8 3
      src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs
  19. 8 1
      src/Hotline.Share/Dtos/Order/QueryOrderDto.cs
  20. 27 0
      src/Hotline/Article/CircularRecordDomainService.cs
  21. 2 0
      src/Hotline/Article/ICircularRecordDomainService.cs
  22. 33 0
      src/Hotline/Authentications/ChangeSessionProvider.cs
  23. 5 0
      src/Hotline/Authentications/FakeSessionContext.cs
  24. 5 0
      src/Hotline/Authentications/Police110SessionContext.cs
  25. 5 0
      src/Hotline/Authentications/ProvinceSessionContext.cs
  26. 5 0
      src/Hotline/Authentications/YbEnterpriseSessionContext.cs
  27. 5 0
      src/Hotline/Authentications/ZzptSessionContext.cs
  28. 4 2
      src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs
  29. 5 0
      src/Hotline/Settings/SettingConstants.cs
  30. 5 0
      src/XF.Domain/Authentications/DefaultSessionContext.cs
  31. 1 0
      src/XF.Domain/Authentications/IChangeSessionProvider.cs
  32. 2 0
      src/XF.Domain/Authentications/ISessionContext.cs
  33. 5 0
      test/Hotline.Tests/Controller/TestSessionContext.cs
  34. 0 5
      test/Hotline.Tests/Startup.cs

+ 42 - 28
src/Hotline.Api/Controllers/OrderController.cs

@@ -62,6 +62,7 @@ using Hotline.Validators.FlowEngine;
 using Hotline.YbEnterprise.Sdk;
 using Mapster;
 using MapsterMapper;
+using MathNet.Numerics.LinearAlgebra.Factorization;
 using MediatR;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
@@ -1968,6 +1969,20 @@ public class OrderController : BaseController
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
 
+	/// <summary>
+	/// 工单延期修改延期时限
+	/// </summary>
+	/// <param name="dto"></param>
+	/// <returns></returns>
+	[HttpPost("alter_delay_day")]
+	[LogFilter("工单延期修改延期时限")]
+	public async Task AlterDelayDay([FromBody] AlterDelayDayDto dto) {
+        if (dto.DelayNum < 1) throw UserFriendlyException.SameMessage("延期申请天数需大于等于1天!");
+        var deday = await _orderDelayRepository.Queryable().Includes(x => x.Order).FirstAsync(x => x.Id == dto.Id, HttpContext.RequestAborted);
+        if (_appOptions.Value.IsLuZhou &&  dto.DelayNum >  deday.Order.TimeLimitCount) throw UserFriendlyException.SameMessage("申请天数需小于等于工单办理时限!");
+        await _orderDelayRepository.Updateable().SetColumns(x => new OrderDelay { DelayNum = dto.DelayNum }).Where(x => x.Id == dto.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
+	}
+
     /// <summary>
     /// 申请延期
     /// </summary>
@@ -2210,7 +2225,7 @@ public class OrderController : BaseController
     /// <param name="workflowId"></param>
     /// <returns></returns>
     [HttpGet("delay/{workflowId}/nextsteps")]
-    public async Task<NextStepsDto> OrderDelayNextsteps(string workflowId)
+    public async Task<object> OrderDelayNextsteps(string workflowId)
     {
         //var workflow = await _workflowRepository.GetAsync(workflowId, HttpContext.RequestAborted);
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
@@ -2239,9 +2254,9 @@ public class OrderController : BaseController
                         result.Steps.Remove(result.Steps.First(x => x.Value == "中心终审"));
                     }
                 }
-
-                return result;
-            }
+				result.IsAlterDay = _appOptions.Value.IsLuZhou && currentStep.Name == "班长审批";
+				return result;
+			}
         }
 
         return null;
@@ -2491,16 +2506,10 @@ public class OrderController : BaseController
 
         var (total, items) = await _orderApplication.MayScreenList(dto)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-        var data = _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items);
+        var data = _mapper.Map<List<OrderVisitDetailDto>>(items);
         var isAdmin = _orderDomainService.IsCheckAdmin();
-        foreach (var item in data)
-        {
-            if (isAdmin == true)
-                item.IsShowOperate = true;
-            else
-                item.IsShowOperate = item.VisitOrgCode == _sessionContext.OrgId ? true : false;
-        }
-        return new PagedDto<OrderVisitDetailDto>(total, _mapper.Map<IReadOnlyList<OrderVisitDetailDto>>(items));
+        data.ForEach(d => d.IsShowOperate = isAdmin == true || (d.VisitOrgCode == _sessionContext.OrgId));
+        return new PagedDto<OrderVisitDetailDto>(total, data);
     }
 
     /// <summary>
@@ -3718,6 +3727,7 @@ public class OrderController : BaseController
                 if (acceptTime != null)
                 {
                     order.ActualHandleStepAcceptTime = acceptTime;
+                    order.CurrentStepAcceptTime = acceptTime;
                     await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
                 }
             }
@@ -4667,13 +4677,13 @@ public class OrderController : BaseController
 
                 if (workflowDto.BusinessType == EBusinessType.Send)
                 {
-                    // 宜宾需求: 1.是否是派单节点  2.是否存在历史派单节点  3.存在获取上个派单节点  4.不存在走平均派单 
-                    if (_appOptions.Value.IsYiBin || _appOptions.Value.IsZiGong)
+					// 宜宾需求: 1.是否是派单节点  2.是否存在历史派单节点  3.存在获取上个派单节点  4.不存在走平均派单   过滤历史派单节点不为派单池
+					if (_appOptions.Value.IsYiBin || _appOptions.Value.IsZiGong)
                     {
-                        var sendOrderTraces = workflow.Traces.Where(x => x.BusinessType == EBusinessType.Send);
+                        var sendOrderTraces = workflow.Traces.Where(x => x.BusinessType == EBusinessType.Send && x.HandlerId != AppDefaults.SendPoolId);
                         if (sendOrderTraces.Any())
                         {
-                            var sendOrderTrace = workflow.Traces.Where(x => x.BusinessType == EBusinessType.Send)
+                            var sendOrderTrace = workflow.Traces.Where(x => x.BusinessType == EBusinessType.Send && x.HandlerId != AppDefaults.SendPoolId)
                                 .OrderByDescending(x => x.CreationTime)
                                 .FirstOrDefault();
                             nextDto.NextHandlers = new List<StepAssignInfo>
@@ -4742,12 +4752,15 @@ public class OrderController : BaseController
                         if (unhandleStep.Id != startStep.Id)
                             nextflowDto.Opinion = "跨级派单,自动办理";
 
-                        var operater = new FakeSessionContext
-                        {
-                            OrgId = unhandleStep.HandlerOrgId,
-                            OrgName = unhandleStep.HandlerOrgName,
-                        };
-                        var (_, _, _, nextSteps) = await _workflowDomainService.NextAsync(operater, nextflowDto,
+                        //var operater = new FakeSessionContext
+                        //{
+                        //    OrgId = unhandleStep.HandlerOrgId,
+                        //    OrgName = unhandleStep.HandlerOrgName,
+                        //};
+
+                        var operater = await _orderApplication.GetHandlerRandomAsync(unhandleStep, cancellationToken);
+
+                        var (_, _, _, nextSteps) = await _workflowDomainService.NextAsync(operater, nextflowDto, 
                             EHandleMode.CrossLevel, order.ExpiredTime,
                             isAutoFillSummaryOpinion, cancellationToken: cancellationToken);
                         tempSteps.AddRange(nextSteps);
@@ -4849,7 +4862,8 @@ public class OrderController : BaseController
                     BusinessType = nextStepDefine.BusinessType,
                 };
 
-                await HandleNextInMainAndSecondaryAsync(current, definition, orgs, nextDto, expiredTime, isAutoFillSummaryOpinion, cancellation);
+                var operater = await _orderApplication.GetHandlerRandomAsync(currentStep, cancellation);
+                await HandleNextInMainAndSecondaryAsync(operater, definition, orgs, nextDto, expiredTime, isAutoFillSummaryOpinion, cancellation);
             }
         }
     }
@@ -6104,10 +6118,10 @@ public class OrderController : BaseController
                 },
                 HttpContext.RequestAborted);
 
-            //         if (order.ActualHandleOrgCode != OrgSeedData.CenterId && order.Status < EOrderStatus.Filed)
-            //         {
-            //             await _circularRecordDomainService.OrderSpecialCircularMessage(special, order, HttpContext.RequestAborted);
-            //}
+            if (_appOptions.Value.IsYiBin && order.ActualHandleOrgCode != OrgSeedData.CenterId && order.Status < EOrderStatus.Filed)
+            {
+                await _circularRecordDomainService.OrderSpecialCircularMessage(special, order, HttpContext.RequestAborted);
+            }
 
             if (string.IsNullOrEmpty(currentStep?.HandlerOrgId))
             {

+ 3 - 12
src/Hotline.Api/Controllers/OrderModuleControllers/OrderCarbonCopyController.cs → src/Hotline.Api/Controllers/OrderControllers/OrderCarbonCopyController.cs

@@ -1,23 +1,14 @@
 using Hotline.Application.Orders;
-using Hotline.Caching.Services;
-using Hotline.FlowEngine.WorkflowModules;
-using Hotline.Orders;
+using Hotline.Caching.Interfaces;
 using Hotline.Repository.SqlSugar.Extensions;
-using Hotline.Settings.TimeLimits;
 using Hotline.Settings;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Order.CarbonCopy;
-using Hotline.Share.Enums.Order;
-using Hotline.Share.Requests;
+using Mapster;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
-using XF.Domain.Authentications;
-using XF.Domain.Repository;
-using XF.Utility.EnumExtensions;
-using Hotline.Caching.Interfaces;
-using Mapster;
 
-namespace Hotline.Api.Controllers.OrderModuleControllers
+namespace Hotline.Api.Controllers.OrderControllers
 {
     /// <summary>
     /// 工单抄送

+ 1 - 1
src/Hotline.Api/Controllers/OrderModuleControllers/OrderComplementController.cs → src/Hotline.Api/Controllers/OrderControllers/OrderComplementController.cs

@@ -2,7 +2,7 @@
 using Hotline.Share.Dtos.Order;
 using Microsoft.AspNetCore.Mvc;
 
-namespace Hotline.Api.Controllers.OrderModuleControllers;
+namespace Hotline.Api.Controllers.OrderControllers;
 
 public class OrderComplementController : BaseController
 {

+ 12 - 0
src/Hotline.Api/Controllers/TestController.cs

@@ -1422,4 +1422,16 @@ ICallApplication callApplication,
 
     //    await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFiled, orderFlowDto, cancellationToken: cancellationToken);
     //}
+
+    [HttpGet("TestSessionChange")]
+    public async Task TestSessionChange()
+    {
+        var a = _sessionContext.UserId;
+        _sessionContext.ChangeSession("08dd0e90-10d6-40ab-8f79-396533bfa755");
+        var b = _sessionContext.UserId;
+        await _sessionContext.ChangeSessionAsync(a, HttpContext.RequestAborted);
+        var c = _sessionContext.UserId;
+
+        await _workflowDomainService.StartAsync(new StartWorkflowDto(), "");
+    }
 }

+ 1 - 1
src/Hotline.Application/Orders/Handles/OrderHandler/AddOrderPushMessageNotifyHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/AddOrderPushMessageNotifyHandler.cs

@@ -6,7 +6,7 @@ using Hotline.Share.Enums.Push;
 using MediatR;
 using Microsoft.Extensions.Logging;
 
-namespace Hotline.Application.Orders.Handles.Order
+namespace Hotline.Application.Orders.Handlers.OrderHandler
 {
     /// <summary>
     /// 新增工单发送短信

+ 2 - 7
src/Hotline.Application/Orders/Handles/OrderHandler/GetOrderDetailNotifyHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/GetOrderDetailNotifyHandler.cs

@@ -1,13 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Hotline.FlowEngine.Workflows;
+using Hotline.FlowEngine.Workflows;
 using Hotline.Orders.Notifications;
 using MediatR;
 
-namespace Hotline.Application.Orders.Handles.Order
+namespace Hotline.Application.Orders.Handlers.OrderHandler
 {
     public class GetOrderDetailNotifyHandler : INotificationHandler<GetOrderDetailNotify>
     {

+ 1 - 9
src/Hotline.Application/Orders/Handles/OrderHandler/OrderRelateCallHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/OrderRelateCallHandler.cs

@@ -1,18 +1,10 @@
 using DotNetCore.CAP;
 using Hotline.Application.CallCenter;
-using Hotline.CallCenter.Calls;
-using Hotline.Orders;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Mq;
-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.Application.Orders.Handles.Order
+namespace Hotline.Application.Orders.Handlers.OrderHandler
 {
     public class OrderRelateCallHandler : ICapSubscribe, ITransientDependency
     {

+ 2 - 10
src/Hotline.Application/Orders/Handles/OrderHandler/OrderVisitSmsHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/OrderVisitSmsHandler.cs

@@ -1,23 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using DotNetCore.CAP;
-using Hotline.FlowEngine.Workflows;
+using DotNetCore.CAP;
 using Hotline.Orders;
-using Hotline.Orders.Notifications;
 using Hotline.Push.FWMessage;
 using Hotline.Push.Notifies;
 using Hotline.Share.Dtos.Push;
 using Hotline.Share.Enums.Push;
 using Hotline.Share.Mq;
-using Hotline.Share.Tools;
 using MediatR;
 using XF.Domain.Dependency;
 using XF.Domain.Repository;
 
-namespace Hotline.Application.Orders.Handles.Order;
+namespace Hotline.Application.Orders.Handlers.OrderHandler;
 public class OrderVisitSmsHandler : INotificationHandler<ReceiveMessageNotify>
 {
     private readonly IOrderVisitDomainService _orderVisitDomainService;

+ 1 - 5
src/Hotline.Application/Orders/Handles/OrderHandler/TranspondCityNotifyHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/TranspondCityNotifyHandler.cs

@@ -1,5 +1,4 @@
 using DotNetCore.CAP;
-using Hotline.EventBus;
 using Hotline.Orders;
 using Hotline.Orders.Notifications;
 using Hotline.OrderTranspond;
@@ -7,13 +6,10 @@ using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using MediatR;
-using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
-using System;
-using Hotline.DI;
 using XF.Domain.Repository;
 
-namespace Hotline.Application.Orders.Handles.Order
+namespace Hotline.Application.Orders.Handlers.OrderHandler
 {
     // [Injection(AppScopes = EAppScope.YiBin)]
     public class TranspondCityNotifyHandler : INotificationHandler<OrderStartWorkflowNotify>

+ 1 - 1
src/Hotline.Application/Orders/Handles/OrderHandler/UpdateOrderPushMessageNotifyHandler.cs → src/Hotline.Application/Orders/Handlers/OrderHandler/UpdateOrderPushMessageNotifyHandler.cs

@@ -6,7 +6,7 @@ using Hotline.Share.Enums.Push;
 using MediatR;
 using Microsoft.Extensions.Logging;
 
-namespace Hotline.Application.Orders.Handles.Order
+namespace Hotline.Application.Orders.Handlers.OrderHandler
 {
     public class UpdateOrderPushMessageNotifyHandler : INotificationHandler<UpdateOrderNotify>
     {

+ 1 - 1
src/Hotline.Application/Orders/Handles/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs → src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenEndWorkflowHandler.cs

@@ -15,7 +15,7 @@ using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
 using XF.Domain.Repository;
 
-namespace Hotline.Application.Orders.Handles.OrderScreenHandler;
+namespace Hotline.Application.Orders.Handlers.OrderScreenHandler;
 public class OrderScreenEndWorkflowHandler : INotificationHandler<EndWorkflowNotify>
 {
     private readonly IOrderRepository _orderRepository;

+ 1 - 1
src/Hotline.Application/Orders/Handles/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs → src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenNextWorkflowHandler.cs

@@ -13,7 +13,7 @@ using XF.Domain.Authentications;
 using XF.Domain.Extensions;
 using XF.Domain.Repository;
 
-namespace Hotline.Application.Orders.Handles.OrderScreen;
+namespace Hotline.Application.Orders.Handlers.OrderScreenHandler;
 public class OrderScreenNextWorkflowHandler : INotificationHandler<NextStepNotify>
 {
     private readonly ICapPublisher _capPublisher;

+ 1 - 1
src/Hotline.Application/Orders/Handles/OrderScreenHandler/OrderScreenStartWorkflowHandler.cs → src/Hotline.Application/Orders/Handlers/OrderScreenHandler/OrderScreenStartWorkflowHandler.cs

@@ -3,7 +3,7 @@ using Hotline.FlowEngine.WorkflowModules;
 using Hotline.Orders;
 using MediatR;
 
-namespace Hotline.Application.Orders.Handles.OrderScreen;
+namespace Hotline.Application.Orders.Handlers.OrderScreenHandler;
 
 public class OrderScreenStartWorkflowHandler : INotificationHandler<StartWorkflowNotify>
 {

+ 2 - 16
src/Hotline.Application/Orders/Handles/SnapshotHandler/GuiderSystemTimeoutHandler.cs → src/Hotline.Application/Orders/Handlers/SnapshotHandler/GuiderSystemTimeoutHandler.cs

@@ -1,24 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Hotline.Application.Orders;
-using Hotline.Authentications;
-using Hotline.Caching.Interfaces;
-using Hotline.EventBus;
-using Hotline.FlowEngine.Notifications;
-using Hotline.FlowEngine.Workflows;
-using Hotline.Orders;
+using Hotline.Caching.Interfaces;
 using Hotline.Settings;
-using Hotline.Share.Dtos.FlowEngine;
-using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Tools;
 using Hotline.Snapshot.Notifications;
 using MediatR;
-using XF.Domain.Exceptions;
 
-namespace Hotline.Application.Orders.Handles.Snapshot
+namespace Hotline.Application.Orders.Handlers.SnapshotHandler
 {
     /// <summary>
     /// 需求:坐席派给网格员的安全隐患工单若未推送成功超过4小时或者网格员超过4小时没回复,则自动流转到标注节点待标注列表

+ 5 - 1
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -457,5 +457,9 @@ namespace Hotline.Application.Orders
 
         Task OrderPrevious(OrderSendBackAudit sendBack, Order order, CancellationToken cancellationToken);
 
-	}
+        /// <summary>
+        /// 依据当前待办节点随意获取一个合法办理人
+        /// </summary>
+        Task<ISessionContext> GetHandlerRandomAsync(WorkflowStep step, CancellationToken cancellationToken);
+    }
 }

+ 123 - 8
src/Hotline.Application/Orders/OrderApplication.cs

@@ -45,6 +45,7 @@ using PanGu;
 using SqlSugar;
 using System.Data;
 using System.Dynamic;
+using ExtendedNumerics.Exceptions;
 using FluentValidation;
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Notifications;
@@ -111,10 +112,11 @@ public class OrderApplication : IOrderApplication, IScopeDependency
     private readonly IRepository<OrderTsDetails> _orderTsDetailsRepository;
     private readonly IRepository<KnowledgeQuote> _knowledgeQuoteRepository;
     private readonly IRepository<OrderSpecial> _orderSpecialRepository;
+    private readonly IRepository<User> _userRepository;
     private readonly IWorkflowApplication _workflowApplication;
     private readonly ICircularRecordDomainService _circularRecordDomainService;
 
-    public OrderApplication(
+	public OrderApplication(
         IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
         IWorkflowDomainService workflowDomainService,
@@ -158,6 +160,7 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         IRepository<OrderTsDetails> orderTsDetailsRepository,
         IRepository<KnowledgeQuote> knowledgeQuoteRepository,
         IRepository<OrderSpecial> orderSpecialRepository,
+        IRepository<User> userRepository,
         IWorkflowApplication workflowApplication,
         ICircularRecordDomainService circularRecordDomainService)
     {
@@ -204,9 +207,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
         _orderTsDetailsRepository = orderTsDetailsRepository;
         _knowledgeQuoteRepository = knowledgeQuoteRepository;
         _orderSpecialRepository = orderSpecialRepository;
+        _userRepository = userRepository;
         _workflowApplication = workflowApplication;
         _circularRecordDomainService = circularRecordDomainService;
-    }
+	}
 
     /// <summary>
     /// 更新工单办理期满时间(延期调用,其他不调用)
@@ -1602,8 +1606,8 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 .OrderByIF(dto is { SortField: "hotspotName", SortRule: 1 }, d => d.HotspotName, OrderByType.Desc) //热点分类降序
                 .OrderByIF(dto is { SortField: "acceptorName", SortRule: 0 }, d => d.AcceptorName, OrderByType.Asc) //受理人升序
                 .OrderByIF(dto is { SortField: "acceptorName", SortRule: 1 }, d => d.AcceptorName, OrderByType.Desc) //受理人降序
-                .OrderByIF(dto is { SortField: "actualHandleTime", SortRule: 0 }, d => d.ActualHandleTime, OrderByType.Asc) //接办时间升序
-                .OrderByIF(dto is { SortField: "actualHandleTime", SortRule: 1 }, d => d.ActualHandleTime, OrderByType.Desc) //接办时间降序
+                .OrderByIF(dto is { SortField: "currentStepAcceptTime", SortRule: 0 }, d => d.CurrentStepAcceptTime, OrderByType.Asc) //接办时间升序
+                .OrderByIF(dto is { SortField: "currentStepAcceptTime", SortRule: 1 }, d => d.CurrentStepAcceptTime, OrderByType.Desc) //接办时间降序
             ;
 
         return query;
@@ -4112,10 +4116,10 @@ public class OrderApplication : IOrderApplication, IScopeDependency
                 cancellation);
 
 
-        //if (order.ActualHandleOrgCode != OrgSeedData.CenterId && order.Status < EOrderStatus.Filed)
-        //{
-        //	await _circularRecordDomainService.OrderSpecialCircularMessage(special, order, cancellation);
-        //}
+        if (_appOptions.Value.IsYiBin && order.ActualHandleOrgCode != OrgSeedData.CenterId && order.Status < EOrderStatus.Filed)
+        {
+            await _circularRecordDomainService.OrderSpecialCircularMessage(special, order, cancellation);
+        }
 
         if (_appOptions.Value.IsZiGong && dto.BusinessType == EBusinessType.Send)
         {
@@ -5235,6 +5239,117 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             await _orderRepository.Updateable().SetColumns(o => new Order() { ProcessType = processType, SendBackNum = order.SendBackNum })
                 .Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
         }
+
+		if (_appOptions.Value.IsYiBin && order.IsProvince && sendBack.ApplyOrgId.Length == 6 && sendBack.SendBackOrgId == OrgSeedData.CenterId )
+		{
+            if (currentStep.FlowAssignType == EFlowAssignType.User)
+            {
+                await _circularRecordDomainService.OrderSendBackCircularMessage(currentStep.HandlerId, currentStep.HandlerName, order, cancellationToken);
+            }
+            else if (currentStep.FlowAssignType == EFlowAssignType.Role && !string.IsNullOrEmpty(currentStep.RoleId))
+            {
+
+                var users = await _userRepository.Queryable().Includes(x => x.Roles).Where(x => x.Roles.Where(x => x.Id == currentStep.RoleId).Any()).ToListAsync();
+                foreach (var user in users)
+                {
+                    await _circularRecordDomainService.OrderSendBackCircularMessage(user.Id, user.Name, order, cancellationToken);
+                }
+            }
+		}
+	}
+
+    /// <summary>
+    /// 依据当前待办节点获取任意一个合法办理人
+    /// </summary>
+    public async Task<ISessionContext> GetHandlerRandomAsync(WorkflowStep step, CancellationToken cancellationToken)
+    {
+        User user;
+        switch (step.BusinessType)
+        {
+            case EBusinessType.Seat:
+                var roleSeat = _systemSettingCacheManager.GetSetting(SettingConstants.RoleZuoXi)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleSeat))
+                    throw new UserFriendlyException($"未配置坐席角色, {SettingConstants.RoleZuoXi}", "未配置坐席角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d=>d.Organization)
+                    .Where(d => d.Roles.Any(x => x.Name == roleSeat))
+                    .FirstAsync(cancellationToken);
+                if(user is null)
+                    throw UserFriendlyException.SameMessage("坐席角色未设置用户");
+               break;
+            case EBusinessType.Send:
+                var roleSend = _systemSettingCacheManager.GetSetting(SettingConstants.RolePaiDan)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleSend))
+                    throw new UserFriendlyException($"未配置派单角色, {SettingConstants.RolePaiDan}", "未配置派单角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => d.Roles.Any(x => x.Name == roleSend))
+                    .FirstAsync(cancellationToken);
+                if (user is null)
+                    throw UserFriendlyException.SameMessage("派单角色未设置用户");
+                break;
+            case EBusinessType.CenterMonitor:
+                var roleCenterMonitor = _systemSettingCacheManager.GetSetting(SettingConstants.SeatsMonitor)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleCenterMonitor))
+                    throw new UserFriendlyException($"未配置中心班长角色, {SettingConstants.SeatsMonitor}", "未配置中心班长角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => d.Roles.Any(x => x.Name == roleCenterMonitor))
+                    .FirstAsync(cancellationToken);
+                if (user is null)
+                    throw UserFriendlyException.SameMessage("中心班长角色未设置用户");
+                break;
+            case EBusinessType.CenterLeader:
+                var roleCenterLeader = _systemSettingCacheManager.GetSetting(SettingConstants.RoleCenterLeader)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleCenterLeader))
+                    throw new UserFriendlyException($"未配置中心领导角色, {SettingConstants.RoleCenterLeader}", "未配置中心领导角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => d.Roles.Any(x => x.Name == roleCenterLeader))
+                    .FirstAsync(cancellationToken);
+                if (user is null)
+                    throw UserFriendlyException.SameMessage("中心领导角色未设置用户");
+                break;
+            case EBusinessType.Department:
+                var roleJingBanRen = _systemSettingCacheManager.GetSetting(SettingConstants.RoleJingBanRen)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleJingBanRen))
+                    throw new UserFriendlyException($"未配置部门经办人角色, {SettingConstants.RoleJingBanRen}", "未配置部门经办人角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d=>d.Organization)
+                    .Where(d => d.OrgId == step.HandlerOrgId && d.Roles.Any(x => x.Name == roleJingBanRen))
+                    .FirstAsync(cancellationToken);
+                if (user is null)
+                    throw new UserFriendlyException($"该部门经办人角色未设置用户,部门:{step.HandlerOrgId}, 角色:{SettingConstants.RoleJingBanRen}");
+                break;
+            case EBusinessType.DepartmentLeader:
+                var roleBuMenLingDao = _systemSettingCacheManager.GetSetting(SettingConstants.RoleLingDao)?.SettingValue.FirstOrDefault();
+                if (string.IsNullOrEmpty(roleBuMenLingDao))
+                    throw new UserFriendlyException($"未配置部门领导角色, {SettingConstants.RoleJingBanRen}", "未配置部门领导角色");
+                user = await _userRepository.Queryable()
+                    .Includes(d => d.Organization)
+                    .Where(d => d.OrgId == step.HandlerOrgId && d.Roles.Any(x => x.Name == roleBuMenLingDao))
+                    .FirstAsync(cancellationToken);
+                if (user is null)
+                    throw new UserFriendlyException($"该部门领导角色未设置用户,部门:{step.HandlerOrgId}, 角色:{SettingConstants.RoleJingBanRen}");
+                break;
+            default:
+                throw new OutOfRangeException(nameof(GetHandlerRandomAsync));
+        }
+
+        //await _sessionContext.ChangeSessionAsync(user.Id, cancellationToken);
+        _sessionContext.ChangeSession(user.Id);
+
+        return new FakeSessionContext
+        {
+            UserId = user.Id,
+            UserName = user.Name,
+            OrgId = user.OrgId,
+            OrgName = user.Organization.Name,
+            OrgAreaCode = user.Organization.AreaCode,
+            OrgAreaName = user.Organization.AreaName,
+            OrgIsCenter = user.Organization.IsCenter,
+            OrgLevel = user.Organization.Level,
+        };
     }
 
     #endregion

+ 2 - 2
src/Hotline.Application/StatisticalReport/CallReport/YiBinCallReportApplication.cs

@@ -318,7 +318,7 @@ public class YiBinCallReportApplication : CallReportApplicationBase, ICallReport
                   InTimeImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.AnsweredTime != null && c.RingTimes <= ringTimes, 1, 0)),//按时接通量
                   InHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.AnsweredTime == null, 1, 0)), //呼入未接通
                   InHangupImmediate = SqlFunc.AggregateSum(SqlFunc.IIF(c.AnsweredTime == null && c.RingTimes <= noConnectByeTimes, 1, 0)),//未接通秒挂量
-                  OverTimeInHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.AnsweredTime == null && c.RingTimes > noConnectByeTimes, 1, 0)), //超时未接通量
+                  OverTimeInHanguped = SqlFunc.AggregateSum(SqlFunc.IIF(c.AnsweredTime == null && c.RingTimes > ringTimes, 1, 0)), //超时未接通量
               }).ToListAsync();
         return list;
     }
@@ -354,7 +354,7 @@ public class YiBinCallReportApplication : CallReportApplicationBase, ICallReport
             .WhereIF(dto.QueryType.HasValue && dto.QueryType == 5,x=> x.AnsweredTime != null && x.RingTimes <= ringTimes) //按时接通量
             .WhereIF(dto.QueryType.HasValue && dto.QueryType == 6,x=> x.AnsweredTime == null) //呼入未接通量
             .WhereIF(dto.QueryType.HasValue && dto.QueryType == 7,x=> x.AnsweredTime == null && x.RingTimes <= noConnectByeTimes) //未接通秒挂量
-            .WhereIF(dto.QueryType.HasValue && dto.QueryType == 8,x=> x.AnsweredTime == null && x.RingTimes > noConnectByeTimes) //超时未接通量
+            .WhereIF(dto.QueryType.HasValue && dto.QueryType == 8,x=> x.AnsweredTime == null && x.RingTimes > ringTimes) //超时未接通量
             .Where(x => x.CallDirection == ECallDirection.In)
             .OrderBy(x => x.BeginRingTime)
             .MergeTable()

+ 8 - 3
src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs

@@ -98,11 +98,16 @@ public class NextStepsWithOpinionDto<TSteps> : NextStepsDto<TSteps>
     /// </summary>
     public ECounterSignType? CounterSignType { get; set; }
 
-    #region 随手拍
     /// <summary>
-    /// 线索分类
+    /// 泸州需求 :是否能修改延期时限
     /// </summary>
-    public List<Kv>? IndustryCase { get; set; }
+    public bool? IsAlterDay { get; set; }
+
+	#region 随手拍
+	/// <summary>
+	/// 线索分类
+	/// </summary>
+	public List<Kv>? IndustryCase { get; set; }
 
     /// <summary>
     /// 补充奖励类型

+ 8 - 1
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -265,7 +265,14 @@ namespace Hotline.Share.Dtos.Order
         public string Id { get; set; }
     }
 
-    public record ApplyDelayDto
+    public record AlterDelayDayDto {
+		public string Id { get; set; }
+        public int DelayNum { get; set; }
+
+	}
+
+
+	public record ApplyDelayDto
     {
         public string OrderId { get; set; }
 

+ 27 - 0
src/Hotline/Article/CircularRecordDomainService.cs

@@ -202,5 +202,32 @@ namespace Hotline.Article
 
 		}
 
+        /// <summary>
+        /// 信件退回公告通知
+        /// </summary>
+        /// <returns></returns>
+		public async Task OrderSendBackCircularMessage(string userId,string userName, Order order, CancellationToken cancellationToken = default)
+		{
+
+			var cMessage = new AddCircularDto
+			{
+				Title = "信件退回信息",
+				Content = $"工单编码为{order.No}的工单,已被退回,请及时处理!",
+				CircularTypeId = "1",
+				CircularTypeName = "公告通知",
+				CircularType = ECircularType.Person,
+				IsMustRead = false,
+				SourceOrgId = _sessionContext.RequiredOrgId,
+				SourceOrgName = _sessionContext.OrgName
+			};
+			var groups = new CircularReadGroupDto
+			{
+				UserId = userId,
+				UserName = userName
+			};
+			cMessage.CircularReadGroups = new List<CircularReadGroupDto> { groups };
+
+		}
+
 	}
 }

+ 2 - 0
src/Hotline/Article/ICircularRecordDomainService.cs

@@ -21,5 +21,7 @@ namespace Hotline.Article
 
         Task OrderSpecialCircularMessage(OrderSpecial special, Order order, CancellationToken cancellationToken = default);
 
+        Task OrderSendBackCircularMessage(string userId, string userName, Order order, CancellationToken cancellationToken = default);
+
 	}
 }

+ 33 - 0
src/Hotline/Authentications/ChangeSessionProvider.cs

@@ -54,4 +54,37 @@ public class ChangeSessionProvider : IChangeSessionProvider, IScopeDependency
         httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(userClaims));
         return httpContext;
     }
+
+    public async Task<HttpContext> ChangeSessionByUserIdAsync(string userId, HttpContext httpContext, CancellationToken cancellation)
+    {
+        httpContext ??= new DefaultHttpContext();
+        var userRepository = _serviceProvider.GetService<IRepository<User>>();
+        //var accountRepository = _serviceProvider.GetService<IAccountRepository>();
+        //var user = userRepository.Queryable().Where(m => m.Id == id).First();
+        //if (user == null) return null;
+        //var account = accountRepository.GetExtAsync(m => m.Id == user.Id, m => m.Includes(x => x.Roles)).GetAwaiter().GetResult();
+
+        var user = await userRepository.Queryable()
+            .Includes(d => d.Account)
+            .Includes(d => d.Organization)
+            .Includes(d => d.Roles)
+            .FirstAsync(d => d.Id == userId, cancellation);
+            
+        List<Claim> userClaims = [
+            new(JwtClaimTypes.Subject, user.Id),
+            new(JwtClaimTypes.PhoneNumber, user.Account.PhoneNo ?? string.Empty),
+            new(ClaimTypes.NameIdentifier, user.Id),
+            new(AppClaimTypes.UserDisplayName, user.Account.Name),
+            new(AppClaimTypes.DepartmentId, user.OrgId ?? string.Empty),
+            new(AppClaimTypes.DepartmentIsCenter, user.Organization?.IsCenter.ToString() ?? string.Empty),
+            new(AppClaimTypes.DepartmentName, user.Organization?.Name ?? string.Empty),
+            new(AppClaimTypes.DepartmentAreaCode, user.Organization?.AreaCode ?? string.Empty),
+            new(AppClaimTypes.DepartmentAreaName, user.Organization?.AreaName ?? string.Empty),
+            new(AppClaimTypes.DepartmentLevel, user.Organization?.Level.ToString() ?? string.Empty),
+            new(AppClaimTypes.AreaId, user.OrgId?.GetHigherOrgId() ?? string.Empty),
+        ];
+        userClaims.AddRange(user.Roles.Select(d => new Claim(JwtClaimTypes.Role, d.Name)));
+        httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(userClaims));
+        return httpContext;
+    }
 }

+ 5 - 0
src/Hotline/Authentications/FakeSessionContext.cs

@@ -55,5 +55,10 @@ namespace Hotline.Authentications
         {
             throw new NotImplementedException();
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 5 - 0
src/Hotline/Authentications/Police110SessionContext.cs

@@ -67,5 +67,10 @@ namespace Hotline.Authentications
         {
             throw new NotImplementedException();
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 5 - 0
src/Hotline/Authentications/ProvinceSessionContext.cs

@@ -72,5 +72,10 @@ namespace Hotline.Authentications
         {
             throw new NotImplementedException();
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 5 - 0
src/Hotline/Authentications/YbEnterpriseSessionContext.cs

@@ -68,5 +68,10 @@ namespace Hotline.Authentications
         {
             throw new NotImplementedException();
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 5 - 0
src/Hotline/Authentications/ZzptSessionContext.cs

@@ -67,5 +67,10 @@ namespace Hotline.Authentications
         {
             throw new NotImplementedException();
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 4 - 2
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -54,6 +54,7 @@ namespace Hotline.FlowEngine.Workflows
             ISystemSettingCacheManager systemSettingCacheManager,
             IWfModuleCacheManager wfModuleCacheManager,
             ISessionContextProvider sessionContextProvider,
+            ISessionContext sessionContext,
             IMapper mapper,
             Publisher publisher,
             ILogger<WorkflowDomainService> logger,
@@ -729,6 +730,7 @@ namespace Hotline.FlowEngine.Workflows
                 .ExecuteCommandAsync();
 
             workflow.ActualHandleStepAcceptTime = currentStep.AcceptTime;
+            workflow.CurrentStepAcceptTime = currentStep.AcceptTime;
             await _workflowRepository.Updateable(workflow).ExecuteCommandAsync(cancellationToken);
 
             return workflow.ActualHandleStepAcceptTime;
@@ -1610,7 +1612,7 @@ namespace Hotline.FlowEngine.Workflows
                               workflow.Steps.MaxBy(d => d.CreationTime);
 
             //update uncomplete traces
-            var uncompleteTraces = workflow.Traces.Where(d => d.Status != EWorkflowStepStatus.Handled).ToList();
+            var uncompleteTraces = workflow.Traces.Where(d => d.Status != EWorkflowStepStatus.Handled && d.TraceStyle == ETraceStyle.Flow).ToList();
             if (uncompleteTraces.Any())
             {
                 foreach (var trace in uncompleteTraces)
@@ -1627,7 +1629,7 @@ namespace Hotline.FlowEngine.Workflows
             }
             else
             {
-                var endTrace = workflow.Traces.Where(d => d.StepType == EStepType.End).MaxBy(d => d.CreationTime);
+                var endTrace = workflow.Traces.Where(d => d.StepType == EStepType.End && d.TraceStyle == ETraceStyle.Flow).MaxBy(d => d.CreationTime);
                 if (endTrace is not null)
                 {
                     endTrace.Opinion += ("\r\n" + dto.Opinion);

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

@@ -190,6 +190,11 @@ namespace Hotline.Settings
         /// </summary>
         public const string RoleLingDao = "RoleLingDao";
 
+        /// <summary>
+        /// 中心领导
+        /// </summary>
+        public const string RoleCenterLeader = "RoleCenterLeader";
+
         /// <summary>
         /// 是否开启登录短信
         /// </summary>

+ 5 - 0
src/XF.Domain/Authentications/DefaultSessionContext.cs

@@ -75,6 +75,11 @@ namespace XF.Domain.Authentications
         {
             _contextAccessor.HttpContext = _changeSessionProvider.ChangeSessionByUserId(id, _contextAccessor.HttpContext);
         }
+
+        public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+        {
+            _contextAccessor.HttpContext = await _changeSessionProvider.ChangeSessionByUserIdAsync(userId, _contextAccessor.HttpContext, cancellation);
+        }
     }
 
     public static class ClaimsPrincipalExtensions

+ 1 - 0
src/XF.Domain/Authentications/IChangeSessionProvider.cs

@@ -9,4 +9,5 @@ namespace XF.Domain.Authentications;
 public interface IChangeSessionProvider
 {
     HttpContext ChangeSessionByUserId(string id, HttpContext httpContext);
+    Task<HttpContext> ChangeSessionByUserIdAsync(string id, HttpContext httpContext, CancellationToken cancellation);
 }

+ 2 - 0
src/XF.Domain/Authentications/ISessionContext.cs

@@ -53,4 +53,6 @@ public interface ISessionContext
     string? OpenId { get; init; }
 
     void ChangeSession(string id);
+
+    Task ChangeSessionAsync(string userId, CancellationToken cancellation);
 }

+ 5 - 0
test/Hotline.Tests/Controller/TestSessionContext.cs

@@ -24,6 +24,11 @@ public class TestSessionContext : ISessionContext, IScopeDependency
         _contextAccessor.HttpContext = _changeSessionProvider.ChangeSessionByUserId(id, _contextAccessor.HttpContext);
     }
 
+    public async Task ChangeSessionAsync(string userId, CancellationToken cancellation)
+    {
+        throw new NotImplementedException();
+    }
+
     public string? OpenId { get { return _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.OpenId); } init { } }
 
     /// <summary>

+ 0 - 5
test/Hotline.Tests/Startup.cs

@@ -11,7 +11,6 @@ using Hotline.Application.Jobs;
 using Hotline.Application.StatisticalReport.CallReport;
 using Hotline.Authentications;
 using Hotline.CallCenter.Configs;
-using Hotline.CallCenter.Tels;
 using Hotline.Configurations;
 using Hotline.DI;
 using Hotline.EventBus;
@@ -19,7 +18,6 @@ using Hotline.File;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Orders.DatabaseEventHandler;
-using Hotline.Pdf;
 using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Repository.SqlSugar.Extensions;
@@ -35,7 +33,6 @@ using Mapster;
 using MediatR;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Identity;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
@@ -183,8 +180,6 @@ public class Startup
             services.AddXingTangDb(callCenterConfiguration.XingTang);
             services.AddScoped<IGuiderSystemService, TiqnQueService>();
             services.AddScoped<IWorkflowDomainService, WorkflowDomainService>();
-            services.AddScoped<IPdfManager, QuestPdfManager>();
-            services.AddScoped<ICallTelClient, XingTang.CallTelClient>();
 
             //ServiceLocator.Instance = services.BuildServiceProvider();
         }