瀏覽代碼

Merge branch 'fix/recall_can_not_handle' into release/yibin

xf 11 月之前
父節點
當前提交
3f07a34568

+ 16 - 0
src/Hotline.Api/Controllers/OrderController.cs

@@ -50,6 +50,7 @@ using System;
 using XF.Domain.Authentications;
 using XF.Domain.Cache;
 using XF.Domain.Constants;
+using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
@@ -4631,6 +4632,21 @@ public class OrderController : BaseController
             throw new UserFriendlyException("该工单已被签收");
         order.Sign(_sessionContext.RequiredUserId, _sessionContext.UserName);
 
+        if (!string.IsNullOrEmpty(order.WorkflowId))
+        {
+            var workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId,
+                    cancellationToken: HttpContext.RequestAborted);
+            workflow.HandlerOrgs = new();
+            workflow.HandlerUsers = new();
+            workflow.Assign(EFlowAssignType.User, _sessionContext.RequiredUserId);
+            await _workflowRepository.UpdateAsync(workflow, HttpContext.RequestAborted);
+
+            order.HandlerOrgs = workflow.HandlerOrgs;
+            order.HandlerUsers= workflow.HandlerUsers;
+            order.FlowedOrgIds = workflow.FlowedOrgIds;
+            order.FlowedUserIds = workflow.FlowedUserIds;
+        }
+
         await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
     }
 

+ 5 - 0
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -96,5 +96,10 @@ namespace Hotline.Application.FlowEngine
         /// </summary>
         Task StartToEndAsync(StartWorkflowDto dto, ISessionContext current, string externalId, DateTime? expiredTime = null,
             CancellationToken cancellationToken = default);
+
+        /// <summary>
+        /// 更新省平台办理结果节点附件
+        /// </summary>
+        Task UpdateProvinceHandleResultFilesAsync(string workflowId, List<FileDto> files, CancellationToken cancellationToken);
     }
 }

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

@@ -1176,5 +1176,24 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         await StartWorkflowAsync(dto, current, externalId, expiredTime, cancellationToken);
     }
 
+    /// <summary>
+    /// 更新省平台办理结果节点附件
+    /// </summary>
+    public async Task UpdateProvinceHandleResultFilesAsync(string workflowId, List<FileDto> files, CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true, withTraces: true,
+            cancellationToken: cancellationToken);
+        var step = workflow.Steps.FirstOrDefault(d => 
+            d.StepHandlers.Any(d => d.OrgId == "001171" || d.OrgId == "001178"));
+        if(step is not null)
+        {
+            step.FileJson = await _fileRepository.AddFileAsync(files, workflow.ExternalId, step.Id, cancellationToken);
+            var trace = workflow.Traces.First(d => d.StepId == step.Id);
+            trace.FileJson = step.FileJson;
+            await _workflowStepRepository.UpdateAsync(step, cancellationToken);
+            await _workflowTraceRepository.UpdateAsync(trace, cancellationToken);
+        }
+    }
+
     #endregion
 }

+ 159 - 10
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -9,8 +9,10 @@ using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.OrderTranspond;
 using Hotline.Settings;
+using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
+using Hotline.Share.Dtos.File;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.OrderTranspond;
@@ -19,6 +21,7 @@ using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Quality;
 using Hotline.Share.Mq;
 using MapsterMapper;
+using StackExchange.Redis;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
@@ -51,6 +54,8 @@ namespace Hotline.Application.Subscribers
         private readonly ISystemOrganizeRepository _systemOrganizeRepository;
         private readonly IRepository<TranspondCityRawData> _transpondCityRawDataRepository;
         private readonly IRepository<Workflow> _workflowRepository;
+        private readonly IRepository<OrderComplement> _orderComplementRepository;
+        private readonly ITimeLimitDomainService _timeLimitDomainService;
         private readonly IOrderApplication _orderApplication;
 
         public DataSharingSubscriber(
@@ -75,6 +80,8 @@ namespace Hotline.Application.Subscribers
             ISystemOrganizeRepository systemOrganizeRepository,
             IRepository<TranspondCityRawData> transpondCityRawDataRepository,
             IRepository<Workflow> workflowRepository,
+            IRepository<OrderComplement> orderComplementRepository,
+            ITimeLimitDomainService timeLimitDomainService,
             IOrderApplication orderApplication
             )
         {
@@ -98,6 +105,8 @@ namespace Hotline.Application.Subscribers
             _systemOrganizeRepository = systemOrganizeRepository;
             _transpondCityRawDataRepository = transpondCityRawDataRepository;
             _workflowRepository = workflowRepository;
+            _orderComplementRepository = orderComplementRepository;
+            _timeLimitDomainService = timeLimitDomainService;
             _orderApplication = orderApplication;
         }
 
