xf 1 년 전
부모
커밋
1932863bb3

+ 3 - 3
src/Hotline.Api/Controllers/OrderController.cs

@@ -229,7 +229,7 @@ public class OrderController : BaseController
     {
         var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
         if (order == null) return;
-        if (order.Status != EOrderStatus.Temporary)
+        if (order.Status != EOrderStatus.WaitForAccept)
             throw UserFriendlyException.SameMessage("非草稿工单不可删除");
         await _orderRepository.RemoveAsync(order);
     }
@@ -249,7 +249,7 @@ public class OrderController : BaseController
             .FirstAsync(d => d.Id == dto.Id);
         if (order == null)
             throw UserFriendlyException.SameMessage("无效工单编号");
-        if (order.Status != EOrderStatus.Temporary || !string.IsNullOrEmpty(order.WorkflowId))
+        if (order.Status != EOrderStatus.WaitForAccept || !string.IsNullOrEmpty(order.WorkflowId))
             throw UserFriendlyException.SameMessage("工单已发起流程");
 
         if (order?.OrderComplain is not null)
@@ -273,7 +273,7 @@ public class OrderController : BaseController
         var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
         if (order == null)
             throw UserFriendlyException.SameMessage("无效工单编号");
-        if (order.Status != EOrderStatus.Temporary || !string.IsNullOrEmpty(order.WorkflowId))
+        if (order.Status != EOrderStatus.WaitForAccept || !string.IsNullOrEmpty(order.WorkflowId))
             throw UserFriendlyException.SameMessage("工单已发起流程");
 
         dto.DefinitionModuleCode = WorkflowModuleConsts.OrderManage;

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/AcceptWorkflowHandler.cs

@@ -29,7 +29,7 @@ namespace Hotline.Application.Handlers.FlowEngine
             switch (workflow.ModuleCode)
             {
                 case WorkflowModuleConsts.OrderManage:
-                    await _orderDomainService.AcceptAsync(notification.Workflow.ExternalId, cancellationToken);
+                    //await _orderDomainService.AcceptAsync(notification.Workflow.ExternalId, cancellationToken);
                     break;
             }
         }

+ 17 - 1
src/Hotline.Application/Handlers/FlowEngine/EndWorkflowHandler.cs

@@ -1,9 +1,12 @@
 using Hotline.CallCenter.Tels;
 using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WfModules;
+using Hotline.FlowEngine.Workflows;
 using Hotline.KnowledgeBase;
 using Hotline.Orders;
+using Hotline.Settings;
 using MediatR;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Application.Handlers.FlowEngine;
 
@@ -13,16 +16,22 @@ public class EndWorkflowHandler : INotificationHandler<EndWorkflowNotify>
     private readonly IKnowledgeDomainService _knowledgeDomainService;
     private readonly IOrderDomainService _orderDomainService;
     private readonly ITelDomainService _telDomainService;
+    private readonly IWorkflowDomainService _workflowDomainService;
+    private readonly ISystemOrganizeRepository _orgRepository;
 
     public EndWorkflowHandler(
         IKnowledgeDomainService knowledgeDomainService,
         IOrderDomainService orderDomainService,
-        ITelDomainService telDomainService
+        ITelDomainService telDomainService,
+        IWorkflowDomainService workflowDomainService,
+        ISystemOrganizeRepository orgRepository
         )
     {
         _knowledgeDomainService = knowledgeDomainService;
         _orderDomainService = orderDomainService;
         _telDomainService = telDomainService;
+        _workflowDomainService = workflowDomainService;
+        _orgRepository = orgRepository;
     }
 
     /// <summary>Handles a notification</summary>
@@ -45,6 +54,13 @@ public class EndWorkflowHandler : INotificationHandler<EndWorkflowNotify>
                 break;
 
             case WorkflowModuleConsts.OrderManage:
+                var levelOneOrg = workflow.ActualHandleOrgCode.GetOrgLevel();
+                var org = await _orgRepository.GetAsync(d => d.OrgCode == levelOneOrg, cancellationToken);
+                if (org is null)
+                    throw new UserFriendlyException($"无效部门编码, levelOneOrg: {levelOneOrg}", "无效部门编码");
+
+                await _workflowDomainService.UpdateOrgLevelOneAsync(workflow, org.OrgCode, org.OrgName, cancellationToken);
+
                 await _orderDomainService.ManageFlowEndAsync(workflow.ExternalId, cancellationToken);
                 break;
 

