-- 1.0.132.sql
-- S0-2026-05-28｜物料替代 ItemSubstituteDetail 数据治理导入
--
-- 业务背景：
--   前端「物料替代」页面（/aidop/s0/manufacturing/material-substitution）
--   后端 AdoS0ItemSubstituteDetailsController 只查 ItemSubstituteDetail 表（当前 0 行）。
--   导入数据落在 ic_bom / ic_bom_child / ic_substitute_group_detail 三张 legacy 表。
--   本脚本将三表 JOIN 后排除原料自身行，导入到 ItemSubstituteDetail。
--
-- 拍板口径：
--   ParentItem      = ic_bom.item_number
--   ItemNum         = ic_bom_child.item_number
--   SubstituteItem  = ic_substitute_group_detail.icitem_number
--   SubstituteQty   = ic_substitute_group_detail.replace_qty
--   SubstituteType  = '替代'
--   Domain          = '8010'  （基于 factory_id 字符串化兜底，非正式业务域；后续如业务给正式 Domain，另开批次修正）
--   tenant_id       = ic_bom_child.tenant_id
--   排除原料自身    : g.icitem_number <> c.item_number
--
-- 预期导入行数：1147（已在阶段 2 + 阶段 3 各跑一次只读校验确认）
--
-- 操作流程：
--   1) 执行段 1【执行前校验】，5 项指标必须命中预期
--   2) 执行段 2【INSERT SELECT】（含 NOT EXISTS 幂等保护）
--   3) 执行段 3【执行后对账】，本批次行数应 = 1147
--   4) 如需回滚，先跑段 4 的 SELECT 预览，再人工取消注释 DELETE


-- ===========================================================================
-- 段 1：执行前校验（只读）
-- 所有 5 项必须全绿才允许执行段 2
-- ===========================================================================

-- 校验 1.1：预计导入行数（应 = 1147）
SELECT COUNT(*) AS expected_insert_rows
FROM ic_bom_child c
INNER JOIN ic_bom b
  ON b.Id = c.bom_id
  AND b.IsDeleted = 0
INNER JOIN ic_substitute_group_detail g
  ON g.substitute_code = c.substitute_code
WHERE c.IsDeleted = 0
  AND NULLIF(TRIM(c.substitute_code),'') IS NOT NULL
  AND NULLIF(TRIM(g.icitem_number),'') IS NOT NULL
  AND g.icitem_number <> c.item_number;

-- 校验 1.2：空值检查（5 个字段都应 = 0）
SELECT
  SUM(b.item_number IS NULL OR TRIM(b.item_number) = '') AS empty_parent,
  SUM(c.item_number IS NULL OR TRIM(c.item_number) = '') AS empty_itemnum,
  SUM(g.icitem_number IS NULL OR TRIM(g.icitem_number) = '') AS empty_substitute,
  SUM(g.replace_qty IS NULL) AS null_qty,
  SUM(c.tenant_id IS NULL OR c.tenant_id = 0) AS empty_tenant
FROM ic_bom_child c
INNER JOIN ic_bom b
  ON b.Id = c.bom_id
  AND b.IsDeleted = 0
INNER JOIN ic_substitute_group_detail g
  ON g.substitute_code = c.substitute_code
WHERE c.IsDeleted = 0
  AND NULLIF(TRIM(c.substitute_code),'') IS NOT NULL
  AND g.icitem_number <> c.item_number;

-- 校验 1.3：三元组重复（total = distinct = 1147；dup = 0）
SELECT total_rows, distinct_triples, total_rows - distinct_triples AS dup_rows
FROM (
  SELECT
    COUNT(*) AS total_rows,
    COUNT(DISTINCT CONCAT_WS('|', c.tenant_id, '8010', b.item_number, c.item_number, g.icitem_number)) AS distinct_triples
  FROM ic_bom_child c
  INNER JOIN ic_bom b
    ON b.Id = c.bom_id
    AND b.IsDeleted = 0
  INNER JOIN ic_substitute_group_detail g
    ON g.substitute_code = c.substitute_code
  WHERE c.IsDeleted = 0
    AND NULLIF(TRIM(c.substitute_code),'') IS NOT NULL
    AND g.icitem_number <> c.item_number
) t;

-- 校验 1.4：目标表当前行数（应 = 0；若 > 0，需评估 NOT EXISTS 的去重效果）
SELECT COUNT(*) AS target_existing_rows
FROM ItemSubstituteDetail;