@@ -112,11 +121,32 @@ namespace Hotline.Application.Subscribers
             {
                 sendBack.Result = dto.Result;
                 sendBack.Reason = dto.Reason;
-                var order = await _orderRepository.GetAsync(sendBack.OrderId, cancellationToken);
-                order.Status = EOrderStatus.WaitForAccept;
-                await _orderRepository.UpdateAsync(order, cancellationToken);
+                if (dto.Files != null && dto.Files.Any())
+                {
+                    sendBack.FileJson = await _fileRepository.AddFileAsync(dto.Files, sendBack.Id, string.Empty, cancellationToken);
+                }
+
                 if (dto.Result is 1)
                 {
+                    var order = await _orderRepository.GetAsync(sendBack.OrderId, cancellationToken);
+                    if (order is null)
+                        throw new UserFriendlyException("无效工单编号");
+                    var now = DateTime.Now;
+                    var handleDuration = order.StartTime.HasValue
+                        ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
+                            now, order.ProcessType is EProcessType.Zhiban)
+                        : 0;
+                    var fileDuration = order.CenterToOrgTime.HasValue
+                        ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
+                            now, order.ProcessType is EProcessType.Zhiban)
+                        : 0;
+                    var allDuration = order.StartTime.HasValue
+                        ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
+                            order.ProcessType is EProcessType.Zhiban)
+                        : 0;
+                    order.File(now, handleDuration, fileDuration, allDuration);
+                    await _orderRepository.UpdateAsync(order, cancellationToken);
+
                     var current = SessionContextCreator.CreateSessionContext(dto.Source);
                     if (string.IsNullOrEmpty(order.WorkflowId))
                     {
@@ -177,6 +207,11 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderRemind)]
         public async Task RecOrderUrgeAsync(ProvinceOrderUrgeDto dto, CancellationToken cancellationToken)
         {
+            var exists = await _orderUrgeRepository.Queryable()
+                .AnyAsync(d => d.DsBisId == dto.DsBisId, cancellationToken);
+            if (exists)
+                throw new UserFriendlyException($"收到重复催办编号: {dto.DsBisId}");
+
             var order = await _orderRepository.Queryable().Where(x => x.ProvinceNo == dto.CaseSerial).FirstAsync(cancellationToken);
             var model = new OrderUrge();
             model.InitId();
@@ -246,6 +281,11 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderSupervise)]
         public async Task RecOrderSuperviseAsync(ProvinceSendOrderSuperviseDto dto, CancellationToken cancellationToken)
         {
+            var exists = await _orderSuperviseRepository.Queryable()
+                .AnyAsync(d => d.SuperviseSerial == dto.ProvinceOrderSuperviseDto.SuperviseSerial, cancellationToken);
+            if (exists)
+                throw new UserFriendlyException($"收到重复督办编号: {dto.ProvinceOrderSuperviseDto.SuperviseSerial}");
+
             var order = await _orderRepository.Queryable().Where(x => x.ProvinceNo == dto.ProvinceOrderSuperviseDto!.CaseSerial).FirstAsync(cancellationToken);
             var org = await _systemOrganizeRepository.GetAsync(x => x.Id == order.ActualHandleOrgCode, cancellationToken);
             var model = new OrderSupervise();
@@ -271,11 +311,16 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(Hotline.Share.Mq.EventNames.SharingOrderScreen)]
         public async Task RecOrderScreenResultAsync(ProvinceSendScreenResultDto dto, CancellationToken cancellationToken)
         {
-            var order = await _orderRepository.Queryable()
-                .Where(x => x.ProvinceNo == dto.ProvinceScreenResult!.CaseSerial)
-                .FirstAsync(cancellationToken);
+            //var order = await _orderRepository.Queryable()
+            //    .Where(x => x.ProvinceNo == dto.ProvinceScreenResult!.CaseSerial)
+            //    .FirstAsync(cancellationToken);
+            //var orderScreen = await _orderScreenRepository.Queryable()
+            //    .Where(x => x.OrderId == order.Id && x.Status == Share.Enums.Order.EScreenStatus.Approval)
+            //    .FirstAsync(cancellationToken);
+
             var orderScreen = await _orderScreenRepository.Queryable()
-                .Where(x => x.OrderId == order.Id && x.Status == Share.Enums.Order.EScreenStatus.Approval)
+                .Where(x => x.Order.ProvinceNo == dto.ProvinceScreenResult.CaseSerial && 
+                            x.Status == EScreenStatus.Approval)
                 .FirstAsync(cancellationToken);
 
             var current = SessionContextCreator.CreateSessionContext(dto.Source);
@@ -435,8 +480,9 @@ namespace Hotline.Application.Subscribers
                 await _workflowApplication.HandleToEndAsync(current, orderDelay.WorkflowId, dto.Opinion, dto.Files,
                     dto.IsPass ? EReviewResult.Approval : EReviewResult.Failed, cancellationToken);
 
-                //await _workflowApplication.JumpToEndAsync(current, orderDelay.WorkflowId, dto.Opinion, dto.Files,
-                //    dto.IsPass ? EReviewResult.Approval : EReviewResult.Failed, cancellationToken);
+                if (dto.Files != null && dto.Files.Any())
+                    orderDelay.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderDelay.Id, orderDelay.WorkflowId, cancellationToken);
+                await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
             }
         }
 
