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」的全部订单行,包含已过交期的 —— " +
"是否延期由规则判定,是否允许首次立案由规则的立案窗口声明,都不在取数层。"
}
};
}