| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess.Providers;
- /// <summary>
- /// S8-RULE02-ORDER-DELIVERY-WARNING-1:S1 销售订单行的<b>交付延期风险</b>数据集。
- ///
- /// <para><b>它衡量的是什么</b>:把「客户要求交期」与「系统按产能算出来的建议交期」放在同一行上,
- /// 二者之差(天)即 <c>measured_value</c>。差值为正 = 系统自己认为这一行会晚。</para>
- ///
- /// <para><b>ETA 不是本数据集算的。</b><c>sys_capacity_date</c> 由 S1 的
- /// <c>OrderReviewOrchestrationService</c> 在订单评审做完资源检查后写入(来源是齐套时间),
- /// 本 Provider 只把它取出来做差。<b>没有这个字段的订单行一律不进结果集</b> ——
- /// 那表示该行还没有过可用的资源检查,没有 ETA 证据,不能靠"离交期还有几天"凑一个预警出来。</para>
- ///
- /// <para><b>粒度是订单行</b>:真实交期(<c>plan_date</c>)与数量(<c>qty</c>)都挂在
- /// <c>crm_seorderentry</c> 上,主表 <c>crm_seorder</c> 没有交期字段。
- /// 一张订单可能有多行、各行交期不同,按主单聚合会把风险行淹掉。</para>
- ///
- /// <para><b>已知能力边界(勿当缺陷"修")</b>:真库 390 行订单行中只有 40 行有
- /// <c>sys_capacity_date</c>(10.3%)—— 只有走过评审资源检查的订单才有 ETA。
- /// 这是覆盖面窄,不是数据质量问题;<b>不得</b>为了提高覆盖率改用
- /// <c>plan_date - N 天</c>、<c>WorkOrdMaster.QtyCompleted</c>(实测 267 行全为 0)
- /// 或任何自造 ETA 来补 —— 那会把"临期提醒"伪装成"延期预测"。</para>
- /// </summary>
- public sealed class S8OrderDeliveryDatasetDefinitions : IS8DatasetDefinitionSource
- {
- /// <summary>数据集编码。与 <see cref="S8OrderDeliveryDataProvider.DatasetCode"/> 必须一致。</summary>
- public const string OrderDeliveryRiskCode = "ORDER_DELIVERY_RISK";
- /// <summary>
- /// 能力声明。
- /// <para><b>只开 OutOfRange</b>:本数据集的判据是「两个日期之差越界」,
- /// 不是「到期日已过」(那是 TIMEOUT),也不是「数量缺口」(那是 SHORTAGE)。
- /// 多开一项能力会让配置页把不成立的规则类型也列成可选。</para>
- /// <para><c>HasDueAt = true</c> 仍然为真 —— 客户要求交期会随行输出,
- /// 供异常展示与排序使用,但它<b>不</b>参与命中判定。</para>
- /// </summary>
- 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<S8DatasetDefinition> 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」的全部订单行,包含已过交期的 —— " +
- "是否延期由规则判定,是否允许首次立案由规则的立案窗口声明,都不在取数层。"
- }
- };
- }
|