diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index e7f6acec2..64c6fabe7 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -6567,14 +6567,20 @@ DROP PROCEDURE IF EXISTS unified_publish_assert_fee_item_preflight; DELIMITER $$ CREATE PROCEDURE unified_publish_assert_fee_item_preflight() BEGIN - IF (SELECT COUNT(*) FROM tmp_fee_item_seed) <> 110 - OR (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'DOMESTIC') <> 84 - OR (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'INTERNATIONAL') <> 26 THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子数量或国内国际范围不正确'; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed) <> 110 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子总数不正确'; END IF; - IF EXISTS (SELECT fee_code FROM tmp_fee_item_seed GROUP BY fee_code HAVING COUNT(*) > 1) - OR EXISTS (SELECT trade_scope, fee_type_name FROM tmp_fee_item_seed GROUP BY trade_scope, fee_type_name HAVING COUNT(*) > 1) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子编码或语义键重复'; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'DOMESTIC') <> 84 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel国内种子数量不正确'; + END IF; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'INTERNATIONAL') <> 26 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel国际种子数量不正确'; + END IF; + IF EXISTS (SELECT fee_code FROM tmp_fee_item_seed GROUP BY fee_code HAVING COUNT(*) > 1) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子编码重复'; + END IF; + IF EXISTS (SELECT trade_scope, fee_type_name FROM tmp_fee_item_seed GROUP BY trade_scope, fee_type_name HAVING COUNT(*) > 1) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子语义键重复'; END IF; IF EXISTS ( SELECT f.id @@ -6648,18 +6654,20 @@ BEGIN IF EXISTS ( SELECT f.id FROM fl_fee_item f - LEFT JOIN tmp_fee_item_seed by_code ON by_code.fee_code = NULLIF(TRIM(f.fee_code), '') - LEFT JOIN tmp_fee_item_seed by_semantic ON by_semantic.trade_scope = f.trade_scope - AND by_semantic.fee_type_name = f.fee_type_name - WHERE f.tenant_id > 0 AND by_code.seed_no IS NULL AND by_semantic.seed_no IS NULL + LEFT JOIN tmp_fee_item_seed matched_seed + ON matched_seed.fee_code = NULLIF(TRIM(f.fee_code), '') + OR (matched_seed.trade_scope = f.trade_scope + AND matched_seed.fee_type_name = f.fee_type_name) + WHERE f.tenant_id > 0 AND matched_seed.seed_no IS NULL ) THEN SELECT 'UNMAPPED_CUSTOMER_ITEM' AS conflict_type, f.id, f.tenant_id, f.fee_code, f.trade_scope, f.fee_type_name FROM fl_fee_item f - LEFT JOIN tmp_fee_item_seed by_code ON by_code.fee_code = NULLIF(TRIM(f.fee_code), '') - LEFT JOIN tmp_fee_item_seed by_semantic ON by_semantic.trade_scope = f.trade_scope - AND by_semantic.fee_type_name = f.fee_type_name - WHERE f.tenant_id > 0 AND by_code.seed_no IS NULL AND by_semantic.seed_no IS NULL; + LEFT JOIN tmp_fee_item_seed matched_seed + ON matched_seed.fee_code = NULLIF(TRIM(f.fee_code), '') + OR (matched_seed.trade_scope = f.trade_scope + AND matched_seed.fee_type_name = f.fee_type_name) + WHERE f.tenant_id > 0 AND matched_seed.seed_no IS NULL; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:存在无法匹配公共种子的客户费用项目'; END IF; IF EXISTS ( diff --git a/firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql b/firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql index b47ce73c4..4bb4cdd04 100644 --- a/firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql +++ b/firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql @@ -170,14 +170,20 @@ DROP PROCEDURE IF EXISTS phase2_publish_assert_fee_item_preflight; DELIMITER $$ CREATE PROCEDURE phase2_publish_assert_fee_item_preflight() BEGIN - IF (SELECT COUNT(*) FROM tmp_fee_item_seed) <> 110 - OR (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'DOMESTIC') <> 84 - OR (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'INTERNATIONAL') <> 26 THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子数量或国内国际范围不正确'; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed) <> 110 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子总数不正确'; END IF; - IF EXISTS (SELECT fee_code FROM tmp_fee_item_seed GROUP BY fee_code HAVING COUNT(*) > 1) - OR EXISTS (SELECT trade_scope, fee_type_name FROM tmp_fee_item_seed GROUP BY trade_scope, fee_type_name HAVING COUNT(*) > 1) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子编码或语义键重复'; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'DOMESTIC') <> 84 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel国内种子数量不正确'; + END IF; + IF (SELECT COUNT(*) FROM tmp_fee_item_seed WHERE trade_scope = 'INTERNATIONAL') <> 26 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel国际种子数量不正确'; + END IF; + IF EXISTS (SELECT fee_code FROM tmp_fee_item_seed GROUP BY fee_code HAVING COUNT(*) > 1) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子编码重复'; + END IF; + IF EXISTS (SELECT trade_scope, fee_type_name FROM tmp_fee_item_seed GROUP BY trade_scope, fee_type_name HAVING COUNT(*) > 1) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:Excel种子语义键重复'; END IF; IF EXISTS ( SELECT f.id @@ -251,18 +257,20 @@ BEGIN IF EXISTS ( SELECT f.id FROM fl_fee_item f - LEFT JOIN tmp_fee_item_seed by_code ON by_code.fee_code = NULLIF(TRIM(f.fee_code), '') - LEFT JOIN tmp_fee_item_seed by_semantic ON by_semantic.trade_scope = f.trade_scope - AND by_semantic.fee_type_name = f.fee_type_name - WHERE f.tenant_id > 0 AND by_code.seed_no IS NULL AND by_semantic.seed_no IS NULL + LEFT JOIN tmp_fee_item_seed matched_seed + ON matched_seed.fee_code = NULLIF(TRIM(f.fee_code), '') + OR (matched_seed.trade_scope = f.trade_scope + AND matched_seed.fee_type_name = f.fee_type_name) + WHERE f.tenant_id > 0 AND matched_seed.seed_no IS NULL ) THEN SELECT 'UNMAPPED_CUSTOMER_ITEM' AS conflict_type, f.id, f.tenant_id, f.fee_code, f.trade_scope, f.fee_type_name FROM fl_fee_item f - LEFT JOIN tmp_fee_item_seed by_code ON by_code.fee_code = NULLIF(TRIM(f.fee_code), '') - LEFT JOIN tmp_fee_item_seed by_semantic ON by_semantic.trade_scope = f.trade_scope - AND by_semantic.fee_type_name = f.fee_type_name - WHERE f.tenant_id > 0 AND by_code.seed_no IS NULL AND by_semantic.seed_no IS NULL; + LEFT JOIN tmp_fee_item_seed matched_seed + ON matched_seed.fee_code = NULLIF(TRIM(f.fee_code), '') + OR (matched_seed.trade_scope = f.trade_scope + AND matched_seed.fee_type_name = f.fee_type_name) + WHERE f.tenant_id > 0 AND matched_seed.seed_no IS NULL; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '二期费用项目迁移失败:存在无法匹配公共种子的客户费用项目'; END IF; IF EXISTS ( diff --git a/firstleg/src/test/java/com/baiyue/firstleg/repository/FeeItemMigrationSqlContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/repository/FeeItemMigrationSqlContractTest.java new file mode 100644 index 000000000..05c24592f --- /dev/null +++ b/firstleg/src/test/java/com/baiyue/firstleg/repository/FeeItemMigrationSqlContractTest.java @@ -0,0 +1,36 @@ +package com.baiyue.firstleg.repository; + +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.assertj.core.api.Assertions.assertThat; + +class FeeItemMigrationSqlContractTest { + @Test + void temporarySeedTableIsNotReopenedWithinOneMysqlStatement() throws Exception { + assertMysqlCompatible(resolve("deploy/sql/头程数据库统一增量-MySQL8.sql")); + assertMysqlCompatible(resolve( + "firstleg/src/main/resources/db/phase2-published-freight-detail-migration.sql")); + } + + private static void assertMysqlCompatible(Path path) throws Exception { + String sql = Files.readString(path, StandardCharsets.UTF_8); + assertThat(sql) + .contains("LEFT JOIN tmp_fee_item_seed matched_seed") + .contains("matched_seed.fee_code = NULLIF(TRIM(f.fee_code), '')") + .contains("matched_seed.trade_scope = f.trade_scope") + .doesNotContain("LEFT JOIN tmp_fee_item_seed by_code") + .doesNotContain("LEFT JOIN tmp_fee_item_seed by_semantic") + .doesNotContain("OR (SELECT COUNT(*) FROM tmp_fee_item_seed") + .doesNotContain("OR EXISTS (SELECT trade_scope, fee_type_name FROM tmp_fee_item_seed"); + } + + private static Path resolve(String value) { + Path direct = Path.of(value); + if (Files.exists(direct)) return direct; + return Path.of("..", value).normalize(); + } +}