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;
