fix(lastleg): align outbound pallet workflows
This commit is contained in:
+1
@@ -166,6 +166,7 @@ class PlatformDispatchOutboundContractTest {
|
||||
for (String action : Set.of(dispatchAction, transfer, outboundDetail, outboundCancel)) {
|
||||
assertFalse(action.contains("name: customerId"));
|
||||
}
|
||||
assertTrue(outboundDetail.contains("pallets[].palletNo"));
|
||||
assertTrue(yaml.contains("platform:overseas-warehouse:dispatch:edit"));
|
||||
assertTrue(yaml.contains("platform:overseas-warehouse:dispatch:cancel"));
|
||||
assertTrue(yaml.contains("platform:overseas-warehouse:dispatch:transfer-delivery"));
|
||||
|
||||
+58
-4
@@ -270,19 +270,26 @@ class DeliveryTransferServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void outboundDetailDoesNotExposeExcludedPalletOrOutboundFulfillmentRows() {
|
||||
void outboundDetailIncludesPalletCodesForDisplay() {
|
||||
OutboundOrder outbound = outbound(301L, 101L, "DSP-101", "OUT-301", "transfer-101");
|
||||
DeliveryOrder delivery = delivery(401L, outbound, "DEL-401");
|
||||
OutboundPalletItem pallet = pallet(501L, "IP-ONT8-20260907-000001-P001", "ONT8", "Ontario", "IN-A", 12);
|
||||
pallet.setSkuCode("SKU-1");
|
||||
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
|
||||
when(deliveryOrders.lockByOutbound("TENANT-A", 301L)).thenReturn(delivery);
|
||||
when(outboundPallets.findByOutbound("TENANT-A", 301L)).thenReturn(List.of(pallet));
|
||||
|
||||
DeliveryResponses.OutboundDetail detail = service.outboundDetail("OUT-301");
|
||||
|
||||
assertEquals("OUT-301", detail.outbound().outboundNo());
|
||||
assertEquals("DEL-401", detail.delivery().deliveryNo());
|
||||
assertTrue(java.util.Arrays.stream(DeliveryResponses.OutboundDetail.class.getRecordComponents())
|
||||
.noneMatch(component -> "pallets".equals(component.getName())));
|
||||
verify(outboundPallets, never()).selectPage(any(Page.class), any());
|
||||
assertEquals(1, detail.pallets().size());
|
||||
assertEquals("IP-ONT8-20260907-000001-P001", detail.pallets().get(0).palletNo());
|
||||
assertEquals("IN-A", detail.pallets().get(0).inboundCode());
|
||||
assertEquals("ONT8", detail.pallets().get(0).destinationWarehouseCode());
|
||||
assertEquals("SKU-1", detail.pallets().get(0).skuCode());
|
||||
assertEquals(12, detail.pallets().get(0).packageCount());
|
||||
verify(outboundPallets).findByOutbound("TENANT-A", 301L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -426,6 +433,53 @@ class DeliveryTransferServiceTest {
|
||||
verify(pdaTasks).listByWarehouse("WH-1", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void outboundNumberResolvesDispatchWorkflowInBoundWarehouse() {
|
||||
OutboundOrder outbound = outbound(301L, 401L, "DSP-401", "OUT-301", "transfer-key");
|
||||
outbound.setOverseasWarehouseId("WH-1");
|
||||
outbound.setOutboundType("DISPATCH_DELIVERY");
|
||||
DispatchOrder dispatch = new DispatchOrder();
|
||||
dispatch.setId(401L); dispatch.setDispatchNo("DSP-401"); dispatch.setOverseasWarehouseId("WH-1");
|
||||
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
|
||||
when(dispatchOrders.findGlobalByDispatchNo("DSP-401")).thenReturn(dispatch);
|
||||
|
||||
DeliveryResponses.PdaTaskResolution result = service.resolvePdaTask("WH-1", "OUT-301");
|
||||
|
||||
assertEquals("DISPATCH", result.workflow());
|
||||
assertEquals("DSP-401", result.dispatchNo());
|
||||
assertEquals("OUT-301", result.outboundNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void outboundNumberResolvesOneClickTaskInBoundWarehouse() {
|
||||
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "one-click-key");
|
||||
outbound.setOverseasWarehouseId("WH-1");
|
||||
outbound.setOutboundType("ONE_CLICK_DROPSHIP");
|
||||
OutboundPdaTask task = new OutboundPdaTask();
|
||||
task.setCustomerId("TENANT-A"); task.setOutboundOrderId(301L); task.setTaskNo("PDA-701");
|
||||
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
|
||||
when(pdaTasks.findByOutboundAndWarehouse("TENANT-A", 301L, "WH-1")).thenReturn(task);
|
||||
|
||||
DeliveryResponses.PdaTaskResolution result = service.resolvePdaTask("WH-1", "OUT-301");
|
||||
|
||||
assertEquals("OUTBOUND", result.workflow());
|
||||
assertEquals("PDA-701", result.taskNo());
|
||||
assertEquals("OUT-301", result.outboundNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void pdaTaskResolutionDoesNotLeakAnotherWarehouse() {
|
||||
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "one-click-key");
|
||||
outbound.setOverseasWarehouseId("WH-2");
|
||||
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
|
||||
|
||||
ResponseStatusException exception = assertThrows(ResponseStatusException.class,
|
||||
() -> service.resolvePdaTask("WH-1", "OUT-301"));
|
||||
|
||||
assertEquals(404, exception.getStatusCode().value());
|
||||
verify(pdaTasks, never()).findByOutboundAndWarehouse(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void outboundPdaDetailReturnsEveryPickablePositionWithStableBusinessCodes() {
|
||||
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "one-click-key");
|
||||
|
||||
+35
@@ -167,6 +167,41 @@ class InboundPdaWorkflowServiceTest {
|
||||
targetPallet.getWarehouseLocationId(), "assign-wrong-warehouse")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvedAssignmentReplacesPlanPalletNumberWithPhysicalWarehouseCode() {
|
||||
targetPallet.setPalletNo("IP-ACY2-20260907-597057-P001");
|
||||
targetPallet.setWarehousePalletId(null);
|
||||
targetPallet.setWarehouseLocationId(null);
|
||||
targetPallet.setWarehouseResourceLockId(null);
|
||||
targetPallet.setAssignmentStatus("PENDING_ASSIGNMENT");
|
||||
WarehouseResourceGateway.WarehousePalletReference resource =
|
||||
new WarehouseResourceGateway.WarehousePalletReference(188L, "A002", 88L, 288L,
|
||||
"IDLE", "ACY2", 1);
|
||||
when(warehouse.reserve("100", 88L, 188L, 288L, "INBOUND_CONTAINER_DESTINATION_PALLET",
|
||||
"CONT-1:WH-A", "INBOUND_CONTAINER_DESTINATION_PALLET:CONT-1:WH-A:188")).thenReturn(999L);
|
||||
|
||||
service.assignResolvedPallet("100", plan, targetPallet, resource);
|
||||
|
||||
assertEquals("A002", targetPallet.getPalletNo());
|
||||
assertEquals(188L, targetPallet.getWarehousePalletId());
|
||||
assertEquals(288L, targetPallet.getWarehouseLocationId());
|
||||
verify(repository).update(targetPallet);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvedAssignmentRejectsPhysicalPalletWithoutBusinessCodeBeforeReservation() {
|
||||
targetPallet.setWarehouseResourceLockId(null);
|
||||
WarehouseResourceGateway.WarehousePalletReference resource =
|
||||
new WarehouseResourceGateway.WarehousePalletReference(188L, " ", 88L, 288L,
|
||||
"IDLE", "ACY2", 1);
|
||||
|
||||
ResponseStatusException exception = assertThrows(ResponseStatusException.class,
|
||||
() -> service.assignResolvedPallet("100", plan, targetPallet, resource));
|
||||
|
||||
assertEquals(409, exception.getStatusCode().value());
|
||||
verify(warehouse, never()).reserve(any(), anyLong(), anyLong(), anyLong(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void cartonScanBindsOnlyExpectedCartonAndRemoveMakesItScannableAgain() {
|
||||
InboundPlanCarton carton = carton("BOX-001", "UNASSIGNED", targetLine.getId(), "WH-A");
|
||||
|
||||
+2
@@ -87,10 +87,12 @@ class InboundStockReceiptServiceTest {
|
||||
assertEquals("Customer", request.getValue().customerName());
|
||||
assertEquals("900", request.getValue().overseasWarehouseId());
|
||||
assertEquals("Los Angeles", request.getValue().overseasWarehouseName());
|
||||
assertEquals("PLT-21", request.getValue().palletNo());
|
||||
ArgumentCaptor<InboundStockReceipt> receipt = ArgumentCaptor.forClass(InboundStockReceipt.class);
|
||||
verify(receipts).insert(receipt.capture());
|
||||
assertEquals(5L, receipt.getValue().getReceivedPackages());
|
||||
assertEquals(10L, receipt.getValue().getInventoryPositionId());
|
||||
assertEquals("PLT-21", receipt.getValue().getPalletNo());
|
||||
assertEquals("INBOUND_COMPLETED", fixture.order.getCurrentStatus());
|
||||
assertEquals("INBOUND_PLAN:COMPLETED", fixture.order.getSubOrderStatus());
|
||||
ArgumentCaptor<LastlegOrderStatusHistory> history = ArgumentCaptor.forClass(LastlegOrderStatusHistory.class);
|
||||
|
||||
+3
-1
@@ -74,13 +74,15 @@ class PdaOperationsOpenApiContractTest {
|
||||
"/api/pda/v1/last-leg/dispatches/{dispatchNo}/complete:",
|
||||
"/api/pda/v1/last-leg/dispatches/{dispatchNo}/depart:",
|
||||
"/api/pda/v1/last-leg/outbound-tasks:",
|
||||
"/api/pda/v1/last-leg/outbound-tasks/resolve/{businessNo}:",
|
||||
"/api/pda/v1/last-leg/outbound-tasks/{taskNo}:",
|
||||
"/api/pda/v1/last-leg/outbound-tasks/{taskNo}/pick:",
|
||||
"/api/pda/v1/last-leg/outbound-tasks/{taskNo}/complete:");
|
||||
for (String path : paths) assertTrue(yaml.contains(path), path);
|
||||
assertEquals(32, paths.size());
|
||||
assertEquals(33, paths.size());
|
||||
assertTrue(yaml.contains("enum: [LOCATION, PALLET]"));
|
||||
assertTrue(yaml.contains("enum: [APPROVE, REWORK]"));
|
||||
assertTrue(yaml.contains("Warehouse 权威实物托盘码"));
|
||||
assertTrue(yaml.contains("enum: [DAMAGED, MISSING_LABEL, LABEL_MISMATCH, UNREADABLE, OTHER]"));
|
||||
assertEquals(3, occurrences(yaml, "body.code=A0404"));
|
||||
assertFalse(yaml.contains("/api/pda/v1/last-leg/delivery"));
|
||||
|
||||
Reference in New Issue
Block a user