-- ============================================================================ -- S5-PURCHASE-RECEIPT-DISPLAY-FIX · Batch 2 存量订正 -- ① UAT-A Golden Data 补数(源表 Domain / Supp / UM) -- ② 标准层旧身份键行清理(domain='null'),由重跑 MDP 链以正确 domain 重建 -- -- 背景(根因已在同批代码修复): -- PurchaseReceiptMdpSyncService.TransformStandardAsync 原先对展示列使用裸 -- JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.x'))。MySQL 下 JSON null 经 JSON_UNQUOTE -- 产出**长度为 4 的字面量字符串 'null'**(实测 IS NULL = 0 / CHAR_LENGTH = 4), -- 于是 mdp_std_purchase_receipt 的 supp / sort_name / um / lot_serial / domain -- 落成 'null',采购收货单页面直接显示 null,前端 `|| '-'` 兜底对真值字符串无效。 -- 代码侧已统一改走 MdpJsonSql.Str/Int/Dec(identity / JOIN 键刻意保留裸取值)。 -- -- 但仅修代码不足以让页面有值:本批 UAT Golden Data 的源单本身 -- Domain / Supp / UM 全为 SQL NULL,维表(ItemMaster / SuppMaster / PurOrdDetail) -- 一律关联落空。故必须同时补源数据,本脚本即做这件事。 -- -- 取值依据(aidopdev 只读取证,2026-09-03): -- Domain = '8010' -- · 采购收货是采购单据,其域应与供应商主数据所在域一致。 -- · 本批 5 张收货单对应的采购订单头 PurOrdMaster(UATA-PO-001..005).Supp 均为 'VEN00060'。 -- · 租户 838257186181189 的 SuppMaster 共 14 行、**全部 Domain='8010'**, -- 其中 VEN00060 = 瑞贝德。该租户不存在任何其他 Domain 的供应商主数据, -- 故 '8010' 是唯一能让 供应商 维表命中的取值,且命中行属于**本租户自己**(无跨租户读)。 -- · 原 PurOrdMaster.Domain='797403760988229' 是租户号误填、非 ERP 域,不采用; -- 本脚本亦不改 PurOrdMaster(不在采购收货链路上,避免扩大范围)。 -- Supp = 'VEN00060'(取自对应 PurOrdMaster.Supp,非臆造) -- UM = 取自对应采购订单行 PurOrdDetail(PurOrd=OrdNbr, Line=OrdLine).UM(本批实测均为 'EA') -- LotSerial:**刻意不补**。上游无任何批次号来源(采购订单行、质检、库存事务均无), -- 按"不伪造"原则留 SQL NULL;修复后页面显示空白而非 'null',已满足展示口径。 -- -- 写入范围(DDL 0): -- PurOrdRctMaster UPDATE ≤5 行 tenant_id=838257186181189 AND CreateUser='UAT_GENERATOR' -- AND Receiver LIKE 'UATRCT-A-%' AND RctType='rc' -- PurOrdRctDetail UPDATE ≤10 行 同上范围 -- PurOrdDetail UPDATE ≤10 行 tenant_id=838257186181189 AND PurOrd LIKE 'UATA-PO-%' -- (补 Domain,使收货 → 采购单号/请购单号 维表关联可用) -- mdp_stg_purchase_receipt DELETE ≤15 行 tenant_id=838257186181189 且 raw_data.Domain 为 JSON null -- mdp_std_purchase_receipt DELETE ≤10 行 tenant_id=838257186181189 AND domain='null' -- -- 明确不做(防止范围蔓延): -- · 不动 tenant 838257212780613(UAT-B) / 838257237606469(UAT-DEMO) 的同类数据; -- · 不动非 UAT_GENERATOR 的任何业务行; -- · 不批量修复 PurOrdRctDetail 全表 240 行 Domain IS NULL; -- · 不做全库 'null' 清洗,不碰其他 mdp_std_* 表; -- · 不改 PurOrdMaster。 -- -- 幂等:源表三条 UPDATE 均以 "Domain IS NULL" 收敛,重复执行 0 行影响; -- DELETE 以 domain='null' 收敛,重跑后该条件不再成立。 -- 顺序要求:本脚本执行后必须重跑 S5 采购收货 MDP 链 -- (POST /api/AidopKanban/s5-purchase-receipt-mdp/refresh 或等价 inbound), -- 否则标准层将暂时为空——DELETE 后、重建前存在这一空窗,属预期。 -- ============================================================================ -- ── 执行前证据 ── SELECT 'BEFORE-src' AS phase, SUM(d.Domain IS NULL) AS detail_domain_null, SUM(d.Supp IS NULL) AS detail_supp_null, SUM(d.UM IS NULL) AS detail_um_null, COUNT(*) AS detail_rows FROM PurOrdRctDetail d WHERE d.tenant_id = 838257186181189 AND d.CreateUser = 'UAT_GENERATOR' AND d.Receiver LIKE 'UATRCT-A-%'; SELECT 'BEFORE-std' AS phase, COUNT(*) AS rows_, SUM(domain = 'null') AS domain_null, SUM(supp = 'null') AS supp_null, SUM(sort_name = 'null') AS sort_name_null, SUM(um = 'null') AS um_null, SUM(lot_serial = 'null') AS lot_serial_null FROM mdp_std_purchase_receipt WHERE tenant_id = 838257186181189; -- ── 1) 收货单主表:补 Domain / Supp(Supp 取自对应采购订单头)── UPDATE PurOrdRctMaster m SET m.Domain = '8010', m.Supp = (SELECT po.Supp FROM PurOrdMaster po WHERE po.tenant_id = m.tenant_id AND po.PurOrd = m.OrdNbr LIMIT 1), m.UpdateTime = NOW() WHERE m.tenant_id = 838257186181189 AND m.CreateUser = 'UAT_GENERATOR' AND m.Receiver LIKE 'UATRCT-A-%' AND m.RctType = 'rc' AND m.Domain IS NULL; -- ── 2) 收货单明细:补 Domain / Supp / UM(UM 取自对应采购订单行)── UPDATE PurOrdRctDetail d SET d.Domain = '8010', d.Supp = (SELECT po.Supp FROM PurOrdMaster po WHERE po.tenant_id = d.tenant_id AND po.PurOrd = d.OrdNbr LIMIT 1), d.UM = (SELECT pd.UM FROM PurOrdDetail pd WHERE pd.tenant_id = d.tenant_id AND pd.PurOrd = d.OrdNbr AND pd.Line = d.OrdLine LIMIT 1), d.UpdateTime = NOW() WHERE d.tenant_id = 838257186181189 AND d.CreateUser = 'UAT_GENERATOR' AND d.Receiver LIKE 'UATRCT-A-%' AND d.RctType = 'rc' AND d.Domain IS NULL; -- ── 3) 采购订单明细:补 Domain,使 收货 → 采购单号 / 请购单号 的维表关联成立 ── UPDATE PurOrdDetail SET Domain = '8010', UpdateTime = NOW() WHERE tenant_id = 838257186181189 AND PurOrd LIKE 'UATA-PO-%' AND Domain IS NULL; -- ── 4) 贴源层:删除补数前的旧快照 ── -- mdp_entity.biz_key_expr = 'Domain,Receiver,Line'(明细)/ 'Domain,Receiver'(主表)。 -- 补数前 Domain 为 NULL,贴源行的 source_biz_key 退化成 RecID(如 '900342'); -- 补数后变成 '8010#UATRCT-A-0001#1'。uk_source_key 含 source_biz_key, -- 因此下一次 Pull 是**插新行而非就地更新**,旧快照(raw_data.Domain 为 JSON null)会残留, -- 并被 transform 重新生成一批 domain='null' 的标准层行 —— 同一收货行出现新旧两条。 -- 只删"raw_data.Domain 为 JSON null"的旧快照,新快照(Domain='8010')不受影响; -- 全新环境(先跑本脚本再首次同步)下本语句为 0 行,无副作用。 DELETE FROM mdp_stg_purchase_receipt WHERE tenant_id = 838257186181189 AND JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Receiver')) LIKE 'UATRCT-A-%' AND JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.Domain')) = 'null'; -- ── 5) 标准层:删除旧身份键行(domain='null');重跑 MDP 会以 domain='8010' 重建 ── -- 唯一键 uk_mdp_std_pur_rct(tenant_id, domain, receiver, line) 含 domain, -- 源侧 Domain 变更后 upsert 会落新键,若不清理则同一张收货单出现新旧两行。 DELETE FROM mdp_std_purchase_receipt WHERE tenant_id = 838257186181189 AND domain = 'null' AND receiver LIKE 'UATRCT-A-%'; -- ── 执行后证据(期望:源表三列 0 个 NULL;标准层本租户 0 行,待重跑重建为 10 行)── SELECT 'AFTER-src' AS phase, SUM(d.Domain IS NULL) AS detail_domain_null, SUM(d.Supp IS NULL) AS detail_supp_null, SUM(d.UM IS NULL) AS detail_um_null, COUNT(*) AS detail_rows FROM PurOrdRctDetail d WHERE d.tenant_id = 838257186181189 AND d.CreateUser = 'UAT_GENERATOR' AND d.Receiver LIKE 'UATRCT-A-%'; SELECT 'AFTER-std' AS phase, COUNT(*) AS rows_ FROM mdp_std_purchase_receipt WHERE tenant_id = 838257186181189;