+ 4 - 4
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -54,10 +54,10 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
         switch (workflow.ModuleCode)
         {
             case WorkflowModuleConsts.OrderManage:
-                var orderDto = await _orderDomainService.ManageFlowNextAsync(
-                      notification.FlowAssignInfo, notification.IsFromCenterToOrg, notification.IsCountersignStart, notification.IsCountersignEnd,
-                      workflow.ExternalId, workflow.ActualHandleTime, workflow.ActualHandleStepName, workflow.ExpiredTime, workflow.ProcessType,
-                      cancellationToken);
+                var order = await _orderDomainService.GetOrderAsync(workflow.ExternalId, cancellationToken);
+                _mapper.Map(workflow, order);
+                var orderDto = await _orderDomainService.ManageFlowNextAsync(notification.FlowAssignInfo, order,
+                    notification.IsFromCenterToOrg, workflow.IsInCountersign(), cancellationToken);
 
                 await _capPublisher.PublishAsync(EventNames.HotlineOrderFlow, new OrderFlowDto
                 {

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/OrderFinalManageHandler.cs

@@ -29,7 +29,7 @@ namespace Hotline.Application.Handlers.FlowEngine
             switch (workflow.ModuleCode)
             {
                 case WorkflowModuleConsts.OrderManage:
-                    await _orderDomainService.FinalManageAsync(notification.Workflow.ExternalId, cancellationToken);
+                    //await _orderDomainService.FinalManageAsync(notification.Workflow.ExternalId, cancellationToken);
                     break;
             }
         }

+ 1 - 1
src/Hotline.Application/Handlers/FlowEngine/OrderRecallFinalManageHandler.cs

@@ -24,7 +24,7 @@ public class OrderRecallFinalManageHandler : INotificationHandler<OrderRecallFin
         switch (workflow.ModuleCode)
         {
             case WorkflowModuleConsts.OrderManage:
-                await _orderDomainService.RecallFinalManageAsync(notification.Workflow.ExternalId, cancellationToken);
+                //await _orderDomainService.RecallFinalManageAsync(notification.Workflow.ExternalId, cancellationToken);
                 break;
         }
 

+ 3 - 2
src/Hotline.Application/Handlers/FlowEngine/StartWorkflowHandler.cs

@@ -6,6 +6,7 @@ using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WfModules;
 using Hotline.KnowledgeBase;
 using Hotline.Orders;
+using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using MediatR;
 using Microsoft.Extensions.Logging;
@@ -49,8 +50,8 @@ namespace Hotline.Application.Handlers.FlowEngine
             {
                 case WorkflowModuleConsts.OrderManage:
                     var order = await _orderDomainService.GetOrderAsync(workflow.ExternalId, cancellationToken);
-                    _mapper.Map(workflow,order);
-                    await _orderDomainService.ManageFlowStartAsync(notification.FlowAssignInfo, notification.IsCountersignStart, order, cancellationToken);
+                    _mapper.Map(workflow, order);
+                    await _orderDomainService.ManageFlowStartAsync(notification.FlowAssignInfo, order, workflow.IsInCountersign(), cancellationToken);
                     break;
                 case WorkflowModuleConsts.KnowledgeAdd:
                 case WorkflowModuleConsts.KnowledgeUpdate:

+ 20 - 10
src/Hotline.Application/Mappers/MapperConfigs.cs

@@ -189,16 +189,26 @@ namespace Hotline.Application.Mappers
             config.ForType<Workflow, Order>()
                 .Map(d => d.WorkflowId, s => s.Id)
                 .Map(d => d.StartTime, s => s.CreationTime)
-                ;//todo
-                 //.Map(d=>d.CurrentStepTime,s=>s.)
-
-            /*
-
-             * //CurrentStepTime = currentStepTime;
-        //CurrentStepName = currentStepName;
-        //ExpiredTime = expiredTime;
-        //ActualHandleStepTime = actualHandleStepTime;
-             */
+                .Map(d => d.ExpiredTime, s => s.ExpiredTime)
+                .Map(d => d.ActualHandleStepCode, s => s.ActualHandleStepCode)
+                .Map(d => d.ActualHandleStepName, s => s.ActualHandleStepName)
+                .Map(d => d.ActualHandleStepCreateTime, s => s.ActualHandleStepCreateTime)
+                .Map(d => d.ActualHandleTime, s => s.ActualHandleTime)
+                .Map(d => d.ActualHandlerId, s => s.ActualHandlerId)
+                .Map(d => d.ActualHandlerName, s => s.ActualHandlerName)
+                .Map(d => d.ActualHandleOrgName, s => s.ActualHandleOrgName)
+                .Map(d => d.ActualHandleOrgCode, s => s.ActualHandleOrgCode)
+                .Map(d => d.ActualOpinion, s => s.ActualOpinion)
+                .Map(d => d.CurrentStepCode, s => s.CurrentStepCode)
+                .Map(d => d.CurrentStepName, s => s.CurrentStepName)
+                .Map(d => d.CurrentStepCreateTime, s => s.CurrentStepCreateTime)
+                .Map(d => d.OrgLevelOneCode, s => s.OrgLevelOneCode)
+                .Map(d => d.OrgLevelOneName, s => s.OrgLevelOneName)
+                .Map(d => d.AcceptorId, s => s.AcceptorId)
+                .Map(d => d.AcceptorName, s => s.AcceptorName)
+                .Map(d => d.ProcessType, s => s.ProcessType)
+                .IgnoreNonMapped(true)
+                ;
 
             #endregion
 

+ 0 - 4
src/Hotline.Share/Enums/FlowEngine/EWorkflowStatus.cs

@@ -4,10 +4,6 @@ public enum EWorkflowStatus
 {
     Runnable = 0,
     Suspended = 10,
-    /// <summary>
-    /// 流程上所有普通节点都办理完成则标记一下,否则处于runnable状态
-    /// </summary>
-    Marked = 15,
     Completed = 20,
     Terminated = 30,
 }

+ 19 - 20
src/Hotline.Share/Enums/Order/EOrderStatus.cs

@@ -4,18 +4,17 @@ namespace Hotline.Share.Enums.Order;
 
 public enum EOrderStatus
 {
-    //todo
     /// <summary>
-    /// 草稿
+    /// 待受理
     /// </summary>
-    [Description("草稿")]
-    Temporary = 0,
+    [Description("待受理")]
+    WaitForAccept = 0,
 
-    /// <summary>
-    /// 待签收
-    /// </summary>
-    [Description("待签收")]
-    WaitForSign = 10,
+    ///// <summary>
+    ///// 待签收
+    ///// </summary>
+    //[Description("待签收")]
+    //WaitForSign = 10,
 
     /// <summary>
     /// 办理中
@@ -29,21 +28,21 @@ public enum EOrderStatus
     [Description("会签中")]
     Countersigning = 30,
 
-    /// <summary>
-    /// 退回
-    /// </summary>
-    [Description("退回")]
-    Return = 40,
+    ///// <summary>
+    ///// 退回
+    ///// </summary>
+    //[Description("退回")]
+    //Return = 40,
 
-    /// <summary>
-    /// 办理完成(最终办结)
-    /// </summary>
-    [Description("办理完成")]
-    Completed = 50,
+    ///// <summary>
+    ///// 办理完成(实际办理部门办理完成)
+    ///// </summary>
+    //[Description("办理完成")]
+    //Completed = 50,
 
     /// <summary>
     /// 已归档
     /// </summary>
-    [Description("已归档")]
+    [Description("办理完成")]
     Filed = 60,
 }

+ 1 - 1
src/Hotline/FlowEngine/Notifications/WorkflowNotify.cs

@@ -7,7 +7,7 @@ namespace Hotline.FlowEngine.Notifications;
 
 public record WorkflowNotify(Workflow Workflow, BasicWorkflowDto Dto) : INotification;
 
-public record StartWorkflowNotify(Workflow Workflow, BasicWorkflowDto Dto, bool IsCountersignStart, FlowAssignInfo FlowAssignInfo) : WorkflowNotify(Workflow, Dto);
+public record StartWorkflowNotify(Workflow Workflow, BasicWorkflowDto Dto, FlowAssignInfo FlowAssignInfo) : WorkflowNotify(Workflow, Dto);
 
 public record NextStepNotify(Workflow Workflow, BasicWorkflowDto Dto, WorkflowTrace Trace, bool IsFromCenterToOrg, bool IsCountersignStart, bool IsCountersignEnd, FlowAssignInfo FlowAssignInfo) : WorkflowNotify(Workflow, Dto);
 

+ 5 - 0
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -77,5 +77,10 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task<(IdName, IReadOnlyList<IdName>)> GetNoVisiteOrgsAsync(string workflowId,
             CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 更新一级部门信息
+        /// </summary>
+        Task UpdateOrgLevelOneAsync(Workflow workflow, string orgCode, string orgName, CancellationToken cancellationToken);
     }
 }

+ 87 - 32
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -65,6 +65,12 @@ public class Workflow : CreationEntity
     [SugarColumn(IsNullable = true)]
     public string? ActualHandleStepName { get; set; }
 
+    /// <summary>
+    /// 实际办理节点id
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? ActualHandleStepId { get; set; }
+
     /// <summary>
     /// 到达实际办理节点时间(stepBox创建时间)
     /// </summary>
@@ -121,6 +127,12 @@ public class Workflow : CreationEntity
     [SugarColumn(IsNullable = true)]
     public string? CurrentStepName { get; set; }
 
+    /// <summary>
+    /// 当前节点id
+    /// </summary>
+    [SugarColumn(IsNullable = true)]
+    public string? CurrentStepId { get; set; }
+
     /// <summary>
     /// 到达当前节点时间(stepBox创建时间)
     /// </summary>
@@ -258,6 +270,8 @@ public class Workflow : CreationEntity
     {
         Status = EWorkflowStatus.Completed;
         CompleteTime = DateTime.Now;
+
+        UpdateActualOption();
     }
 
     public void Terminate(string opinion)
@@ -267,45 +281,72 @@ public class Workflow : CreationEntity
         ActualOpinion = opinion;
     }
 
-    ///// <summary>
-    ///// 流程进行流转
-    ///// </summary>
-    //public void FLow(string currentStepName, DateTime currentStepTime, string? currentCountersignCode = null)
-    //{
-    //    ActualHandleStepName = currentStepName;
-    //    ActualHandleStepTime = currentStepTime;
-    //    if (!string.IsNullOrEmpty(currentCountersignCode))
-    //        TopCountersignStepCode = currentCountersignCode;
-    //}
-
     /// <summary>
     /// 更新实际办理节点、部门数据
     /// </summary>
-    public void ActualHandle(
-        string actualHandleStepName, DateTime actualHandleTime,
-        string actualHandleOrgName, string actualHandleOrgCode)
+    private void ActualHandle(
+        WorkflowStep currentStep,
+        string actualHandlerId,
+        string actualHandlerName,
+        string actualHandleOrgCode,
+        string actualHandleOrgName)
     {
-        ActualHandleStepName = actualHandleStepName;
-        ActualHandleTime = actualHandleTime;
-        ActualHandleOrgName = actualHandleOrgName;
+        ActualHandleStepCode = currentStep.Code;
+        ActualHandleStepName = currentStep.Name;
+        ActualHandleStepId = currentStep.Id;
+        ActualHandleStepCreateTime = currentStep.CreationTime;
+        ActualHandleTime = DateTime.Now;
+        ActualHandlerId = actualHandlerId;
+        ActualHandlerName = actualHandlerName;
         ActualHandleOrgCode = actualHandleOrgCode;
+        ActualHandleOrgName = actualHandleOrgName;
+    }
+
+    /// <summary>
+    /// 归档时为最终办理意见赋值
+    /// </summary>
+    public void UpdateActualOption()
+    {
+        var stepBox = StepBoxes.FirstOrDefault(d => d.Code == ActualHandleStepCode);
+        if (stepBox is null)
+            throw new UserFriendlyException($"未查询到对应实际办理节点,workflowId: {Id}");
+        var step = stepBox.Steps.FirstOrDefault(d => d.Id == ActualHandleStepId);
+        if (step is null)
+            throw new UserFriendlyException($"未查询到对应实际办理子节点,workflowId: {Id}");
+        ActualOpinion = step.Opinion;
     }
 
     /// <summary>
     /// 更新workflow中实际办理节点数据(节点,时间,部门)
     /// </summary>
-    public void SetWorkflowActualHandleInfo(WorkflowStep currentStepBox, WorkflowStep nextStepBox, string handlerOrgName, string handlerOrgCode)
+    public void UpdateWorkflowActualHandleInfo(WorkflowStep currentStepBox, WorkflowStep currentStep, string actualHandlerId,
+        string actualHandlerName, string handlerOrgCode, string handlerOrgName)
     {
-        //1.不在会签中,未发起会签(普通处理) 2.不在会签中,发起会签(保存会签节点),3.会签中,不更新
-        if (IsInCountersign()) return;
+        //a.会签中分为1.之前无会签,当前节点发起会签,记录当前节点 2. 之前有会签,不更新  b.非会签中,记录当前节点
+        if (IsInCountersign() && !currentStep.HasStartedCountersign) return;
 
-        if (nextStepBox.StepType is EStepType.CountersignEnd or EStepType.End) return;
+        if (currentStepBox.StepType is EStepType.CountersignEnd or EStepType.End) return;
 
-        ActualHandle(currentStepBox.Name, currentStepBox.CreationTime, handlerOrgName, handlerOrgCode);
+        ActualHandle(currentStep, actualHandlerId, actualHandlerName, handlerOrgCode, handlerOrgName);
+    }
 
+    /// <summary>
+    /// 更新当前办理节点信息
+    /// </summary>
+    public void UpdateWorkflowCurrentStepInfo(bool isStartCountersign, WorkflowStep currentStep, WorkflowStep nextStep)
+    {
+        //非会签:指当前被指派节点,会签:会签发起节点
+        if (IsInCountersign()) return;
+
+        CurrentHandle(isStartCountersign ? currentStep : nextStep);
+    }
 
-        //if (isStartCountersign)
-        //    SetTopCountersignStepCode(stepBox.Code);
+    public void CurrentHandle(WorkflowStep step)
+    {
+        CurrentStepCode = step.Code;
+        CurrentStepName = step.Name;
+        CurrentStepId = step.Id;
+        CurrentStepCreateTime = step.CreationTime;
     }
 
     /// <summary>
@@ -313,15 +354,9 @@ public class Workflow : CreationEntity
     /// </summary>
     public bool CheckIfCountersignOver()
     {
-        //var countersignStepBox = StepBoxes.First(d => d.Code == TopCountersignStepCode);
-        //var isCountersignOver = countersignStepBox.Steps.All(d =>
-        //    d.Status is EWorkflowStepStatus.Completed &&
-        //    (!d.HasStartCountersign || d.IsCountersignComplete.GetValueOrDefault()));
-        //return isCountersignOver;
         return Countersigns.All(d => d.IsCompleted());
     }
 
-
     /// <summary>
     /// 流程是否处于会签中
     /// </summary>
@@ -427,8 +462,8 @@ public class Workflow : CreationEntity
     /// </summary>
     /// <returns></returns>
     public bool CanHandle(string userId, string orgCode) =>
-        Status is EWorkflowStatus.Runnable or EWorkflowStatus.Marked
-        && (HandlerUsers.Any(d => d.Id == userId) || HandlerOrgs.Any(d => d.Id == orgCode));
+        Status is EWorkflowStatus.Runnable &&
+        (HandlerUsers.Any(d => d.Id == userId) || HandlerOrgs.Any(d => d.Id == orgCode));
 
     private void RemoveCurrentHandleGroup(string handlerId, string handlerOrg)
     {
@@ -485,7 +520,27 @@ public class Workflow : CreationEntity
         }
     }
 
