diff --git a/deploy/sql/海外区域统一增量-MySQL8.sql b/deploy/sql/海外区域统一增量-MySQL8.sql index 6b02596d9..ac65f97a9 100644 --- a/deploy/sql/海外区域统一增量-MySQL8.sql +++ b/deploy/sql/海外区域统一增量-MySQL8.sql @@ -204,6 +204,22 @@ SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE 'ALTER TABLE ll_loading_order_status_history ADD KEY idx_ll_loading_history_customer_order(customer_id,order_id,created_at)')); PREPARE phase4_loading_history_customer_stmt FROM @ddl; EXECUTE phase4_loading_history_customer_stmt; DEALLOCATE PREPARE phase4_loading_history_customer_stmt; +-- 尾程订单明细实体、事件消费者和详情查询均使用 customer_id;已有开发库需从主订单回填。 +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='ll_order_detail' AND column_name='customer_id'), 'SELECT 1', + 'ALTER TABLE ll_order_detail ADD COLUMN customer_id VARCHAR(128) NULL COMMENT ''客户数据隔离键'' AFTER id')); +PREPARE phase4_order_detail_customer_stmt FROM @ddl; EXECUTE phase4_order_detail_customer_stmt; DEALLOCATE PREPARE phase4_order_detail_customer_stmt; +UPDATE ll_order_detail detail +JOIN ll_order orders ON orders.id=detail.order_id +SET detail.customer_id=orders.customer_id +WHERE detail.customer_id IS NULL; +ALTER TABLE ll_order_detail + MODIFY COLUMN customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键'; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() + AND table_name='ll_order_detail' AND index_name='idx_ll_detail_customer_order'), 'SELECT 1', + 'ALTER TABLE ll_order_detail ADD KEY idx_ll_detail_customer_order(customer_id,order_id,id)')); +PREPARE phase4_order_detail_customer_stmt FROM @ddl; EXECUTE phase4_order_detail_customer_stmt; DEALLOCATE PREPARE phase4_order_detail_customer_stmt; + -- 四期平台排车查询、智能预排与草稿锁;不开放编辑、发车、PDA 出库或派送。 CREATE TABLE IF NOT EXISTS ll_dispatch_order ( id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptService.java index 69fa42e4b..5bb25ffc9 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptService.java @@ -116,6 +116,7 @@ public class InboundStockReceiptService { order.setUpdatedAt(completedAt); orders.updateById(order); LastlegOrderStatusHistory history = new LastlegOrderStatusHistory(); + history.setCustomerId(order.getCustomerId()); history.setOrderId(order.getId()); history.setFromStatus(before); history.setToStatus("INBOUND_COMPLETED"); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java index 2d144ffc4..1f2845e1c 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java @@ -46,9 +46,11 @@ public class LastlegOrderService { public LastlegOrderDetailResponse detail(String customerId, long orderId) { LastlegOrder order = findOwned(customerId, orderId); List cargo = detailMapper.selectList(new LambdaQueryWrapper() + .eq(LastlegOrderDetail::getCustomerId, order.getCustomerId()) .eq(LastlegOrderDetail::getOrderId, orderId).orderByAsc(LastlegOrderDetail::getId)); List history = historyMapper.selectList( new LambdaQueryWrapper() + .eq(LastlegOrderStatusHistory::getCustomerId, order.getCustomerId()) .eq(LastlegOrderStatusHistory::getOrderId, orderId) .orderByAsc(LastlegOrderStatusHistory::getCreatedAt)); return new LastlegOrderDetailResponse(summary(order), cargo, history.stream() @@ -89,6 +91,7 @@ public class LastlegOrderService { .eq(LastlegOrderDetail::getOrderId, order.getId())); LastlegOrderStatusHistory history = new LastlegOrderStatusHistory(); + history.setCustomerId(order.getCustomerId()); history.setOrderId(order.getId()); history.setFromStatus(fromStatus); history.setToStatus(DESTINATION_ASSIGNED); diff --git a/lastleg-service/src/main/resources/db/lastleg.sql b/lastleg-service/src/main/resources/db/lastleg.sql index 5da318484..3c2f5c587 100644 --- a/lastleg-service/src/main/resources/db/lastleg.sql +++ b/lastleg-service/src/main/resources/db/lastleg.sql @@ -79,6 +79,7 @@ CREATE TABLE IF NOT EXISTS ll_order ( CREATE TABLE IF NOT EXISTS ll_order_detail ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单明细主键', + customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', order_id BIGINT NOT NULL COMMENT '尾程订单 ID', source_inbound_detail_id VARCHAR(128) NOT NULL COMMENT '来源入仓明细 ID', sku_code VARCHAR(128) COMMENT 'SKU 编码', @@ -99,7 +100,8 @@ CREATE TABLE IF NOT EXISTS ll_order_detail ( shipping_mark VARCHAR(255) COMMENT '唛头', PRIMARY KEY(id), UNIQUE KEY uk_ll_detail_source(order_id,source_inbound_detail_id), - KEY idx_ll_detail_order(order_id) + KEY idx_ll_detail_order(order_id), + KEY idx_ll_detail_customer_order(customer_id,order_id,id) ) ENGINE=InnoDB COMMENT='尾程订单实装商品冻结明细'; CREATE TABLE IF NOT EXISTS ll_loading_order_status_history ( diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptServiceTest.java index 1199e5409..1e28bfc5b 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundStockReceiptServiceTest.java @@ -84,7 +84,9 @@ class InboundStockReceiptServiceTest { assertEquals(10L, receipt.getValue().getInventoryPositionId()); assertEquals("INBOUND_COMPLETED", fixture.order.getCurrentStatus()); assertEquals("INBOUND_PLAN:COMPLETED", fixture.order.getSubOrderStatus()); - verify(orderHistories).insert(any(LastlegOrderStatusHistory.class)); + ArgumentCaptor history = ArgumentCaptor.forClass(LastlegOrderStatusHistory.class); + verify(orderHistories).insert(history.capture()); + assertEquals("100", history.getValue().getCustomerId()); } @Test diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/schema/LastlegOrderDetailSchemaContractTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/schema/LastlegOrderDetailSchemaContractTest.java new file mode 100644 index 000000000..f1276e0ed --- /dev/null +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/schema/LastlegOrderDetailSchemaContractTest.java @@ -0,0 +1,36 @@ +package com.baiyue.lastleg.schema; + +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 LastlegOrderDetailSchemaContractTest { + @Test + void orderDetailHasCustomerIsolationInBaselineAndRepeatableUpgrade() throws Exception { + String baseline = new ClassPathResource("db/lastleg.sql") + .getContentAsString(StandardCharsets.UTF_8); + String unified = Files.readString(Path.of("..", "deploy", "sql", "海外区域统一增量-MySQL8.sql"), + StandardCharsets.UTF_8); + String service = Files.readString(Path.of("src", "main", "java", "com", "baiyue", "lastleg", + "service", "LastlegOrderService.java"), StandardCharsets.UTF_8); + + assertThat(baseline) + .contains("CREATE TABLE IF NOT EXISTS ll_order_detail") + .contains("customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键'") + .contains("KEY idx_ll_detail_customer_order(customer_id,order_id,id)"); + assertThat(unified) + .contains("table_name='ll_order_detail' AND column_name='customer_id'") + .contains("UPDATE ll_order_detail detail") + .contains("SET detail.customer_id=orders.customer_id") + .contains("MODIFY COLUMN customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键'") + .contains("ADD KEY idx_ll_detail_customer_order(customer_id,order_id,id)"); + assertThat(service) + .contains(".eq(LastlegOrderDetail::getCustomerId, order.getCustomerId())") + .contains(".eq(LastlegOrderStatusHistory::getCustomerId, order.getCustomerId())"); + } +} diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java index 5c71ee8db..fdc785be6 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java @@ -78,6 +78,7 @@ class LastlegOrderServiceTest { assertEquals("LAX-02", cargo.getValue().getDestinationWarehouseCode()); ArgumentCaptor history = ArgumentCaptor.forClass(LastlegOrderStatusHistory.class); verify(histories).insert(history.capture()); + assertEquals("100", history.getValue().getCustomerId()); assertEquals("PENDING_ASSIGNMENT", history.getValue().getFromStatus()); assertEquals("DESTINATION_ASSIGNED", history.getValue().getToStatus()); }