using Admin.NET.Plugin.AiDOP.Infrastructure.S8; using Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess; using Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers; namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.Definitions; /// /// S8 正式规则定义的集中登记处(当前仅 Rule 01)。 /// /// 集中一处而非每规则一个文件,理由与 相同: /// 重复 rule_code 在数组里人工一眼可查;新增规则只加一个元素,不必再改 Startup.cs /// public sealed class S8PurchaseDeliveryRuleDefinitions : IS8RuleDefinitionSource { /// Rule 01 编码。全链身份,任何地方引用必须逐字用本常量,不写字面量。 public const string PurchaseDeliveryDateDelayCode = "RULE_S4_PURCHASE_DELIVERY_DATE_DELAY"; /// Rule 01 建单使用的异常类型。 public const string PurchaseDeliveryExceptionTypeCode = "PURCHASE_DELIVERY_ABNORMAL"; /// Rule 01 源对象类型。**参与 dedup_key**。 public const string PurchaseOrderLineObjectType = "PURCHASE_ORDER_LINE"; public IEnumerable GetDefinitions() => new[] { new S8RuleDefinition { RuleCode = PurchaseDeliveryDateDelayCode, DisplayName = "采购交期延误", Description = "采购订单行已过约定到期日仍未完成交付时提报异常。" + "到期日取交付计划需求日期,缺失时回落采购订单到期日;" + "已完成 / 已关闭 / 已取消的订单行不再判为延误。", DatasetCode = S8BusinessDatasetDefinitions.PurchaseDeliveryCode, RuleType = S8TimeoutRuleEvaluator.RuleTypeCode, RuleMechanism = "DATE", SourceObjectType = PurchaseOrderLineObjectType, SceneCode = S8ModuleCode.S4, StageCode = S8ModuleCode.S4, OrderFlowCode = "MATERIAL_PURCHASE", ExceptionTypeCode = PurchaseDeliveryExceptionTypeCode, // 面向业务管理员的只读说明。刻意不写 dwd_supplier_delivery / COALESCE / 列名 —— // 配置页展示的是"这条规则按什么判",不是"它怎么实现的"。 JudgementSummary = "到期日取交付计划的需求日期;该日期缺失时回落为采购订单的到期日。" + "订单行状态为已完成 / 已关闭 / 已取消时不再判为延误。", DedupIdentitySummary = "采购订单号 + 订单行号", // ──────────────────────────────────────────────────────────────── // 判定语义。四个列名都是 canonical 名 —— Provider 直接以这些名字产出行 // (见 S8PurchaseDeliveryDataProvider 的 SELECT 别名契约)。 // // due_at 的血缘已完成取证:Provider 的 COALESCE(need_date, due_date) // 与数据中台自身的 DELAYED 判据 // COALESCE(交付计划 need_date, 采购订单 need_date, 采购订单 due_date) < now // 展开后逐字等价(S3MdpSyncTransformService 的 dwd_supplier_delivery INSERT)。 // 实测佐证:UAT 租户最新快照 36 行,evaluator 命中 28 条, // 与中台自行标记的 DELAYED 28 条完全一致。 // // ⚠️ UNPROVEN_CONTRACT_SEMANTICS:以上只证明 S8 与中台口径一致, // 并未证明 need_date 等同于与供应商约定的承诺交期。该问题需追至源系统 // PurOrdDetail.NeedDate 并由业务确认,在此之前 due_at 不得被当作交付合同依据。 // ──────────────────────────────────────────────────────────────── Timeout = new S8TimeoutSemantics { DueAtColumn = S8CanonicalColumns.DueAt, StatusColumn = S8CanonicalColumns.Status, // 去重身份 = po_no + '#' + po_line,由 Provider 拼好后放在 source_object_id 列。 // 真库证据:dwd_supplier_delivery 全表 39854 行 / 4 租户 / 97 个快照, // (tenant_id, stat_date, po_no, po_line) 重复组为 0。 SourceObjectIdColumn = S8CanonicalColumns.SourceObjectId, RelatedObjectCodeColumn = S8CanonicalColumns.RelatedObjectCode, // status 域 = COMPLETED / DELAYED / OPEN / CLOSED / CANCELLED / PARTIAL // (三个写入方合并取证:S3MdpSyncTransformService / DeliveryScheduleService / // ProcessOutsourceOrderService)。 // 下列三个视为已完成;DELAYED / OPEN / PARTIAL 均可命中。 CompletedStates = new[] { "COMPLETED", "CLOSED", "CANCELLED" } }, Parameters = new S8RuleParameterPolicy { PollIntervalSecondsDefault = 300, TriggerCountRequiredDefault = 1, // 交期类异常抖动主要来自快照切换,连续两次未命中才判恢复。 RecoverCountRequiredDefault = 2, GraceMinutesDefault = 0, SeverityDefault = S8SeverityCode.Serious, AllowsDepartmentDefaults = true, // S8-RULE-READINESS-1:本规则的数据集 dwd_supplier_delivery **没有部门列**, // 命中行带不出 occurrence / responsible,建单时部门只能来自这两个运行参数。 // 不配就是「启用成功、调度成功、异常一条建不出来」——各层都报成功的静默失败。 // 故声明为启用前置条件,由 S8RuleReadinessGate 在三条执行入口统一拦截。 RequiresDepartmentDefaultsForEnable = true } } }; }