+    /// <summary>
+    /// 更新受理人信息
+    /// </summary>
+    public void UpdateAcceptor(string userId, string userName)
+    {
+        AcceptorId = userId;
+        AcceptorName = userName;
+    }
+
+    /// <summary>
+    /// 更新一级部门信息
+    /// </summary>
+    public void UpdateOrgLevelOne(string orgCode, string orgName)
+    {
+        OrgLevelOneCode = orgCode;
+        OrgLevelOneName = orgName;
+    }
+
     #endregion
+
+
 }
 
 /// <summary>

+ 52 - 55
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -1,6 +1,7 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Notifications;
 using Hotline.FlowEngine.WfModules;
+using Hotline.Settings;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
@@ -92,7 +93,7 @@ namespace Hotline.FlowEngine.Workflows
             //创建开始节点
             var (startStepBox, startStep, firstStepBox) = await CreateStartAndFirstStepAsync(workflow, dto, cancellationToken);
 
-            //todo 1.创建开始节点trace 2.创建firstStep(开始节点的下一个节点),firstStep为已办理 3.创建sec节点
+            //1.创建开始节点trace 2.创建firstStep(开始节点的下一个节点),办理firstStep 3.创建sec节点
             //办理firstStep
             var firstStep = firstStepBox.Steps.First();
             var counterSignType = GetCounterSignType(firstStep.BusinessProperty);
