147 lines
7.4 KiB
Java
147 lines
7.4 KiB
Java
package com.baiyue.lastleg.schema;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
class Phase5OverseasUpgradeSqlContractTest {
|
|
private static final List<String> PHASE5_TABLES = List.of(
|
|
"ll_dispatch_pda_task", "ll_dispatch_pda_pick", "ll_dispatch_pda_operation",
|
|
"ll_dispatch_pda_pick_order", "ll_outbound_order", "ll_outbound_pallet_item",
|
|
"ll_outbound_pda_task", "ll_outbound_pda_pick", "ll_delivery_order",
|
|
"ll_delivery_operation", "ll_dropship_order_profile", "ll_dropship_carton",
|
|
"ll_dropship_sku_inventory", "ll_dropship_carton_ledger", "ll_exception_order",
|
|
"ll_exception_return_item", "ll_exception_order_command", "ll_customer_visit");
|
|
|
|
@Test
|
|
void overseasFixedEntryCreatesEveryPhase5TableExactlyOnce() throws Exception {
|
|
String overseas = repositoryFile("deploy/sql/海外区域统一增量-MySQL8.sql");
|
|
|
|
for (String table : PHASE5_TABLES) {
|
|
String create = "CREATE TABLE " + table + " (";
|
|
assertThat(overseas.indexOf(create)).as(table).isGreaterThanOrEqualTo(0);
|
|
assertThat(count(overseas, create)).as(table).isEqualTo(1);
|
|
assertThat(overseas.indexOf(table)).as(table + " first reference")
|
|
.isEqualTo(overseas.indexOf(create) + "CREATE TABLE ".length());
|
|
}
|
|
assertThat(overseas).doesNotContain("assert_phase5_lastleg_identifiers_migratable", "ALTER TABLE ll_");
|
|
}
|
|
|
|
@Test
|
|
void overseasFixedEntryContainsFinalPhase5ShapesWithoutMigrationBackfill() throws Exception {
|
|
String overseas = repositoryFile("deploy/sql/海外区域统一增量-MySQL8.sql");
|
|
String normalized = normalize(overseas);
|
|
|
|
assertThat(createStatement(overseas, "ll_outbound_order")).contains(
|
|
"customer_id", "outbound_type", "lx_codes", "request_hash");
|
|
assertThat(createStatement(overseas, "ll_outbound_pallet_item")).contains("picked_package_count");
|
|
assertThat(createStatement(overseas, "ll_delivery_order")).contains(
|
|
"customer_id", "overseas_warehouse_name", "waybill_no", "signed_packages");
|
|
assertThat(normalized).contains("check(signed_packagesisnullor(signed_packages>=0andsigned_packages<=package_count))");
|
|
assertThat(createStatement(overseas, "ll_dropship_order_profile")).contains(
|
|
"source_pallet_no", "manifest_version", "manifest_package_count",
|
|
"manifest_fragment_count", "manifest_hash");
|
|
assertThat(normalized).contains(
|
|
"keyidx_ll_dropship_profile_manifest(source_pallet_no,manifest_hash)",
|
|
"uniquekeyuk_ll_dropship_sku_inventory(profile_id,sku_code)");
|
|
assertThat(createStatement(overseas, "ll_relabel_item")).contains(
|
|
"destination_fba_warehouse_code", "source_inventory_balance_id",
|
|
"source_inventory_position_id", "source_inbound_order_id");
|
|
assertThat(overseas).doesNotContain("\nUPDATE ", "\nDELETE ", "ALTER TABLE ll_");
|
|
}
|
|
|
|
@Test
|
|
void transferFinalMeasurementColumnsAreCreatedBeforeAnyBusinessWrite() throws Exception {
|
|
for (String path : List.of("lastleg-service/src/main/resources/db/lastleg.sql",
|
|
"deploy/sql/海外区域统一增量-MySQL8.sql")) {
|
|
String sql = repositoryFile(path);
|
|
String carton = createStatement(sql, "ll_warehouse_transfer_carton");
|
|
for (String column : List.of("customer_carton_mark", "length_cm", "width_cm", "height_cm",
|
|
"gross_weight_kg", "counted_quantity", "count_idempotency_key", "count_request_hash",
|
|
"counted_by", "counted_at", "discrepancy_reason", "transfer_pallet_id", "sku_items_json")) {
|
|
assertThat(carton).as(path + ":" + column).contains(column);
|
|
}
|
|
assertThat(createStatement(sql, "ll_warehouse_transfer_item")).contains("declared_quantity");
|
|
assertThat(createStatement(sql, "ll_cargo_discard_item")).contains("idx_ll_cargo_discard_return_carton");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void overseasFixedEntryAndModuleBaselineBothDefineCompletePhase5Tables() throws Exception {
|
|
String baseline = repositoryFile("lastleg-service/src/main/resources/db/lastleg.sql");
|
|
String overseas = repositoryFile("deploy/sql/海外区域统一增量-MySQL8.sql");
|
|
|
|
for (String table : PHASE5_TABLES) {
|
|
assertThat(createStatement(overseas, table)).as(table)
|
|
.contains("PRIMARY KEY", "COMMENT='");
|
|
assertThat(createStatement(baseline, table)).as(table)
|
|
.contains("PRIMARY KEY", "COMMENT='");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void unifiedSessionDoesNotInitializeASecondAuthorizationProjection() throws Exception {
|
|
String overseas = repositoryFile("deploy/sql/海外区域统一增量-MySQL8.sql");
|
|
assertThat(overseas).doesNotContain("CREATE TABLE ll_security_projection", "CREATE TABLE ll_security_event_inbox",
|
|
"baseline-platform-admin-authorization-v0", "@platform_admin_overseas_authorities");
|
|
String primary = repositoryFile("deploy/sql/头程数据库统一增量-MySQL8.sql");
|
|
assertThat(primary).contains("CREATE TABLE iam_security_subject_version", "CREATE TABLE iam_security_tenant_version");
|
|
}
|
|
|
|
@Test
|
|
void overseasReturnOrdersUseTheFinalCleanSchemaWithoutLegacyBackfill() throws Exception {
|
|
String overseas = repositoryFile("deploy/sql/海外区域统一增量-MySQL8.sql");
|
|
|
|
assertThat(overseas).contains("CREATE TABLE ll_return_order (", "CREATE TABLE ll_return_order_item (")
|
|
.doesNotContain("o.source_order_id COLLATE", "o.source_order_no COLLATE");
|
|
}
|
|
|
|
@Test
|
|
void domesticFixedEntryKeepsIamPermissionsButOwnsNoLastlegBusinessSchema() throws Exception {
|
|
String domestic = repositoryFile("deploy/sql/头程数据库统一增量-MySQL8.sql");
|
|
|
|
assertThat(domestic).contains(
|
|
"platform:overseas-warehouse:dispatch:list",
|
|
"platform:overseas-warehouse:exception-order:list",
|
|
"platform:overseas-warehouse:customer-visit:list");
|
|
assertThat(domestic).doesNotContain(
|
|
"USE baiyue_lastleg",
|
|
"CREATE DATABASE IF NOT EXISTS baiyue_lastleg",
|
|
"CREATE TABLE IF NOT EXISTS ll_",
|
|
"ALTER TABLE ll_");
|
|
}
|
|
|
|
private static String createStatement(String sql, String table) {
|
|
String token = "CREATE TABLE IF NOT EXISTS " + table + " (";
|
|
int start = sql.indexOf(token);
|
|
if (start < 0) {
|
|
token = "CREATE TABLE " + table + " (";
|
|
start = sql.indexOf(token);
|
|
}
|
|
int end = sql.indexOf(';', start);
|
|
assertThat(start).as(table).isGreaterThanOrEqualTo(0);
|
|
assertThat(end).as(table).isGreaterThan(start);
|
|
return sql.substring(start, end + 1);
|
|
}
|
|
|
|
private static String normalize(String sql) {
|
|
return sql.toLowerCase(Locale.ROOT).replaceAll("\\s+", "");
|
|
}
|
|
|
|
private static int count(String source, String token) {
|
|
return source.split(java.util.regex.Pattern.quote(token), -1).length - 1;
|
|
}
|
|
|
|
private static String repositoryFile(String relative) throws Exception {
|
|
Path path = Path.of(relative);
|
|
if (!Files.exists(path)) path = Path.of("..").resolve(relative);
|
|
return Files.readString(path, StandardCharsets.UTF_8);
|
|
}
|
|
}
|