@@ -464,7 +510,7 @@ namespace Hotline.Application.Subscribers
             {
                 case "0":
                     //退回:撤回至发起人
-                    await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, dto.Opinion, current, cancellationToken);
+                    await _workflowDomainService.RecallToStartStepAsync(order.WorkflowId, dto.Opinion, current, cancellationToken);//todo think是否需要保存附件至省平台办理节点?
                     break;
                 case "1":
                     //办结:归档
@@ -472,6 +518,22 @@ namespace Hotline.Application.Subscribers
                         cancellationToken: cancellationToken);
                     break;
             }
+
+            var now = DateTime.Now;
+            var handleDuration = order.StartTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value,
+                    now, order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            var fileDuration = order.CenterToOrgTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.CenterToOrgTime.Value,
+                    now, order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            var allDuration = order.StartTime.HasValue
+                ? _timeLimitDomainService.CalcWorkTime(order.StartTime.Value, now,
+                    order.ProcessType is EProcessType.Zhiban)
+                : 0;
+            order.File(now, handleDuration, fileDuration, allDuration);
+            await _orderRepository.UpdateAsync(order, cancellationToken);
         }
 
         /// <summary>
@@ -531,6 +593,93 @@ namespace Hotline.Application.Subscribers
             await _orderDomainService.AddOrderComplementAsync(dto, cancellationToken);
         }
 