@@ -110,14 +111,20 @@ namespace Hotline.FlowEngine.Workflows
                 EWorkflowStepStatus.Created, firstStepBox, firstStep, EWorkflowTraceStatus.Normal,
                 workflow.ExpiredTime, cancellationToken);
 
-            //更新实际办理节点名称、时间
-            workflow.SetWorkflowActualHandleInfo(firstStepBox, secondStepBox, _sessionContext.OrgName, _sessionContext.RequiredOrgCode);
+            //更新实际办理节点信息
+            workflow.UpdateWorkflowActualHandleInfo(firstStepBox, firstStep,
+                _sessionContext.RequiredUserId, _sessionContext.UserName,
+                _sessionContext.OrgName, _sessionContext.RequiredOrgCode);
+
+            //更新当前办理节点信息
+            workflow.UpdateWorkflowCurrentStepInfo(dto.IsStartCountersign, firstStep, secondStepBox.Steps.First());
 
             //发起会签时记录顶层会签节点
             if (dto.IsStartCountersign && !workflow.IsInCountersign())
                 workflow.StartCountersign(firstStepBox.Code, counterSignType);
 
-
+            //更新受理人信息
+            workflow.UpdateAcceptor(_sessionContext.RequiredUserId, _sessionContext.UserName);
 
             workflow.UpdateHandlers(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode,
             flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
@@ -128,7 +135,7 @@ namespace Hotline.FlowEngine.Workflows
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
             //publish
-            await _mediator.Publish(new StartWorkflowNotify(workflow, dto, dto.IsStartCountersign, flowAssignInfo), cancellationToken);
+            await _mediator.Publish(new StartWorkflowNotify(workflow, dto, flowAssignInfo), cancellationToken);
 
         }
 
