贴标申请,仓储转运

This commit is contained in:
2026-09-22 08:49:21 +08:00
parent 9147190d67
commit 9a8412279c
28 changed files with 549 additions and 48 deletions
@@ -44,6 +44,12 @@ class RelabelContractTest {
String migration = Files.readString(Path.of("..", "scripts", "db", "incremental.sql"), StandardCharsets.UTF_8).toLowerCase();
String deployment = Files.readString(Path.of("..", "deploy", "sql", "海外区域统一增量-MySQL8.sql"),
StandardCharsets.UTF_8).toLowerCase();
for (String schema : new String[] { baseline, deployment }) {
assertTrue(schema.contains("key idx_ll_relabel_application_order (lastleg_order_id)"));
assertFalse(schema.contains("unique key uk_ll_relabel_application_order"),
"One received return order must support multiple relabel applications for remaining stock");
assertTrue(schema.contains("unique key uk_ll_relabel_application_idempotency"));
}
for (String schema : new String[] { baseline, migration }) {
assertTrue(schema.contains("ll_relabel_application"));
assertTrue(schema.contains("ll_relabel_item"));
@@ -466,12 +466,13 @@ class RelabelApplicationServiceTest {
}
@Test
void completedReturnRelabelOrderEntersPendingAssignment() {
void completedReturnRelabelKeepsParentInboundCompleted() {
RelabelApplication application = application(11L, "FBR-1", "10001", "key-1", "hash", RelabelApplicationService.READY_FOR_OUTBOUND);
application.setLastlegOrderId(21L);
application.setFulfillmentStatus("PRE_DISPATCH_CREATED");
LastlegOrder order = order(21L, "10001", "LMO-RELABEL-1", "PROCESSING");
order.setOrderType("RETURN_RELABEL");
order.setRelabelOrderNo("FBR-1");
when(applications.lockNo("10001", "FBR-1")).thenReturn(application);
stubDetail(application);
when(orders.selectById(21L)).thenReturn(order);
@@ -481,10 +482,32 @@ class RelabelApplicationServiceTest {
assertEquals("COMPLETED", application.getStatus());
assertEquals("OUTBOUNDED", application.getFulfillmentStatus());
assertEquals("PENDING_ASSIGNMENT", order.getCurrentStatus());
assertEquals("INBOUND_COMPLETED", order.getCurrentStatus());
assertEquals("COMPLETED", order.getRelabelStatus());
}
@Test
void completingEarlierReturnRelabelDoesNotOverwriteLaterApplicationStatus() {
RelabelApplication application = application(11L, "FBR-FIRST", "10001", "key-1", "hash", RelabelApplicationService.READY_FOR_OUTBOUND);
application.setLastlegOrderId(21L);
application.setFulfillmentStatus("PRE_DISPATCH_CREATED");
LastlegOrder order = order(21L, "10001", "LMO-RELABEL-1", "INBOUND_COMPLETED");
order.setOrderType("RETURN_RELABEL");
order.setRelabelOrderNo("FBR-SECOND");
order.setRelabelStatus("PROCESSING");
when(applications.lockNo("10001", "FBR-FIRST")).thenReturn(application);
stubDetail(application);
when(orders.selectById(21L)).thenReturn(order);
service.changeStatus("10001", "FBR-FIRST", "operator-2",
new RelabelRequests.ChangeStatus("COMPLETED", "finished"));
assertEquals("COMPLETED", application.getStatus());
assertEquals("INBOUND_COMPLETED", order.getCurrentStatus());
assertEquals("PROCESSING", order.getRelabelStatus());
assertEquals("FBR-SECOND", order.getRelabelOrderNo());
}
@Test
void completingPartialRelabelReleasesOnlyNotifiedPackages() {
RelabelApplication application = application(11L, "FBR-PARTIAL", "10001", "key-partial", "hash", RelabelApplicationService.READY_FOR_OUTBOUND);
@@ -508,8 +531,10 @@ class RelabelApplicationServiceTest {
@Test
void truckCustomerConfirmationIsIdempotentAndWaitsForPreDispatch() {
RelabelApplication application = confirmationApplication("TRUCK", false);
LastlegOrder linked = order(21L, "10001", "LMO-RELABEL-1", "WAIT_RELABEL");
when(applications.lockNo("10001", "FBR-1")).thenReturn(application);
stubDetail(application);
when(orders.selectById(21L)).thenReturn(linked);
service.confirmCompletion("10001", "FBR-1", "customer-1",
new RelabelRequests.CustomerConfirm("confirm-1", "photos accepted"));
@@ -520,6 +545,7 @@ class RelabelApplicationServiceTest {
verify(pdaTasks).updateWithVersion(review.capture(), eq(1));
assertEquals("COMPLETED", review.getValue().getStatus());
assertEquals("CONFIRMED", review.getValue().getReviewDecision());
assertEquals("WAIT_OUTBOUND", linked.getCurrentStatus());
assertNull(application.getOutboundOrderNo());
verify(outboundOrders, never()).insert(any(OutboundOrder.class));
@@ -555,6 +581,7 @@ class RelabelApplicationServiceTest {
@Test
void transferRelabelConfirmationReleasesTransferForDispatch() {
RelabelApplication application = confirmationApplication("TRUCK", false);
application.setLastlegOrderId(88L);
WarehouseTransferOrder transfer = new WarehouseTransferOrder();
transfer.setId(77L); transfer.setCustomerId("10001"); transfer.setRelabelNo("FBR-1");
transfer.setStatus("WAIT_RELABEL"); transfer.setLastlegOrderId(88L); transfer.setFbaWarehouseCode("ONT8");
@@ -38,6 +38,7 @@ class RelabelReturnCartonCandidateTest {
cartonItem.setProductNameZh("退货商品"); cartonItem.setQuantity(12L);
when(cartons.findAvailable("10001", "WH-1")).thenReturn(List.of(carton));
when(cartonItems.listCarton(9001L)).thenReturn(List.of(cartonItem));
when(cartons.relabelledQuantity(9001L, "SKU-RETURN")).thenReturn(1L);
List<RelabelResponses.InventoryCandidate> result = service.candidates("10001", "WH-1", "RC-WH");
@@ -45,8 +46,8 @@ class RelabelReturnCartonCandidateTest {
assertEquals("RETURN_CARTON", result.get(0).sourceType());
assertEquals(9001L, result.get(0).returnCartonId());
assertEquals("RC-WH-0001", result.get(0).cartonMark());
assertEquals(12, result.get(0).availablePackages());
assertEquals(11, result.get(0).availablePackages());
assertEquals("SKU-RETURN", result.get(0).skuItems().get(0).skuCode());
assertEquals(12, result.get(0).skuItems().get(0).quantity());
assertEquals(11, result.get(0).skuItems().get(0).quantity());
}
}