336 lines
14 KiB
SQL
336 lines
14 KiB
SQL
SET @po_receipt_item_merge_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'po_receipt_item'
|
||
AND COLUMN_NAME = 'merge_to_lot_id'
|
||
);
|
||
SET @po_receipt_item_merge_sql := IF(
|
||
@po_receipt_item_merge_column_exists = 0,
|
||
'ALTER TABLE po_receipt_item ADD COLUMN merge_to_lot_id BIGINT NULL COMMENT ''合并入库目标库存批次ID;为空表示新建独立批次'' AFTER lot_no',
|
||
'SELECT ''po_receipt_item.merge_to_lot_id already exists'''
|
||
);
|
||
PREPARE po_receipt_item_merge_stmt FROM @po_receipt_item_merge_sql;
|
||
EXECUTE po_receipt_item_merge_stmt;
|
||
DEALLOCATE PREPARE po_receipt_item_merge_stmt;
|
||
|
||
SET @stock_lot_parent_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'parent_lot_id'
|
||
);
|
||
SET @stock_lot_parent_sql := IF(
|
||
@stock_lot_parent_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN parent_lot_id BIGINT NULL COMMENT ''父批次ID;用于合并批次、退货批次或成品来源追溯'' AFTER lot_no',
|
||
'SELECT ''wh_stock_lot.parent_lot_id already exists'''
|
||
);
|
||
PREPARE stock_lot_parent_stmt FROM @stock_lot_parent_sql;
|
||
EXECUTE stock_lot_parent_stmt;
|
||
DEALLOCATE PREPARE stock_lot_parent_stmt;
|
||
|
||
SET @stock_lot_role_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'lot_role'
|
||
);
|
||
SET @stock_lot_role_sql := IF(
|
||
@stock_lot_role_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN lot_role VARCHAR(32) NOT NULL DEFAULT ''INVENTORY'' COMMENT ''批次角色:INBOUND_RAW/MERGED_RAW/FINISHED_FROM_RAW_BATCH/RETURNED_FINISHED/INVENTORY'' AFTER parent_lot_id',
|
||
'SELECT ''wh_stock_lot.lot_role already exists'''
|
||
);
|
||
PREPARE stock_lot_role_stmt FROM @stock_lot_role_sql;
|
||
EXECUTE stock_lot_role_stmt;
|
||
DEALLOCATE PREPARE stock_lot_role_stmt;
|
||
|
||
SET @stock_lot_sub_batch_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'material_sub_batch_no'
|
||
);
|
||
SET @stock_lot_sub_batch_sql := IF(
|
||
@stock_lot_sub_batch_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN material_sub_batch_no VARCHAR(80) NULL COMMENT ''原材料生产分批号,格式JH_材料号_0001'' AFTER lot_role',
|
||
'SELECT ''wh_stock_lot.material_sub_batch_no already exists'''
|
||
);
|
||
PREPARE stock_lot_sub_batch_stmt FROM @stock_lot_sub_batch_sql;
|
||
EXECUTE stock_lot_sub_batch_stmt;
|
||
DEALLOCATE PREPARE stock_lot_sub_batch_stmt;
|
||
|
||
SET @stock_lot_source_material_lot_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'source_material_lot_id'
|
||
);
|
||
SET @stock_lot_source_material_lot_sql := IF(
|
||
@stock_lot_source_material_lot_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN source_material_lot_id BIGINT NULL COMMENT ''成品批次来源原材料库存批次ID'' AFTER source_line_id',
|
||
'SELECT ''wh_stock_lot.source_material_lot_id already exists'''
|
||
);
|
||
PREPARE stock_lot_source_material_lot_stmt FROM @stock_lot_source_material_lot_sql;
|
||
EXECUTE stock_lot_source_material_lot_stmt;
|
||
DEALLOCATE PREPARE stock_lot_source_material_lot_stmt;
|
||
|
||
SET @stock_lot_source_material_sub_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'source_material_sub_batch_no'
|
||
);
|
||
SET @stock_lot_source_material_sub_sql := IF(
|
||
@stock_lot_source_material_sub_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN source_material_sub_batch_no VARCHAR(80) NULL COMMENT ''成品批次来源原材料生产分批号'' AFTER source_material_lot_id',
|
||
'SELECT ''wh_stock_lot.source_material_sub_batch_no already exists'''
|
||
);
|
||
PREPARE stock_lot_source_material_sub_stmt FROM @stock_lot_source_material_sub_sql;
|
||
EXECUTE stock_lot_source_material_sub_stmt;
|
||
DEALLOCATE PREPARE stock_lot_source_material_sub_stmt;
|
||
|
||
SET @stock_lot_source_material_summary_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND COLUMN_NAME = 'source_material_summary'
|
||
);
|
||
SET @stock_lot_source_material_summary_sql := IF(
|
||
@stock_lot_source_material_summary_column_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD COLUMN source_material_summary VARCHAR(1000) NULL COMMENT ''成品批次来源原材料分批摘要'' AFTER source_material_sub_batch_no',
|
||
'SELECT ''wh_stock_lot.source_material_summary already exists'''
|
||
);
|
||
PREPARE stock_lot_source_material_summary_stmt FROM @stock_lot_source_material_summary_sql;
|
||
EXECUTE stock_lot_source_material_summary_stmt;
|
||
DEALLOCATE PREPARE stock_lot_source_material_summary_stmt;
|
||
|
||
SET @completion_source_material_lot_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'pp_completion_receipt_item'
|
||
AND COLUMN_NAME = 'source_material_lot_id'
|
||
);
|
||
SET @completion_source_material_lot_sql := IF(
|
||
@completion_source_material_lot_column_exists = 0,
|
||
'ALTER TABLE pp_completion_receipt_item ADD COLUMN source_material_lot_id BIGINT NULL COMMENT ''成品来源原材料库存批次ID'' AFTER lot_no',
|
||
'SELECT ''pp_completion_receipt_item.source_material_lot_id already exists'''
|
||
);
|
||
PREPARE completion_source_material_lot_stmt FROM @completion_source_material_lot_sql;
|
||
EXECUTE completion_source_material_lot_stmt;
|
||
DEALLOCATE PREPARE completion_source_material_lot_stmt;
|
||
|
||
SET @completion_source_material_sub_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'pp_completion_receipt_item'
|
||
AND COLUMN_NAME = 'source_material_sub_batch_no'
|
||
);
|
||
SET @completion_source_material_sub_sql := IF(
|
||
@completion_source_material_sub_column_exists = 0,
|
||
'ALTER TABLE pp_completion_receipt_item ADD COLUMN source_material_sub_batch_no VARCHAR(80) NULL COMMENT ''成品来源原材料生产分批号'' AFTER source_material_lot_id',
|
||
'SELECT ''pp_completion_receipt_item.source_material_sub_batch_no already exists'''
|
||
);
|
||
PREPARE completion_source_material_sub_stmt FROM @completion_source_material_sub_sql;
|
||
EXECUTE completion_source_material_sub_stmt;
|
||
DEALLOCATE PREPARE completion_source_material_sub_stmt;
|
||
|
||
SET @completion_source_material_summary_column_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'pp_completion_receipt_item'
|
||
AND COLUMN_NAME = 'source_material_summary'
|
||
);
|
||
SET @completion_source_material_summary_sql := IF(
|
||
@completion_source_material_summary_column_exists = 0,
|
||
'ALTER TABLE pp_completion_receipt_item ADD COLUMN source_material_summary VARCHAR(1000) NULL COMMENT ''成品来源原材料分批摘要'' AFTER source_material_sub_batch_no',
|
||
'SELECT ''pp_completion_receipt_item.source_material_summary already exists'''
|
||
);
|
||
PREPARE completion_source_material_summary_stmt FROM @completion_source_material_summary_sql;
|
||
EXECUTE completion_source_material_summary_stmt;
|
||
DEALLOCATE PREPARE completion_source_material_summary_stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS pp_work_order_material_issue (
|
||
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
|
||
work_order_material_id BIGINT NOT NULL COMMENT '工单用料ID',
|
||
work_order_id BIGINT NOT NULL COMMENT '生产工单ID',
|
||
material_item_id BIGINT NOT NULL COMMENT '原材料物料ID',
|
||
source_lot_id BIGINT NOT NULL COMMENT '来源原材料库存批次ID',
|
||
material_sub_batch_no VARCHAR(80) NOT NULL COMMENT '兼容字段:来源库存批次号',
|
||
issued_qty DECIMAL(18,6) NOT NULL DEFAULT 0 COMMENT '领用数量',
|
||
issued_weight_kg DECIMAL(18,6) NOT NULL DEFAULT 0 COMMENT '领用重量(kg)',
|
||
unit_cost DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '领用单价',
|
||
amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '领用金额',
|
||
issue_time DATETIME NOT NULL COMMENT '领用时间',
|
||
operator_user_id BIGINT NULL COMMENT '操作人用户ID',
|
||
remark VARCHAR(255) NULL COMMENT '备注',
|
||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
INDEX idx_material_issue_work_order (work_order_id),
|
||
INDEX idx_material_issue_lot (source_lot_id),
|
||
INDEX idx_material_issue_material (material_item_id),
|
||
FOREIGN KEY (work_order_material_id) REFERENCES pp_work_order_material(id),
|
||
FOREIGN KEY (work_order_id) REFERENCES pp_work_order(id),
|
||
FOREIGN KEY (material_item_id) REFERENCES md_item(id),
|
||
FOREIGN KEY (source_lot_id) REFERENCES wh_stock_lot(id)
|
||
) ENGINE=InnoDB COMMENT='工单原材料领用分批记录';
|
||
|
||
SET @idx_po_receipt_item_merge_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'po_receipt_item'
|
||
AND INDEX_NAME = 'idx_receipt_item_merge_to_lot'
|
||
);
|
||
SET @idx_po_receipt_item_merge_sql := IF(
|
||
@idx_po_receipt_item_merge_exists = 0,
|
||
'ALTER TABLE po_receipt_item ADD INDEX idx_receipt_item_merge_to_lot (merge_to_lot_id)',
|
||
'SELECT ''idx_receipt_item_merge_to_lot already exists'''
|
||
);
|
||
PREPARE idx_po_receipt_item_merge_stmt FROM @idx_po_receipt_item_merge_sql;
|
||
EXECUTE idx_po_receipt_item_merge_stmt;
|
||
DEALLOCATE PREPARE idx_po_receipt_item_merge_stmt;
|
||
|
||
SET @idx_stock_lot_source_material_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'wh_stock_lot'
|
||
AND INDEX_NAME = 'idx_stock_lot_source_material'
|
||
);
|
||
SET @idx_stock_lot_source_material_sql := IF(
|
||
@idx_stock_lot_source_material_exists = 0,
|
||
'ALTER TABLE wh_stock_lot ADD INDEX idx_stock_lot_source_material (source_material_lot_id, source_material_sub_batch_no)',
|
||
'SELECT ''idx_stock_lot_source_material already exists'''
|
||
);
|
||
PREPARE idx_stock_lot_source_material_stmt FROM @idx_stock_lot_source_material_sql;
|
||
EXECUTE idx_stock_lot_source_material_stmt;
|
||
DEALLOCATE PREPARE idx_stock_lot_source_material_stmt;
|
||
|
||
SET @idx_completion_source_material_exists := (
|
||
SELECT COUNT(*)
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'pp_completion_receipt_item'
|
||
AND INDEX_NAME = 'idx_completion_source_material'
|
||
);
|
||
SET @idx_completion_source_material_sql := IF(
|
||
@idx_completion_source_material_exists = 0,
|
||
'ALTER TABLE pp_completion_receipt_item ADD INDEX idx_completion_source_material (source_material_lot_id, source_material_sub_batch_no)',
|
||
'SELECT ''idx_completion_source_material already exists'''
|
||
);
|
||
PREPARE idx_completion_source_material_stmt FROM @idx_completion_source_material_sql;
|
||
EXECUTE idx_completion_source_material_stmt;
|
||
DEALLOCATE PREPARE idx_completion_source_material_stmt;
|
||
|
||
UPDATE wh_stock_lot lot
|
||
JOIN md_item item ON item.id = lot.item_id
|
||
SET lot.lot_role = CASE
|
||
WHEN item.item_type = 'RAW_MATERIAL' AND lot.source_doc_type = 'PURCHASE_RECEIPT' THEN 'INBOUND_RAW'
|
||
WHEN item.item_type = 'FINISHED_GOOD' AND lot.source_doc_type = 'FG_RECEIPT' THEN 'FINISHED_GOOD'
|
||
ELSE lot.lot_role
|
||
END
|
||
WHERE lot.lot_role = 'INVENTORY';
|
||
|
||
INSERT INTO pp_work_order_material_issue (
|
||
work_order_material_id,
|
||
work_order_id,
|
||
material_item_id,
|
||
source_lot_id,
|
||
material_sub_batch_no,
|
||
issued_qty,
|
||
issued_weight_kg,
|
||
unit_cost,
|
||
amount,
|
||
issue_time,
|
||
operator_user_id,
|
||
remark,
|
||
created_at,
|
||
updated_at
|
||
)
|
||
SELECT
|
||
source_rows.work_order_material_id,
|
||
source_rows.work_order_id,
|
||
source_rows.material_item_id,
|
||
source_rows.source_lot_id,
|
||
CONCAT('JH_', source_rows.material_code, '_', LPAD(source_rows.seq_no, 4, '0')) AS material_sub_batch_no,
|
||
source_rows.issued_qty,
|
||
source_rows.issued_weight_kg,
|
||
source_rows.unit_cost,
|
||
source_rows.amount,
|
||
source_rows.issue_time,
|
||
source_rows.operator_user_id,
|
||
source_rows.remark,
|
||
NOW(),
|
||
NOW()
|
||
FROM (
|
||
SELECT
|
||
wom.id AS work_order_material_id,
|
||
wom.work_order_id AS work_order_id,
|
||
txn.item_id AS material_item_id,
|
||
txn.lot_id AS source_lot_id,
|
||
item.item_code AS material_code,
|
||
ROW_NUMBER() OVER (PARTITION BY txn.item_id ORDER BY txn.biz_time, txn.id) AS seq_no,
|
||
ABS(txn.qty_change) AS issued_qty,
|
||
ABS(txn.weight_change_kg) AS issued_weight_kg,
|
||
txn.unit_cost AS unit_cost,
|
||
ABS(txn.amount) AS amount,
|
||
txn.biz_time AS issue_time,
|
||
txn.operator_user_id AS operator_user_id,
|
||
txn.remark AS remark
|
||
FROM wh_inventory_txn txn
|
||
JOIN pp_work_order_material wom
|
||
ON wom.id = txn.source_line_id
|
||
AND wom.work_order_id = txn.source_doc_id
|
||
JOIN md_item item ON item.id = txn.item_id
|
||
WHERE txn.txn_type = 'MATERIAL_ISSUE'
|
||
AND txn.source_doc_type = 'WORK_ORDER'
|
||
AND txn.lot_id IS NOT NULL
|
||
AND NOT EXISTS (SELECT 1 FROM pp_work_order_material_issue)
|
||
) source_rows;
|
||
|
||
UPDATE pp_completion_receipt_item item
|
||
JOIN pp_completion_receipt receipt ON receipt.id = item.completion_receipt_id
|
||
JOIN (
|
||
SELECT
|
||
issue.work_order_id,
|
||
MIN(issue.source_lot_id) AS source_material_lot_id,
|
||
SUBSTRING_INDEX(GROUP_CONCAT(issue.material_sub_batch_no ORDER BY issue.id SEPARATOR ','), ',', 1) AS source_material_sub_batch_no,
|
||
LEFT(
|
||
GROUP_CONCAT(
|
||
CONCAT(issue.material_sub_batch_no, ' / ', material.item_name, ' / ', issue.issued_weight_kg, 'kg / ¥', issue.amount)
|
||
ORDER BY issue.id
|
||
SEPARATOR ';'
|
||
),
|
||
1000
|
||
) AS source_material_summary
|
||
FROM pp_work_order_material_issue issue
|
||
JOIN md_item material ON material.id = issue.material_item_id
|
||
GROUP BY issue.work_order_id
|
||
) source_map ON source_map.work_order_id = receipt.work_order_id
|
||
SET
|
||
item.source_material_lot_id = COALESCE(item.source_material_lot_id, source_map.source_material_lot_id),
|
||
item.source_material_sub_batch_no = COALESCE(item.source_material_sub_batch_no, source_map.source_material_sub_batch_no),
|
||
item.source_material_summary = COALESCE(item.source_material_summary, source_map.source_material_summary)
|
||
WHERE item.source_material_lot_id IS NULL;
|
||
|
||
UPDATE wh_stock_lot lot
|
||
JOIN pp_completion_receipt_item item
|
||
ON lot.source_doc_type = 'FG_RECEIPT'
|
||
AND lot.source_line_id = item.id
|
||
SET
|
||
lot.parent_lot_id = COALESCE(lot.parent_lot_id, item.source_material_lot_id),
|
||
lot.lot_role = 'FINISHED_FROM_RAW_BATCH',
|
||
lot.source_material_lot_id = COALESCE(lot.source_material_lot_id, item.source_material_lot_id),
|
||
lot.source_material_sub_batch_no = COALESCE(lot.source_material_sub_batch_no, item.source_material_sub_batch_no),
|
||
lot.source_material_summary = COALESCE(lot.source_material_summary, item.source_material_summary)
|
||
WHERE item.source_material_lot_id IS NOT NULL;
|