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