@@ -193,7 +200,7 @@ namespace Hotline.FlowEngine.Workflows
         {
             if (!workflow.CanHandle(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode)) return;
             //工单完成以后查看的场景
-            if (workflow.Status != EWorkflowStatus.Runnable && workflow.Status != EWorkflowStatus.Marked) return;
+            if (workflow.Status != EWorkflowStatus.Runnable) return;
 
             var (currentStepBox, currentStep) = GetUnCompleteStepOrDefault(workflow.StepBoxes, orgCode, userId);
             if (currentStep is null) return;
@@ -316,6 +323,7 @@ namespace Hotline.FlowEngine.Workflows
                 await NextTraceAsync(workflow, dto, endStep, cancellationToken);
 
                 workflow.Complete();
+
                 await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
                 await _mediator.Publish(new EndWorkflowNotify(workflow), cancellationToken);
@@ -331,25 +339,25 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.CenterToOrgTime = DateTime.Now;
             }
 
-            //最终办理意见与时间处理(解决工单业务需求,如果流程配置普通节点后未配置汇总节点则不会运行到此处)
-            var normalSteps = workflow.StepBoxes
-                .Where(d => d.StepType is EStepType.Normal)
-                .SelectMany(d => d.Steps);
-            var isAllCompleted = normalSteps.All(d => d.Status is EWorkflowStepStatus.Completed);
-            if (isAllCompleted)
-            {
-                //最终办理
-                workflow.ActualOpinion = dto.Opinion;
-                workflow.Status = EWorkflowStatus.Marked;
-                await _mediator.Publish(new OrderFinalManageNotify(workflow), cancellationToken);
-            }
-            else if (workflow.Status is EWorkflowStatus.Marked)
-            {
-                //汇总以后又重新指派到非汇总节点办理
-                workflow.ResetOption();
-                workflow.Status = EWorkflowStatus.Runnable;
-                await _mediator.Publish(new OrderRecallFinalManageNotify(workflow), cancellationToken);
-            }
+            ////最终办理意见与时间处理(解决工单业务需求,如果流程配置普通节点后未配置汇总节点则不会运行到此处)
+            //var normalSteps = workflow.StepBoxes
+            //    .Where(d => d.StepType is EStepType.Normal)
+            //    .SelectMany(d => d.Steps);
+            //var isAllCompleted = normalSteps.All(d => d.Status is EWorkflowStepStatus.Completed);
+            //if (isAllCompleted)
+            //{
+            //    //最终办理
+            //    workflow.ActualOpinion = dto.Opinion;
+            //    workflow.Status = EWorkflowStatus.Marked;
+            //    await _mediator.Publish(new OrderFinalManageNotify(workflow), cancellationToken);
+            //}
+            //else if (workflow.Status is EWorkflowStatus.Marked)
+            //{
+            //    //汇总以后又重新指派到非汇总节点办理
+            //    workflow.ResetOption();
+            //    workflow.Status = EWorkflowStatus.Runnable;
+            //    await _mediator.Publish(new OrderRecallFinalManageNotify(workflow), cancellationToken);
+            //}
 
             //创建下一节点(会签汇总节点不重复创建)
             var nextStepBox = await CreateStepAsync(isStartCountersign, workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Created,
@@ -386,7 +394,12 @@ namespace Hotline.FlowEngine.Workflows
             }
 
             //更新实际办理节点名称、时间
-            workflow.SetWorkflowActualHandleInfo(currentStepBox, nextStepBox, _sessionContext.OrgName, _sessionContext.RequiredOrgCode);
+            workflow.UpdateWorkflowActualHandleInfo(currentStepBox, currentStep,
+                _sessionContext.RequiredUserId, _sessionContext.UserName,
+                _sessionContext.RequiredOrgCode, _sessionContext.OrgName);
+
+            //更新当前办理节点信息
+            workflow.UpdateWorkflowCurrentStepInfo(dto.IsStartCountersign, currentStep, nextStepBox.Steps.First());
 
             //发起会签时记录顶层会签节点
             if (isStartCountersign && !workflow.IsInCountersign())
@@ -448,7 +461,7 @@ namespace Hotline.FlowEngine.Workflows
             //orgToCenter会触发重新计算期满时间,1.无需审核按当前时间进行计算 2.需审核按审核通过时间计算
             var isOrgToCenter = CheckIfFlowFromOrgToCenter(currentStepBox, prevStepBox);
             if (isOrgToCenter)
-                workflow.ExpiredTime = CalculateExpiredTime("");
+                workflow.ExpiredTime = CalculateExpiredTime("");//todo
 
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
@@ -620,7 +633,16 @@ namespace Hotline.FlowEngine.Workflows
             return (new IdName(workflow.ActualHandleOrgCode, workflow.ActualHandleOrgName), items);
         }
 
