fix(iam): 修复仓库角色统一迁移执行

This commit is contained in:
2026-08-10 13:00:13 +08:00
parent 64ba5ae249
commit 20996b050b
3 changed files with 88 additions and 31 deletions
@@ -8713,15 +8713,28 @@ DELIMITER ;
CALL assert_phase3_final_schema();
DROP PROCEDURE IF EXISTS assert_phase3_final_schema;
-- 二、三期对外统一使用 INBOUNDED;历史 WAIT_SPLIT 仅由查询适配为 INBOUNDED,统一迁移不改写主表或历史状态。
SELECT 'PASS' AS migration_status,
'统一增量全部执行完成;箱号映射、单箱测量、三期订舱、拖车预约、出仓、报关、船期、装柜模型桥接、PDA收敛、费用、公共资源及可靠审计结构校验通过' AS message;
-- PDA 部分拣货释放策略:NULL/AUTO 按比例释放,MANUAL + [] 表示人工明确不释放。
USE baiyue_firstleg;
ALTER TABLE fl_loading_pick_item
ADD COLUMN IF NOT EXISTS release_mode VARCHAR(10) NULL COMMENT 'AUTO按比例释放,MANUAL按人工选择释放' AFTER item_status,
ADD COLUMN IF NOT EXISTS release_location_ids JSON NULL COMMENT '人工选择释放库位ID;空数组表示明确释放0个' AFTER release_mode;
DROP PROCEDURE IF EXISTS phase3_pda_add_column;
DELIMITER $$
CREATE PROCEDURE phase3_pda_add_column(IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_ddl 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 @phase3_pda_ddl = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN ', p_ddl);
PREPARE phase3_pda_stmt FROM @phase3_pda_ddl;
EXECUTE phase3_pda_stmt;
DEALLOCATE PREPARE phase3_pda_stmt;
END IF;
END$$
DELIMITER ;
CALL phase3_pda_add_column('fl_loading_pick_item', 'release_mode',
'`release_mode` VARCHAR(10) NULL COMMENT ''AUTO按比例释放,MANUAL按人工选择释放'' AFTER `item_status`');
CALL phase3_pda_add_column('fl_loading_pick_item', 'release_location_ids',
'`release_location_ids` JSON NULL COMMENT ''人工选择释放库位ID;空数组表示明确释放0个'' AFTER `release_mode`');
-- PDA 多人协作:领取粒度由整柜任务下沉为单条拣货明细。
CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment (
pick_item_id BIGINT UNSIGNED NOT NULL,
@@ -8739,10 +8752,21 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment (
CONSTRAINT chk_loading_pick_item_assignment_type CHECK (assignment_type IN ('CLAIMED', 'ASSIGNED'))
) ENGINE=InnoDB COMMENT='PDA拣货明细领取与作业员分配';
SET @phase3_pda_check_ddl = IF(
EXISTS (SELECT 1 FROM information_schema.table_constraints
WHERE constraint_schema = DATABASE()
AND table_name = 'fl_loading_pick_operation'
AND constraint_name = 'chk_loading_pick_operation_action'
AND constraint_type = 'CHECK'),
'ALTER TABLE fl_loading_pick_operation DROP CHECK chk_loading_pick_operation_action',
'SELECT 1');
PREPARE phase3_pda_check_stmt FROM @phase3_pda_check_ddl;
EXECUTE phase3_pda_check_stmt;
DEALLOCATE PREPARE phase3_pda_check_stmt;
ALTER TABLE fl_loading_pick_operation
DROP CHECK IF EXISTS chk_loading_pick_operation_action,
ADD CONSTRAINT chk_loading_pick_operation_action
CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW'));
CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW'));
DROP PROCEDURE IF EXISTS assert_phase3_pda_item_assignment_schema;
DELIMITER $$
@@ -8763,8 +8787,20 @@ DELIMITER ;
CALL assert_phase3_pda_item_assignment_schema();
DROP PROCEDURE IF EXISTS assert_phase3_pda_item_assignment_schema;
ALTER TABLE fl_inbound_pallet_allocation
ADD COLUMN IF NOT EXISTS reservation_id BIGINT UNSIGNED NULL COMMENT '仓库预占资源唯一ID,A0共享场景用于区分托盘' AFTER location_code;
CALL phase3_pda_add_column('fl_inbound_pallet_allocation', 'reservation_id',
'`reservation_id` BIGINT UNSIGNED NULL COMMENT ''仓库预占资源唯一ID,A0共享场景用于区分托盘'' AFTER `location_code`');
SET @phase3_pda_index_ddl = IF(
EXISTS (SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_pallet_allocation'
AND index_name = 'idx_allocation_reservation'),
'SELECT 1',
'ALTER TABLE fl_inbound_pallet_allocation ADD INDEX idx_allocation_reservation (reservation_id)');
PREPARE phase3_pda_index_stmt FROM @phase3_pda_index_ddl;
EXECUTE phase3_pda_index_stmt;
DEALLOCATE PREPARE phase3_pda_index_stmt;
DROP PROCEDURE IF EXISTS phase3_pda_add_column;
/* Phase 3: six-carrier schedule query tasks, truthful manual fallback and three-day rate limit. */
USE baiyue_firstleg;
@@ -9080,19 +9116,23 @@ INSERT INTO tmp_phase3_warehouse_role_permission (role_code, permission_code) VA
('WAREHOUSE_TALLY', 'platform:firstleg:pda:view'),
('WAREHOUSE_TALLY', 'platform:firstleg:pda:review'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:view'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:edit'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:picking:view');
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:edit');
DROP PROCEDURE IF EXISTS assert_phase3_warehouse_role_permissions_available;
DELIMITER $$
CREATE PROCEDURE assert_phase3_warehouse_role_permissions_available()
BEGIN
IF (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_OPERATOR') <> 5
OR (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_PICKER') <> 2
OR (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_TALLY') <> 12 THEN
DECLARE operator_permission_count INT DEFAULT 0;
DECLARE picker_permission_count INT DEFAULT 0;
DECLARE tally_permission_count INT DEFAULT 0;
SELECT COALESCE(SUM(role_code = 'WAREHOUSE_OPERATOR'), 0),
COALESCE(SUM(role_code = 'WAREHOUSE_PICKER'), 0),
COALESCE(SUM(role_code = 'WAREHOUSE_TALLY'), 0)
INTO operator_permission_count, picker_permission_count, tally_permission_count
FROM tmp_phase3_warehouse_role_permission;
IF operator_permission_count <> 5
OR picker_permission_count <> 2
OR tally_permission_count <> 12 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '仓库角色初始化失败:角色权限组合数量不符合预期';
END IF;
@@ -9205,3 +9245,8 @@ CALL assert_phase3_warehouse_roles_ready();
DROP PROCEDURE assert_phase3_warehouse_roles_ready;
DROP TEMPORARY TABLE IF EXISTS tmp_phase3_warehouse_role_permission;
-- 二、三期对外统一使用 INBOUNDED;历史 WAIT_SPLIT 仅由查询适配为 INBOUNDED,统一迁移不改写主表或历史状态。
-- 必须保持为整份脚本最后一个结果,避免后续增量失败却被部署端误判为成功。
SELECT 'PASS' AS migration_status,
'统一增量全部执行完成;PDA多人协作、船司查询和仓库角色最小权限等全部增量及断言通过' AS message;
@@ -85,19 +85,23 @@ INSERT INTO tmp_phase3_warehouse_role_permission (role_code, permission_code) VA
('WAREHOUSE_TALLY', 'platform:firstleg:pda:view'),
('WAREHOUSE_TALLY', 'platform:firstleg:pda:review'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:view'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:edit'),
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:picking:view');
('WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:edit');
DROP PROCEDURE IF EXISTS assert_phase3_warehouse_role_permissions_available;
DELIMITER $$
CREATE PROCEDURE assert_phase3_warehouse_role_permissions_available()
BEGIN
IF (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_OPERATOR') <> 5
OR (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_PICKER') <> 2
OR (SELECT COUNT(*) FROM tmp_phase3_warehouse_role_permission
WHERE role_code = 'WAREHOUSE_TALLY') <> 12 THEN
DECLARE operator_permission_count INT DEFAULT 0;
DECLARE picker_permission_count INT DEFAULT 0;
DECLARE tally_permission_count INT DEFAULT 0;
SELECT COALESCE(SUM(role_code = 'WAREHOUSE_OPERATOR'), 0),
COALESCE(SUM(role_code = 'WAREHOUSE_PICKER'), 0),
COALESCE(SUM(role_code = 'WAREHOUSE_TALLY'), 0)
INTO operator_permission_count, picker_permission_count, tally_permission_count
FROM tmp_phase3_warehouse_role_permission;
IF operator_permission_count <> 5
OR picker_permission_count <> 2
OR tally_permission_count <> 12 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '仓库角色初始化失败:角色权限组合数量不符合预期';
END IF;
@@ -17,7 +17,14 @@ class WarehouseRoleSqlContractTest {
@Test
void unifiedDeploymentContainsTheSameWarehouseRoleContract() throws Exception {
assertWarehouseRoleContract(unifiedSql());
String sql = unifiedSql();
assertWarehouseRoleContract(sql);
assertThat(sql)
.doesNotContain("\n ADD COLUMN IF NOT EXISTS")
.doesNotContain("DROP CHECK IF EXISTS");
assertThat(sql.lastIndexOf("SELECT 'PASS' AS migration_status"))
.isGreaterThan(sql.indexOf("CALL assert_phase3_warehouse_roles_ready()"));
assertThat(sql.trim()).endsWith("AS message;");
}
private static void assertWarehouseRoleContract(String sql) {
@@ -32,9 +39,9 @@ class WarehouseRoleSqlContractTest {
.contains("'WAREHOUSE_TALLY', 'platform:firstleg:pda:review'")
.contains("'WAREHOUSE_TALLY', 'platform:firstleg:inbound:loading:edit'")
.contains("'WAREHOUSE_OPERATOR', 'platform:firstleg:inbound:loading:edit'")
.contains("WHERE role_code = 'WAREHOUSE_OPERATOR') <> 5")
.contains("WHERE role_code = 'WAREHOUSE_PICKER') <> 2")
.contains("WHERE role_code = 'WAREHOUSE_TALLY') <> 12")
.contains("operator_permission_count <> 5")
.contains("picker_permission_count <> 2")
.contains("tally_permission_count <> 12")
.contains("依赖的三期平台权限尚未完整部署")
.contains("DELETE role_permission")
.contains("expected.permission_code IS NULL")
@@ -61,6 +68,7 @@ class WarehouseRoleSqlContractTest {
.doesNotContain("platform:firstleg:outbound-dispatch:confirm");
assertThat(roleGrantBlock(sql, "WAREHOUSE_TALLY"))
.doesNotContain("platform:firstleg:inbound:loading:complete")
.doesNotContain("platform:firstleg:inbound:picking:view")
.doesNotContain("platform:firstleg:outbound-dispatch:confirm");
assertThat(sql)
.doesNotContain("'WAREHOUSE_OPERATOR', 'platform:firstleg:pda:assign'")