diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapper.java index 382697527..a7788ba18 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapper.java @@ -12,14 +12,11 @@ public interface InboundCodeRelationshipMapper { @Select("SELECT o.customer_id AS customerId,o.customer_name AS customerName,o.order_no AS orderNo," + "o.current_status AS orderStatus,p.plan_no AS planNo,p.status AS planStatus," + "COALESCE(p.status,o.current_status) AS receivingStatus," + - "COALESCE(b.overseas_warehouse_id,o.overseas_warehouse_id,CAST(p.overseas_warehouse_id AS CHAR)) AS overseasWarehouseId," + - "b.overseas_warehouse_code AS overseasWarehouseCode," + - "COALESCE(b.overseas_warehouse_name,o.overseas_warehouse_name) AS overseasWarehouseName " + + "CAST(p.overseas_warehouse_id AS CHAR) AS overseasWarehouseId " + "FROM ll_order o " + "LEFT JOIN ll_inbound_plan_line l ON l.customer_id=o.customer_id AND l.order_id=o.id AND l.inbound_code=o.inbound_code " + "LEFT JOIN ll_inbound_plan p ON p.customer_id=o.customer_id AND p.id=l.plan_id " + - "LEFT JOIN ll_inventory_balance b ON b.customer_id=o.customer_id AND b.inbound_order_id=o.id AND b.inbound_code=o.inbound_code " + - "WHERE o.inbound_code=#{inboundCode} ORDER BY o.customer_id,o.id,p.id,b.id") + "WHERE o.inbound_code=#{inboundCode} ORDER BY o.customer_id,o.id,p.id") List bases(@Param("inboundCode") String inboundCode); @Select("SELECT DISTINCT r.pallet_no FROM ll_inbound_stock_receipt r " + diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/model/InboundCodeRelationshipRows.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/model/InboundCodeRelationshipRows.java index 79c9f2424..49cf48766 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/model/InboundCodeRelationshipRows.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/model/InboundCodeRelationshipRows.java @@ -15,8 +15,6 @@ public final class InboundCodeRelationshipRows { private String planStatus; private String receivingStatus; private String overseasWarehouseId; - private String overseasWarehouseCode; - private String overseasWarehouseName; } @Data diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipService.java index 3e72514d1..612837483 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipService.java @@ -3,6 +3,7 @@ package com.baiyue.lastleg.inventory.query.service; import com.baiyue.lastleg.inventory.query.dto.InboundCodeRelationshipResponse; import com.baiyue.lastleg.inventory.query.mapper.InboundCodeRelationshipMapper; import com.baiyue.lastleg.inventory.query.model.InboundCodeRelationshipRows; +import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway; import jakarta.annotation.Resource; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; @@ -14,6 +15,7 @@ import java.util.Objects; @Service public class InboundCodeRelationshipService { @Resource private InboundCodeRelationshipMapper mapper; + @Resource private WarehouseResourceGateway warehouse; public InboundCodeRelationshipResponse find(String inboundCode) { String normalized = required(inboundCode); @@ -30,10 +32,6 @@ public class InboundCodeRelationshipService { "customer name"); String warehouseId = unique(bases.stream().map(InboundCodeRelationshipRows.Base::getOverseasWarehouseId).toList(), "overseas warehouse ID"); - String warehouseCode = unique(bases.stream().map(InboundCodeRelationshipRows.Base::getOverseasWarehouseCode).toList(), - "overseas warehouse code"); - String warehouseName = unique(bases.stream().map(InboundCodeRelationshipRows.Base::getOverseasWarehouseName).toList(), - "overseas warehouse name"); List orders = bases.stream() .filter(value -> trim(value.getOrderNo()) != null) .map(value -> new InboundCodeRelationshipResponse.TaillegOrder( @@ -50,14 +48,26 @@ public class InboundCodeRelationshipService { value.getProductNameZh(), value.getProductNameEn(), number(value.getPackageCount()))).toList(); String status = unique(bases.stream().map(InboundCodeRelationshipRows.Base::getReceivingStatus).toList(), "overseas receiving status"); - InboundCodeRelationshipResponse.OverseasWarehouse warehouse = warehouseId == null - && warehouseCode == null && warehouseName == null ? null - : new InboundCodeRelationshipResponse.OverseasWarehouse(warehouseId, warehouseCode, warehouseName); + InboundCodeRelationshipResponse.OverseasWarehouse warehouseView = resolveWarehouse(warehouseId); return new InboundCodeRelationshipResponse(normalized, true, - new InboundCodeRelationshipResponse.Customer(customerId, customerName), warehouse, status, + new InboundCodeRelationshipResponse.Customer(customerId, customerName), warehouseView, status, orders, plans, mapper.palletCodes(customerId, normalized), inventory); } + private InboundCodeRelationshipResponse.OverseasWarehouse resolveWarehouse(String warehouseId) { + if (warehouseId == null) return null; + final long id; + try { + id = Long.parseLong(warehouseId); + } catch (NumberFormatException exception) { + throw new ResponseStatusException(HttpStatus.CONFLICT, + "Inbound code has invalid overseas warehouse ID snapshot"); + } + WarehouseResourceGateway.WarehouseReference value = warehouse.requireActiveSharedWarehouse(id); + return new InboundCodeRelationshipResponse.OverseasWarehouse( + String.valueOf(value.warehouseId()), value.warehouseCode(), value.warehouseName()); + } + private static InboundCodeRelationshipResponse empty(String inboundCode) { return new InboundCodeRelationshipResponse(inboundCode, false, null, null, null, List.of(), List.of(), List.of(), List.of()); diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapperContractTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapperContractTest.java index 50f32fbe0..99f17f18e 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapperContractTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/mapper/InboundCodeRelationshipMapperContractTest.java @@ -13,7 +13,9 @@ class InboundCodeRelationshipMapperContractTest { String sql = String.join(" ", InboundCodeRelationshipMapper.class .getMethod("bases", String.class).getAnnotation(Select.class).value()); - assertThat(sql).contains("ll_order", "ll_inbound_plan", "ll_inventory_balance"); - assertThat(sql).doesNotContain("customerId}", "warehouse.", "iam."); + assertThat(sql) + .contains("ll_order", "ll_inbound_plan", "CAST(p.overseas_warehouse_id AS CHAR)") + .doesNotContain("o.source_warehouse_id", "o.overseas_warehouse_id", + "ll_inventory_balance", "customerId}", "warehouse.", "iam."); } } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipServiceTest.java index 75d71274a..23594f9dc 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/query/service/InboundCodeRelationshipServiceTest.java @@ -2,6 +2,7 @@ package com.baiyue.lastleg.inventory.query.service; import com.baiyue.lastleg.inventory.query.mapper.InboundCodeRelationshipMapper; import com.baiyue.lastleg.inventory.query.model.InboundCodeRelationshipRows; +import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,12 +24,14 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class InboundCodeRelationshipServiceTest { @Mock InboundCodeRelationshipMapper mapper; + @Mock WarehouseResourceGateway warehouse; private InboundCodeRelationshipService service; @BeforeEach void setUp() { service = new InboundCodeRelationshipService(); ReflectionTestUtils.setField(service, "mapper", mapper); + ReflectionTestUtils.setField(service, "warehouse", warehouse); } @Test @@ -49,6 +52,9 @@ class InboundCodeRelationshipServiceTest { void relationshipUsesBusinessNumbersAndKeepsLongIdentifiersAsStrings() { InboundCodeRelationshipRows.Base row = base("2092618717861048321", "Customer A"); when(mapper.bases("NYEXX2608300001")).thenReturn(List.of(row, row)); + when(warehouse.requireActiveSharedWarehouse(193000000000200003L)).thenReturn( + new WarehouseResourceGateway.WarehouseReference( + 193000000000200003L, "US-LAX-01", "洛杉矶一号仓", "ACTIVE")); when(mapper.palletCodes("2092618717861048321", "NYEXX2608300001")) .thenReturn(List.of("PAL-LAX-001")); InboundCodeRelationshipRows.InventorySku sku = new InboundCodeRelationshipRows.InventorySku(); @@ -60,6 +66,8 @@ class InboundCodeRelationshipServiceTest { assertThat(result.found()).isTrue(); assertThat(result.customer().customerId()).isEqualTo("2092618717861048321"); assertThat(result.overseasWarehouse().warehouseId()).isEqualTo("193000000000200003"); + assertThat(result.overseasWarehouse().warehouseCode()).isEqualTo("US-LAX-01"); + assertThat(result.overseasWarehouse().warehouseName()).isEqualTo("洛杉矶一号仓"); assertThat(result.taillegOrders()).extracting("orderNo").containsExactly("LMO-260830-0001"); assertThat(result.taillegOrders()).extracting("orderStatus").containsExactly("INBOUND_PLANNED"); assertThat(result.inboundPlans()).extracting("planNo").containsExactly("LIP-260830-0001"); @@ -81,6 +89,21 @@ class InboundCodeRelationshipServiceTest { verify(mapper, never()).inventory(anyString(), anyString()); } + @Test + void orderWithoutAClaimedPlanDoesNotExposeDomesticSourceWarehouseAsOverseas() { + InboundCodeRelationshipRows.Base row = base("2092618717861048321", "Customer A"); + row.setOverseasWarehouseId(null); + when(mapper.bases("NYEXX2608300027")).thenReturn(List.of(row)); + when(mapper.palletCodes("2092618717861048321", "NYEXX2608300027")).thenReturn(List.of()); + when(mapper.inventory("2092618717861048321", "NYEXX2608300027")).thenReturn(List.of()); + + var result = service.find("NYEXX2608300027"); + + assertThat(result.found()).isTrue(); + assertThat(result.overseasWarehouse()).isNull(); + verifyNoInteractions(warehouse); + } + @Test void blankAndOversizedInboundCodesAreRejected() { assertThatThrownBy(() -> service.find(" ")).isInstanceOf(ResponseStatusException.class) @@ -96,7 +119,6 @@ class InboundCodeRelationshipServiceTest { value.setOrderNo("LMO-260830-0001"); value.setOrderStatus("INBOUND_PLANNED"); value.setPlanNo("LIP-260830-0001"); value.setPlanStatus("COMPLETED"); value.setReceivingStatus("COMPLETED"); value.setOverseasWarehouseId("193000000000200003"); - value.setOverseasWarehouseCode("US-LAX-01"); value.setOverseasWarehouseName("洛杉矶一号仓"); return value; } }