-- =============================================================================
|
-- 扁平 BOM + 工序统一领料 + 报工领料门禁 数据库迁移脚本
|
-- 适用版本:2026-08-12 需求(简化BOM配置 / 工艺路线按工序生成 / 领料下沉到工序报工)
|
-- 执行顺序:先执行本脚本(加字段 + 回填 + 数据检查),再发布后端代码。
|
-- 说明:
|
-- 1. 本脚本不物理删除 technology_bom_structure / production_bom_structure 的
|
-- 历史层级与数量列(parent_id / unit_quantity / demanded_quantity / unit),
|
-- 仅停止使用其业务语义,保证历史订单与报表可回溯。
|
-- 2. 第 3 部分是“数据检查”,需要人工确认后再决定是否执行对应的清理语句。
|
-- =============================================================================
|
|
-- -----------------------------------------------------------------------------
|
-- 1. 领料主记录增加工序工单归属:领料从订单级下沉到工序(工单)级
|
-- -----------------------------------------------------------------------------
|
ALTER TABLE production_order_pick
|
ADD COLUMN production_operation_task_id BIGINT NULL COMMENT '生产工单id(工序任务),领料归属的工序执行单元' AFTER production_order_id;
|
|
CREATE INDEX idx_pop_operation_task ON production_order_pick (production_operation_task_id);
|
CREATE INDEX idx_pop_order_operation ON production_order_pick (production_order_id, technology_operation_id);
|
|
-- 回填历史领料的工单归属:
|
-- 只回填能够唯一确认的记录(同一条领料的流水里工单ID唯一)。
|
-- 无法唯一确认的历史数据保持为 NULL:它们仍会出现在订单领料汇总中,
|
-- 但不会被当作某道工序的领料,因此不会错误解锁工序报工。
|
UPDATE production_order_pick pop
|
JOIN (SELECT pick_id,
|
MIN(production_operation_task_id) AS task_id
|
FROM production_order_pick_record
|
WHERE production_operation_task_id IS NOT NULL
|
GROUP BY pick_id
|
HAVING COUNT(DISTINCT production_operation_task_id) = 1) r
|
ON r.pick_id = pop.id
|
SET pop.production_operation_task_id = r.task_id
|
WHERE pop.production_operation_task_id IS NULL;
|
|
-- -----------------------------------------------------------------------------
|
-- 2. 报工投入记录来源领料:保证同一笔领料只被一次报工归集,避免重复投入
|
-- -----------------------------------------------------------------------------
|
ALTER TABLE production_product_input
|
ADD COLUMN production_order_pick_id BIGINT NULL COMMENT '来源领料记录id(production_order_pick.id)' AFTER product_model_id;
|
|
-- 唯一索引:MySQL 允许多个 NULL,历史投入记录(无来源领料)不受影响,
|
-- 新数据则保证一条领料不会被两条报工投入重复引用。
|
CREATE UNIQUE INDEX uk_ppi_production_order_pick ON production_product_input (production_order_pick_id);
|
|
-- -----------------------------------------------------------------------------
|
-- 3. 历史 BOM 数据检查与清理(先查,再由业务确认后执行清理)
|
-- -----------------------------------------------------------------------------
|
|
-- 3.1 检查:旧的 BOM 成品根节点(无父节点、无工序,且规格等于 BOM 成品规格)。
|
-- 这些行不是物料,新版本查询已将其过滤,建议确认后删除。
|
SELECT tbs.id,
|
tbs.bom_id,
|
tb.bom_no,
|
tbs.product_model_id
|
FROM technology_bom_structure tbs
|
JOIN technology_bom tb ON tbs.bom_id = tb.id
|
WHERE tbs.parent_id IS NULL
|
AND tbs.operation_id IS NULL
|
AND tbs.product_model_id = tb.product_model_id;
|
|
-- 3.1 清理(确认无误后执行)
|
-- DELETE tbs
|
-- FROM technology_bom_structure tbs
|
-- JOIN technology_bom tb ON tbs.bom_id = tb.id
|
-- WHERE tbs.parent_id IS NULL
|
-- AND tbs.operation_id IS NULL
|
-- AND tbs.product_model_id = tb.product_model_id;
|
|
-- 3.2 检查:缺少消耗工序的物料行。
|
-- 扁平 BOM 要求每个物料都必须指定消耗工序,否则该 BOM 无法生成工艺路线,
|
-- 必须在“产品结构详情”页面补齐,不能默认给一个工序。
|
SELECT tbs.id,
|
tbs.bom_id,
|
tb.bom_no,
|
tbs.product_model_id
|
FROM technology_bom_structure tbs
|
JOIN technology_bom tb ON tbs.bom_id = tb.id
|
WHERE tbs.operation_id IS NULL
|
AND NOT (tbs.parent_id IS NULL AND tbs.product_model_id = tb.product_model_id);
|
|
-- 3.3 检查:同一 BOM 下重复的“物料规格 + 消耗工序”。
|
-- 新版本保存时会拒绝重复配置,历史重复数据需要先合并。
|
SELECT bom_id,
|
product_model_id,
|
operation_id,
|
COUNT(*) AS duplicate_count
|
FROM technology_bom_structure
|
WHERE operation_id IS NOT NULL
|
GROUP BY bom_id, product_model_id, operation_id
|
HAVING COUNT(*) > 1;
|
|
-- 3.4 检查:历史多层 BOM 中曾作为“上一道工序产出”的中间节点。
|
-- 这些行原本代表自制半成品产出,不是需要领用的物料。
|
-- 扁平化后它们会变成可领用物料,需要业务确认是否删除。
|
SELECT child.id,
|
child.bom_id,
|
tb.bom_no,
|
child.product_model_id,
|
child.operation_id
|
FROM technology_bom_structure child
|
JOIN technology_bom tb ON child.bom_id = tb.id
|
WHERE EXISTS (SELECT 1
|
FROM technology_bom_structure sub
|
WHERE sub.parent_id = child.id);
|
|
-- 3.5 可选:将历史层级降为一级(确认 3.1 / 3.4 处理完成后再执行)。
|
-- 新代码不再读取 parent_id 的业务语义,本步骤只是让数据与模型保持一致。
|
-- UPDATE technology_bom_structure SET parent_id = NULL WHERE parent_id IS NOT NULL;
|
|
-- 3.6 检查:历史订单 BOM 快照中的成品根节点(快照保持独立,默认不改写)。
|
-- 新版本领料建议已按“工序非空 + 规格不等于成品规格”过滤,历史快照可保持原样。
|
SELECT pbs.id,
|
pbs.production_order_id,
|
pbs.production_order_bom_id,
|
pbs.product_model_id
|
FROM production_bom_structure pbs
|
JOIN production_order_bom pob ON pbs.production_order_bom_id = pob.id
|
WHERE pbs.parent_id IS NULL
|
AND pbs.technology_operation_id IS NULL
|
AND pbs.product_model_id = pob.product_model_id;
|