namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers; /// /// S8-RULE02-ORDER-DELIVERY-WARNING-1:S1 销售订单行的交付延期风险数据集。 /// /// 它衡量的是什么:把「客户要求交期」与「系统按产能算出来的建议交期」放在同一行上, /// 二者之差(天)即 measured_value。差值为正 = 系统自己认为这一行会晚。 /// /// ETA 不是本数据集算的。sys_capacity_date 由 S1 的 /// OrderReviewOrchestrationService 在订单评审做完资源检查后写入(来源是齐套时间), /// 本 Provider 只把它取出来做差。没有这个字段的订单行一律不进结果集 —— /// 那表示该行还没有过可用的资源检查,没有 ETA 证据,不能靠"离交期还有几天"凑一个预警出来。 /// /// 粒度是订单行:真实交期(plan_date)与数量(qty)都挂在 /// crm_seorderentry 上,主表 crm_seorder 没有交期字段。 /// 一张订单可能有多行、各行交期不同,按主单聚合会把风险行淹掉。 /// /// 已知能力边界(勿当缺陷"修"):真库 390 行订单行中只有 40 行有 /// sys_capacity_date(10.3%)—— 只有走过评审资源检查的订单才有 ETA。 /// 这是覆盖面窄,不是数据质量问题;不得为了提高覆盖率改用 /// plan_date - N 天WorkOrdMaster.QtyCompleted(实测 267 行全为 0) /// 或任何自造 ETA 来补 —— 那会把"临期提醒"伪装成"延期预测"。 /// public sealed class S8OrderDeliveryDatasetDefinitions : IS8DatasetDefinitionSource { /// 数据集编码。与 必须一致。 public const string OrderDeliveryRiskCode = "ORDER_DELIVERY_RISK"; /// /// 能力声明。 /// 只开 OutOfRange:本数据集的判据是「两个日期之差越界」, /// 不是「到期日已过」(那是 TIMEOUT),也不是「数量缺口」(那是 SHORTAGE)。 /// 多开一项能力会让配置页把不成立的规则类型也列成可选。 /// HasDueAt = true 仍然为真 —— 客户要求交期会随行输出, /// 供异常展示与排序使用,但它参与命中判定。 /// internal static readonly S8DatasetCapabilities OrderDeliveryRiskCapabilities = new() { SupportsTimeout = false, SupportsShortage = false, SupportsOutOfRange = true, HasSourceObjectId = true, HasRelatedObjectCode = true, HasDueAt = true, HasStatus = false, HasMeasuredValue = true, HasTargetQty = false, HasActualQty = false }; public IEnumerable GetDefinitions() => new[] { new S8DatasetDefinition { DatasetCode = OrderDeliveryRiskCode, DisplayName = "订单交付风险(订单行级)", Kind = S8DatasetKind.Object, Status = S8DatasetStatus.Defined, Capabilities = OrderDeliveryRiskCapabilities, // mdp_std_so 是当前态镜像:upsert 覆盖、没有「发布/翻牌」这一步, // 读者(本数据集的 Provider)也从不按批次取数 —— // 表里因此不存在一个「与本轮是否完成相关、且可能被破坏」的表级状态, // 健康度完全由生产运行本身决定,不加表级不变量。 // (唯一的候选「每租户单一 sync_batch_id」既非必要也非充分: // 它今天恒为真只是孤儿行被反复盖上当前批次戳的副产物, // 而最新批次过滤生效后它会合法地变成 false。) AuthoritySpec = new Health.S8AuthoritySpec { ProducerJobCode = "S1_MDP_SYNC_TRANSFORM", AuthorityKind = Health.S8AuthorityKind.CurrentStateMirror }, Description = "来源 crm_seorderentry(订单行)左连 crm_seorder(主单);粒度为订单行" + "(bill_no + entry_seq,实测 390/390 唯一);" + "measured_value = DATEDIFF(sys_capacity_date, plan_date),即系统建议交期晚于客户要求交期的天数;" + "plan_date(客户要求交期)实测 100% 非空,是唯一可靠的 DueDate;" + "sys_capacity_date(系统建议交期)由订单评审资源检查写入,实测覆盖 40/390。" + "结果集含「未关闭、未删除、且已有 ETA」的全部订单行,包含已过交期的 —— " + "是否延期由规则判定,是否允许首次立案由规则的立案窗口声明,都不在取数层。" } }; }