diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index fef4f9ee8..c33af83b7 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -18134,6 +18134,149 @@ DELIMITER ; CALL assert_terminal_drayage_schema(); DROP PROCEDURE IF EXISTS assert_terminal_drayage_schema; +-- 货柜双工作台权限开始(与 iam/db/container-workspace-permissions.sql 保持一致) +-- 国内送柜报关与国外清关提柜双工作台权限;国内沿用现有货柜权限,国外直接收敛到独立权限族。 +USE baiyue_iam; +SET NAMES utf8mb4; + +DROP PROCEDURE IF EXISTS migrate_container_workspace_permissions; +DELIMITER $$ +CREATE PROCEDURE migrate_container_workspace_permissions() +BEGIN + IF EXISTS ( + SELECT 1 FROM iam_permission + WHERE (id = 5102090 AND permission_code <> 'platform:firstleg:container:list') + OR (id = 5102092 AND permission_code <> 'platform:firstleg:container:create') + OR (id = 5102093 AND permission_code <> 'platform:firstleg:container:edit') + OR (id = 5102200 AND permission_code <> 'platform:firstleg:terminal-drayage:list') + OR (id = 5102201 AND permission_code <> 'platform:firstleg:terminal-drayage:document:edit') + OR (id = 5102202 AND permission_code <> 'platform:firstleg:terminal-drayage:fleet:edit') + OR (id = 5102203 AND permission_code <> 'platform:firstleg:terminal-drayage:pickup-appointment:edit') + OR (id = 5102204 AND permission_code <> 'platform:firstleg:terminal-drayage:pickup:confirm') + OR (id = 5102205 AND permission_code <> 'platform:firstleg:terminal-drayage:empty-return:confirm') + ) OR EXISTS ( + SELECT 1 FROM iam_permission + WHERE (permission_code = 'platform:firstleg:container:list' AND id <> 5102090) + OR (permission_code = 'platform:firstleg:container:create' AND id <> 5102092) + OR (permission_code = 'platform:firstleg:container:edit' AND id <> 5102093) + OR (permission_code = 'platform:firstleg:terminal-drayage:list' AND id <> 5102200) + OR (permission_code = 'platform:firstleg:terminal-drayage:document:edit' AND id <> 5102201) + OR (permission_code = 'platform:firstleg:terminal-drayage:fleet:edit' AND id <> 5102202) + OR (permission_code = 'platform:firstleg:terminal-drayage:pickup-appointment:edit' AND id <> 5102203) + OR (permission_code = 'platform:firstleg:terminal-drayage:pickup:confirm' AND id <> 5102204) + OR (permission_code = 'platform:firstleg:terminal-drayage:empty-return:confirm' AND id <> 5102205) + ) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='货柜双工作台权限初始化失败:权限ID或编码冲突'; + END IF; + + INSERT INTO iam_permission + (id, tenant_id, app_code, permission_type, parent_id, permission_code, + permission_name, route_path, http_method, sort_no, status, built_in, deleted) + VALUES + (5102090,0,'PLATFORM','MENU',5102000,'platform:firstleg:container:list', + '国内送柜报关','/container-loading/domestic','GET',40,'ACTIVE',1,0), + (5102092,0,'PLATFORM','BUTTON',5102090,'platform:firstleg:container:create', + '建立国内货柜',NULL,'POST',20,'ACTIVE',1,0), + (5102093,0,'PLATFORM','BUTTON',5102090,'platform:firstleg:container:edit', + '维护国内货柜资料',NULL,'PUT',30,'ACTIVE',1,0), + (5102200,0,'PLATFORM','MENU',5102000,'platform:firstleg:terminal-drayage:list', + '国外清关提柜','/container-loading/overseas','GET',41,'ACTIVE',1,0), + (5102201,0,'PLATFORM','BUTTON',5102200,'platform:firstleg:terminal-drayage:document:edit', + '维护目的港清关与DO/PU',NULL,'POST',10,'ACTIVE',1,0), + (5102202,0,'PLATFORM','BUTTON',5102200,'platform:firstleg:terminal-drayage:fleet:edit', + '维护目的港码头车队',NULL,'POST',20,'ACTIVE',1,0), + (5102203,0,'PLATFORM','BUTTON',5102200,'platform:firstleg:terminal-drayage:pickup-appointment:edit', + '预约目的港提柜',NULL,'POST',30,'ACTIVE',1,0), + (5102204,0,'PLATFORM','BUTTON',5102200,'platform:firstleg:terminal-drayage:pickup:confirm', + '确认目的港实际提柜',NULL,'POST',40,'ACTIVE',1,0), + (5102205,0,'PLATFORM','BUTTON',5102200,'platform:firstleg:terminal-drayage:empty-return:confirm', + '确认目的港实际还柜',NULL,'POST',50,'ACTIVE',1,0) + ON DUPLICATE KEY UPDATE + permission_type=VALUES(permission_type), parent_id=VALUES(parent_id), + permission_name=VALUES(permission_name), route_path=VALUES(route_path), + http_method=VALUES(http_method), sort_no=VALUES(sort_no), status='ACTIVE', + built_in=1, deleted=0; + + -- list 已包含详情只读;旧 container:view 不再作为别名或双权限入口。 + DELETE grant_row FROM iam_role_permission grant_row + JOIN iam_permission permission + ON permission.id=grant_row.permission_id AND permission.tenant_id=grant_row.tenant_id + WHERE permission.tenant_id=0 + AND permission.permission_code='platform:firstleg:container:view'; + UPDATE iam_permission + SET status='INACTIVE', deleted=1 + WHERE tenant_id=0 AND permission_code='platform:firstleg:container:view'; + + -- 平台超级管理员和现有订单运营保持货柜全链路能力;其他角色按两个菜单独立授权。 + INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) + SELECT 0, role.id, permission.id, CURRENT_TIMESTAMP(3) + FROM iam_role role + JOIN iam_permission permission + ON permission.tenant_id=0 AND permission.app_code='PLATFORM' + AND permission.permission_code IN ( + 'platform:firstleg:container:list', + 'platform:firstleg:container:create', + 'platform:firstleg:container:edit', + 'platform:firstleg:terminal-drayage:list', + 'platform:firstleg:terminal-drayage:document:edit', + 'platform:firstleg:terminal-drayage:fleet:edit', + 'platform:firstleg:terminal-drayage:pickup-appointment:edit', + 'platform:firstleg:terminal-drayage:pickup:confirm', + 'platform:firstleg:terminal-drayage:empty-return:confirm') + WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND role.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR') + AND role.status='ACTIVE' AND role.deleted=0 + AND permission.status='ACTIVE' AND permission.deleted=0; + + IF (SELECT COUNT(*) FROM iam_permission + WHERE tenant_id=0 AND app_code='PLATFORM' AND status='ACTIVE' AND deleted=0 + AND permission_code IN ( + 'platform:firstleg:container:list', + 'platform:firstleg:container:create', + 'platform:firstleg:container:edit', + 'platform:firstleg:terminal-drayage:list', + 'platform:firstleg:terminal-drayage:document:edit', + 'platform:firstleg:terminal-drayage:fleet:edit', + 'platform:firstleg:terminal-drayage:pickup-appointment:edit', + 'platform:firstleg:terminal-drayage:pickup:confirm', + 'platform:firstleg:terminal-drayage:empty-return:confirm')) <> 9 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='货柜双工作台权限初始化失败:权限目录不完整'; + END IF; + + IF (SELECT COUNT(DISTINCT CONCAT(role.role_code, ':', permission.permission_code)) + FROM iam_role_permission grant_row + JOIN iam_role role + ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id + JOIN iam_permission permission + ON permission.id=grant_row.permission_id AND permission.tenant_id=grant_row.tenant_id + WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND role.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR') + AND permission.permission_code IN ( + 'platform:firstleg:container:list', + 'platform:firstleg:container:create', + 'platform:firstleg:container:edit', + 'platform:firstleg:terminal-drayage:list', + 'platform:firstleg:terminal-drayage:document:edit', + 'platform:firstleg:terminal-drayage:fleet:edit', + 'platform:firstleg:terminal-drayage:pickup-appointment:edit', + 'platform:firstleg:terminal-drayage:pickup:confirm', + 'platform:firstleg:terminal-drayage:empty-return:confirm')) <> 18 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='货柜双工作台权限初始化失败:平台默认角色授权不完整'; + END IF; + + IF EXISTS (SELECT 1 FROM iam_permission + WHERE tenant_id=0 AND permission_code='platform:firstleg:container:view' + AND (status='ACTIVE' OR deleted=0)) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='货柜双工作台权限初始化失败:旧查看权限仍然有效'; + END IF; +END$$ +DELIMITER ; + +CALL migrate_container_workspace_permissions(); +DROP PROCEDURE IF EXISTS migrate_container_workspace_permissions; +-- 货柜双工作台权限结束,恢复头程数据库上下文 +USE baiyue_firstleg; + CALL baiyue_firstleg.assert_unified_final_schema(); DROP PROCEDURE IF EXISTS baiyue_firstleg.assert_unified_final_schema; SELECT 'PASS' AS migration_status, diff --git a/iam/src/test/java/com/baiyue/iam/repository/ContainerWorkspacePermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/ContainerWorkspacePermissionSqlContractTest.java index c1864ab61..40f5c5878 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/ContainerWorkspacePermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/ContainerWorkspacePermissionSqlContractTest.java @@ -4,6 +4,8 @@ import org.junit.jupiter.api.Test; import org.springframework.core.io.ClassPathResource; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Pattern; @@ -89,6 +91,25 @@ class ContainerWorkspacePermissionSqlContractTest { "INSERT IGNORE INTO iam_role_permission"); } + @Test + void unifiedIncrementContainsTheCompleteModuleSql() throws Exception { + Path unifiedPath = Path.of("deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + if (!Files.exists(unifiedPath)) { + unifiedPath = Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + } + String unified = Files.readString(unifiedPath, StandardCharsets.UTF_8); + String startMarker = "-- 货柜双工作台权限开始(与 iam/db/container-workspace-permissions.sql 保持一致)"; + String endMarker = "-- 货柜双工作台权限结束,恢复头程数据库上下文"; + int start = unified.indexOf(startMarker); + int bodyStart = unified.indexOf('\n', start) + 1; + int end = unified.indexOf(endMarker, bodyStart); + + assertThat(start).isGreaterThanOrEqualTo(0); + assertThat(bodyStart).isGreaterThan(start); + assertThat(end).isGreaterThan(bodyStart); + assertThat(unified.substring(bodyStart, end).trim()).isEqualTo(sql().trim()); + } + private static String sql() throws Exception { return new ClassPathResource("db/container-workspace-permissions.sql") .getContentAsString(StandardCharsets.UTF_8);