-- ===================================================================================== -- 1.0.544 · S8 Stage-3 采购订单完成态标准事实层(mdp_std_purchase_order_completion) -- -- ── 为什么必须是独立一张表 ────────────────────────────────────────────────────────── -- 采购订单的生命周期在拆库后由两个系统分阶段共管(见 doc/plan/旧DOP-MES-WMS/对接任务书/ -- 附-字段共管矩阵.md §6/§7,以及 DataPlatform/Wms/PurOrdWmsPushService.cs 的 -- 「Status 只建行写空串;收货态由 WMS 维护」): -- 建单阶段 → Ai-DOP(本库 PurOrdDetail,投影为 mdp_std_purchase_order.status) -- 收货/关闭 → WMS/MES(Source B 的 PurOrdDetail.Status) -- 两侧值域实测零重叠(本库 R/O 各 208/240 行、0 个 C;Source B 空串 97 行 + C 1 行、 -- 0 个 R/O),且两侧 RecID 分属不相交 ID 空间,因此【不能】把 Source B 的执行态 -- 覆盖进 mdp_std_purchase_order.status —— 那会把两个系统的事实混进同一列、抹掉 provenance。 -- -- ── Grain ─────────────────────────────────────────────────────────────────────────── -- CANONICAL_GRAIN = (tenant_id, po_no, po_line) -- 依据:① Source B 的业务键是 (Domain, PurOrd, Line),而 Domain 在 165 实测只有 8010 -- 一个账套,退化为 (PurOrd, Line); -- ② 实测本库 449/449 组 (po_no, po_line) 单租户、147/147 个 po_no 单租户, -- 与 MdpHotWatchService 的「采购单号本库唯一」断言一致; -- ③ mdp_std_purchase_order 无 domain 列,消费侧只能按 (tenant_id, po_no, po_line) 关联。 -- domain / potype / source_row_id / source_id 是 provenance,【不进】唯一键。 -- -- ── 三态与可逆 ────────────────────────────────────────────────────────────────────── -- raw_status='C' → COMPLETED -- raw_status='' → NOT_COMPLETED -- raw_status IS NULL 或其它非空值 → UNKNOWN(绝不滑成 NOT_COMPLETED) -- Source B 无该行 → NOT_OBSERVED:【本表不落行】,绝不由 Source A 反向造行 -- 上游 pr_WMS_UpdatePurOrdRctTransactionProcessing2 的写法是 -- `Status=(case when ... then 'C' else '' end)`,退货会把 C 打回空串, -- 故本表是【当前状态】而非一次性事件,Writer 必须允许 COMPLETED → NOT_COMPLETED 回退。 -- -- ── 刻意不做 ──────────────────────────────────────────────────────────────────────── -- 不建 completion_time:Source B 的 UpdateTime 会被 Ai-DOP 自己的 PO_WMS_POD 回推刷新 -- (实测 98 行里 90 行的最后更新者是 DOP 用户或 MDP_HOT),无法表达「何时变成 C」。 -- observed_at / sync_time 是观测时刻,【禁止】冒充业务完成时间。 -- 不做订单级完成聚合;不做 ObjectCompleted;不读 IQC;不写任何源表。 -- ===================================================================================== CREATE TABLE IF NOT EXISTS `mdp_std_purchase_order_completion` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `tenant_id` BIGINT NOT NULL COMMENT '租户。权威 = HotWatch watch.TenantId 或本地 PO 身份反查;绝不由 Domain 推导', `factory_id` BIGINT NULL DEFAULT 1 COMMENT '工厂。Source B 无该概念,恒 1,保留以对齐 mdp_std_* 形状', `po_no` VARCHAR(100) NOT NULL COMMENT '采购单号 = Source B PurOrdDetail.PurOrd(canonical)', `po_line` VARCHAR(50) NOT NULL COMMENT '采购行号 = Source B PurOrdDetail.Line(canonical)', `domain` VARCHAR(24) NULL COMMENT 'Source B 账套 = PurOrdDetail.Domain(实测恒 8010)。仅作 provenance,【不是租户边界】,不进唯一键', `potype` VARCHAR(20) NULL COMMENT 'Source B PurOrdDetail.Potype,仅作上下文', `raw_status` VARCHAR(8) NULL COMMENT 'Source B PurOrdDetail.Status 原值(已 TRIM):C=收完关闭 / 空串=未完成 / NULL=源列为空', `completion_status` VARCHAR(20) NOT NULL COMMENT '完成结论:COMPLETED(C) / NOT_COMPLETED(空串) / UNKNOWN(NULL 或未知值)。派生自 raw_status,绝不来自 Source A', `source_system` VARCHAR(50) NOT NULL COMMENT '产出该事实的源系统编码(mdp_source.source_code),明示这是 WMS 侧事实', `source_id` BIGINT NULL COMMENT 'mdp_source.id,便于切源后追溯', `source_row_id` VARCHAR(100) NULL COMMENT 'Source B PurOrdDetail.RecID。source-local identity,禁止与本库 RecID 比较或判新旧', `source_update_time` DATETIME NULL COMMENT 'Source B UpdateTime。⚠️ 非权威:会被 PO_WMS_POD 回推刷新,禁止当作完成时间', `source_update_user` VARCHAR(50) NULL COMMENT 'Source B UpdateUser。用于区分 WMS 动作与 Ai-DOP 回推(MDP_HOT)', `observed_at` DATETIME NOT NULL COMMENT '本次观测到该状态的时刻。⚠️ 观测时间,禁止冒充业务完成时间', `sync_batch_id` VARCHAR(100) NOT NULL COMMENT '同步批次', `sync_time` DATETIME NOT NULL COMMENT '同步时间', `create_time` DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_mdp_std_po_completion` (`tenant_id`, `po_no`, `po_line`), KEY `idx_std_po_compl_status` (`tenant_id`, `completion_status`), KEY `idx_std_po_compl_batch` (`sync_batch_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='S8 Stage-3 采购订单完成态标准事实层。Grain = 一条采购行(tenant_id + po_no + po_line)。来源 = WMS/MES 执行系统,当前状态可逆';