fix(inventory): enforce warehouse transfer reservation ownership
This commit is contained in:
+35
-1
@@ -59,6 +59,7 @@ class PdaPalletOperationServiceTest {
|
||||
assertThrows(ResponseStatusException.class, () -> ReflectionTestUtils.invokeMethod(service, "requireUnallocatedRelabel", app));
|
||||
}
|
||||
@Mock private PdaPalletOperationMapper mapper;
|
||||
@Mock private com.baiyue.lastleg.inventory.command.mapper.InventoryCommandMapper inventoryCommands;
|
||||
@Mock private InventoryPositionMapper positions;
|
||||
@Mock private InventoryBalanceMapper balances;
|
||||
@Mock private InventoryLedgerMapper ledgers;
|
||||
@@ -75,6 +76,7 @@ class PdaPalletOperationServiceTest {
|
||||
@BeforeEach void setUp() {
|
||||
service = new PdaPalletOperationService();
|
||||
ReflectionTestUtils.setField(service, "mapper", mapper);
|
||||
ReflectionTestUtils.setField(service, "inventoryCommands", inventoryCommands);
|
||||
ReflectionTestUtils.setField(service, "positions", positions);
|
||||
ReflectionTestUtils.setField(service, "balances", balances);
|
||||
ReflectionTestUtils.setField(service, "ledgers", ledgers);
|
||||
@@ -187,6 +189,35 @@ class PdaPalletOperationServiceTest {
|
||||
assertTrue(result.printableHtml().contains("RL-1"));
|
||||
}
|
||||
|
||||
@Test void reservedSourceIsRejectedBeforeAnyRemoteTransition() {
|
||||
var source = new PalletPhysicalGateway.PalletReference(20L, "SOURCE", 88L, 1020L,
|
||||
"OCCUPIED", null, 1);
|
||||
var target = new PalletPhysicalGateway.PalletReference(10L, "TARGET", 88L, 1010L,
|
||||
"IDLE", null, 2);
|
||||
when(physical.resolve("SOURCE")).thenReturn(source);
|
||||
when(physical.resolve("TARGET")).thenReturn(target);
|
||||
when(physical.resolveLocation(88L, target.locationId())).thenReturn(
|
||||
new PalletPhysicalGateway.LocationReference(target.locationId(), "LOC-1010", "STORAGE", "ACTIVE"));
|
||||
var row = row(100L, 20L, 1L, 5L);
|
||||
when(mapper.content("88", 20L)).thenReturn(List.of(row));
|
||||
when(mapper.content("88", 10L)).thenReturn(List.of());
|
||||
when(mapper.palletPackages("88", 20L)).thenReturn(5L);
|
||||
when(mapper.palletPackages("88", 10L)).thenReturn(0L);
|
||||
when(mapper.lockPosition("88", 100L)).thenReturn(row);
|
||||
when(inventoryCommands.transferReservation(row.getCustomerId(), 100L)).thenReturn(
|
||||
new com.baiyue.lastleg.inventory.command.mapper.InventoryCommandMapper.TransferReservation(900L, 5));
|
||||
AtomicReference<PdaPalletOperation> operation = new AtomicReference<>();
|
||||
doAnswer(call -> { operation.set(call.getArgument(0)); return 1; }).when(mapper).insert(any(PdaPalletOperation.class));
|
||||
when(mapper.selectById(anyLong())).thenAnswer(call -> operation.get());
|
||||
var request = new PalletOperationRequests.Assemble("reserved", new PalletOperationRequests.PalletExpectation("TARGET", 2),
|
||||
List.of(new PalletOperationRequests.PalletExpectation("SOURCE", 1)),
|
||||
List.of(new PalletOperationRequests.MoveLine(100L, 5L, 1L)), "assemble");
|
||||
assertThrows(ResponseStatusException.class, () -> service.assemble(identity(), request));
|
||||
verify(physical, never()).apply(anyLong(), any(), anyString(), anyLong(), anyString(), any());
|
||||
verify(positions, never()).updateById(any(InventoryPosition.class));
|
||||
verifyNoInteractions(ledgers);
|
||||
}
|
||||
|
||||
@Test void localConcurrencyFailureCompensatesEveryAppliedPhysicalTransitionInReverseSafeForm() {
|
||||
var source = new PalletPhysicalGateway.PalletReference(20L, "SOURCE", 88L, 1020L,
|
||||
"OCCUPIED", null, 1);
|
||||
@@ -203,7 +234,7 @@ class PdaPalletOperationServiceTest {
|
||||
when(mapper.content("88", 10L)).thenReturn(List.of());
|
||||
when(mapper.palletPackages("88", 20L)).thenReturn(5L);
|
||||
when(mapper.palletPackages("88", 10L)).thenReturn(0L);
|
||||
when(mapper.lockPosition("88", 100L)).thenReturn(stale);
|
||||
when(mapper.lockPosition("88", 100L)).thenReturn(planned, stale);
|
||||
|
||||
AtomicReference<PdaPalletOperation> operation = new AtomicReference<>();
|
||||
doAnswer(invocation -> { operation.set(invocation.getArgument(0)); return 1; })
|
||||
@@ -304,6 +335,9 @@ class PdaPalletOperationServiceTest {
|
||||
doAnswer(invocation -> { target.set(invocation.getArgument(0)); return 1; }).when(positions)
|
||||
.insert(any(InventoryPosition.class));
|
||||
PalletInventoryRow held = row(100L, 20L, 3L, 0L); held.setPalletNo("SOURCE"); held.setHoldPackages(2L);
|
||||
when(inventoryCommands.relabelTransfer(application.getCustomerId(), application.getId())).thenReturn(900L);
|
||||
when(inventoryCommands.transferReservation(application.getCustomerId(), 100L)).thenReturn(
|
||||
new com.baiyue.lastleg.inventory.command.mapper.InventoryCommandMapper.TransferReservation(900L, 2));
|
||||
when(mapper.content("88", 20L)).thenReturn(List.of(held));
|
||||
when(mapper.content("88", 10L)).thenReturn(List.of());
|
||||
when(mapper.lockPosition("88", 100L)).thenReturn(held);
|
||||
|
||||
Reference in New Issue
Block a user