-        #region private
+        /// <summary>
+        /// 更新一级部门信息
+        /// </summary>
+        public async Task UpdateOrgLevelOneAsync(Workflow workflow, string orgCode, string orgName, CancellationToken cancellationToken)
+        {
+            workflow.UpdateOrgLevelOne(orgCode, orgName);
+            await _workflowRepository.UpdateAsync(workflow, cancellationToken);
+        }
+
+        #region private method
 
         /// <summary>
         /// 判断会签类型(中心会签或部门会签)
@@ -810,7 +832,7 @@ namespace Hotline.FlowEngine.Workflows
             {
                 nextStep.SetAssigned();
             }
-
+            
             await _workflowStepRepository.UpdateRangeAsync(nextSteps, cancellationToken);
         }
 
@@ -1003,7 +1025,7 @@ namespace Hotline.FlowEngine.Workflows
 
         private static void CheckWhetherRunnable(EWorkflowStatus status)
         {
-            if (status != EWorkflowStatus.Runnable && status != EWorkflowStatus.Marked)
+            if (status != EWorkflowStatus.Runnable)
                 throw UserFriendlyException.SameMessage("当前流程状态不可继续流转");
         }
 
@@ -1013,31 +1035,6 @@ namespace Hotline.FlowEngine.Workflows
                 throw UserFriendlyException.SameMessage("无办理权限");
         }
 
-        /// <summary>
-        /// 创建开始节点(保存开始流程的办理意见,对应definition的start节点)
-        /// </summary>
-        //private async Task<(WorkflowStep stepBox, WorkflowStep step)> CreateStartStepAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken)
-        //{
-        //    if (workflow.StepBoxes.Any())
-        //        throw UserFriendlyException.SameMessage("无法重复创建开始节点");
-
-        //    var startStepDefinition = workflow.Definition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
-        //    if (startStepDefinition == null)
-        //        throw new UserFriendlyException($"模板未配置开始节点, defineCode: {workflow.Definition.Code}", "模板未配置开始节点");
-
-        //    var stepBox = CreateStepBox(workflow.Id, startStepDefinition, string.Empty);
-        //    await _workflowStepRepository.AddAsync(stepBox, cancellationToken);
-
-        //    //start节点的办理人分类默认为用户,即为当前发起流程的操作员
-        //    var handler = new IdName { Id = _sessionContext.RequiredUserId, Name = _sessionContext.UserName };
-        //    var step = await CreateStartSubStepAsync(handler, dto, stepBox, cancellationToken);
-
-        //    //开始节点trace
-        //    await CreateTraceAsync(workflow, step, cancellationToken: cancellationToken);
-
-        //    return (stepBox, step);
-        //}
-
         private async Task<(WorkflowStep startStepBox, WorkflowStep startStep, WorkflowStep firstStepBox)> CreateStartAndFirstStepAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken)
         {
             if (workflow.StepBoxes.Any())

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

@@ -29,13 +29,12 @@ namespace Hotline.Orders
         /// <summary>
         /// 工单办理流程开始(流程开始后触发)
         /// </summary>
-        Task ManageFlowStartAsync(FlowAssignInfo assignInfo, bool isCountersignStart, Order order, CancellationToken cancellationToken);
+        Task ManageFlowStartAsync(FlowAssignInfo assignInfo, Order order, bool isInCountersign, CancellationToken cancellationToken);
 
         /// <summary>
         /// 工单办理流程流转(每个节点办理都会触发)
         /// </summary>
-        Task<OrderDto> ManageFlowNextAsync(FlowAssignInfo assignInfo, bool isFromCenterToOrg, bool isCountersignStart, bool isCountersignEnd,
-            string? orderId, DateTime? currentStepTime, string? currentStepName, DateTime expiredTime, EProcessType processType, CancellationToken cancellationToken);
+        Task<OrderDto> ManageFlowNextAsync(FlowAssignInfo assignInfo, Order order, bool isFromCenterToOrg, bool isInCountersign, CancellationToken cancellationToken);
 
         /// <summary>
         /// 工单最终办理(此完结流程并未结束)
@@ -66,12 +65,5 @@ namespace Hotline.Orders
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         Task ManageFlowJumpAsync(string workflowId, FlowAssignInfo assignInfo, CancellationToken cancellationToken);
-
-        /// <summary>
-        /// 工单办理流程从中心流转至部门
-        /// </summary>
-        /// <param name="workflowId"></param>
-        /// <returns></returns>
-        Task FlowFromCenterToOrgAsync(string workflowId, CancellationToken cancellationToken);
     }
 }

+ 50 - 86
src/Hotline/Orders/Order.cs

@@ -18,11 +18,11 @@ namespace Hotline.Orders
         /// <summary>
         /// 来源渠道(电话、网站、APP等)
         /// </summary>
-        [SugarColumn(DefaultValue = "QT")]
+        [SugarColumn(DefaultValue = "其他")]
         public string SourceChannel { get; set; }
 
-        [SugarColumn(DefaultValue = "其他")]
-        public string SourceChannelText { get; set; }
+        [SugarColumn(DefaultValue = "QT")]
+        public string SourceChannelCode { get; set; }
 
         /// <summary>
         /// 渠道为电话时,此字段存在(Call.Id)
@@ -165,9 +165,9 @@ namespace Hotline.Orders
         /// <summary>
         /// 重复工单
         /// </summary>
+        //todo 1vN
         [SugarColumn(ColumnDescription = "重复工单Id", IsNullable = true)]
         public string? DuplicateId { get; set; }
-        //todo 1vN
         [SugarColumn(ColumnDescription = "重复工单标题", IsNullable = true)]
         public string? DuplicateTitle { get; set; }
 
