| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers;
- /// <summary>
- /// S8-RULE01-PURCHASE-DELIVERY-A:业务数据集定义的集中登记处。
- ///
- /// <b>为什么集中一处而不是每个数据集一个 source 类</b>:
- /// <see cref="S8DatasetCatalog"/> 对重复 DatasetCode 抛 <c>InvalidOperationException</c>,
- /// 而它注册为 <c>AddTransient</c> —— 重复登记的失败形态是「首次解析该服务的那个请求 500」,
- /// <b>不是启动崩溃</b>。启动日志干净 ≠ 目录健康。集中在一个数组里,重复项人工一眼可查;
- /// 将来新增数据集只加一个元素,不必再改 <c>Startup.cs</c>。
- ///
- /// <b>本类只回答「系统认知中存在哪些数据集、各自能力如何」</b>,不回答「谁供数」——
- /// 后者是 <see cref="S8MonitoringDataProviderRegistry"/> 的职责。二者分离才能表达
- /// 「数据集已定义、规则可存草稿、但 Provider 未上线因此不可启用」这个必要的中间状态。
- /// </summary>
- public sealed class S8BusinessDatasetDefinitions : IS8DatasetDefinitionSource
- {
- /// <summary>采购交付(订单行级)数据集编码。Provider 与规则的 dataset_code 必须逐字引用本常量。</summary>
- public const string PurchaseDeliveryCode = "PURCHASE_DELIVERY";
- /// <summary>
- /// 采购交付数据集的能力声明。<b>唯一来源</b>:
- /// <see cref="S8PurchaseDeliveryDataProvider"/> 直接引用本字段,不另写一份字面量。
- ///
- /// 目录与 Provider 各写一份会漂移,而漂移只在 <see cref="S8DatasetEnableGate"/> 第 ⑨ 步
- /// (运行期启用时)才被发现,报 <c>dataset_capability_mismatch</c>——那时已经晚了。
- ///
- /// <b>刻意不声明数量类能力</b>(SupportsShortage / HasTargetQty / HasActualQty):
- /// <c>dwd_supplier_delivery</c> 物理上有 <c>order_qty</c> / <c>remaining_qty</c>,但字段级审计
- /// 已证 <c>remaining_qty</c> 在 781/784 行恒等于 <c>order_qty</c>(收货量在源系统、STD、DWD 三层全断),
- /// 不可作为机制判断依据。Capability 的语义是「当前可可信用于机制判断」,不是「表里有这一列」;
- /// 声明 true 会让 Enable Gate 放行 SHORTAGE 规则,把不可信数据变成可启用能力。
- /// 两列仍随 payload 落盘,仅供排查与后续数据治理观察。
- /// </summary>
- internal static readonly S8DatasetCapabilities PurchaseDeliveryCapabilities = new()
- {
- SupportsTimeout = true,
- SupportsShortage = false,
- SupportsOutOfRange = false,
- HasSourceObjectId = true,
- HasRelatedObjectCode = true,
- HasDueAt = true,
- HasStatus = true,
- HasMeasuredValue = false,
- HasTargetQty = false,
- HasActualQty = false
- };
- public IEnumerable<S8DatasetDefinition> GetDefinitions() => new[]
- {
- new S8DatasetDefinition
- {
- DatasetCode = PurchaseDeliveryCode,
- DisplayName = "采购交付(订单行级)",
- Kind = S8DatasetKind.Object,
- Status = S8DatasetStatus.Defined,
- Capabilities = PurchaseDeliveryCapabilities,
- // Authority 的写入方不止 MDP 转换:DeliveryScheduleService 与 ProcessOutsourceOrderService
- // 两条 API 路径也直接写 dwd_supplier_delivery,且都不写 mdp_transform_run_log。
- // 于是运行日志无法证明表里最终的数据出自谁 —— 判 UNKNOWN、拦截恢复判定。
- //
- // 这只冻结「从缺席做负面推断」这一件事:建单与刷新照常,
- // 因为 hit 是对某行存在的正面观测,写入方混杂不会凭空造出一行。
- // 解冻条件:Authority 收敛为单一写入方、补上 membership 淘汰、补齐租户 JOIN 谓词。
- AuthoritySpec = new Health.S8AuthoritySpec
- {
- ProducerJobCode = "S3_MDP_SYNC_TRANSFORM",
- AuthorityKind = Health.S8AuthorityKind.CurrentStateMirror,
- ProducerTrusted = false,
- UntrustedReasonCode = Health.S8AuthorityHealthReason.Rule01MultiWriterUntrusted
- },
- // S8-RULE01-PURCHASE-DELIVERY-CLOSURE-1:due_at 的业务语义已完成血缘取证,
- // 从「UAT_EXECUTION_MAPPING / 待生产确认」升级为「与中台自身逾期判据同源」。
- //
- // 证据链(S3MdpSyncTransformService.cs 的 dwd_supplier_delivery INSERT):
- // · 落库 need_date := COALESCE(ds.need_date, po.need_date)
- // 其中 ds = mdp_std_delivery_schedule 按 (tenant,factory,po_no,po_line) 聚合的 MIN(need_date)
- // · 落库 due_date := po.due_date 原样
- // · delivery_status 的 DELAYED 判据 := COALESCE(ds.need_date, po.need_date, po.due_date) < now
- // 因此 Provider 的 COALESCE(need_date, due_date) 展开后与该判据**逐字等价**,
- // 不是另起一套口径。实测佐证:UAT 租户最新快照 36 行中,evaluator 判定命中 28 条,
- // 与中台自行标记的 DELAYED 28 条完全一致(COMPLETED 7 / OPEN 1 均正确不命中)。
- Description =
- "来源 dwd_supplier_delivery;粒度为采购订单行(po_no + po_line,实测每快照日唯一);" +
- "按 Tenant 最新 stat_date 收敛(factory 不参与本数据集过滤,见 Provider 注释);" +
- "due_at = COALESCE(need_date, due_date),已证与数据中台自身的 DELAYED 判据 " +
- "COALESCE(交付计划 need_date, 采购订单 need_date, 采购订单 due_date) 同源等价;" +
- "status 域 = COMPLETED / DELAYED / OPEN / CLOSED / CANCELLED / PARTIAL(三个写入方合并)。" +
- "⚠️ UNPROVEN_CONTRACT_SEMANTICS:上述只证明了 S8 与中台口径一致," +
- "并未证明 need_date 等同于与供应商约定的承诺交期 —— 该问题需追至源系统 " +
- "PurOrdDetail.NeedDate 并由业务确认,在此之前 due_at 不得被当作交付合同依据。"
- }
- };
- }
|