namespace Admin.NET.Plugin.AiDOP.DataPlatform;
///
/// 中立层 KPI 必填列。某通道的投影 SQL 必须写出这些列,写不出的列登记在 。
///
public static class NeutralRequiredColumns
{
public sealed record RequiredColumn(string Name, string? SemanticCode);
public static IReadOnlyList For(string? stdObject) =>
string.Equals(stdObject, "INV_TRANS", StringComparison.OrdinalIgnoreCase)
?
[
new("location", "INV_LOCATION"),
new("lot_serial", "INV_LOT"),
new("create_user", "INV_CREATE_USER"),
new("end_balance", "INV_END_BALANCE"),
new("dimension1", null),
new("eff_date", null),
// S5_L1_001 物料上线周期、S7_L1_001 订单发货周期都以 approved_time 为唯一时间基准:
// 该列整列为空时两个 KPI 只会算出 NO_DATA,且不会报错,故必须当必填列守住。
new("approved_time", null),
new("doc_qty", "DOC_QTY_CLOSE"),
new("line_closed_flag", "DOC_QTY_CLOSE")
]
: [];
public static readonly string[] InvTrans =
[
"location", "lot_serial", "create_user", "end_balance", "dimension1", "eff_date", "approved_time", "doc_qty", "line_closed_flag"
];
public sealed record Projection(string Channel, string RelativePath, string Marker, string[] Present, string[] Missing);
public static readonly Projection[] Channels =
[
new("T8",
Path.Combine("DataPlatform", "T8BaseInboundMdpSyncService.NeutralProjection.cs"),
"ProjectInvTransSql",
["doc_qty", "eff_date", "approved_time", "dimension1", "line_closed_flag", "location", "lot_serial", "create_user", "end_balance"],
[]),
new("PUSH",
Path.Combine("DataPlatform", "T8BaseInboundMdpSyncService.NeutralProjection.cs"),
"BuildProjectApiInvTransSql",
["location", "lot_serial", "create_user", "end_balance", "doc_qty", "line_closed_flag", "dimension1", "eff_date", "approved_time"],
[]),
new("PULL",
Path.Combine("DataPlatform", "T8BaseInboundMdpSyncService.NeutralProjection.cs"),
"BuildProjectApiInvTransSql",
["location", "lot_serial", "create_user", "end_balance", "doc_qty", "line_closed_flag", "dimension1", "eff_date", "approved_time"],
[]),
new("165",
Path.Combine("MaterialWarehouse", "InventoryMdpSyncService.cs"),
"MaterializeInvTransStdAsync",
["location", "lot_serial", "create_user", "end_balance", "doc_qty", "dimension1", "eff_date", "approved_time"],
["line_closed_flag"]),
// 165 的销售发运走 ASN 明细单独一段投影(任务 A-3),是 mdp_std_inv_trans 的第二个写入口。
// 它漏掉 approved_time 时 S7 三个指标会一起静默变成 NO_DATA,故必须单列为一个通道守住。
new("165_ASN",
Path.Combine("DataPlatform", "Wms", "ShipTransNeutralProjection.cs"),
// 标记只写表名:带上 INSERT INTO 会被「中立层写入必须调用来源闸门」的守卫当成写入点。
"mdp_std_inv_trans",
["location", "lot_serial", "create_user", "dimension1", "eff_date", "approved_time", "doc_qty"],
["end_balance", "line_closed_flag"]),
// NATIVE 不写 mdp_std_inv_trans(自有数据只进工单、BOM、员工、销售订单行),
// 故不参与库存流水必填列的覆盖断言,这里只记它自己的写入方标记。
new("NATIVE",
Path.Combine("DataPlatform", "NativeNeutralProjectionService.cs"),
"AIDOP_NATIVE",
["written_by"],
[])
];
}