Files
baiyue-firstleg/scripts/db/recent-schema-incremental-20261008.sql
T
2026-10-08 15:55:47 +08:00

550 lines
34 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.
-- 2026-10-08 近期结构增量汇总(MySQL 8.0.16+)
-- 范围:2026-09-21 至 2026-10-08;用于已有业务库升级,不是空库初始化。
-- 按 USE 显式切换 baiyue_iam / baiyue_firstleg / baiyue_lastleg / baiyue_lastlag_warehouse。
-- 独立文件,无 SOURCE 或外部文件依赖;在目标 MySQL 连接中执行整个文件。
-- 不创建数据库、不写业务行、不含账号或密码;DDL 隐式提交,出错立即停止,不使用 --force。
-- 可重复执行,也支持仅部分新增字段已存在的情况。
-- 来源:recent-schema-incremental-20260923.sql、customs-two-file-incremental-20260926.sql、
-- return-receipt-box-count-incremental-20260929.sql、return-outbound-box-nullable-20260929.sql、
-- return-packing-incremental-20261008.sql 以及 incremental.sql 的 2026-09-29 追加项。
-- 2026-09-23 近期字段与表结构统一增量(MySQL 8.0+)
--
-- 范围:2026-09-21 至 2026-09-22 合入的结构变化。
-- 特性:显式切换到所属 schema;字段和索引均通过 information_schema 判断;可重复执行。
-- 边界:不创建数据库、不删除业务字段/表、不包含权限种子或业务数据修正。
-- 注意:DDL 在 MySQL 中会隐式提交;任一步失败后应停止执行并核对目标实例。
SET NAMES utf8mb4;
-- ============================================================================
-- IAM:国内头程 PDA 操作员绑定作业仓
-- ============================================================================
USE baiyue_iam;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_name = 'iam_membership'
)
AND NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'iam_membership'
AND column_name = 'domestic_warehouse_id'
),
'ALTER TABLE iam_membership ADD COLUMN domestic_warehouse_id BIGINT NULL COMMENT ''国内头程PDA操作员绑定的唯一国内作业仓ID'' AFTER overseas_warehouse_id',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @domestic_warehouse_index_columns = (
SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index SEPARATOR ',')
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'iam_membership'
AND index_name = 'idx_membership_domestic_warehouse'
);
SET @domestic_warehouse_index_non_unique = (
SELECT MIN(non_unique)
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'iam_membership'
AND index_name = 'idx_membership_domestic_warehouse'
);
SET @ddl = CASE
WHEN NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'iam_membership'
AND column_name = 'domestic_warehouse_id'
) THEN 'SELECT 1'
WHEN @domestic_warehouse_index_columns IS NULL THEN
'ALTER TABLE iam_membership ADD KEY idx_membership_domestic_warehouse (tenant_id, domestic_warehouse_id, status)'
WHEN @domestic_warehouse_index_columns <> 'tenant_id,domestic_warehouse_id,status'
OR @domestic_warehouse_index_non_unique <> 1 THEN
'ALTER TABLE iam_membership DROP INDEX idx_membership_domestic_warehouse, ADD KEY idx_membership_domestic_warehouse (tenant_id, domestic_warehouse_id, status)'
ELSE 'SELECT 1'
END;
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
-- ============================================================================
-- Firstleg:人工 FBA 报价允许缺少船司价格快照
-- ============================================================================
USE baiyue_firstleg;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_fee'
AND column_name = 'carrier_rate_id' AND is_nullable = 'NO'
),
'ALTER TABLE fl_inbound_fee MODIFY COLUMN carrier_rate_id BIGINT UNSIGNED NULL COMMENT ''船司FBA价格ID;人工报价为空''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_fee'
AND column_name = 'carrier_rate_version' AND is_nullable = 'NO'
),
'ALTER TABLE fl_inbound_fee MODIFY COLUMN carrier_rate_version INT UNSIGNED NULL COMMENT ''船司价格版本快照;人工报价为空''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_fee'
AND column_name = 'rate_effective_from' AND is_nullable = 'NO'
),
'ALTER TABLE fl_inbound_fee MODIFY COLUMN rate_effective_from DATETIME(3) NULL COMMENT ''价格生效开始快照;人工报价为空''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
-- ============================================================================
-- Firstleg:墨家测量收件箱扩展为箱唛/SKU 双分流
-- ============================================================================
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'inbound_code'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN inbound_code VARCHAR(64) NULL COMMENT ''箱码命中后的权威入仓码;SKU记录为空'' AFTER box_code',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'measurement_kind'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN measurement_kind VARCHAR(16) NOT NULL DEFAULT ''BOX_LABEL'' COMMENT ''测量分流:BOX_LABEL箱唛;SKU一件代发SKU'' AFTER box_code',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'weight_kg'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN weight_kg DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT ''设备实测重量kg'' AFTER height_cm',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'weight_kg'
AND (column_type <> 'decimal(18,3)' OR is_nullable <> 'NO' OR column_default IS NOT NULL
OR column_comment <> '设备实测重量kg')
),
'ALTER TABLE fl_mojia_measurement_receipt MODIFY COLUMN weight_kg DECIMAL(18,3) NOT NULL COMMENT ''设备实测重量kg''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'sync_status'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN sync_status VARCHAR(24) NULL COMMENT ''SKU同步状态:PENDING/SYNCING/SUCCESS/FAILED'' AFTER status',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'sync_failure_code'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN sync_failure_code VARCHAR(64) NULL COMMENT ''SKU同步失败业务码'' AFTER sync_status',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'sync_failure_reason'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN sync_failure_reason VARCHAR(500) NULL COMMENT ''脱敏后的SKU同步失败原因'' AFTER sync_failure_code',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'lingxing_sku_id'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN lingxing_sku_id VARCHAR(128) NULL COMMENT ''领星SKU内部标识'' AFTER sync_failure_reason',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'revision'
),
'ALTER TABLE fl_mojia_measurement_receipt ADD COLUMN revision INT NOT NULL DEFAULT 1 COMMENT ''当前测量版本号'' AFTER lingxing_sku_id',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'match_failure_code' AND is_nullable = 'NO'
),
'ALTER TABLE fl_mojia_measurement_receipt MODIFY COLUMN match_failure_code VARCHAR(16) NULL COMMENT ''正式箱唛业务匹配失败码''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'match_failure_reason' AND is_nullable = 'NO'
),
'ALTER TABLE fl_mojia_measurement_receipt MODIFY COLUMN match_failure_reason VARCHAR(500) NULL COMMENT ''脱敏后的箱唛匹配失败原因''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'box_code'
AND column_comment <> '设备扫描的原始箱码或不带#的SKU'
),
'ALTER TABLE fl_mojia_measurement_receipt MODIFY COLUMN box_code VARCHAR(128) NOT NULL COMMENT ''设备扫描的原始箱码或不带#的SKU''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'fl_mojia_measurement_receipt'
AND column_name = 'status'
AND column_comment <> '原始收件状态;SKU记录使用SKU_PENDING_SYNC'
),
'ALTER TABLE fl_mojia_measurement_receipt MODIFY COLUMN status VARCHAR(24) NOT NULL DEFAULT ''UNMATCHED'' COMMENT ''原始收件状态;SKU记录使用SKU_PENDING_SYNC''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
-- ============================================================================
-- Lastleg:同一尾程单允许多次换标申请,订单关联由唯一索引改为普通索引
-- ============================================================================
USE baiyue_lastleg;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'll_relabel_application'
AND index_name = 'uk_ll_relabel_application_order'
),
'ALTER TABLE ll_relabel_application DROP INDEX uk_ll_relabel_application_order',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @relabel_order_index_columns = (
SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index SEPARATOR ',')
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'll_relabel_application'
AND index_name = 'idx_ll_relabel_application_order'
);
SET @relabel_order_index_non_unique = (
SELECT MIN(non_unique)
FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'll_relabel_application'
AND index_name = 'idx_ll_relabel_application_order'
);
SET @ddl = CASE
WHEN @relabel_order_index_columns IS NULL THEN
'ALTER TABLE ll_relabel_application ADD KEY idx_ll_relabel_application_order (lastleg_order_id)'
WHEN @relabel_order_index_columns <> 'lastleg_order_id'
OR @relabel_order_index_non_unique <> 1 THEN
'ALTER TABLE ll_relabel_application DROP INDEX idx_ll_relabel_application_order, ADD KEY idx_ll_relabel_application_order (lastleg_order_id)'
ELSE 'SELECT 1'
END;
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
-- ============================================================================
-- Overseas Warehouse:A0 系统共享溢出库位标记
-- 注意:正式 schema 名沿用项目现有拼写 baiyue_lastlag_warehouse。
-- ============================================================================
USE baiyue_lastlag_warehouse;
SET @ddl = IF(
NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'wh_location'
AND column_name = 'shared_overflow'
),
'ALTER TABLE wh_location ADD COLUMN shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否系统共享溢出库位(A0)'' AFTER location_type',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
SET @ddl = IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'wh_location'
AND column_name = 'shared_overflow'
AND (column_type <> 'tinyint(1)' OR is_nullable <> 'NO'
OR COALESCE(column_default, '') <> '0'
OR column_comment <> '是否系统共享溢出库位(A0)')
),
'ALTER TABLE wh_location MODIFY COLUMN shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否系统共享溢出库位(A0)''',
'SELECT 1'
);
PREPARE recent_schema_stmt FROM @ddl;
EXECUTE recent_schema_stmt;
DEALLOCATE PREPARE recent_schema_stmt;
-- 最终只读核对;四行均应返回 READY。
SELECT 'baiyue_iam' AS target_schema,
IF(
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'baiyue_iam' AND table_name = 'iam_membership' AND column_name = 'domestic_warehouse_id')
AND (SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index SEPARATOR ',') FROM information_schema.statistics WHERE table_schema = 'baiyue_iam' AND table_name = 'iam_membership' AND index_name = 'idx_membership_domestic_warehouse') = 'tenant_id,domestic_warehouse_id,status',
'READY', 'CHECK_REQUIRED'
) AS schema_status
UNION ALL
SELECT 'baiyue_firstleg',
IF(
(SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'baiyue_firstleg' AND table_name = 'fl_mojia_measurement_receipt' AND column_name IN ('measurement_kind','weight_kg','sync_status','sync_failure_code','sync_failure_reason','lingxing_sku_id','revision')) = 7
AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'baiyue_firstleg' AND table_name = 'fl_inbound_fee' AND column_name IN ('carrier_rate_id','carrier_rate_version','rate_effective_from') AND is_nullable = 'YES') = 3,
'READY', 'CHECK_REQUIRED'
)
UNION ALL
SELECT 'baiyue_lastleg',
IF(
NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = 'baiyue_lastleg' AND table_name = 'll_relabel_application' AND index_name = 'uk_ll_relabel_application_order')
AND (SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index SEPARATOR ',') FROM information_schema.statistics WHERE table_schema = 'baiyue_lastleg' AND table_name = 'll_relabel_application' AND index_name = 'idx_ll_relabel_application_order') = 'lastleg_order_id'
AND (SELECT MIN(non_unique) FROM information_schema.statistics WHERE table_schema = 'baiyue_lastleg' AND table_name = 'll_relabel_application' AND index_name = 'idx_ll_relabel_application_order') = 1,
'READY', 'CHECK_REQUIRED'
)
UNION ALL
SELECT 'baiyue_lastlag_warehouse',
IF(
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = 'baiyue_lastlag_warehouse'
AND table_name = 'wh_location'
AND column_name = 'shared_overflow'
AND column_type = 'tinyint(1)'
AND is_nullable = 'NO'
AND COALESCE(column_default, '') = '0'
),
'READY', 'CHECK_REQUIRED'
);
-- 报关两文件流程:回执与真实报关完税文件分离。
-- 仅在已确认目标测试库后执行;所有 DDL 可重复执行,不创建数据库、不写业务数据。
USE baiyue_firstleg;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_customs_container' AND column_name='broker_submitted_by'), 'ALTER TABLE fl_customs_container ADD COLUMN broker_submitted_by BIGINT UNSIGNED NULL COMMENT ''发送报关行执行的操作人ID''', 'SELECT 1');
PREPARE recent_customs_stmt FROM @ddl; EXECUTE recent_customs_stmt; DEALLOCATE PREPARE recent_customs_stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_customs_container' AND column_name='broker_submitted_by_name'), 'ALTER TABLE fl_customs_container ADD COLUMN broker_submitted_by_name VARCHAR(64) NULL COMMENT ''发送报关行执行的操作人名称''', 'SELECT 1');
PREPARE recent_customs_stmt FROM @ddl; EXECUTE recent_customs_stmt; DEALLOCATE PREPARE recent_customs_stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_customs_container' AND column_name='broker_submitted_at'), 'ALTER TABLE fl_customs_container ADD COLUMN broker_submitted_at DATETIME(3) NULL COMMENT ''发送报关行执行时间''', 'SELECT 1');
PREPARE recent_customs_stmt FROM @ddl; EXECUTE recent_customs_stmt; DEALLOCATE PREPARE recent_customs_stmt;
CREATE TABLE IF NOT EXISTS fl_customs_final_document (
id BIGINT UNSIGNED NOT NULL COMMENT '真实报关完税文件ID',
source_document_id BIGINT UNSIGNED NOT NULL COMMENT '对应冻结客户资料ID',
file_id BIGINT UNSIGNED NOT NULL COMMENT 'File服务文件ID',
file_name VARCHAR(255) NOT NULL COMMENT '真实报关完税文件名称快照',
file_hash CHAR(64) NOT NULL COMMENT '真实报关完税文件SHA-256摘要',
content_type VARCHAR(128) NULL COMMENT '真实报关完税文件媒体类型',
size_bytes BIGINT UNSIGNED NOT NULL COMMENT '真实报关完税文件大小(字节)',
uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传操作人ID',
uploaded_by_name VARCHAR(64) NULL COMMENT '上传操作人名称快照',
uploaded_at DATETIME(3) NOT NULL COMMENT '上传时间',
version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '完税文件版本号',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY(id),
UNIQUE KEY uk_customs_final_source(source_document_id),
CONSTRAINT fk_customs_final_source FOREIGN KEY(source_document_id) REFERENCES fl_customs_customer_document(id)
) ENGINE=InnoDB COMMENT='真实报关完税文件当前版本';
-- 退货/换标近期结构增量汇总(MySQL 8.0+)
--
-- 目标数据库:baiyue_lastleg
-- 覆盖:退货箱级签收、箱级出库、退货合箱预占/追溯、换标箱唛总文件。
-- 本文件只执行 DDL,不写入业务数据;所有字段、索引和约束均按元数据判断,
-- 可在同一个目标库上重复执行。数据库不存在或基线表缺失时会立即报错并停止。
SET NAMES utf8mb4;
USE `baiyue_lastleg`;
-- 2026-09-29:箱维度退货出库不绑定托盘。
SET @ddl = IF(
EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'll_outbound_pallet_item')
AND EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_outbound_pallet_item' AND column_name = 'pallet_no' AND is_nullable = 'NO'),
'ALTER TABLE ll_outbound_pallet_item MODIFY COLUMN pallet_no VARCHAR(128) NULL COMMENT ''托盘号,箱维度出库为空''',
'SELECT 1'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 2026-09-29:退货签收单元、SKU 箱数及来源实物追溯。
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'unit_type'), 'ALTER TABLE ll_return_receipt ADD COLUMN unit_type VARCHAR(16) NULL COMMENT ''签收类型 PALLET/BOX/PARCEL''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'unit_code'), 'ALTER TABLE ll_return_receipt ADD COLUMN unit_code VARCHAR(128) NULL COMMENT ''签收单元业务码''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'total_box_count'), 'ALTER TABLE ll_return_receipt ADD COLUMN total_box_count BIGINT NULL COMMENT ''签收 SKU 箱数汇总''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'length'), 'ALTER TABLE ll_return_receipt ADD COLUMN length DECIMAL(12,3) NULL COMMENT ''实测尺寸 cm''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'width'), 'ALTER TABLE ll_return_receipt ADD COLUMN width DECIMAL(12,3) NULL COMMENT ''实测尺寸 cm''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'height'), 'ALTER TABLE ll_return_receipt ADD COLUMN height DECIMAL(12,3) NULL COMMENT ''实测尺寸 cm''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name = 'weight'), 'ALTER TABLE ll_return_receipt ADD COLUMN weight DECIMAL(12,3) NULL COMMENT ''实测重量 kg''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt_item' AND column_name = 'box_count'), 'ALTER TABLE ll_return_receipt_item ADD COLUMN box_count BIGINT NULL COMMENT ''SKU 签收箱数''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND column_name = 'source_unit_type'), 'ALTER TABLE ll_return_inventory_carton ADD COLUMN source_unit_type VARCHAR(32) NULL COMMENT ''来源实物类型''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND column_name = 'source_unit_code'), 'ALTER TABLE ll_return_inventory_carton ADD COLUMN source_unit_code VARCHAR(128) NULL COMMENT ''来源实物业务码''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 2026-09-29:换标箱唛总文件。
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_relabel_application' AND column_name = 'carton_total_file_id'), 'ALTER TABLE ll_relabel_application ADD COLUMN carton_total_file_id VARCHAR(128) NULL COMMENT ''箱唛总文件 ID''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_relabel_application' AND column_name = 'carton_total_file_name'), 'ALTER TABLE ll_relabel_application ADD COLUMN carton_total_file_name VARCHAR(255) NULL COMMENT ''箱唛总文件名''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 合箱计划及精确来源/结果快照。
CREATE TABLE IF NOT EXISTS ll_return_packing_plan (
id BIGINT NOT NULL COMMENT '合箱计划 ID', plan_no VARCHAR(128) NOT NULL COMMENT '计划业务号',
customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键', overseas_warehouse_id VARCHAR(128) NOT NULL COMMENT '海外仓 ID',
return_nos_json JSON NOT NULL COMMENT '来源退货单范围', boxes_json JSON NOT NULL COMMENT '目标箱明细',
mode VARCHAR(32) NOT NULL COMMENT 'SKU 散件或 BOX 箱合并', status VARCHAR(32) NOT NULL COMMENT '计划状态',
remark VARCHAR(1000) NULL COMMENT '合箱备注', idempotency_key VARCHAR(255) NOT NULL COMMENT '创建幂等键',
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
pushed_at DATETIME(3) NULL COMMENT '审核推送时间', completed_at DATETIME(3) NULL COMMENT '作业完成时间',
PRIMARY KEY (id), UNIQUE KEY uk_ll_return_packing_plan_no (plan_no),
UNIQUE KEY uk_ll_return_packing_plan_key (customer_id, idempotency_key),
KEY idx_ll_return_packing_plan_warehouse (overseas_warehouse_id, status, pushed_at)
) ENGINE=InnoDB COMMENT='退货合箱计划';
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan' AND column_name = 'source_items_json'), 'ALTER TABLE ll_return_packing_plan ADD COLUMN source_items_json JSON NULL COMMENT ''精确来源箱和 SKU 锁定数量''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan' AND column_name = 'result_marks_json'), 'ALTER TABLE ll_return_packing_plan ADD COLUMN result_marks_json JSON NULL COMMENT ''完成生成或并入的目标箱唛''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan' AND column_name = 'request_hash'), 'ALTER TABLE ll_return_packing_plan ADD COLUMN request_hash VARCHAR(64) NULL COMMENT ''创建载荷摘要''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan' AND column_name = 'completion_hash'), 'ALTER TABLE ll_return_packing_plan ADD COLUMN completion_hash VARCHAR(64) NULL COMMENT ''完成载荷摘要''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan' AND column_name = 'result_labels_json'), 'ALTER TABLE ll_return_packing_plan ADD COLUMN result_labels_json JSON NULL COMMENT ''计划完工标签快照''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton_item' AND column_name = 'packing_reserved_quantity'), 'ALTER TABLE ll_return_inventory_carton_item ADD COLUMN packing_reserved_quantity BIGINT NOT NULL DEFAULT 0 COMMENT ''合箱计划预占件数''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND column_name = 'location_code'), 'ALTER TABLE ll_return_inventory_carton ADD COLUMN location_code VARCHAR(128) NULL COMMENT ''退货箱当前库位''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND column_name = 'putaway_at'), 'ALTER TABLE ll_return_inventory_carton ADD COLUMN putaway_at DATETIME(3) NULL COMMENT ''退货箱上架时间''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_operation' AND column_name = 'result_json'), 'ALTER TABLE ll_return_inventory_operation ADD COLUMN result_json JSON NULL COMMENT ''幂等操作不可变返回快照''', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
CREATE TABLE IF NOT EXISTS ll_return_packing_trace (
id BIGINT NOT NULL COMMENT '合箱追溯 ID', customer_id VARCHAR(128) NOT NULL COMMENT '原客户隔离键',
operation_id BIGINT NOT NULL COMMENT '合箱操作 ID', source_carton_mark VARCHAR(128) NOT NULL COMMENT '来源箱唛',
target_carton_mark VARCHAR(128) NOT NULL COMMENT '目标箱唛', return_no VARCHAR(128) NOT NULL COMMENT '原始退货单号',
sku_code VARCHAR(128) NOT NULL COMMENT 'SKU', quantity BIGINT NOT NULL COMMENT '本次移动件数',
created_at DATETIME(3) NOT NULL COMMENT '发生时间', PRIMARY KEY (id),
KEY idx_return_packing_trace_order (customer_id, return_no, created_at),
KEY idx_return_packing_trace_target (customer_id, target_carton_mark, sku_code),
KEY idx_return_packing_trace_source (customer_id, source_carton_mark, sku_code),
CONSTRAINT chk_return_packing_trace_quantity CHECK (quantity > 0)
) ENGINE=InnoDB COMMENT='退货合箱逐 SKU 原始退货单不可变追溯';
-- 原子替换两个 CHECK;新定义验证失败时原约束保留。
SET @recent_drop_check_0 = IF(EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_schema=DATABASE() AND table_name='ll_return_inventory_carton' AND constraint_name='chk_ll_return_inventory_carton_quantity'), 'DROP CHECK chk_ll_return_inventory_carton_quantity, ', '');
SET @recent_drop_check_1 = IF(EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_schema=DATABASE() AND table_name='ll_return_inventory_carton' AND constraint_name='chk_ll_return_inventory_carton_status'), 'DROP CHECK chk_ll_return_inventory_carton_status, ', '');
SET @ddl = CONCAT('ALTER TABLE ll_return_inventory_carton ', @recent_drop_check_0, @recent_drop_check_1, 'ADD CONSTRAINT chk_ll_return_inventory_carton_quantity CHECK ((status IN (''AVAILABLE'',''PACKING_RESERVED'',''RELABEL_PENDING'',''OUTBOUND_PENDING'',''OUTBOUNDED'',''DISCARD_PENDING'') AND sku_types>0 AND total_quantity>0) OR (status IN (''MERGED'',''DISCARDED'') AND sku_types=0 AND total_quantity=0)), ADD CONSTRAINT chk_ll_return_inventory_carton_status CHECK (status IN (''AVAILABLE'',''PACKING_RESERVED'',''RELABEL_PENDING'',''OUTBOUND_PENDING'',''MERGED'',''OUTBOUNDED'',''DISCARD_PENDING'',''DISCARDED''))');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 同一签收批次可拆成多个退货箱:唯一约束改为普通索引。
SET @ddl = IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND index_name = 'uk_ll_return_inventory_carton_receipt'), 'ALTER TABLE ll_return_inventory_carton DROP INDEX uk_ll_return_inventory_carton_receipt', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND index_name = 'idx_ll_return_inventory_carton_receipt'), 'ALTER TABLE ll_return_inventory_carton ADD INDEX idx_ll_return_inventory_carton_receipt (source_receipt_id)', 'SELECT 1');
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SELECT DATABASE() AS target_database,
IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'll_return_receipt' AND column_name IN ('unit_type','unit_code','total_box_count','length','width','height','weight')) = 7, 'READY', 'CHECK_REQUIRED') AS receipt_schema,
IF(EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_plan') AND EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'll_return_packing_trace'), 'READY', 'CHECK_REQUIRED') AS packing_schema,
IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = 'll_return_inventory_carton' AND index_name = 'idx_ll_return_inventory_carton_receipt'), 'READY', 'CHECK_REQUIRED') AS carton_index;