允许私人地址按独立托盘生成海外入库计划
This commit is contained in:
+10
@@ -48,6 +48,15 @@ class InboundPlanOrderMapperContractTest {
|
||||
row = jdbc.queryForMap(sql, "C1", 1L);
|
||||
assertEquals("ABE3", row.get("fbaWarehouseCode"));
|
||||
assertEquals(row.get("destinationWarehouseCode"), row.get("fbaWarehouseCode"));
|
||||
|
||||
jdbc.update("INSERT INTO ll_order (id,customer_id) VALUES (2,'C1')");
|
||||
jdbc.update("INSERT INTO ll_order_detail VALUES (2,NULL,NULL,'私人地址 A')");
|
||||
row = jdbc.queryForMap(sql, "C1", 2L);
|
||||
assertEquals(1L, ((Number) row.get("destinationCount")).longValue());
|
||||
assertEquals("私人地址 A", row.get("destinationWarehouseName"));
|
||||
jdbc.update("INSERT INTO ll_order_detail VALUES (2,NULL,NULL,'私人地址 B')");
|
||||
row = jdbc.queryForMap(sql, "C1", 2L);
|
||||
assertEquals(2L, ((Number) row.get("destinationCount")).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,6 +66,7 @@ class InboundPlanOrderMapperContractTest {
|
||||
String sql = String.join(" ", method.getAnnotation(Select.class).value());
|
||||
assertTrue(sql.contains("COALESCE(NULLIF(o.transfer_warehouse_code,''),NULLIF(o.fba_warehouse_code,'')) AS fbaWarehouseCode"),
|
||||
method.getName());
|
||||
assertTrue(sql.contains("NULLIF(TRIM(d.destination_warehouse_name),'')"), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
@@ -70,6 +70,33 @@ class ContainerInboundPlanPreviewTest {
|
||||
assertEquals(List.of("DESTINATION_NOT_READY"), result.groups().get(4).orders().get(0).blockers());
|
||||
}
|
||||
|
||||
@Test
|
||||
void privateAddressReadinessRequiresOneNamedDestinationWithoutMasterWarehouseIdentity() {
|
||||
when(orderMapper.containerPreviewOrders("BOOKING-PRIVATE")).thenReturn(List.of(
|
||||
privateAddressRow(1L, "私人地址 A", 1),
|
||||
privateAddressRow(2L, " ", 1),
|
||||
privateAddressRow(3L, "私人地址 B", 2)));
|
||||
|
||||
var result = service.previewContainer("BOOKING-PRIVATE");
|
||||
var orders = result.groups().stream().flatMap(group -> group.orders().stream()).toList();
|
||||
var ready = orders.stream().filter(order -> order.orderId().equals("1")).findFirst().orElseThrow();
|
||||
assertEquals("READY", ready.readiness());
|
||||
assertEquals("PRIVATE_ADDRESS", ready.destinationType());
|
||||
assertEquals(List.of(), ready.blockers());
|
||||
assertEquals(1, ready.targetPalletCount());
|
||||
assertEquals(2, result.blockedOrderCount());
|
||||
orders.stream().filter(order -> !order.orderId().equals("1")).forEach(order ->
|
||||
assertEquals(List.of("DESTINATION_NOT_READY"), order.blockers()));
|
||||
}
|
||||
|
||||
private InboundPlanOrderMapper.ContainerPreviewOrderRow privateAddressRow(long id, String name, int destinations) {
|
||||
return new InboundPlanOrderMapper.ContainerPreviewOrderRow("100", id, "LM-" + id, "FO-" + id,
|
||||
"测试客户", "FIRST_LEG", "OVERSEAS", "IN-" + id, "PENDING_ASSIGNMENT", null,
|
||||
"MSCU6639870", 1, 4, BigDecimal.ONE, "193000000000200003", "US-LAX-01",
|
||||
"洛杉矶仓", null, null, null, name, destinations, false, 1,
|
||||
null, null, null, null, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashesBlockedPreviewEvenWhenContainerAndWarehouseFactsAreNull() {
|
||||
when(orderMapper.containerPreviewOrders("BOOKING-NULL")).thenReturn(List.of(
|
||||
|
||||
+38
@@ -37,6 +37,7 @@ import java.time.LocalDate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
@@ -101,6 +102,43 @@ class InboundPlanServiceTest {
|
||||
.thenReturn(java.time.LocalDate.of(2026, 9, 15));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertsPrivateAddressWithoutCreatingADestinationWarehouseIdentity() {
|
||||
SourceOrderSnapshot source = new SourceOrderSnapshot(2L, "100", "MSCU6639870", "RK-PRIVATE",
|
||||
"PENDING_ASSIGNMENT", null, BigDecimal.ONE, 4, 1,
|
||||
"193000000000200003", "US-LAX-01", "洛杉矶仓", null, null, null, "私人地址 A", 1, 0);
|
||||
when(orderMapper.lockOrder("100", 2L)).thenReturn(List.of(source));
|
||||
when(orderMapper.markPlanned(any(), any(), any(), org.mockito.ArgumentMatchers.anyInt(), any()))
|
||||
.thenReturn(1);
|
||||
|
||||
var result = service.convert("100", 2L);
|
||||
|
||||
assertEquals(1, result.palletCount());
|
||||
ArgumentCaptor<InboundPlanLine> line = ArgumentCaptor.forClass(InboundPlanLine.class);
|
||||
verify(lineMapper).insert(line.capture());
|
||||
assertNull(line.getValue().getDestinationWarehouseId());
|
||||
assertNull(line.getValue().getDestinationWarehouseCode());
|
||||
assertEquals("私人地址 A", line.getValue().getDestinationWarehouseName());
|
||||
assertEquals(4, line.getValue().getRequiredPackageCount());
|
||||
ArgumentCaptor<InboundPlanPallet> pallet = ArgumentCaptor.forClass(InboundPlanPallet.class);
|
||||
verify(palletMapper).insert(pallet.capture());
|
||||
assertEquals("私人地址 A", pallet.getValue().getDestinationWarehouseName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsPrivateAddressWithoutANamedDestination() {
|
||||
SourceOrderSnapshot source = new SourceOrderSnapshot(2L, "100", "MSCU6639870", "RK-PRIVATE",
|
||||
"PENDING_ASSIGNMENT", null, BigDecimal.ONE, 4, 1,
|
||||
"193000000000200003", "US-LAX-01", "洛杉矶仓", null, null, null, " ", 1, 0);
|
||||
when(orderMapper.lockOrder("100", 2L)).thenReturn(List.of(source));
|
||||
|
||||
ResponseStatusException failure = assertThrows(ResponseStatusException.class,
|
||||
() -> service.convert("100", 2L));
|
||||
|
||||
assertEquals(400, failure.getStatusCode().value());
|
||||
verify(planMapper, never()).insert(any(InboundPlan.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertsOnlyTheSelectedInboundOrderToItsOwnPlan() throws Exception {
|
||||
assertNotNull(InboundPlanService.class.getMethod("convert", String.class, Long.class)
|
||||
|
||||
Reference in New Issue
Block a user