This commit is contained in:
2026-10-19 16:41:20 +08:00
parent 44c76d8953
commit e0677e7ae7
22 changed files with 546 additions and 18 deletions
@@ -134,6 +134,9 @@ class DeliveryTransferServiceTest {
@BeforeEach
void setUp() {
service = new DeliveryTransferService();
var outboundQuantities = new com.baiyue.lastleg.delivery.repository.OutboundQuantityRepository();
ReflectionTestUtils.setField(outboundQuantities, "pallets", outboundPallets);
ReflectionTestUtils.setField(service, "outboundQuantities", outboundQuantities);
ReflectionTestUtils.setField(service, "deliveryExecution", new DeliveryExecutionGuard(new com.baiyue.lastleg.delivery.repository.DeliveryExecutionRepository(outboundOrders, deliveryOrders)));
var actualSources = mock(DispatchCargoSourceQuery.class);
ReflectionTestUtils.setField(service, "cargoSources", actualSources);
@@ -731,6 +734,20 @@ class DeliveryTransferServiceTest {
assertEquals("DISCARD_OUTBOUND".equals(type) ? null : "LX-REAL-001", detail.outbound().lxCodes());
}
/** 已有废弃出库即便快照误存五件,列表及详情汇总也应显示一箱。 */
@Test
void discardOutboundSummaryCountsReturnCartonOnceAcrossSkuLines() {
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "outbound-301");
outbound.setOutboundType("DISCARD_OUTBOUND"); outbound.setPackageCount(5);
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
var first = pallet(501L, "PALLET-1", null, null, "RT-1", 2);
first.setCartonMarks("BOX-1"); first.setReturnSkuQuantity(2L);
var second = pallet(502L, "PALLET-1", null, null, "RT-1", 3);
second.setCartonMarks("BOX-1"); second.setReturnSkuQuantity(3L);
when(outboundPallets.findByOutbound("TENANT-A", 301L)).thenReturn(List.of(first, second));
assertEquals(1, service.outboundDetail("OUT-301").outbound().packageCount());
}
@Test
void dispatchOutboundStillRequiresItsDeliveryDocument() {
OutboundOrder outbound = outbound(301L, 101L, "DSP-101", "OUT-301", "dispatch-301");
@@ -189,6 +189,28 @@ class PdaCargoDiscardServiceTest {
verify(photoService).confirm(same(application), eq("散箱"), eq(List.of(101L)), eq(false));
}
/** 退货一箱五件按指定箱作业,不得按五箱或整托处理。 */
@Test void returnCartonUsesPieceUnitAndRequiresSelectedCartonEvenWhenBoundToPallet() {
item.setSourceType("RETURN_CARTON"); item.setReturnCartonId(31L); item.setDiscardPackages(5);
var carton = new com.baiyue.lastleg.returnreceipt.entity.ReturnInventoryCarton();
carton.setCustomerId("CUSTOMER"); carton.setPalletCode("PALLET-1"); carton.setCartonMark("RETURN-BOX-1");
when(returnCartons.selectById(31L)).thenReturn(carton);
when(applications.selectList(any())).thenReturn(List.of(application));
var task = service.resolve(identity, "PALLET-1", "CD-1");
assertEquals("CARTON", task.scanMode());
assertEquals(List.of("RETURN-BOX-1"), task.cartonMarks());
assertEquals(5, task.skus().get(0).plannedPackages());
assertEquals("件", task.skus().get(0).quantityUnit());
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", request(5)));
verifyNoInteractions(adjustments);
var confirm = new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, 5)),
List.of(101L), List.of("RETURN-BOX-1"), false);
service.confirm(identity, "CD-1", "PALLET-1", confirm);
assertEquals(1, application.getTotalPackages());
assertEquals(new BigDecimal("5.00"), application.getTotalFee());
verify(adjustments).discardPalletItem(eq("CUSTOMER"), same(application), same(item), anyList(), eq(5), eq("OP"), any());
}
@Test void partialBoundPalletOnlyExposesSelectedBoxesAndRequiresTheirScan() {
looseTask(); item.setCartonScanRequired(true);
var stockService = (com.baiyue.lastleg.discard.service.CargoDiscardStockService) ReflectionTestUtils.getField(service, "stockService");
@@ -104,4 +104,23 @@ class CargoDiscardOutboundServiceTest {
assertThrows(ResponseStatusException.class, () -> service.create(application, "OP"));
verify(outbounds, never()).insert(any(OutboundOrder.class)); verify(pallets, never()).insert(any(OutboundPalletItem.class));
}
/** 同一退货箱含多个 SKU 时箱数只记一次,件数仍逐 SKU 保留。 */
@Test void returnCartonProjectionSeparatesOneBoxFromFivePiecesAndSyncsCompletion() {
first.setReturnCartonId(31L); first.setSourceType("RETURN_CARTON"); first.setDiscardPackages(2);
second.setReturnCartonId(31L); second.setSourceType("RETURN_CARTON"); second.setDiscardPackages(3);
var carton = new ReturnInventoryCarton(); carton.setCustomerId("C1"); carton.setOverseasWarehouseId("99");
carton.setCartonMark("BOX-31"); carton.setPalletCode("PALLET-1");
when(returnCartons.selectById(31L)).thenReturn(carton);
service.create(application, "OP");
assertEquals(1, document.getPackageCount());
assertEquals(1, snapshots.stream().mapToInt(OutboundPalletItem::getPackageCount).sum());
assertEquals(5, snapshots.stream().mapToLong(OutboundPalletItem::getReturnSkuQuantity).sum());
first.setPdaStatus("COMPLETED"); first.setActualDiscardPackages(2);
second.setPdaStatus("COMPLETED"); second.setActualDiscardPackages(3);
application.setStatus("PDA_COMPLETED");
service.sync(application);
assertEquals(1, document.getPackageCount());
assertEquals(1, snapshots.stream().mapToInt(OutboundPalletItem::getPickedPackageCount).sum());
}
}
@@ -99,6 +99,9 @@ class CargoDiscardServiceTest {
@BeforeEach
void setUp() {
service = new CargoDiscardService();
var quantities = new com.baiyue.lastleg.discard.repository.CargoDiscardQuantityRepository();
ReflectionTestUtils.setField(quantities, "items", items);
ReflectionTestUtils.setField(service, "quantities", quantities);
ReflectionTestUtils.setField(service, "warehouseDirectory", warehouseDirectory);
lenient().when(warehouseDirectory.receivingWarehouses(any())).thenReturn(com.baiyue.common.core.api.ApiResponse.success(List.of(
new com.baiyue.lastleg.client.DomesticWarehouseDirectoryClient.ReceivingWarehouse(99L, "LAX", "洛杉矶仓", "US", "ACTIVE"))));
@@ -227,6 +230,32 @@ class CargoDiscardServiceTest {
assertEquals("SKU-RETURN", result.get(0).skus().get(0).skuCode());
}
/** 创建和已有单据查询均按退货箱去重,五件不可计为五箱。 */
@Test void returnMixedSkuCartonCreatesOneBoxAndExistingSummaryReadsOneBox() {
var carton = new ReturnInventoryCarton(); carton.setId(901L); carton.setCustomerId("100");
carton.setOverseasWarehouseId("99"); carton.setSourceReturnNo("RT-1"); carton.setCartonMark("BOX-1");
carton.setStatus("AVAILABLE");
var skuA = new ReturnInventoryCartonItem(); skuA.setSkuCode("A"); skuA.setQuantity(2L);
var skuB = new ReturnInventoryCartonItem(); skuB.setSkuCode("B"); skuB.setQuantity(3L);
when(returnCartons.lockId(901L)).thenReturn(carton);
when(returnCartons.selectById(901L)).thenReturn(carton);
when(returnCartonItems.lockSku(901L, "A")).thenReturn(skuA);
when(returnCartonItems.lockSku(901L, "B")).thenReturn(skuB);
when(returnCartonItems.lockCarton(901L)).thenReturn(List.of(skuA, skuB));
when(returnCartons.markDiscardPending(901L, "100")).thenReturn(1);
var detail = service.create("100", "OP", new CargoDiscardRequests.Create(List.of(
new CargoDiscardRequests.Item(null, 901L, "A", 2),
new CargoDiscardRequests.Item(null, 901L, "B", 3)), "return-five-pieces", null));
assertEquals(1, storedApplication.get().getTotalPackages());
assertEquals(new BigDecimal("5.00"), storedApplication.get().getTotalFee());
assertEquals(1, detail.summary().totalPackages());
assertEquals(5, storedItems.stream().mapToInt(CargoDiscardItem::getDiscardPackages).sum());
storedApplication.get().setTotalPackages(5); storedApplication.get().setTotalFee(new BigDecimal("25.00"));
var existing = service.detail("100", storedApplication.get().getDiscardNo());
assertEquals(1, existing.summary().totalPackages());
assertEquals(new BigDecimal("5.00"), existing.summary().totalFee());
}
@Test
void approvalPushesToPdaWithoutDeductingInventory() {
CargoDiscardApplication application = pendingApplication();