+        public async Task RecFilesAsync(ReceiveFilesFromDsDto dto, CancellationToken cancellationToken)
+        {
+            if (dto.Files == null || !dto.Files.Any())
+                throw new UserFriendlyException("未收到任何附件");
+
+            switch (dto.DsBisType)
+            {
+                case EDsBisType.AcceptOrder:
+                    var order = await _orderRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+                    if (order is null)
+                        throw new UserFriendlyException("无效省工单编号");
+
+                    order.FileJson = await _fileRepository.AddFileAsync(dto.Files, order.Id, order.WorkflowId ?? string.Empty, cancellationToken);
+                    await _orderRepository.UpdateAsync(order, cancellationToken);
+                    break;
+                case EDsBisType.OrderPreviousResult:
+                    var sendBack = await _orderSendBackRepository.Queryable()
+                        .Where(d => d.Order.ProvinceNo == dto.ProvinceNo)
+                        .FirstAsync(cancellationToken);
+                    if (sendBack is null)
+                        throw new UserFriendlyException("无效省工单退回编号");
+
+                    sendBack.FileJson = await _fileRepository.AddFileAsync(dto.Files, sendBack.Id, string.Empty, cancellationToken);
+                    await _orderSendBackRepository.UpdateAsync(sendBack, cancellationToken);
+                    break;
+                case EDsBisType.SendOrderSupervise:
+                    var orderSupervise = await _orderSuperviseRepository
+                        .GetAsync(d => d.SuperviseSerial == dto.SuperviseId, cancellationToken);
+                    if (orderSupervise is null)
+                        throw new UserFriendlyException("无效省工单督办编号");
+
+                    orderSupervise.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderSupervise.Id, "", cancellationToken);
+                    await _orderSuperviseRepository.AddAsync(orderSupervise, cancellationToken);
+                    break;
+                case EDsBisType.SendOrderUrge:
+                    var orderUrge = await _orderUrgeRepository
+                        .GetAsync(d => d.DsBisId == dto.DsBisId, cancellationToken);
+                    if (orderUrge is null)
+                        throw new UserFriendlyException("无效省工单催办业务编号");
+
+                    orderUrge.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderUrge.Id, "", cancellationToken);
+                    await _orderUrgeRepository.UpdateAsync(orderUrge, cancellationToken);
+                    break;
+                case EDsBisType.OrderScreenResult:
+                    var orderScreen = await _orderScreenRepository.Queryable()
+                        .Where(x => x.Order.ProvinceNo == dto.ProvinceNo && x.Status == Share.Enums.Order.EScreenStatus.Approval)
+                        .FirstAsync(cancellationToken);
+                    if (orderScreen is null)
+                        throw new UserFriendlyException("未查询到对应省工单甄别数据");
+
+                    orderScreen.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderScreen.Id, "", cancellationToken);
+                    await _orderScreenRepository.UpdateAsync(orderScreen, cancellationToken);
+                    break;
+                case EDsBisType.OrderDelayResult:
+                    var orderDelay = await _orderDelayRepository.Queryable()
+                        .Where(d => d.Order.ProvinceNo == dto.ProvinceNo && d.DelayState == EDelayState.Examining)
+                        .FirstAsync(cancellationToken);
+                    if (orderDelay is null)
+                        throw new UserFriendlyException($"未查询到延期数据, ProvinceNo: {dto.ProvinceNo}");
+
+                    if (dto.Files != null && dto.Files.Any())
+                        orderDelay.FileJson = await _fileRepository.AddFileAsync(dto.Files, orderDelay.Id, orderDelay.WorkflowId, cancellationToken);
+                    await _orderDelayRepository.UpdateAsync(orderDelay, cancellationToken);
+                    break;
+                case EDsBisType.SendOrderComplement:
+                    var complement = await _orderComplementRepository
+                        .GetAsync(d => d.DsBisId == dto.DsBisId, cancellationToken);
+                    if (complement is null)
+                        throw new UserFriendlyException(
+                            $"未查询到补充信息, ProvinceNo: {dto.ProvinceNo}, DsBisIs: {dto.DsBisId}");
+
+                    if (dto.Files.Any()) complement.FileJson = await _fileRepository.AddFileAsync(dto.Files, complement.Id, "", cancellationToken);
+                    await _orderComplementRepository.UpdateAsync(complement, cancellationToken);
+                    break;
+                case EDsBisType.OrderHandleResult:
+                    var order1 = await _orderRepository.GetAsync(d=>d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+                    if (order1 is null)
+                        throw new UserFriendlyException($"无效工单编号, ProvinceNo: {dto.ProvinceNo}");
+                    if (string.IsNullOrEmpty(order1.WorkflowId))
+                        throw new UserFriendlyException($"该工单未开启流程,ProvinceNo: {dto.ProvinceNo}");
+                    await _workflowApplication.UpdateProvinceHandleResultFilesAsync(order1.WorkflowId, dto.Files, cancellationToken);
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
         /// <summary>
         /// 接收市州互转返回数据
         /// </summary>

+ 6 - 1
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/OrderSendBackResultDto.cs

@@ -1,8 +1,11 @@
-namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
+using Hotline.Share.Dtos.File;
+
+namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto;
 
 public class OrderSendBackResultDto : DsSource
 {
     public string Id { get; set; }
+
     /// <summary>
     /// 省上退回反馈结果
     /// </summary>
@@ -12,4 +15,6 @@ public class OrderSendBackResultDto : DsSource
     /// 省上退回反馈
     /// </summary>
     public string? Reason { get; set; }
+
+    public List<FileDto> Files { get; set; }
 }

+ 5 - 0
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/ProvinceOrderUrgeDto.cs

@@ -29,6 +29,11 @@ public class ProvinceOrderUrgeDto
     /// </summary>
     public string AreaCode { get; set; }
 
+    /// <summary>
+    /// 省平台业务编号
+    /// </summary>
+    public string DsBisId { get; set; }
+
     /// <summary>
     /// 附件列表
     /// </summary>

+ 1 - 1
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/ProvinceSendOrderSuperviseDto.cs

@@ -8,7 +8,7 @@ namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto
     /// </summary>
     public class ProvinceSendOrderSuperviseDto
     {
-        public ProvinceOrderSuperviseDto? ProvinceOrderSuperviseDto { get; set; }
+        public ProvinceOrderSuperviseDto ProvinceOrderSuperviseDto { get; set; }
 
         public List<FileDto>? Files { get; set; }
     }

+ 80 - 0
src/Hotline.Share/Dtos/DataSharing/PusherHotlineDto/ReceiveFilesFromDsDto.cs

@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Hotline.Share.Dtos.File;
+
+namespace Hotline.Share.Dtos.DataSharing.PusherHotlineDto
+{
+    public class ReceiveFilesFromDsDto
+    {
+        /// <summary>
+        /// DS业务类型
+        /// </summary>
+        public EDsBisType DsBisType { get; set; }
+
+        /// <summary>
+        /// 业务操作编号
+        /// </summary>
+        public string DsBisId { get; set; }
+
+        /// <summary>
+        /// 省编号
+        /// </summary>
+        public string ProvinceNo { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<FileDto> Files { get; set; }
+
+        /// <summary>
+        /// 督办编号
+        /// </summary>
+        public string SuperviseId { get; set; }
+    }
+
+    public enum EDsBisType
+    {
+        /// <summary>
+        /// 工单受理
+        /// </summary>
+        AcceptOrder = 1,
+
+        /// <summary>
+        /// 工单退回审核结果
+        /// </summary>
+        OrderPreviousResult = 2,
+
+        /// <summary>
+        /// 督办派发
+        /// </summary>
+        SendOrderSupervise = 3,
+
+        /// <summary>
+        /// 催单
+        /// </summary>
+        SendOrderUrge = 4,
+
+        /// <summary>
+        /// 甄别结果
+        /// </summary>
+        OrderScreenResult = 5,
+
+        /// <summary>
+        /// 延期审核结果
+        /// </summary>
+        OrderDelayResult = 6,
+
+        /// <summary>
+        /// 工单补充
+        /// </summary>
+        SendOrderComplement = 7,
+
+        /// <summary>
+        /// 工单办理结果
+        /// </summary>
+        OrderHandleResult = 8
+    }
+}

+ 5 - 0
src/Hotline.Share/Dtos/Order/AddOrderComplementDto.cs

@@ -11,6 +11,11 @@ public class AddOrderComplementDto
     /// </summary>
     public string Opinion { get; set; }
 
+    /// <summary>
+    /// 省平台业务编号
+    /// </summary>
+    public string? DsBisId { get; set; }
+
     /// <summary>
     /// 附件
     /// </summary>

+ 5 - 0
src/Hotline/Orders/OrderComplement.cs

@@ -17,6 +17,11 @@ public class OrderComplement : CreationEntity
     [SugarColumn(Length = 2000)]
     public string Opinion { get; set; }
 
+    /// <summary>
+    /// 省平台业务编号
+    /// </summary>
+    public string? DsBisId { get; set; }
+
     /// <summary>
     /// 附件
     /// </summary>

+ 9 - 4
src/Hotline/Orders/OrderUrge.cs

@@ -75,10 +75,15 @@ namespace Hotline.Orders {
 		[SugarColumn(ColumnDescription = "回复人")]
 		public string? ReplyId { get; set; }
 
-		/// <summary>
-		/// 
-		/// </summary>
-		[Navigate(NavigateType.OneToOne, nameof(OrderId))]
+        /// <summary>
+        /// 省平台业务编号
+        /// </summary>
+        public string? DsBisId { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [Navigate(NavigateType.OneToOne, nameof(OrderId))]
 		public Order Order { get; set; }
 
 		[SugarColumn(ColumnDescription = "回复人")]