ForgeFlow-ERP/backend/sql/unify_inventory_lot_trace_patch.sql
2026-06-12 16:00:56 +08:00

117 lines
4.6 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

CREATE TABLE IF NOT EXISTS po_purchase_order_sales_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
purchase_order_id BIGINT NOT NULL,
sales_order_id BIGINT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_po_so_link (purchase_order_id, sales_order_id),
KEY idx_po_so_link_so (sales_order_id),
CONSTRAINT fk_po_so_link_po FOREIGN KEY (purchase_order_id) REFERENCES po_purchase_order(id) ON DELETE CASCADE,
CONSTRAINT fk_po_so_link_so FOREIGN KEY (sales_order_id) REFERENCES so_sales_order(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SET @idx_wh_stock_lot_item_lot_no_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'wh_stock_lot'
AND INDEX_NAME = 'idx_wh_stock_lot_item_lot_no'
);
SET @idx_wh_stock_lot_item_lot_no_sql := IF(
@idx_wh_stock_lot_item_lot_no_exists = 0,
'ALTER TABLE wh_stock_lot ADD INDEX idx_wh_stock_lot_item_lot_no (item_id, lot_no)',
'SELECT ''idx_wh_stock_lot_item_lot_no already exists'''
);
PREPARE idx_wh_stock_lot_item_lot_no_stmt FROM @idx_wh_stock_lot_item_lot_no_sql;
EXECUTE idx_wh_stock_lot_item_lot_no_stmt;
DEALLOCATE PREPARE idx_wh_stock_lot_item_lot_no_stmt;
SET @duplicate_stock_lot_no_groups := (
SELECT COUNT(*)
FROM (
SELECT lot_no
FROM wh_stock_lot
WHERE lot_no IS NOT NULL
GROUP BY lot_no
HAVING COUNT(*) > 1
) duplicated_lots
);
SET @uq_wh_stock_lot_lot_no_sql := (
SELECT IF(
@duplicate_stock_lot_no_groups > 0,
CONCAT('SIGNAL SQLSTATE ''45000'' SET MESSAGE_TEXT = ''wh_stock_lot.lot_no存在重复重复批次号组数=', @duplicate_stock_lot_no_groups, ',请先清理后再执行迁移'''),
IF(
NOT EXISTS (
SELECT 1
FROM (
SELECT INDEX_NAME
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'wh_stock_lot'
GROUP BY INDEX_NAME
HAVING MAX(NON_UNIQUE) = 0
AND COUNT(*) = 1
AND SUM(CASE WHEN COLUMN_NAME = 'lot_no' THEN 1 ELSE 0 END) = 1
) existing_unique_lot_no_indexes
),
'ALTER TABLE wh_stock_lot ADD UNIQUE KEY uq_wh_stock_lot_lot_no (lot_no)',
'SELECT ''uq_wh_stock_lot_lot_no already exists'''
)
)
);
PREPARE uq_wh_stock_lot_lot_no_stmt FROM @uq_wh_stock_lot_lot_no_sql;
EXECUTE uq_wh_stock_lot_lot_no_stmt;
DEALLOCATE PREPARE uq_wh_stock_lot_lot_no_stmt;
SET @idx_pp_issue_source_lot_exists := (
SELECT COUNT(DISTINCT INDEX_NAME)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'pp_work_order_material_issue'
AND COLUMN_NAME = 'source_lot_id'
);
SET @idx_pp_issue_source_lot_sql := IF(
@idx_pp_issue_source_lot_exists = 0,
'ALTER TABLE pp_work_order_material_issue ADD INDEX idx_pp_issue_source_lot (source_lot_id)',
'SELECT ''source_lot_id index already exists on pp_work_order_material_issue'''
);
PREPARE idx_pp_issue_source_lot_stmt FROM @idx_pp_issue_source_lot_sql;
EXECUTE idx_pp_issue_source_lot_stmt;
DEALLOCATE PREPARE idx_pp_issue_source_lot_stmt;
SET @uk_material_sub_batch_no_exists := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'pp_work_order_material_issue'
AND INDEX_NAME = 'uk_material_sub_batch_no'
);
SET @drop_uk_material_sub_batch_no_sql := IF(
@uk_material_sub_batch_no_exists > 0,
'ALTER TABLE pp_work_order_material_issue DROP INDEX uk_material_sub_batch_no',
'SELECT ''uk_material_sub_batch_no already absent on pp_work_order_material_issue'''
);
PREPARE drop_uk_material_sub_batch_no_stmt FROM @drop_uk_material_sub_batch_no_sql;
EXECUTE drop_uk_material_sub_batch_no_stmt;
DEALLOCATE PREPARE drop_uk_material_sub_batch_no_stmt;
INSERT INTO po_purchase_order_sales_order (purchase_order_id, sales_order_id, created_at, updated_at)
SELECT DISTINCT po.id, so.id, NOW(), NOW()
FROM po_purchase_order po
JOIN po_purchase_order_item poi ON poi.purchase_order_id = po.id
JOIN mrp_material_demand md ON md.id = poi.source_demand_id
JOIN so_sales_order_item soi ON soi.id = md.sales_order_item_id
JOIN so_sales_order so ON so.id = soi.sales_order_id
WHERE NOT EXISTS (
SELECT 1
FROM po_purchase_order_sales_order existing
WHERE existing.purchase_order_id = po.id
AND existing.sales_order_id = so.id
);
UPDATE pp_work_order_material_issue issue
JOIN wh_stock_lot lot ON lot.id = issue.source_lot_id
SET issue.material_sub_batch_no = lot.lot_no
WHERE issue.material_sub_batch_no IS NULL
OR issue.material_sub_batch_no <> lot.lot_no;