@@ -201,26 +201,6 @@ namespace Hotline.Orders
         /// </summary>
         public EOrderStatus Status { get; set; }
 
-        /// <summary>
-        /// 工单开始时间(受理/接办时间=流程开启时间)
-        /// </summary>
-        public DateTime? StartTime { get; set; }
-
-        /// <summary>
-        /// 过期时间
-        /// </summary>
-        public DateTime? ExpiredTime { get; set; }
-
-        /// <summary>
-        /// 工单办理完成时间,实际办理部门的办理时间(汇总节点的上一个非汇总节点办理完成时间,开启会签时清空该字段)
-        /// </summary>
-        public DateTime? CompleteTime { get; set; }
-
-        /// <summary>
-        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
-        /// </summary>
-        public DateTime? FiledTime { get; set; }
-
         /// <summary>
         /// 过期状态 //todo 延迟消息更新此字段
         /// </summary>
@@ -278,6 +258,26 @@ namespace Hotline.Orders
 
         #region 流程信息
 
+        /// <summary>
+        /// 工单开始时间(受理/接办时间=流程开启时间)
+        /// </summary>
+        public DateTime? StartTime { get; set; }
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public DateTime? ExpiredTime { get; set; }
+
+        ///// <summary>
+        ///// 工单办理完成时间,实际办理部门的办理时间(汇总节点的上一个非汇总节点办理完成时间,开启会签时清空该字段)
+        ///// </summary>
+        //public DateTime? CompleteTime { get; set; }
+
+        /// <summary>
+        /// 归档时间(暂为流程结束时间,因流程结束自动归档)
+        /// </summary>
+        public DateTime? FiledTime { get; set; }
+
         #region 实际办理信息(节点,部门,意见)
 
         /// <summary>
@@ -441,17 +441,20 @@ namespace Hotline.Orders
             EmployeeId = employeeId;
             if (!string.IsNullOrEmpty(Contact))
                 ContactMask = Contact.MaskPhoneNumber();
-            Status = EOrderStatus.Temporary;
+            Status = EOrderStatus.WaitForAccept;
             ExpiredStatus = EExpiredStatus.Normal;
         }
 
         /// <summary>
         /// 开始工单办理流程
         /// </summary>
-        public void StartManageFlow()
-        {
-            Status = EOrderStatus.WaitForSign;
-        }
+        public void StartManageFlow() => Status = EOrderStatus.Handling;
+
+        /// <summary>
+        /// 更新工单办理中状态
+        /// </summary>
+        public void UpdateHandlingStatus(bool isInCountersign) =>
+            Status = isInCountersign ? EOrderStatus.Countersigning : EOrderStatus.Handling;
 
         /// <summary>
         /// 接办
@@ -462,59 +465,21 @@ namespace Hotline.Orders
             Status = EOrderStatus.Handling;
         }
 
-        /// <summary>
-        /// 工单办理流程流转(每次办理都会调用该方法)
-        /// </summary>
-        public void ManageFlow(
-            bool isCountersignStart,
-            bool isCountersignEnd
-            //DateTime? currentStepTime,
-            //string? currentStepName,
-            //DateTime expiredTime,
-            //DateTime? actualHandleStepTime, 
-            //string? actualHandleOrgName, 
-            //string? actualHandleOrgCode, 
-            //string actualOpinion
-            )
-        {
-            if (Status is EOrderStatus.Countersigning && !isCountersignEnd) return;
-
-            //1.如果order未处于会签中,则判断是否发起会签(isstartCountersign) 2.如果处于会签中,则判断会签是否结束(isCountersignEnd)
-            if (Status is EOrderStatus.Countersigning && isCountersignEnd)
-            {
-                Status = EOrderStatus.WaitForSign;
-            }
-            else if (Status is EOrderStatus.Handling && isCountersignStart)
-            {
-                Status = EOrderStatus.Countersigning;
-            }
-            else
-            {
-                Status = EOrderStatus.WaitForSign;
-            }
-            //CurrentStepTime = currentStepTime;
-            //CurrentStepName = currentStepName;
-            //ExpiredTime = expiredTime;
-            //ActualHandleStepTime = actualHandleStepTime;
-        }
+        ///// <summary>
+        ///// 最终办理
+        ///// </summary>
+        //public void FinalManage()
+        //{
+        //    Status = EOrderStatus.Completed;
+        //}
 
-        /// <summary>
-        /// 最终办理
-        /// </summary>
-        public void FinalManage()
-        {
-            Status = EOrderStatus.Completed;
-            CompleteTime = DateTime.Now;
-        }
-
-        /// <summary>
-        /// 撤回最终办理
-        /// </summary>
-        public void RecallFinalManage()
-        {
-            Status = EOrderStatus.WaitForSign;
-            CompleteTime = null;
-        }
+        ///// <summary>
+        ///// 撤回最终办理
+        ///// </summary>
+        //public void RecallFinalManage()
+        //{
+        //    Status = EOrderStatus.WaitForSign;
+        //}
 
         /// <summary>
         /// 归档
@@ -525,11 +490,10 @@ namespace Hotline.Orders
             FiledTime = DateTime.Now;
         }
 
-        public void Jump()
-        {
-            Status = EOrderStatus.WaitForSign;
-            CompleteTime = null;
-        }
+        //public void Jump()
+        //{
+        //    Status = EOrderStatus.WaitForSign;
+        //}
 
         /// <summary>
         /// 工单从中心派往部门办理

+ 9 - 37
src/Hotline/Orders/OrderDomainService.cs

@@ -82,16 +82,15 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     /// <summary>
     /// 工单办理流程开始(流程开始后触发)
     /// </summary>
