feat(firstleg): enforce single remainder split schema
This commit is contained in:
+15
-4
@@ -22,10 +22,13 @@ class InboundParentChildSqlContractTest {
|
||||
.contains("'fl_inbound_order', 'package_count'")
|
||||
.contains("'fl_inbound_order', 'split_purpose'")
|
||||
.contains("SET split_purpose = 'REMAINDER'")
|
||||
.contains("active_remainder_root_id")
|
||||
.contains("GENERATED ALWAYS AS (CASE WHEN inbound_role = 'MASTER'")
|
||||
.contains("GENERATED ALWAYS AS (CASE WHEN inbound_role = 'CHILD'")
|
||||
.contains("DROP INDEX uk_inbound_tenant_order")
|
||||
.contains("uk_inbound_master_order")
|
||||
.contains("uk_inbound_parent_split_sequence")
|
||||
.contains("uk_inbound_one_active_remainder")
|
||||
.contains("DROP INDEX uk_inbound_parent_sequence");
|
||||
}
|
||||
|
||||
@@ -54,17 +57,23 @@ class InboundParentChildSqlContractTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void protectsOwnershipAndTotals() {
|
||||
void protectsSingleRemainderWritesAndConservation() {
|
||||
assertThat(sql)
|
||||
.contains("子入仓单必须绑定同一客户的有效主单")
|
||||
.contains("parent_order.version > NEW.expected_parent_version")
|
||||
.contains("NEW.loaded_package_count")
|
||||
.contains("NEW.remaining_package_count")
|
||||
.contains("NEW.loaded_package_count + NEW.remaining_package_count <> NEW.package_count")
|
||||
.contains("NEW.loaded_child_inbound_id IS NOT NULL")
|
||||
.contains("NEW.child_inbound_id = batch.remainder_child_inbound_id")
|
||||
.contains("source_order.package_count = NEW.loaded_package_count")
|
||||
.contains("item.child_inbound_id <> NEW.remainder_child_inbound_id")
|
||||
.contains("<> NEW.remaining_package_count")
|
||||
.contains("根入仓单原始箱数与已完成分片及当前余量不守恒")
|
||||
.contains("COALESCE(source_order.package_count, source_order.total_package_count) = NEW.package_count")
|
||||
.contains("AND plan_item.deleted = 0))))\n OR NOT EXISTS (")
|
||||
.contains("source_batch.inbound_id = COALESCE(batch.source_inbound_id, batch.parent_inbound_id)")
|
||||
.contains("拆分批次来源必须是箱数匹配且未消费的根主单或余量子单")
|
||||
.contains("拆分批次来源必须是箱数守恒的根主单或余量分片")
|
||||
.contains("SUM(split_item.package_count) > source_item.package_count")
|
||||
.contains("子单承接箱数超过来源测量箱规箱数")
|
||||
.contains("child_order.package_count >= NEW.package_count")
|
||||
@@ -75,13 +84,14 @@ class InboundParentChildSqlContractTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesMultiChildAndMultiSkuTotals() {
|
||||
void validatesSingleRemainderAndMultiSkuTotals() {
|
||||
assertThat(sql)
|
||||
.contains("uk_inbound_parent_split_sequence")
|
||||
.contains("uk_inbound_one_active_remainder")
|
||||
.contains("uk_inbound_split_batch_line")
|
||||
.contains("uk_inbound_split_batch_source_child")
|
||||
.contains("COUNT(DISTINCT item.child_inbound_id)")
|
||||
.contains("NOT BETWEEN 1 AND 2")
|
||||
.contains("<> CASE WHEN NEW.remaining_package_count > 0 THEN 1 ELSE 0 END")
|
||||
.contains("child_order.package_count <> SUM(item.package_count)");
|
||||
}
|
||||
|
||||
@@ -108,6 +118,7 @@ class InboundParentChildSqlContractTest {
|
||||
assertThat(sql)
|
||||
.contains("table_name = 'fl_inbound_split_batch'")
|
||||
.contains("uk_inbound_split_source_once")
|
||||
.contains("uk_inbound_one_active_remainder")
|
||||
.contains("table_name = 'fl_inbound_split_item'")
|
||||
.contains("uk_inbound_split_batch_source_child")
|
||||
.contains("is_nullable = 'NO'")
|
||||
|
||||
+16
@@ -107,6 +107,22 @@ class Phase3FinalUnifiedSqlContractTest {
|
||||
.doesNotContain("UNIQUE KEY `uk_inbound_split_batch_source_item`");
|
||||
}
|
||||
|
||||
@Test
|
||||
void unifiedEntryEnforcesSingleRemainderWritesAndKeepsLegacyColumns() throws Exception {
|
||||
String sql = normalise(Files.readString(resolveUnified()));
|
||||
|
||||
assertThat(sql)
|
||||
.contains("'fl_inbound_order', 'active_remainder_root_id'")
|
||||
.contains("uk_inbound_one_active_remainder")
|
||||
.contains("uk_inbound_split_source_once")
|
||||
.contains("NEW.loaded_child_inbound_id IS NOT NULL")
|
||||
.contains("NEW.child_inbound_id = batch.remainder_child_inbound_id")
|
||||
.contains("source_order.package_count = NEW.loaded_package_count")
|
||||
.contains("根入仓单原始箱数与已完成分片及当前余量不守恒")
|
||||
.contains("'fl_inbound_split_batch', 'loaded_child_inbound_id'")
|
||||
.contains("fk_inbound_split_loaded_child");
|
||||
}
|
||||
|
||||
private static void assertBlock(String unified, String marker, String nextMarker, String modulePath)
|
||||
throws Exception {
|
||||
int start = unified.indexOf(marker);
|
||||
|
||||
+3
-2
@@ -16,7 +16,7 @@ class SplitPreloadSqlContractTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void limitsSecondaryInboundDepth() throws Exception {
|
||||
void limitsNewChildrenToRootBasedRemainders() throws Exception {
|
||||
String sql = moduleMigration();
|
||||
assertThat(sql)
|
||||
.contains("parent_inbound_id")
|
||||
@@ -25,7 +25,8 @@ class SplitPreloadSqlContractTest {
|
||||
.contains("split_status")
|
||||
.contains("uk_inbound_parent_split_sequence")
|
||||
.contains("fk_inbound_parent_order")
|
||||
.contains("子入仓单必须标记LOADED或REMAINDER")
|
||||
.contains("新建子入仓单只能作为余量分片")
|
||||
.contains("uk_inbound_one_active_remainder")
|
||||
.contains("入仓单主子归属创建后不可修改");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user