-- 校验 1.5：tenant_id 三表一致性（应只出现 797403760988229 一行）
SELECT
  c.tenant_id AS child_tenant,
  b.tenant_id AS bom_tenant,
  g.tenant_id AS group_tenant,
  COUNT(*) AS row_cnt
FROM ic_bom_child c
INNER JOIN ic_bom b
  ON b.Id = c.bom_id
INNER JOIN ic_substitute_group_detail g
  ON g.substitute_code = c.substitute_code
WHERE c.IsDeleted = 0
  AND NULLIF(TRIM(c.substitute_code),'') IS NOT NULL
GROUP BY c.tenant_id, b.tenant_id, g.tenant_id;


-- ===========================================================================
-- 段 2：INSERT SELECT（数据导入）
-- 含 NOT EXISTS 幂等保护：重复执行不会产生重复数据
-- ===========================================================================

INSERT INTO ItemSubstituteDetail
  (ParentItem, ItemNum, SubstituteItem, SubstituteQty,
   SubstituteType, Remark, Domain, CreateUser, CreateTime, tenant_id)
SELECT
  b.item_number                                                                          AS ParentItem,
  c.item_number                                                                          AS ItemNum,
  g.icitem_number                                                                        AS SubstituteItem,
  g.replace_qty                                                                          AS SubstituteQty,
  '替代'                                                                                  AS SubstituteType,
  CONCAT('migrated from ic_bom_child Id=', c.Id, ', substitute_code=', c.substitute_code) AS Remark,
  '8010'                                                                                 AS Domain,
  'data-migration'                                                                       AS CreateUser,
  NOW()                                                                                  AS CreateTime,
  c.tenant_id                                                                            AS tenant_id
FROM ic_bom_child c
INNER JOIN ic_bom b
  ON b.Id = c.bom_id
  AND b.IsDeleted = 0
INNER JOIN ic_substitute_group_detail g
  ON g.substitute_code = c.substitute_code
WHERE c.IsDeleted = 0
  AND NULLIF(TRIM(c.substitute_code),'') IS NOT NULL
  AND NULLIF(TRIM(g.icitem_number),'') IS NOT NULL
  AND g.icitem_number <> c.item_number
  AND NOT EXISTS (
    SELECT 1
    FROM ItemSubstituteDetail x
    WHERE x.tenant_id = c.tenant_id
      AND x.Domain = '8010'
      AND x.ParentItem = b.item_number
      AND x.ItemNum = c.item_number
      AND x.SubstituteItem = g.icitem_number
  );


-- ===========================================================================
-- 段 3：执行后对账（只读）
-- ===========================================================================

-- 对账 3.1：本批次导入行数（应 = 1147）
SELECT COUNT(*) AS migrated_rows
FROM ItemSubstituteDetail
WHERE CreateUser = 'data-migration'
  AND Remark LIKE 'migrated from ic_bom_child Id=%, substitute_code=%'
  AND Domain = '8010'
  AND tenant_id = 797403760988229;

-- 对账 3.2：ItemSubstituteDetail 总行数（应 = 1147，假设目标表初始为 0）
SELECT COUNT(*) AS total_rows FROM ItemSubstituteDetail;

-- 对账 3.3：按 Domain / SubstituteType / tenant_id 分组
SELECT Domain, SubstituteType, tenant_id, COUNT(*) AS row_cnt
FROM ItemSubstituteDetail
GROUP BY Domain, SubstituteType, tenant_id
ORDER BY row_cnt DESC;


-- ===========================================================================
-- 段 4：回滚 SQL 草案
-- 默认全部注释，仅在需要完整回退本批次时人工评审后取消注释
-- 四重限定（CreateUser + Remark + Domain + tenant_id）避免误删人工维护数据
-- ===========================================================================

-- 回滚 4.1：先 SELECT 预览要删除的行数（应 = 阶段 3 实际 INSERT 行数）
-- SELECT COUNT(*) AS rollback_rows_preview
-- FROM ItemSubstituteDetail
-- WHERE CreateUser = 'data-migration'
--   AND Remark LIKE 'migrated from ic_bom_child Id=%, substitute_code=%'
--   AND Domain = '8010'
--   AND tenant_id = 797403760988229;

-- 回滚 4.2：实际 DELETE（仅当预览数对账无误时才取消注释）
-- DELETE FROM ItemSubstituteDetail
-- WHERE CreateUser = 'data-migration'
--   AND Remark LIKE 'migrated from ic_bom_child Id=%, substitute_code=%'
--   AND Domain = '8010'
--   AND tenant_id = 797403760988229;
