diff --git a/auth/src/test/java/com/baiyue/auth/repository/InitialAccountSeedSqlContractTest.java b/auth/src/test/java/com/baiyue/auth/repository/InitialAccountSeedSqlContractTest.java new file mode 100644 index 000000000..025bf6ec7 --- /dev/null +++ b/auth/src/test/java/com/baiyue/auth/repository/InitialAccountSeedSqlContractTest.java @@ -0,0 +1,34 @@ +package com.baiyue.auth.repository; + +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 static org.assertj.core.api.Assertions.assertThat; + +class InitialAccountSeedSqlContractTest { + @Test + void initializesOnlyThePlatformAndItTestAdministratorAccounts() throws Exception { + assertAccountSeed(new ClassPathResource("db/phase1-admin-accounts.sql") + .getContentAsString(StandardCharsets.UTF_8)); + assertAccountSeed(Files.readString(unifiedSql(), StandardCharsets.UTF_8)); + } + + private static void assertAccountSeed(String sql) { + assertThat(sql) + .contains("(1000001, 'platform_admin'") + .contains("'平台系统管理员', 'ACTIVE'") + .contains("(1000002, 'merchant_admin'") + .contains("'IT 测试客户管理员', 'ACTIVE'") + .contains("password_change_required") + .doesNotContain("一期演示企业管理员"); + } + + private static Path unifiedSql() { + Path path = Path.of("deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + return Files.exists(path) ? path : Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + } +} diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index e27f4e424..f82c3b86f 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -1081,8 +1081,9 @@ INSERT INTO iam_tenant ( '91310000ITTEST0001', 'IT 测试客户管理员', '13800000000', 'it-test@example.com', NOW(3), 1000001, 1000001, 0, 0) ON DUPLICATE KEY UPDATE - tenant_name = VALUES(tenant_name), tenant_type = VALUES(tenant_type), + tenant_code = VALUES(tenant_code), tenant_name = VALUES(tenant_name), tenant_type = VALUES(tenant_type), status = 'ACTIVE', legal_name = VALUES(legal_name), + unified_social_credit_code = VALUES(unified_social_credit_code), contact_name = VALUES(contact_name), contact_phone = VALUES(contact_phone), contact_email = VALUES(contact_email), approved_at = COALESCE(approved_at, NOW(3)), approved_by = VALUES(approved_by), deleted = 0; diff --git a/iam/src/main/resources/db/phase1-admin-rbac.sql b/iam/src/main/resources/db/phase1-admin-rbac.sql index 11143f480..4159ce349 100644 --- a/iam/src/main/resources/db/phase1-admin-rbac.sql +++ b/iam/src/main/resources/db/phase1-admin-rbac.sql @@ -31,8 +31,9 @@ INSERT INTO iam_tenant ( '91310000ITTEST0001', 'IT 测试客户管理员', '13800000000', 'it-test@example.com', NOW(3), 1000001, 1000001, 0, 0) ON DUPLICATE KEY UPDATE - tenant_name = VALUES(tenant_name), tenant_type = VALUES(tenant_type), + tenant_code = VALUES(tenant_code), tenant_name = VALUES(tenant_name), tenant_type = VALUES(tenant_type), status = 'ACTIVE', legal_name = VALUES(legal_name), + unified_social_credit_code = VALUES(unified_social_credit_code), contact_name = VALUES(contact_name), contact_phone = VALUES(contact_phone), contact_email = VALUES(contact_email), approved_at = COALESCE(approved_at, NOW(3)), approved_by = VALUES(approved_by), deleted = 0; diff --git a/iam/src/test/java/com/baiyue/iam/repository/InitialIdentitySeedSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/InitialIdentitySeedSqlContractTest.java new file mode 100644 index 000000000..86f26ec04 --- /dev/null +++ b/iam/src/test/java/com/baiyue/iam/repository/InitialIdentitySeedSqlContractTest.java @@ -0,0 +1,37 @@ +package com.baiyue.iam.repository; + +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 static org.assertj.core.api.Assertions.assertThat; + +class InitialIdentitySeedSqlContractTest { + @Test + void initializesPlatformAndItTestCustomerIdentitiesWithStableIds() throws Exception { + assertIdentitySeed(new ClassPathResource("db/phase1-admin-rbac.sql") + .getContentAsString(StandardCharsets.UTF_8)); + assertIdentitySeed(Files.readString(unifiedSql(), StandardCharsets.UTF_8)); + } + + private static void assertIdentitySeed(String sql) { + assertThat(sql) + .contains("(0, 'PLATFORM', '虫虫出海平台'") + .contains("(10001, 'IT_TEST', 'IT 测试客户'") + .contains("(2000001, 1000001, 'INTERNAL', '平台系统管理员'") + .contains("(2000002, 1000002, 'ENTERPRISE', 'IT 测试客户管理员'") + .contains("(3000001, 0, 2000001, 'EMPLOYEE'") + .contains("(3000002, 10001, 2000002, 'OWNER'") + .contains("tenant_code = VALUES(tenant_code)") + .doesNotContain("PHASE1_DEMO") + .doesNotContain("一期演示企业"); + } + + private static Path unifiedSql() { + Path path = Path.of("deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + return Files.exists(path) ? path : Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"); + } +} diff --git a/scripts/admin-test-env-modules/phase3-container-loading.mjs b/scripts/admin-test-env-modules/phase3-container-loading.mjs index 0b5445956..1e1c24152 100644 --- a/scripts/admin-test-env-modules/phase3-container-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-container-loading.mjs @@ -68,12 +68,11 @@ export async function run(context) { const bookingDraft = { customerId: tenantId, customerName: inbound?.summary?.customerName || `验收客户-${tenantId}`, channelCode: channelCode || 'FBA', channelName, warehouseId, warehouseName, - billOfLadingNo: `BL-${suffix}`, shippingCompanyId: null, shippingCompanyName: `验收船公司-${suffix}`, - bookingAgentId: null, bookingAgentName: `验收代理-${suffix}`, vesselName: `验收船-${suffix}`, - voyageNo: `V-${suffix}`, departurePortCode: 'CNSZX', departurePortName: '深圳', + shippingCompanyId: null, shippingCompanyName: `验收船公司-${suffix}`, + bookingAgentId: null, bookingAgentName: `验收代理-${suffix}`, + departurePortCode: 'CNSZX', departurePortName: '深圳', destinationPortCode: 'USLAX', destinationPortName: '洛杉矶', placeOfDelivery: 'LAX', - serviceTerm: 'CY/CY', freightTerm: 'PREPAID', estimatedSailingAt: '2026-09-01T08:00:00', - estimatedArrivalAt: '2026-09-20T08:00:00', remark: context.marker, + serviceTerm: 'CY/CY', freightTerm: 'PREPAID', remark: context.marker, parties: [{ partyType: 'SHIPPER', partyName: `发货方-${suffix}` }, { partyType: 'CONSIGNEE', partyName: `收货方-${suffix}` }, { partyType: 'NOTIFY_PARTY', partyName: `通知方-${suffix}` }], diff --git a/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs b/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs index 519c66b3b..1dea2579f 100644 --- a/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs @@ -136,6 +136,8 @@ test('container loading creates and confirms booking before scoped candidates', ]) assert.match(value, /channelCode: channelCode/) assert.match(value, /warehouseId, warehouseName/) + const draft = value.slice(value.indexOf('const bookingDraft = {'), value.indexOf('context.assert(MODULE, \'订舱渠道与仓库快照完整\'')) + assert.doesNotMatch(draft, /billOfLadingNo|vesselName|voyageNo|estimatedSailingAt|estimatedArrivalAt/) assert.match(value, /containerAllocations\?\.\[0\]/) assert.match(value, /bookingId=\$\{encodeURIComponent\(containerId\)\}&warehouseId=/) assert.doesNotMatch(value, /POST', CONTAINERS, containerPayload/) diff --git a/warehouse/src/test/java/com/baiyue/warehouse/repository/InitialWarehouseResourceSeedSqlContractTest.java b/warehouse/src/test/java/com/baiyue/warehouse/repository/InitialWarehouseResourceSeedSqlContractTest.java new file mode 100644 index 000000000..7a4c50d72 --- /dev/null +++ b/warehouse/src/test/java/com/baiyue/warehouse/repository/InitialWarehouseResourceSeedSqlContractTest.java @@ -0,0 +1,41 @@ +package com.baiyue.warehouse.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 InitialWarehouseResourceSeedSqlContractTest { + @Test + void initializesAvailablePalletAndLocationsForBothDomesticWarehouses() throws Exception { + assertModuleSeed(Files.readString(Path.of("src", "main", "resources", "db", "phase2-pallet-seed.sql"), + StandardCharsets.UTF_8)); + assertUnifiedSeed(Files.readString(Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"), + StandardCharsets.UTF_8)); + } + + private static void assertModuleSeed(String sql) { + assertSeed(sql, "190000000000000001", "190000000000000002", "190000000000000"); + } + + private static void assertUnifiedSeed(String sql) { + assertSeed(sql, "193000000000200001", "193000000000200002", "193000000000200"); + } + + private static void assertSeed(String sql, String yiwuId, String dongguanId, String idPrefix) { + assertThat(sql) + .contains("0," + yiwuId + ",'TP-001'") + .contains("0," + dongguanId + ",'TP-002'") + .contains("(" + idPrefix + "201,0," + yiwuId + ",'A','A区','A1'") + .contains("(" + idPrefix + "202,0," + yiwuId + ",'A','A区','A0'") + .contains("(" + idPrefix + "203,0," + dongguanId + ",'A','A区','A1'") + .contains("(" + idPrefix + "204,0," + dongguanId + ",'A','A区','A0'") + .contains("shared_overflow") + .contains("'AVAILABLE'") + .doesNotContain("INSERT INTO wh_location_reservation") + .doesNotContain("INSERT INTO wh_location_occupancy"); + } +}