-    public async Task ManageFlowStartAsync(FlowAssignInfo assignInfo, bool isCountersignStart, Order order, CancellationToken cancellationToken)
+    public async Task ManageFlowStartAsync(FlowAssignInfo assignInfo, Order order, bool isInCountersign, CancellationToken cancellationToken)
     {
         //var order = await GetOrderAsync(orderId, cancellationToken);
         CheckOrderIfFiled(order);
-        
+
         //更新指派信息
         order.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlers());
 
-        //更新流转信息
-        order.ManageFlow(isCountersignStart, false);
+        order.UpdateHandlingStatus(isInCountersign);
 
         await _orderRepository.UpdateAsync(order, cancellationToken);
 
@@ -102,22 +101,15 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     /// <summary>
     /// 工单办理(每个节点都会触发)
     /// </summary>
-    public async Task<OrderDto> ManageFlowNextAsync(FlowAssignInfo assignInfo,
-        bool isFromCenterToOrg, bool isCountersignStart, bool isCountersignEnd,
-        string? orderId, DateTime? currentStepTime, string? currentStepName,
-        DateTime expiredTime, EProcessType processType,
-        CancellationToken cancellationToken)
+    public async Task<OrderDto> ManageFlowNextAsync(FlowAssignInfo assignInfo, Order order, bool isFromCenterToOrg, bool isInCountersign, CancellationToken cancellationToken)
     {
-        var order = await GetOrderAsync(orderId, cancellationToken);
+        //var order = await GetOrderAsync(orderId, cancellationToken);
         CheckOrderIfFiled(order);
 
         //更新指派信息
         order.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlers());
 
-        //更新流转信息
-        //todo
-        //order.ManageFlow(isCountersignStart, isCountersignEnd, currentStepTime, currentStepName, expiredTime);
-        order.ProcessType = processType;
+        order.UpdateHandlingStatus(isInCountersign);
 
         await _orderRepository.UpdateAsync(order, cancellationToken);
 
@@ -143,7 +135,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     {
         var order = await GetOrderAsync(orderId, cancellationToken);
         CheckOrderIfFiled(order);
-        order.FinalManage();
+        //order.FinalManage();
         await _orderRepository.UpdateAsync(order, cancellationToken);
     }
 
@@ -155,7 +147,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
     {
         var order = await GetOrderAsync(orderId, cancellationToken);
         CheckOrderIfFiled(order);
-        order.RecallFinalManage();
+        //order.RecallFinalManage();
         await _orderRepository.UpdateAsync(order, cancellationToken);
     }
 
@@ -187,31 +179,11 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
 
         order.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlers());
 
-        order.Jump();
+        //order.Jump();
 
         await _orderRepository.UpdateAsync(order, cancellationToken);
     }
 
-    /// <summary>
-    /// 工单办理流程从中心流转至部门
-    /// </summary>
-    /// <param name="workflowId"></param>
-    /// <returns></returns>
-    public async Task FlowFromCenterToOrgAsync(string workflowId, CancellationToken cancellationToken)
-    {
-        var order = await GetOrderByFlowIdAsync(workflowId, cancellationToken);
-        CheckOrderIfFiled(order);
-
-        if (order.ProcessType == EProcessType.Zhiban)
-        {
-            order.FlowFromCenterToOrg();
-            await _orderRepository.UpdateAsync(order, cancellationToken);
-
-            await _capPublisher.PublishAsync(EventNames.HotlineOrderCenterToOrg, _mapper.Map<OrderDto>(order),
-                cancellationToken: cancellationToken);
-        }
-    }
-
     public async Task<Order> GetOrderAsync(string? orderId, CancellationToken cancellationToken)
     {
         if (string.IsNullOrEmpty(orderId))

+ 36 - 7
src/Hotline/Settings/SystemOrganize.cs

@@ -1,8 +1,6 @@
-
+using Hotline.SeedData;
 using SqlSugar;
 using System.ComponentModel;
-using System.Reflection.Metadata;
-using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
@@ -75,10 +73,41 @@ public class SystemOrganize : CreationEntity
     public List<SystemOrganize> Children { get; set; }
 
 
-    public void InitOrgLevel()
+    public void InitOrgLevel() => OrgLevel = OrgCode.CalcOrgLevel();
+}
+
+public static class OrgExtensions
+{
+    public static int CalcOrgLevel(this string orgCode)
     {
-        if (OrgCode.Length % 3 != 0)
+        if (orgCode.Length % 3 != 0)
             throw new UserFriendlyException("非法部门Code");
-        OrgLevel = (OrgCode.Length / 3) - 1;
+        return (orgCode.Length / 3) - 1;
+    }
+
+    public static bool CheckIfOrgLevelIs(this string orgCode, int orgLevel)
+    {
+        //中心算做一级部门
+        if (orgLevel == 1 && orgCode == OrgSeedData.CallCenterCode)
+            return true;
+
+        var level = orgCode.CalcOrgLevel();
+        return level == orgLevel;
+    }
+
+    /// <summary>
+    /// 根据orgCode获取该部门所属等级的部门
+    /// </summary>
+    /// <param name="orgCode"></param>
+    /// <param name="orgLevel"></param>
+    /// <returns></returns>
+    public static string GetOrgLevel(this string orgCode, int orgLevel = 1)
+    {
+        if (string.IsNullOrEmpty(orgCode))
+            throw UserFriendlyException.SameMessage("无效部门编码");
+        //中心算做一级部门
+        if (orgLevel == 1 && orgCode == OrgSeedData.CallCenterCode) return orgCode;
+
+        return orgCode.Substring(0, 3 * (orgLevel + 1));
     }
-}
+}