using Hotline.FlowEngine.Definitions; using Hotline.Orders; using Hotline.Share.Dtos.FlowEngine; using Hotline.Share.Enums.FlowEngine; using Hotline.Share.Enums.Order; using SqlSugar; using XF.Domain.Entities; using XF.Domain.Exceptions; using XF.Domain.Extensions; using XF.Domain.Repository; namespace Hotline.FlowEngine.Workflows; public class Workflow : CreationEntity { public string DefinitionId { get; set; } #region 业务模块 [SugarColumn(IsNullable = true)] public string? ModuleId { get; set; } [SugarColumn(IsNullable = true)] public string? ModuleName { get; set; } [SugarColumn(IsNullable = true)] public string? ModuleCode { get; set; } #endregion [SugarColumn(Length = 2000)] public string Title { get; set; } /// /// 到期时间(期满时间) /// public DateTime ExpiredTime { get; set; } /// /// 办理时间限制(如:24小时、7个工作日) /// public string TimeLimit { get; set; } /// /// 流程流转到end节点的时间(配置模板的end节点前一个节点办理完成时间) /// public DateTime? CompleteTime { get; set; } /// /// 流程状态 /// public EWorkflowStatus Status { get; set; } #region 实际办理节点,部门 /// /// 实际办理节点名称(会签状态此字段保存最外层会签办理节点名称) /// [SugarColumn(IsNullable = true)] public string? ActualHandleStepName { get; set; } /// /// 到达实际办理节点时间(stepBox创建时间) /// public DateTime? ActualHandleStepTime { get; set; } /// /// 实际办理部门名称 /// [SugarColumn(IsNullable = true)] public string? ActualHandleOrgName { get; set; } /// /// 实际办理部门编码 /// [SugarColumn(IsNullable = true)] public string? ActualHandleOrgCode { get; set; } #endregion /// /// 会签类型 /// public ECounterSignType? CounterSignType { get; set; } /// /// 会签办理节点code,嵌套会签为最外层会签办理节点code(不处于会签状态则无值) /// [SugarColumn(IsNullable = true)] public string? TopCountersignStepCode { get; set; } /// /// 处理方式(直办、交办) /// [SugarColumn(DefaultValue = "10")] public EProcessType ProcessType { get; set; } = EProcessType.Zhiban; /// /// 交办时间 /// public DateTime AssignTime { get; set; } /// /// 办理意见(冗余,办理中...or 最终办理意见) /// [SugarColumn(Length = 2000)] public string Opinion { get; set; } = "办理中..."; /// /// 办理人id /// [SugarColumn(ColumnDataType = "json", IsJson = true)] public List HandlerUsers { get; set; } = new(); /// /// 办理部门code /// [SugarColumn(ColumnDataType = "json", IsJson = true)] public List HandlerOrgs { get; set; } = new(); /// /// 指派部门code(所有流经部门留痕) /// [SugarColumn(ColumnDataType = "json", IsJson = true)] public List AssignOrgCodes { get; set; } = new(); /// /// 指派办理人Id(所有流经办理人留痕) /// [SugarColumn(ColumnDataType = "json", IsJson = true)] public List AssignUserIds { get; set; } = new(); /// /// 外部业务唯一标识 /// public string ExternalId { get; set; } [Navigate(NavigateType.OneToOne, nameof(DefinitionId))] public Definition Definition { get; set; } /// /// 补充信息 /// [Navigate(NavigateType.OneToMany, nameof(WorkflowSupplement.WorkflowId))] public List Supplements { get; set; } ///// ///// 接办信息 ///// //[Navigate(NavigateType.OneToMany, nameof(WorkflowAssign.WorkflowId))] //public List Assigns { get; set; } /// /// 会签 /// [Navigate(NavigateType.OneToMany, nameof(WorkflowCountersign.WorkflowId))] public List Countersigns { get; set; } /// /// 主节点,依据流转进度动态生成或删除 /// [SugarColumn(IsIgnore = true)] public List StepBoxes { get; set; } [SugarColumn(IsIgnore = true)] public List Traces { get; set; } = new(); #region Method /// /// 流程结束 /// public void Complete() { Status = EWorkflowStatus.Completed; CompleteTime = DateTime.Now; } public void Terminate(string opinion) { Status = EWorkflowStatus.Terminated; CompleteTime = DateTime.Now; Opinion = opinion; } ///// ///// 流程进行流转 ///// //public void FLow(string currentStepName, DateTime currentStepTime, string? currentCountersignCode = null) //{ // ActualHandleStepName = currentStepName; // ActualHandleStepTime = currentStepTime; // if (!string.IsNullOrEmpty(currentCountersignCode)) // TopCountersignStepCode = currentCountersignCode; //} /// /// 更新实际办理节点、部门数据 /// public void ActualHandle( string actualHandleStepName, DateTime actualHandleStepTime, string actualHandleOrgName, string actualHandleOrgCode) { ActualHandleStepName = actualHandleStepName; ActualHandleStepTime = actualHandleStepTime; ActualHandleOrgName = actualHandleOrgName; ActualHandleOrgCode = actualHandleOrgCode; } /// /// 更新workflow中实际办理节点数据(节点,时间,部门) /// public void SetWorkflowActualHandleInfo(WorkflowStep currentStepBox, WorkflowStep nextStepBox, string handlerOrgName, string handlerOrgCode) { //1.不在会签中,未发起会签(普通处理) 2.不在会签中,发起会签(保存会签节点),3.会签中,不更新 if (IsInCountersign()) return; if (nextStepBox.StepType is EStepType.CountersignEnd or EStepType.End) return; ActualHandle(currentStepBox.Name, currentStepBox.CreationTime, handlerOrgName, handlerOrgCode); //if (isStartCountersign) // SetTopCountersignStepCode(stepBox.Code); } /// /// 检查会签是否结束 /// 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()); } /// /// 流程是否处于会签中 /// /// public bool IsInCountersign() => !string.IsNullOrEmpty(TopCountersignStepCode); /// /// 开始会签 /// public void StartCountersign(string currentCountersignCode, ECounterSignType counterSignType) { TopCountersignStepCode = currentCountersignCode; CounterSignType = counterSignType; } /// /// 结束流程会签状态 /// public void EndCountersign() => TopCountersignStepCode = null; /// /// 重置最终办理意见 /// public void ResetOption() => Opinion = "办理中..."; /// /// 重新设置办理人(删除当前待办人/部门),撤回/跳转场景,因当前办理人不是流程指定办理人 /// /// /// public void ResetHandlers(EFlowAssignType assignType, List handlerObjects) { HandlerOrgs = new List(); HandlerUsers = new List(); SetHandlers(assignType, handlerObjects); } /// /// 更新当前办理人(待办人或部门),正常流转场景 /// public void UpdateHandlers(string handlerId, string handlerOrg, EFlowAssignType assignType, List handlerObjects) { RemoveCurrentHandleGroup(handlerId, handlerOrg); SetHandlers(assignType, handlerObjects); } private void SetHandlers(EFlowAssignType assignType, List handlerObjects) { switch (assignType) { case EFlowAssignType.Org: HandlerOrgs.AddRange(handlerObjects); HandlerOrgs = HandlerOrgs.Distinct().ToList(); break; case EFlowAssignType.User: HandlerUsers.AddRange(handlerObjects); HandlerUsers = HandlerUsers.Distinct().ToList(); break; default: throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null); } } /// /// 更新当前办理人(逐级退回场景) /// /// /// /// public void UpdatePreviousHandlers(string handlerId, string handlerOrg, WorkflowStep prevStep) { RemoveCurrentHandleGroup(handlerId, handlerOrg); var groupId = Guid.NewGuid().ToString(); var handlerObjects = prevStep.Handlers.Select(d => new HandlerGroupItem { GroupId = groupId, Id = d.Id, Name = d.Name }); switch (prevStep.HandlerType) { case EHandlerType.OrgLevel: case EHandlerType.OrgType: case EHandlerType.AssignOrg: HandlerOrgs.AddRange(handlerObjects); HandlerOrgs = HandlerOrgs.Distinct().ToList(); break; case EHandlerType.Role: case EHandlerType.AssignUser: HandlerUsers.AddRange(handlerObjects); HandlerUsers = HandlerUsers.Distinct().ToList(); break; default: throw new ArgumentOutOfRangeException(); } } /// /// 当前用户是否可以办理该流程 /// /// 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)); private void RemoveCurrentHandleGroup(string handlerId, string handlerOrg) { if (string.IsNullOrEmpty(handlerId) && string.IsNullOrEmpty(handlerOrg)) throw new UserFriendlyException($"{nameof(RemoveCurrentHandleGroup)}, 办理对象参数为空"); var groupOrg = HandlerOrgs.FirstOrDefault(d => d.Id == handlerOrg); if (groupOrg != null) { HandlerOrgs.RemoveAll(d => d.GroupId == groupOrg.GroupId); } var groupUser = HandlerUsers.FirstOrDefault(d => d.Id == handlerId); if (groupUser != null) { HandlerUsers.RemoveAll(d => d.GroupId == groupUser.GroupId); } } public void Assign(EFlowAssignType type, string handler) { handler = handler.ToLower(); switch (type) { case EFlowAssignType.Org: var orgCodes = handler.GetHigherOrgCodes(true).ToList(); AssignOrgCodes.AddRange(orgCodes); AssignOrgCodes = AssignOrgCodes.Distinct().ToList(); break; case EFlowAssignType.User: if (!AssignUserIds.Exists(d => d == handler)) AssignUserIds.Add(handler); break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } } public void Assign(EFlowAssignType type, IEnumerable handlers) { handlers = handlers.Select(d => d.ToLower()); switch (type) { case EFlowAssignType.Org: var orgCodes = handlers.SelectMany(d => d.GetHigherOrgCodes(true)).ToList(); AssignOrgCodes.AddRange(orgCodes); AssignOrgCodes = AssignOrgCodes.Distinct().ToList(); break; case EFlowAssignType.User: AssignUserIds.AddRange(handlers); AssignUserIds = AssignUserIds.Distinct().ToList(); break; default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } } #endregion } /// /// 办理对象分组(以办理step分组,多人办理一个step为一组) /// public class HandlerGroupItem : IdName { public string GroupId { get; set; } }