Workflow.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using Hotline.FlowEngine.Definitions;
  2. using Hotline.Share.Enums.FlowEngine;
  3. using SqlSugar;
  4. using XF.Domain.Entities;
  5. using XF.Domain.Repository;
  6. namespace Hotline.FlowEngine.Workflows;
  7. public class Workflow : CreationEntity
  8. {
  9. public string DefinitionId { get; set; }
  10. [SugarColumn(IsNullable = true)]
  11. public string? ModuleId { get; set; }
  12. /// <summary>
  13. /// 业务模块名称
  14. /// </summary>
  15. [SugarColumn(IsNullable = true)]
  16. public string? ModuleName { get; set; }
  17. [SugarColumn(IsNullable = true)]
  18. public string? ModuleCode { get; set; }
  19. [SugarColumn(Length = 2000)]
  20. public string Title { get; set; }
  21. /// <summary>
  22. /// 到期时间
  23. /// </summary>
  24. public DateTime ExpiredTime { get; set; }
  25. /// <summary>
  26. /// 流程流转到end节点的时间(配置模板的end节点前一个节点办理完成时间)
  27. /// </summary>
  28. public DateTime? CompleteTime { get; set; }
  29. public EWorkflowStatus Status { get; set; }
  30. /// <summary>
  31. /// 当前办理节点名称(会签状态此字段保存最外层会签办理节点名称)
  32. /// </summary>
  33. [SugarColumn(IsNullable = true)]
  34. public string? CurrentStepName { get; set; }
  35. /// <summary>
  36. /// 到达当前办理节点时间(stepBox创建时间)
  37. /// </summary>
  38. public DateTime? CurrentStepTime { get; set; }
  39. /// <summary>
  40. /// 会签办理节点code,嵌套会签为最外层会签办理节点code(不处于会签状态则无值)
  41. /// </summary>
  42. [SugarColumn(IsNullable = true)]
  43. public string? TopCountersignStepCode { get; set; }
  44. /// <summary>
  45. /// 中心直办件
  46. /// </summary>
  47. public bool IsStraight { get; set; } = true;
  48. /// <summary>
  49. /// 交办时间
  50. /// </summary>
  51. public DateTime AssignTime { get; set; }
  52. /// <summary>
  53. /// 办理时间限制(如:24小时、7个工作日)
  54. /// </summary>
  55. public string TimeLimit { get; set; }
  56. /// <summary>
  57. /// 办理意见(冗余,办理中...or 最终办理意见)
  58. /// </summary>
  59. [SugarColumn(Length = 2000)]
  60. public string Opinion { get; set; } = "办理中...";
  61. /// <summary>
  62. /// 办理人id
  63. /// </summary>
  64. [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
  65. public List<string> HandlerUsers { get; set; } = new();
  66. /// <summary>
  67. /// 办理部门code
  68. /// </summary>
  69. [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
  70. public List<string> HandlerOrgs { get; set; } = new();
  71. ///// <summary>
  72. ///// 外部业务唯一标识
  73. ///// </summary>
  74. //public string ExternalId { get; set; }
  75. [Navigate(NavigateType.OneToOne, nameof(DefinitionId))]
  76. public Definition Definition { get; set; }
  77. /// <summary>
  78. /// 补充信息
  79. /// </summary>
  80. [Navigate(NavigateType.OneToMany, nameof(WorkflowSupplement.WorkflowId))]
  81. public List<WorkflowSupplement> Supplements { get; set; }
  82. /// <summary>
  83. /// 接办信息
  84. /// </summary>
  85. [Navigate(NavigateType.OneToMany, nameof(WorkflowAssign.WorkflowId))]
  86. public List<WorkflowAssign> Assigns { get; set; }
  87. /// <summary>
  88. /// 会签
  89. /// </summary>
  90. [Navigate(NavigateType.OneToMany, nameof(WorkflowCountersign.WorkflowId))]
  91. public List<WorkflowCountersign> Countersigns { get; set; }
  92. /// <summary>
  93. /// 主节点,依据流转进度动态生成或删除
  94. /// </summary>
  95. [SugarColumn(IsIgnore = true)]
  96. public List<WorkflowStep> StepBoxes { get; set; }
  97. [SugarColumn(IsIgnore = true)]
  98. public List<WorkflowTrace> Traces { get; set; } = new();
  99. #region Mehod
  100. /// <summary>
  101. /// 流程结束
  102. /// </summary>
  103. public void Complete()
  104. {
  105. Status = EWorkflowStatus.Completed;
  106. CompleteTime = DateTime.Now;
  107. }
  108. public void Terminate()
  109. {
  110. Status = EWorkflowStatus.Terminated;
  111. CompleteTime = DateTime.Now;
  112. }
  113. /// <summary>
  114. /// 流程进行流转
  115. /// </summary>
  116. public void FLow(string currentStepName, DateTime currentStepTime, string? currentCountersignCode = null)
  117. {
  118. CurrentStepName = currentStepName;
  119. CurrentStepTime = currentStepTime;
  120. if (!string.IsNullOrEmpty(currentCountersignCode))
  121. TopCountersignStepCode = currentCountersignCode;
  122. }
  123. /// <summary>
  124. /// 检查会签是否结束
  125. /// </summary>
  126. public bool CheckIfCountersignOver()
  127. {
  128. //var countersignStepBox = StepBoxes.First(d => d.Code == TopCountersignStepCode);
  129. //var isCountersignOver = countersignStepBox.Steps.All(d =>
  130. // d.Status is EWorkflowStepStatus.Completed &&
  131. // (!d.HasStartCountersign || d.IsCountersignComplete.GetValueOrDefault()));
  132. //return isCountersignOver;
  133. return Countersigns.All(d => d.IsCompleted());
  134. }
  135. public void EndCountersign() => TopCountersignStepCode = null;
  136. /// <summary>
  137. /// 更新workflow中当前停留节点,时间和会签开始节点code
  138. /// </summary>
  139. /// <param name="isStartCountersign"></param>
  140. /// <param name="stepBox"></param>
  141. public void SetWorkflowCurrentStepInfo(bool isStartCountersign, WorkflowStep stepBox)
  142. {
  143. //1.不在会签中,未发起会签(普通处理) 2.不在会签中,发起会签(保存会签节点),3.会签中,不更新
  144. if (IsInCountersign()) return;
  145. if (isStartCountersign)
  146. {
  147. FLow(stepBox.Name, stepBox.CreationTime, stepBox.Code);
  148. }
  149. else
  150. {
  151. FLow(stepBox.Name, stepBox.CreationTime);
  152. }
  153. }
  154. /// <summary>
  155. /// 流程是否处于会签中
  156. /// </summary>
  157. /// <returns></returns>
  158. public bool IsInCountersign() => !string.IsNullOrEmpty(TopCountersignStepCode);
  159. /// <summary>
  160. /// 结束流程会签状态
  161. /// </summary>
  162. public void CloseCountersignStatus() => TopCountersignStepCode = null;
  163. /// <summary>
  164. /// 重置最终办理意见
  165. /// </summary>
  166. public void ResetOption() => Opinion = "办理中...";
  167. /// <summary>
  168. /// 更新当前办理人(代办人或部门)
  169. /// </summary>
  170. public void UpdateHandlers(string handlerId, string handlerOrg, EFlowAssignType assignType, IEnumerable<string> handlers)
  171. {
  172. HandlerUsers.Remove(handlerId);
  173. HandlerOrgs.Remove(handlerOrg);
  174. switch (assignType)
  175. {
  176. case EFlowAssignType.Org:
  177. HandlerOrgs.AddRange(handlers);
  178. HandlerOrgs = HandlerOrgs.Distinct().ToList();
  179. break;
  180. case EFlowAssignType.User:
  181. HandlerUsers.AddRange(handlers);
  182. HandlerUsers = HandlerUsers.Distinct().ToList();
  183. break;
  184. default:
  185. throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null);
  186. }
  187. }
  188. /// <summary>
  189. /// 当前用户是否可以办理该流程
  190. /// </summary>
  191. /// <returns></returns>
  192. public bool CanHandle(string userId, string orgCode) =>
  193. HandlerUsers.Contains(userId) || HandlerOrgs.Contains(orgCode);
  194. #endregion
  195. }