2026-08-04 10:07:45 +08:00
SET NAMES utf8mb4 ;
USE baiyue_firstleg ;
-- 二期 FBA 计费增量迁移。通过 information_schema 判断,允许重复部署。
DROP PROCEDURE IF EXISTS phase2_fba_add_column ;
DELIMITER $$
CREATE PROCEDURE phase2_fba_add_column ( IN p_table VARCHAR ( 64 ), IN p_column VARCHAR ( 64 ), IN p_definition TEXT )
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema . COLUMNS
WHERE TABLE_SCHEMA = DATABASE () AND TABLE_NAME = p_table AND COLUMN_NAME = p_column
) THEN
SET @ sql = CONCAT ( 'ALTER TABLE `' , p_table , '` ADD COLUMN `' , p_column , '` ' , p_definition );
PREPARE stmt FROM @ sql ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
END IF ;
END $$
DELIMITER ;
CALL phase2_fba_add_column ( 'fl_inbound_order' , 'carrier_id' , "BIGINT UNSIGNED NULL COMMENT '计费船司逻辑ID' AFTER channel_name" );
CALL phase2_fba_add_column ( 'fl_inbound_order' , 'carrier_name' , "VARCHAR(128) NULL COMMENT '计费船司名称快照' AFTER carrier_id" );
CALL phase2_fba_add_column ( 'fl_carrier_fba_rate' , 'business_type' , "VARCHAR(32) NOT NULL DEFAULT 'FBA' COMMENT '业务或计费类型' AFTER origin_warehouse_name" );
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'version' , "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted" );
2026-09-03 10:44:34 +08:00
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'length_factor' , "DECIMAL(18,6) NOT NULL DEFAULT 1 COMMENT '长度计算系数' AFTER conversion_factor" );
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'width_factor' , "DECIMAL(18,6) NOT NULL DEFAULT 1 COMMENT '宽度计算系数' AFTER length_factor" );
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'height_factor' , "DECIMAL(18,6) NOT NULL DEFAULT 1 COMMENT '高度计算系数' AFTER width_factor" );
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'default_rule' , "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '客户默认生效规则' AFTER status" );
2026-09-10 12:18:33 +08:00
CALL phase2_fba_add_column ( 'fl_customer_charge_rule' , 'initialization_key' , "VARCHAR(128) NULL COMMENT '客户创建执行器幂等键及补偿归属' AFTER remark" );
2026-08-04 10:07:45 +08:00
CALL phase2_fba_add_column ( 'fl_carrier_fba_rate' , 'version' , "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rule_code' , "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '客户规则编码快照' AFTER carrier_rate_version" );
2026-09-03 21:09:22 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'measurement_id' , "BIGINT UNSIGNED NULL COMMENT '费用绑定的测量批次ID快照' AFTER inbound_id" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'measurement_source' , "VARCHAR(32) NULL COMMENT '计费尺寸来源快照:OUTER为外箱规数据' AFTER measurement_id" );
2026-08-04 10:07:45 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'customer_id' , "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID快照' AFTER rule_code" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'customer_name' , "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '客户名称快照' AFTER customer_id" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'business_type' , "VARCHAR(32) NOT NULL DEFAULT '' COMMENT '业务类型快照' AFTER customer_name" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'tax_mode' , "VARCHAR(24) NULL COMMENT '包税模式快照' AFTER business_type" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rounding_scale' , "TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '计费量保留位数快照' AFTER tax_mode" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rounding_mode' , "VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式快照' AFTER rounding_scale" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rule_effective_from' , "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '客户规则生效开始快照' AFTER rounding_mode" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rule_effective_to' , "DATETIME(3) NULL COMMENT '客户规则生效结束快照' AFTER rule_effective_from" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rate_code' , "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '船司价格编码快照' AFTER rule_effective_to" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'origin_warehouse_id' , "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '起运仓ID快照' AFTER rate_code" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'origin_warehouse_name' , "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '起运仓名称快照' AFTER origin_warehouse_id" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'channel_code' , "VARCHAR(64) NOT NULL DEFAULT '' COMMENT '渠道编码快照' AFTER origin_warehouse_name" );
2026-08-07 15:19:21 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'carrier_id' , "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '船司ID快照' AFTER channel_code" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'carrier_name' , "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '船司名称快照' AFTER carrier_id" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'destination_code' , "VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'FBA仓编码快照' AFTER carrier_name" );
2026-08-04 10:07:45 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rate_effective_from' , "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '价格生效开始快照' AFTER destination_code" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'rate_effective_to' , "DATETIME(3) NULL COMMENT '价格生效结束快照' AFTER rate_effective_from" );
2026-09-03 21:09:22 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'customer_confirmed_by' , "BIGINT UNSIGNED NULL COMMENT '客户确认人用户ID' AFTER sent_at" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'customer_confirmed_by_name' , "VARCHAR(64) NULL COMMENT '客户确认人名称快照' AFTER customer_confirmed_by" );
CALL phase2_fba_add_column ( 'fl_inbound_fee' , 'customer_confirmed_at' , "DATETIME(3) NULL COMMENT '客户确认费用时间;非空后费用版本锁定' AFTER customer_confirmed_by_name" );
2026-08-04 10:07:45 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_idempotency' , 'result_resource_id' , "BIGINT UNSIGNED NULL COMMENT '成功结果资源ID' AFTER result_json" );
2026-08-05 09:30:08 +08:00
CALL phase2_fba_add_column ( 'fl_inbound_pallet_allocation' , 'warehouse_resource_tenant_id' ,
2026-08-05 16:26:10 +08:00
"BIGINT UNSIGNED NULL COMMENT '平台公共仓储资源固定使用 0;tenant_id 仍是客户隔离键' AFTER warehouse_id" );
2026-08-05 09:30:08 +08:00
2026-08-05 16:26:10 +08:00
-- 仓储资源是平台公共主数据;存量分配快照统一迁移到平台作用域 0,再收口非空约束。
2026-08-05 09:30:08 +08:00
UPDATE fl_inbound_pallet_allocation
2026-08-05 16:26:10 +08:00
SET warehouse_resource_tenant_id = 0
WHERE warehouse_resource_tenant_id IS NULL OR warehouse_resource_tenant_id <> 0 ;
SET @ resource_tenant_needs_modify = ( SELECT COUNT ( * ) FROM information_schema . COLUMNS
2026-08-05 09:30:08 +08:00
WHERE TABLE_SCHEMA = DATABASE () AND TABLE_NAME = 'fl_inbound_pallet_allocation'
2026-08-05 16:26:10 +08:00
AND COLUMN_NAME = 'warehouse_resource_tenant_id'
AND ( IS_NULLABLE = 'YES' OR COLUMN_COMMENT <> '平台公共仓储资源固定使用 0;tenant_id 仍是客户隔离键' ));
SET @ sql = IF ( @ resource_tenant_needs_modify > 0 ,
"ALTER TABLE fl_inbound_pallet_allocation MODIFY COLUMN warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL COMMENT '平台公共仓储资源固定使用 0;tenant_id 仍是客户隔离键'" ,
2026-08-05 09:30:08 +08:00
'SELECT 1' );
PREPARE stmt FROM @ sql ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-08-04 10:07:45 +08:00
DROP PROCEDURE IF EXISTS phase2_fba_add_column ;
2026-09-10 12:18:33 +08:00
SET @ idx_exists = ( SELECT COUNT ( * ) FROM information_schema . STATISTICS
WHERE TABLE_SCHEMA = DATABASE () AND TABLE_NAME = 'fl_customer_charge_rule'
AND INDEX_NAME = 'idx_charge_rule_initialization' );
SET @ sql = IF ( @ idx_exists = 0 ,
'ALTER TABLE fl_customer_charge_rule ADD INDEX idx_charge_rule_initialization (tenant_id, initialization_key)' ,
'SELECT 1' );
PREPARE stmt FROM @ sql ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-08-04 10:07:45 +08:00
-- 旧索引可能缺少业务类型、船司和结束时间;用新索引名并存,避免破坏线上依赖。
SET @ idx_exists = ( SELECT COUNT ( * ) FROM information_schema . STATISTICS
WHERE TABLE_SCHEMA = DATABASE () AND TABLE_NAME = 'fl_carrier_fba_rate' AND INDEX_NAME = 'idx_fba_rate_unique_match' );
SET @ sql = IF ( @ idx_exists = 0 ,
'ALTER TABLE fl_carrier_fba_rate ADD INDEX idx_fba_rate_unique_match (tenant_id, origin_warehouse_id, business_type, channel_code, carrier_id, destination_code, charge_unit, status, effective_from, effective_to)' ,
'SELECT 1' );
PREPARE stmt FROM @ sql ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;