ExceptionEscalationBizHandler.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Admin.NET.Plugin.ApprovalFlow;
  2. using Admin.NET.Plugin.ApprovalFlow.Service;
  3. using Admin.NET.Plugin.AiDOP.Entity.S8;
  4. namespace Admin.NET.Plugin.AiDOP.Service.S8;
  5. /// <summary>
  6. /// 异常升级审批业务回调
  7. /// BizType = "EXCEPTION_ESCALATION"
  8. /// </summary>
  9. public class ExceptionEscalationBizHandler : IFlowBizHandler, ITransient
  10. {
  11. public string BizType => "EXCEPTION_ESCALATION";
  12. private readonly SqlSugarRepository<AdoS8Exception> _rep;
  13. private readonly SqlSugarRepository<AdoS8ExceptionTimeline> _timelineRep;
  14. public ExceptionEscalationBizHandler(
  15. SqlSugarRepository<AdoS8Exception> rep,
  16. SqlSugarRepository<AdoS8ExceptionTimeline> timelineRep)
  17. {
  18. _rep = rep;
  19. _timelineRep = timelineRep;
  20. }
  21. public async Task OnFlowStarted(long bizId, long instanceId)
  22. {
  23. var e = await _rep.GetByIdAsync(bizId) ?? throw new S8BizException("异常不存在");
  24. e.Status = "ESCALATED";
  25. e.ActiveFlowInstanceId = instanceId;
  26. e.ActiveFlowBizType = BizType;
  27. e.UpdatedAt = DateTime.Now;
  28. await _rep.UpdateAsync(e);
  29. await InsertTimelineAsync(e.Id, "ESCALATE_START", "发起升级", null, "ESCALATED", instanceId, null);
  30. }
  31. public async Task OnFlowCompleted(long bizId, long instanceId, FlowInstanceStatusEnum finalStatus, long? lastApproverId)
  32. {
  33. var e = await _rep.GetByIdAsync(bizId) ?? throw new S8BizException("异常不存在");
  34. e.ActiveFlowInstanceId = null;
  35. e.ActiveFlowBizType = null;
  36. e.UpdatedAt = DateTime.Now;
  37. if (finalStatus == FlowInstanceStatusEnum.Approved)
  38. {
  39. e.Status = "ASSIGNED";
  40. // S8-SYSUSER-ONLY-1:lastApproverId 与 AssigneeUserId 现在是同一个 ID 空间,直接写。
  41. //
  42. // 原实现要先经 EmployeeMaster.SysUserId 反查出 employee.RecID 才能落库,
  43. // 反查不到就"保留原值 + 在 timeline 备注里说明"。真库 1105 名员工只有 8 个绑了账号,
  44. // 也就是说升级审批通过后处理人几乎总是不变 —— 而页面上看到的是「升级已确认」。
  45. // 桥没了,这条静默失败路径也就没了。
  46. string? assigneeNote = null;
  47. if (lastApproverId is > 0)
  48. e.AssigneeUserId = lastApproverId.Value;
  49. else
  50. assigneeNote = "未提供审批人信息,处理人保持原值";
  51. await _rep.UpdateAsync(e);
  52. await InsertTimelineAsync(e.Id, "ESCALATE_APPROVED",
  53. assigneeNote == null ? "升级已确认" : $"升级已确认({assigneeNote})",
  54. "ESCALATED", "ASSIGNED",
  55. instanceId, lastApproverId);
  56. }
  57. else if (finalStatus == FlowInstanceStatusEnum.Cancelled)
  58. {
  59. e.Status = "IN_PROGRESS";
  60. await _rep.UpdateAsync(e);
  61. await InsertTimelineAsync(e.Id, "ESCALATE_CANCELLED", "发起人撤回升级申请", "ESCALATED", "IN_PROGRESS",
  62. instanceId, lastApproverId);
  63. }
  64. else
  65. {
  66. e.Status = "IN_PROGRESS";
  67. await _rep.UpdateAsync(e);
  68. await InsertTimelineAsync(e.Id, "ESCALATE_REJECTED", "升级被驳回", "ESCALATED", "IN_PROGRESS",
  69. instanceId, lastApproverId);
  70. }
  71. }
  72. public async Task<Dictionary<string, object>> GetBizData(long bizId)
  73. {
  74. var e = await _rep.GetByIdAsync(bizId);
  75. if (e == null) return new Dictionary<string, object>();
  76. return new Dictionary<string, object>
  77. {
  78. ["severity"] = e.Severity ?? string.Empty,
  79. ["sceneCode"] = e.SceneCode ?? string.Empty,
  80. ["priorityLevel"] = e.PriorityLevel ?? string.Empty,
  81. ["factoryCode"] = e.FactoryId.ToString(),
  82. };
  83. }
  84. private async Task InsertTimelineAsync(long exceptionId, string code, string label,
  85. string? from, string? to, long? instanceId, long? approverId)
  86. {
  87. string? remark = null;
  88. if (instanceId.HasValue && approverId.HasValue)
  89. remark = $"审批实例ID: {instanceId},审批人: {approverId}";
  90. else if (instanceId.HasValue)
  91. remark = $"审批实例ID: {instanceId}";
  92. else if (approverId.HasValue)
  93. remark = $"审批人: {approverId}";
  94. await _timelineRep.InsertAsync(new AdoS8ExceptionTimeline
  95. {
  96. ExceptionId = exceptionId,
  97. ActionCode = code,
  98. ActionLabel = label,
  99. FromStatus = from,
  100. ToStatus = to,
  101. OperatorUserId = approverId,
  102. ActionRemark = remark,
  103. CreatedAt = DateTime.Now
  104. });
  105. }
  106. }