提交
This commit is contained in:
+10
@@ -672,6 +672,16 @@ class DeliveryTransferServiceTest {
|
||||
assertEquals(4, detail.pallets().get(0).packageCount());
|
||||
}
|
||||
|
||||
@org.junit.jupiter.params.ParameterizedTest
|
||||
@org.junit.jupiter.params.provider.ValueSource(strings = {"DISCARD_OUTBOUND", "ONE_CLICK_DROPSHIP"})
|
||||
void discardDoesNotExposeHistoricInboundCodeAsLxButDropshipKeepsRealLx(String type) {
|
||||
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "outbound-301");
|
||||
outbound.setOutboundType(type); outbound.setLxCodes("LX-REAL-001");
|
||||
when(outboundOrders.findGlobalByNo("OUT-301")).thenReturn(outbound);
|
||||
var detail = service.outboundDetail("OUT-301");
|
||||
assertEquals("DISCARD_OUTBOUND".equals(type) ? null : "LX-REAL-001", detail.outbound().lxCodes());
|
||||
}
|
||||
|
||||
@Test
|
||||
void dispatchOutboundStillRequiresItsDeliveryDocument() {
|
||||
OutboundOrder outbound = outbound(301L, 101L, "DSP-101", "OUT-301", "dispatch-301");
|
||||
|
||||
+41
@@ -3,10 +3,51 @@ package com.baiyue.lastleg.discard;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonItemMapper;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class CargoDiscardSchemaContractTest {
|
||||
@Test
|
||||
void returnCartonDeductionAllowsZeroButRejectsNegativeStock() throws Exception {
|
||||
String baseline;
|
||||
try (var input = getClass().getResourceAsStream("/db/lastleg.sql")) {
|
||||
baseline = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
var constraint = java.util.regex.Pattern.compile(
|
||||
"CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK\\(([^)]+)\\)")
|
||||
.matcher(baseline);
|
||||
assertTrue(constraint.find());
|
||||
String deduction = ReturnInventoryCartonItemMapper.class.getMethod("deduct", long.class, long.class)
|
||||
.getAnnotation(Update.class).value()[0]
|
||||
.replace("#{quantity}", "?").replace("#{id}", "?");
|
||||
try (var connection = DriverManager.getConnection("jdbc:h2:mem:discard_zero_quantity;MODE=MySQL")) {
|
||||
try (var statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE ll_return_inventory_carton_item (id BIGINT PRIMARY KEY, "
|
||||
+ "quantity BIGINT NOT NULL, CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK("
|
||||
+ constraint.group(1) + "))");
|
||||
statement.execute("INSERT INTO ll_return_inventory_carton_item VALUES (1, 3)");
|
||||
try (var update = connection.prepareStatement(deduction)) {
|
||||
update.setLong(1, 3); update.setLong(2, 1); update.setLong(3, 3);
|
||||
assertEquals(1, update.executeUpdate());
|
||||
update.setLong(1, 1); update.setLong(3, 1);
|
||||
assertEquals(0, update.executeUpdate());
|
||||
}
|
||||
try (var result = statement.executeQuery("SELECT quantity FROM ll_return_inventory_carton_item WHERE id=1")) {
|
||||
assertTrue(result.next());
|
||||
assertEquals(0, result.getLong(1));
|
||||
}
|
||||
assertThrows(SQLException.class, () -> statement.executeUpdate(
|
||||
"UPDATE ll_return_inventory_carton_item SET quantity=-1 WHERE id=1"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void baselineContainsDiscardApplicationReservationAndHistoryTables() throws Exception {
|
||||
String sql;
|
||||
|
||||
+16
@@ -15,6 +15,22 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MerchantCargoDiscardControllerTest {
|
||||
@Test
|
||||
void completionUsesAuthenticatedCustomerAndIndependentPermission() throws Exception {
|
||||
controller.confirmCompletion(user(100L, "MERCHANT"), "CD001");
|
||||
verify(service).confirmCompletion("100", "CD001", "1");
|
||||
assertThrows(ResponseStatusException.class,
|
||||
() -> controller.confirmCompletion(user(0L, "PLATFORM"), "CD001"));
|
||||
var guard = MerchantCargoDiscardController.class.getMethod("confirmCompletion", AuthenticatedUser.class, String.class)
|
||||
.getAnnotation(org.springframework.security.access.prepost.PreAuthorize.class);
|
||||
org.junit.jupiter.api.Assertions.assertEquals(
|
||||
"hasAuthority('merchant:overseas-warehouse:discard:confirm')", guard.value());
|
||||
org.junit.jupiter.api.Assertions.assertFalse(java.util.Arrays.stream(CargoDiscardController.class.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(org.springframework.web.bind.annotation.PostMapping.class))
|
||||
.flatMap(method -> java.util.Arrays.stream(method.getAnnotation(org.springframework.web.bind.annotation.PostMapping.class).value()))
|
||||
.anyMatch(path -> path.endsWith("/complete") || path.endsWith("/confirm-completion")));
|
||||
}
|
||||
|
||||
private final CargoDiscardService service = mock(CargoDiscardService.class);
|
||||
private final MerchantCargoDiscardController controller = controller();
|
||||
private final CargoDiscardRequests.Query query = new CargoDiscardRequests.Query(
|
||||
|
||||
+9
@@ -43,6 +43,7 @@ class CargoDiscardOutboundServiceTest {
|
||||
application = new CargoDiscardApplication(); application.setId(1L); application.setCustomerId("C1");
|
||||
application.setDiscardNo("CD-TEST"); application.setOverseasWarehouseId("99");
|
||||
application.setTotalPackages(5); application.setStatus("APPROVED");
|
||||
application.setInboundCodes("RT-123,RK-456");
|
||||
first = line(11L, 21L, 3); second = line(12L, 22L, 2);
|
||||
when(items.listApplication("C1", 1L)).thenReturn(List.of(first, second));
|
||||
when(cartons.listApplication("C1", 1L)).thenReturn(List.of());
|
||||
@@ -63,6 +64,7 @@ class CargoDiscardOutboundServiceTest {
|
||||
@Test void approvalCreatesExactlyOneDocumentAndImmutablePlannedLines() {
|
||||
service.create(application, "OP"); service.create(application, "OP");
|
||||
assertEquals("DISCARD_OUTBOUND", document.getOutboundType()); assertEquals("WAIT_PICK", document.getStatus());
|
||||
assertNull(document.getLxCodes());
|
||||
assertEquals(5, document.getPackageCount()); assertEquals(2, document.getPalletCount());
|
||||
assertTrue(service.outboundNo(application).startsWith("OB-"));
|
||||
assertEquals(List.of(3, 2), snapshots.stream().map(OutboundPalletItem::getPackageCount).toList());
|
||||
@@ -82,6 +84,13 @@ class CargoDiscardOutboundServiceTest {
|
||||
service.create(application, "OP"); application.setStatus("CANCELLED"); service.sync(application);
|
||||
assertEquals("CANCELLED", document.getStatus()); assertTrue(snapshots.stream().allMatch(s -> "CANCELLED".equals(s.getStatus())));
|
||||
}
|
||||
@Test void syncClearsHistoricallyMislabelledInboundCodesWithoutChangingSourceSnapshots() {
|
||||
first.setInboundCode("RK-456");
|
||||
service.create(application, "OP"); document.setLxCodes("RT-123,RK-456");
|
||||
service.sync(application);
|
||||
assertNull(document.getLxCodes()); assertEquals("RK-456", snapshots.get(0).getInboundCode());
|
||||
assertEquals("RT-123,RK-456", application.getInboundCodes());
|
||||
}
|
||||
@Test void returnSourceKeepsRealCartonMarkWithoutInventingPalletNumber() {
|
||||
first.setReturnCartonId(31L); first.setSourceType("RETURN_CARTON");
|
||||
var carton = new ReturnInventoryCarton(); carton.setId(31L); carton.setCustomerId("C1");
|
||||
|
||||
+46
-1
@@ -47,6 +47,36 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CargoDiscardServiceTest {
|
||||
@Test
|
||||
void customerConfirmationClosesPdaCompletedApplicationOnceWithoutAnotherDeduction() {
|
||||
CargoDiscardApplication application = new CargoDiscardApplication();
|
||||
application.setId(1001L); application.setCustomerId("100"); application.setDiscardNo("CD001");
|
||||
application.setTotalPackages(1); application.setOverseasWarehouseName("测试仓"); application.setStatus(CargoDiscardService.PDA_COMPLETED);
|
||||
storedApplication.set(application);
|
||||
when(applications.lockNo("100", "CD001")).thenReturn(application);
|
||||
|
||||
service.confirmCompletion("100", "CD001", "CUSTOMER");
|
||||
var confirmedAt = application.getCustomerConfirmedAt();
|
||||
org.junit.jupiter.api.Assertions.assertNotNull(confirmedAt);
|
||||
assertEquals(CargoDiscardService.COMPLETED, application.getStatus());
|
||||
assertEquals("客户确认废弃完成", storedHistories.get(0).getRemark());
|
||||
service.confirmCompletion("100", "CD001", "CUSTOMER");
|
||||
assertEquals(confirmedAt, application.getCustomerConfirmedAt());
|
||||
assertEquals(1, storedHistories.size());
|
||||
verify(applications, times(1)).updateById(application);
|
||||
org.mockito.Mockito.verifyNoInteractions(adjustments, inventory, returnCartonItems);
|
||||
}
|
||||
|
||||
@org.junit.jupiter.params.ParameterizedTest
|
||||
@org.junit.jupiter.params.provider.ValueSource(strings = {"PENDING_REVIEW", "APPROVED", "REJECTED", "CANCELLED"})
|
||||
void customerCannotConfirmBeforePdaCompletion(String status) {
|
||||
CargoDiscardApplication application = new CargoDiscardApplication(); application.setStatus(status);
|
||||
when(applications.lockNo("100", "CD001")).thenReturn(application);
|
||||
org.junit.jupiter.api.Assertions.assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
() -> service.confirmCompletion("100", "CD001", "CUSTOMER"));
|
||||
verify(applications, never()).updateById(any(CargoDiscardApplication.class));
|
||||
}
|
||||
|
||||
@Mock CargoDiscardApplicationMapper applications;
|
||||
@Mock CargoDiscardItemMapper items;
|
||||
@Mock CargoDiscardCartonMapper discardCartons;
|
||||
@@ -57,6 +87,7 @@ class CargoDiscardServiceTest {
|
||||
@Mock LastlegOrderStatusHistoryMapper orderHistories;
|
||||
@Mock ReturnInventoryCartonMapper returnCartons;
|
||||
@Mock ReturnInventoryCartonItemMapper returnCartonItems;
|
||||
@Mock com.baiyue.lastleg.client.DomesticWarehouseDirectoryClient warehouseDirectory;
|
||||
|
||||
private CargoDiscardService service;
|
||||
private final CargoDiscardOutboundService outboundService = org.mockito.Mockito.mock(CargoDiscardOutboundService.class);
|
||||
@@ -68,6 +99,9 @@ class CargoDiscardServiceTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = new CargoDiscardService();
|
||||
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"))));
|
||||
ReflectionTestUtils.setField(service, "outboundService", outboundService);
|
||||
ReflectionTestUtils.setField(service, "stockService", org.mockito.Mockito.mock(CargoDiscardStockService.class));
|
||||
ReflectionTestUtils.setField(service, "photoService", org.mockito.Mockito.mock(CargoDiscardPhotoService.class));
|
||||
@@ -97,6 +131,7 @@ class CargoDiscardServiceTest {
|
||||
@Test
|
||||
void createReservesExactSkuCartonsWithoutDeductingInventory() {
|
||||
LastlegOrder order = order();
|
||||
order.setOverseasWarehouseId("99"); order.setOverseasWarehouseName(null);
|
||||
DropshipSkuInventory sku = skuInventory();
|
||||
when(orders.selectById(101L)).thenReturn(order);
|
||||
when(inventory.countAvailable("100", 101L, "SKU-1")).thenReturn(2L);
|
||||
@@ -109,6 +144,7 @@ class CargoDiscardServiceTest {
|
||||
List.of(new CargoDiscardRequests.Item(101L, null, "SKU-1", 2)), "discard-create-1", "damaged"));
|
||||
|
||||
assertEquals(CargoDiscardService.PENDING_REVIEW, detail.summary().status());
|
||||
assertEquals("洛杉矶仓", storedApplication.get().getOverseasWarehouseName());
|
||||
assertEquals(2, detail.summary().totalPackages());
|
||||
assertEquals(new BigDecimal("10.00"), detail.summary().totalFee());
|
||||
assertEquals(2, storedLinks.size());
|
||||
@@ -116,6 +152,14 @@ class CargoDiscardServiceTest {
|
||||
verify(inventory, never()).deductSkuInventory(any(), anyLong(), anyInt());
|
||||
}
|
||||
|
||||
@Test void historicalDiscardDetailResolvesMissingWarehouseNameByOperatingWarehouseId() {
|
||||
CargoDiscardApplication application = pendingApplication();
|
||||
application.setOverseasWarehouseId("99"); application.setOverseasWarehouseName(null);
|
||||
storedApplication.set(application);
|
||||
assertEquals("洛杉矶仓", service.detail("100", application.getDiscardNo()).summary().overseasWarehouseName());
|
||||
verify(applications, never()).updateById(any(CargoDiscardApplication.class));
|
||||
}
|
||||
|
||||
|
||||
@Test void selectedBoxesCreatePartialApplicationWithoutReservingUnselectedStock() {
|
||||
when(orders.selectById(101L)).thenReturn(order());
|
||||
@@ -159,7 +203,7 @@ class CargoDiscardServiceTest {
|
||||
ReturnInventoryCarton carton = new ReturnInventoryCarton();
|
||||
carton.setId(901L);
|
||||
carton.setCustomerId("100");
|
||||
carton.setOverseasWarehouseId("WH-1");
|
||||
carton.setOverseasWarehouseId("99");
|
||||
carton.setSourceReturnNo("RT-20260928-001");
|
||||
carton.setCartonMark("RC-LAX-001");
|
||||
carton.setStatus("AVAILABLE");
|
||||
@@ -176,6 +220,7 @@ class CargoDiscardServiceTest {
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("RETURN_CARTON", result.get(0).sourceType());
|
||||
assertEquals("洛杉矶仓", result.get(0).overseasWarehouseName());
|
||||
assertEquals(901L, result.get(0).returnCartonId());
|
||||
assertEquals("RC-LAX-001", result.get(0).cartonMark());
|
||||
assertEquals(4, result.get(0).availablePackages());
|
||||
|
||||
+10
@@ -18,6 +18,16 @@ class WarehouseTransferCargoValidationTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void skuUnitsAndExpectedCartonsAreIndependent() {
|
||||
try (var factory = Validation.buildDefaultValidatorFactory()) {
|
||||
var validator = factory.getValidator();
|
||||
assertTrue(validator.validate(new WarehouseTransferRequests.Item("SKU-A", "货物", 3, null, 120L)).isEmpty());
|
||||
assertTrue(!validator.validate(new WarehouseTransferRequests.Item("SKU-A", "货物", 3, null, 0L)).isEmpty());
|
||||
assertTrue(!validator.validate(new WarehouseTransferRequests.Item("SKU-A", "货物", 0, null, 120L)).isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void cartonRelabelAllowsOriginalSkuToBeOmitted() {
|
||||
try (var factory = Validation.buildDefaultValidatorFactory()) {
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.baiyue.lastleg.transfer.service;
|
||||
|
||||
import com.baiyue.lastleg.transfer.dto.WarehouseTransferRequests;
|
||||
import com.baiyue.lastleg.transfer.entity.*;
|
||||
import com.baiyue.lastleg.transfer.mapper.*;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
class WarehouseTransferCartonCountTest {
|
||||
WarehouseTransferService service;
|
||||
WarehouseTransferOrderMapper orders = mock(WarehouseTransferOrderMapper.class);
|
||||
WarehouseTransferCartonMapper cartons = mock(WarehouseTransferCartonMapper.class);
|
||||
WarehouseTransferItemMapper items = mock(WarehouseTransferItemMapper.class);
|
||||
WarehouseTransferPalletMapper palletMapper = mock(WarehouseTransferPalletMapper.class);
|
||||
WarehouseTransferPallet pallet;
|
||||
WarehouseTransferOrder order;
|
||||
WarehouseTransferCarton a, b;
|
||||
@BeforeEach void setup() {
|
||||
service = spy(new WarehouseTransferService());
|
||||
ReflectionTestUtils.setField(service, "transfers", orders);
|
||||
ReflectionTestUtils.setField(service, "transferCartons", cartons);
|
||||
ReflectionTestUtils.setField(service, "transferItems", items);
|
||||
ReflectionTestUtils.setField(service, "transferPallets", palletMapper);
|
||||
pallet = new WarehouseTransferPallet(); pallet.setId(200L); pallet.setStatus("GENERATED"); pallet.setWarehousePalletId(900L);
|
||||
when(palletMapper.listOrder("C1", 1L)).thenReturn(List.of(pallet));
|
||||
ReflectionTestUtils.setField(service, "objectMapper", new ObjectMapper());
|
||||
doReturn(null).when(service).detail(anyString(), anyString());
|
||||
order = new WarehouseTransferOrder(); order.setId(1L); order.setCustomerId("C1"); order.setTransferNo("WT1"); order.setStatus("WAIT_PDA_RECEIVING"); order.setPackageCount(2);
|
||||
a = box("BOX1", 10L); b = box("BOX2", 11L);
|
||||
when(orders.lockForPda("WT1", "77")).thenReturn(order);
|
||||
when(cartons.listOrder("C1", 1L)).thenReturn(List.of(a,b));
|
||||
var ia = new WarehouseTransferItem(); ia.setId(10L); ia.setSkuCode("A");
|
||||
var ib = new WarehouseTransferItem(); ib.setId(11L); ib.setSkuCode("B");
|
||||
when(items.selectList(any())).thenReturn(List.of(ia,ib));
|
||||
}
|
||||
WarehouseTransferCarton box(String mark, long item) { var box = new WarehouseTransferCarton(); box.setCartonMark(mark); box.setCartonIndex((int)item); box.setTransferItemId(item); return box; }
|
||||
WarehouseTransferRequests.CountCarton input(String mark, String sku, long quantity) { return new WarehouseTransferRequests.CountCarton(mark, null, 200L, new BigDecimal("20"),new BigDecimal("30"),new BigDecimal("40"),new BigDecimal("2.5"),sku,quantity); }
|
||||
WarehouseTransferRequests.CountCartons request(String key, WarehouseTransferRequests.CountCarton... rows) { return new WarehouseTransferRequests.CountCartons(key,List.of(rows),null); }
|
||||
@Test void multiSkuBoxesPersistDimensionsPiecesAndReplayWithoutWriting() {
|
||||
var request = request("K1",input("BOX1","A",12),input("BOX2","B",7));
|
||||
service.countCartons("OP1",77L,"WT1",request);
|
||||
assertEquals(12L,a.getCountedQuantity()); assertEquals(7L,b.getCountedQuantity()); assertNotNull(a.getCountedAt()); assertEquals("OP1",a.getCountedBy()); assertEquals(new BigDecimal("2.5"),b.getGrossWeightKg());
|
||||
assertEquals(200L,a.getTransferPalletId()); assertEquals(2,pallet.getCartonCount());
|
||||
assertEquals(new BigDecimal("0.048000"),pallet.getVolumeCbm()); assertEquals(new BigDecimal("5.0"),pallet.getGrossWeightKg());
|
||||
clearInvocations(cartons); order.setStatus("WAIT_CUSTOMER_CONFIRMATION");
|
||||
service.countCartons("OP1",77L,"WT1",request);
|
||||
verify(cartons,never()).updateById(any(WarehouseTransferCarton.class));
|
||||
assertThrows(ResponseStatusException.class,()->service.countCartons("OP1",77L,"WT1",request("K1",input("BOX1","A",13),input("BOX2","B",7))));
|
||||
}
|
||||
@Test void missingDuplicateForeignSkuAndInvalidQuantityRejectBeforeWrites() {
|
||||
var invalid = List.of(request("K",input("BOX1","A",1)),request("K",input("BOX1","A",1),input("BOX1","A",2)),request("K",input("OTHER","A",1),input("BOX2","B",2)),request("K",input("BOX1","B",1),input("BOX2","B",2)),request("K",input("BOX1","A",0),input("BOX2","B",2)));
|
||||
for(var request:invalid) assertThrows(ResponseStatusException.class,()->service.countCartons("OP1",77L,"WT1",request));
|
||||
verify(cartons,never()).updateById(any(WarehouseTransferCarton.class));
|
||||
}
|
||||
@Test void shortReceiptNeedsReasonAndPreservesMissingBoxFact() {
|
||||
var request = new WarehouseTransferRequests.CountCartons("SHORT",List.of(input("BOX1","A",3)),"少到一箱");
|
||||
service.countCartons("OP1",77L,"WT1",request);
|
||||
assertEquals("COUNTED",a.getStatus()); assertEquals("NOT_RECEIVED",b.getStatus());
|
||||
assertEquals("少到一箱",b.getDiscrepancyReason()); assertNull(b.getCountedQuantity());
|
||||
}
|
||||
@Test void extraReceiptGeneratesOwnedBoxAndReconcilesToDeclaredSku() {
|
||||
var extra = new WarehouseTransferRequests.CountCarton(null,11L,200L,new BigDecimal("10"),new BigDecimal("20"),new BigDecimal("30"),BigDecimal.ONE,"B",4);
|
||||
service.countCartons("OP1",77L,"WT1",new WarehouseTransferRequests.CountCartons("EXTRA",List.of(input("BOX1","A",1),input("BOX2","B",2),extra),"多到一箱"));
|
||||
var captured = org.mockito.ArgumentCaptor.forClass(WarehouseTransferCarton.class);
|
||||
verify(cartons).insert(captured.capture());
|
||||
assertEquals("WT1#EX-12",captured.getValue().getCartonMark()); assertEquals("C1",captured.getValue().getCustomerId()); assertEquals(4L,captured.getValue().getCountedQuantity());
|
||||
}
|
||||
@Test void cartonsRequireGeneratedPalletOwnedByThisOrder() {
|
||||
when(palletMapper.listOrder("C1",1L)).thenReturn(List.of());
|
||||
assertThrows(ResponseStatusException.class,()->service.countCartons("OP1",77L,"WT1",request("K",input("BOX1","A",1),input("BOX2","B",2))));
|
||||
verify(cartons,never()).updateById(any(WarehouseTransferCarton.class));
|
||||
when(palletMapper.listOrder("C1",1L)).thenReturn(List.of(pallet)); pallet.setStatus("DRAFT");
|
||||
assertThrows(ResponseStatusException.class,()->service.countCartons("OP1",77L,"WT1",request("K",input("BOX1","A",1),input("BOX2","B",2))));
|
||||
}
|
||||
@Test void multiSkuPalletCreatesOneInboundLineAllocationWithSummedBoxes() {
|
||||
var plans = mock(com.baiyue.lastleg.inboundplan.mapper.InboundPlanMapper.class);
|
||||
var lines = mock(com.baiyue.lastleg.inboundplan.mapper.InboundPlanLineMapper.class);
|
||||
var pallets = mock(com.baiyue.lastleg.inboundplan.mapper.InboundPlanPalletMapper.class);
|
||||
var allocations = mock(com.baiyue.lastleg.inboundplan.mapper.InboundPlanPalletAllocationMapper.class);
|
||||
ReflectionTestUtils.setField(service,"inboundPlans",plans); ReflectionTestUtils.setField(service,"inboundPlanLines",lines);
|
||||
ReflectionTestUtils.setField(service,"inboundPlanPallets",pallets); ReflectionTestUtils.setField(service,"inboundPlanAllocations",allocations);
|
||||
order.setLastlegOrderId(9L); order.setInboundCode("WT1");
|
||||
var plan = new com.baiyue.lastleg.inboundplan.entity.InboundPlan(); plan.setId(100L);
|
||||
var line = new com.baiyue.lastleg.inboundplan.entity.InboundPlanLine(); line.setId(101L);
|
||||
when(plans.findBySourceOrder("C1",9L)).thenReturn(plan); when(lines.selectOne(any())).thenReturn(line);
|
||||
var pallet = new WarehouseTransferPallet(); pallet.setId(200L); pallet.setCartonCount(3); pallet.setVolumeCbm(BigDecimal.ONE); pallet.setSequenceNo(1);
|
||||
var first = new WarehouseTransferPalletItem(); first.setTransferPalletId(200L); first.setTransferItemId(10L); first.setPackageCount(1);
|
||||
var second = new WarehouseTransferPalletItem(); second.setTransferPalletId(200L); second.setTransferItemId(11L); second.setPackageCount(2);
|
||||
ReflectionTestUtils.invokeMethod(service,"completeTransferInboundPlan","C1",order,List.of(pallet),List.of(first,second),java.time.LocalDateTime.now());
|
||||
var result=org.mockito.ArgumentCaptor.forClass(com.baiyue.lastleg.inboundplan.entity.InboundPlanPalletAllocation.class);
|
||||
verify(allocations,times(1)).insert(result.capture()); assertEquals(3,result.getValue().getPickedPackageCount()); assertEquals(3,result.getValue().getCountedPackageCount());
|
||||
}
|
||||
@Test void otherWarehouseCannotReadOrWriteAndCompletedCountsCannotBeOverwritten() {
|
||||
assertThrows(ResponseStatusException.class,()->service.countCartons("OP1",88L,"WT1",request("K",input("BOX1","A",1))));
|
||||
service.countCartons("OP1",77L,"WT1",request("K",input("BOX1","A",1),input("BOX2","B",2)));
|
||||
clearInvocations(cartons);
|
||||
assertThrows(ResponseStatusException.class,()->service.countCartons("OP2",77L,"WT1",request("NEW",input("BOX1","A",9),input("BOX2","B",2))));
|
||||
verify(cartons,never()).updateById(any(WarehouseTransferCarton.class));
|
||||
}
|
||||
}
|
||||
+11
-13
@@ -48,19 +48,17 @@ class WarehouseTransferPalletAllocationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void persistedOverReceiptUsesTheSameStableAllocationRule() {
|
||||
WarehouseTransferPallet first = persistedPallet(4);
|
||||
WarehouseTransferPallet second = persistedPallet(3);
|
||||
|
||||
var allocations = WarehouseTransferService.derivePersistedPalletAllocations(
|
||||
List.of(item(11L, 3), item(12L, 2)), List.of(first, second));
|
||||
|
||||
assertEquals(7, allocations.stream().mapToInt(value -> value.packageCount()).sum());
|
||||
assertEquals(3, allocations.stream().filter(value -> value.transferItemId() == 11L)
|
||||
.mapToInt(value -> value.packageCount()).sum());
|
||||
assertEquals(4, allocations.stream().filter(value -> value.transferItemId() == 12L)
|
||||
.mapToInt(value -> value.packageCount()).sum());
|
||||
assertEquals(List.of(0, 0, 1), allocations.stream().map(value -> value.palletIndex()).toList());
|
||||
void countedBoxesDetermineSkuPlacementRatherThanDeclarationOrder() {
|
||||
WarehouseTransferPallet first = persistedPallet(2); first.setId(100L);
|
||||
WarehouseTransferPallet second = persistedPallet(1); second.setId(200L);
|
||||
var a = new com.baiyue.lastleg.transfer.entity.WarehouseTransferCarton(); a.setTransferItemId(12L); a.setTransferPalletId(100L);
|
||||
var b = new com.baiyue.lastleg.transfer.entity.WarehouseTransferCarton(); b.setTransferItemId(12L); b.setTransferPalletId(100L);
|
||||
var c = new com.baiyue.lastleg.transfer.entity.WarehouseTransferCarton(); c.setTransferItemId(11L); c.setTransferPalletId(200L);
|
||||
var allocations = WarehouseTransferService.deriveCountedPalletAllocations(List.of(a,b,c),List.of(first,second));
|
||||
assertEquals(List.of(new WarehouseTransferService.DerivedPalletAllocation(0,12L,2),new WarehouseTransferService.DerivedPalletAllocation(1,11L,1)),allocations);
|
||||
c.setTransferPalletId(999L);
|
||||
org.junit.jupiter.api.Assertions.assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
() -> WarehouseTransferService.deriveCountedPalletAllocations(List.of(a,b,c),List.of(first,second)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+8
@@ -322,6 +322,10 @@ class WarehouseTransferServiceTest {
|
||||
WarehouseTransferOrder transfer = transfer(WarehouseTransferService.WAIT_PDA_RECEIVING);
|
||||
transfer.setOperatingWarehouseId("77");
|
||||
WarehouseTransferPallet pallet = measuredPallet("GENERATED");
|
||||
var counted = java.util.stream.IntStream.rangeClosed(1, 5).mapToObj(index -> {
|
||||
var box = new WarehouseTransferCarton(); box.setStatus("COUNTED"); box.setCountedAt(LocalDateTime.now()); return box;
|
||||
}).toList();
|
||||
when(transferCartons.listOrder("TENANT-A", transfer.getId())).thenReturn(counted);
|
||||
when(transfers.lockForPda("WTR-1", "77")).thenReturn(transfer);
|
||||
when(transferItems.selectList(any())).thenReturn(List.of(transferItem(51L, "SKU-1", 5)));
|
||||
WarehouseTransferMeasurementPhoto photo = new WarehouseTransferMeasurementPhoto();
|
||||
@@ -366,6 +370,10 @@ class WarehouseTransferServiceTest {
|
||||
new InventoryCommandResponse(1L, "STOCK_IN", 801L, 901L, 5, 0, 0, 0, false, false));
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
|
||||
var counted = java.util.stream.IntStream.rangeClosed(1, 5).mapToObj(index -> {
|
||||
var box = new WarehouseTransferCarton(); box.setTransferPalletId(pallet.getId()); box.setTransferItemId(item.getId()); box.setCartonIndex(index); box.setTotalCartons(5); box.setCartonMark("BOX-" + index); box.setStatus("COUNTED"); box.setCountedAt(LocalDateTime.now()); return box;
|
||||
}).toList();
|
||||
when(transferCartons.listOrder("TENANT-A", transfer.getId())).thenReturn(counted);
|
||||
var result = service.palletize("OP-1", 77L, "WTR-1",
|
||||
new WarehouseTransferRequests.Palletize("DONE-1", List.of(9001L)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user