S8ExceptionReportDispatcher.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. using Admin.NET.Plugin.AiDOP.Entity.S8;
  2. using Admin.NET.Plugin.AiDOP.Service.S8.Rules;
  3. namespace Admin.NET.Plugin.AiDOP.Service.S8;
  4. /// <summary>
  5. /// S8-STEP6E-CFG-WATCH-ORCHESTRATION-DEDUPE-UI-CERT-1:Watch 主链的**业务建单边界**。
  6. ///
  7. /// <para>只抽象一件事——「就一次命中提交一次异常报告」。这是
  8. /// <c>S8WatchSchedulerService</c> 调用 <c>S8ManualReportService</c> 的**唯一最窄位置**
  9. /// (抗抖门通过之后、计数回写/检测日志/通知派发之前)。</para>
  10. ///
  11. /// <para><b>为什么需要它</b>:Watch 主链的编排(数据源加载 → evaluator → 检测状态 → 抗抖 →
  12. /// dedupe)必须能在认证中真实跑通,但真实建单会连带写 <c>ado_s8_exception</c>、
  13. /// <c>ado_s8_exception_timeline</c>,并触发 ApprovalFlow 建实例/任务/日志——这些既不可回滚
  14. /// (只有 exception + timeline 在同一事务内,其余全是自动提交),也依赖部门主数据。
  15. /// 把边界抽出来后,认证 Host 可以只替换这一个接口,从而做到:
  16. /// 上游全真实、建单意图可核对、业务副作用为零。</para>
  17. ///
  18. /// <para>⚠️ <b>生产语义不得改变</b>:正式实现只做一次纯委派,不改参数、不改事务、
  19. /// 不改异常处理、不改 dedupe、不改通知、不改返回值语义。</para>
  20. /// </summary>
  21. public interface IS8ExceptionReportDispatcher
  22. {
  23. /// <summary>把一次规则命中提交为标准异常单;参数与返回值同 <see cref="S8ManualReportService.CreateFromHitAsync"/>。</summary>
  24. Task<AdoS8Exception> CreateFromHitAsync(long tenantId, long factoryId, S8RuleHit hit);
  25. }
  26. /// <summary>
  27. /// 正式实现:**纯委派**,零业务逻辑。Furion 按 <c>ITransient</c> 自动注册到
  28. /// <see cref="IS8ExceptionReportDispatcher"/>,无需改动 Startup。
  29. /// </summary>
  30. public sealed class S8ExceptionReportDispatcher : IS8ExceptionReportDispatcher, ITransient
  31. {
  32. private readonly S8ManualReportService _manualReportService;
  33. public S8ExceptionReportDispatcher(S8ManualReportService manualReportService) =>
  34. _manualReportService = manualReportService;
  35. public Task<AdoS8Exception> CreateFromHitAsync(long tenantId, long factoryId, S8RuleHit hit) =>
  36. _manualReportService.CreateFromHitAsync(tenantId, factoryId, hit);
  37. }