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; }
}