fix(inventory): enforce warehouse transfer reservation ownership
This commit is contained in:
+49
-3
@@ -86,6 +86,50 @@ class WarehouseTransferRelabelPersistenceTest {
|
||||
session.getMapper(WarehouseTransferRelabelBindingMapper.class).insert(binding);
|
||||
}
|
||||
void position(long id,long pallet,long available,long hold,String batch){jdbc.update("INSERT INTO ll_inventory_position(id,customer_id,balance_id,overseas_warehouse_id,destination_warehouse_code,pallet_id,pallet_no,batch_no,available_packages,hold_packages,allocated_packages,picked_packages,receiving_packages,version) VALUES (?,'7',60,'9','ABE4',?,?,?, ?,?,0,0,0,0)",id,pallet,"P-"+pallet,batch,available,hold);}
|
||||
@Test void linkedRelabelCreationAndReleaseUseRealTransferOwnerAndInventory() {
|
||||
transfer.setRelabelNo("RL-OWN");
|
||||
application.setRelabelNo("RL-OWN"); application.setLastlegOrderId(10L);
|
||||
session.getMapper(WarehouseTransferOrderMapper.class).insert(transfer);
|
||||
var relabel=new com.baiyue.lastleg.relabel.service.RelabelApplicationService();
|
||||
ReflectionTestUtils.setField(relabel,"warehouseTransfers",session.getMapper(WarehouseTransferOrderMapper.class));
|
||||
ReflectionTestUtils.setField(relabel,"inventoryCommands",inventory);
|
||||
var hold=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(101L,1,"RL-OWN",null,
|
||||
"RELABEL:RL-OWN","LINKED-HOLD",null);
|
||||
tx.executeWithoutResult(status->ReflectionTestUtils.invokeMethod(relabel,"holdRelabelInventory",
|
||||
"7","operator",hold,10L,null));
|
||||
assertEquals(1L,jdbc.queryForObject("SELECT hold_packages FROM ll_inventory_position WHERE id=101",Long.class));
|
||||
var release=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(101L,1,"RL-OWN",null,
|
||||
"RELABEL:RL-OWN","LINKED-RELEASE",null);
|
||||
tx.executeWithoutResult(status->ReflectionTestUtils.invokeMethod(relabel,"releaseRelabelInventory",
|
||||
"7","operator",release,application));
|
||||
assertEquals(0L,jdbc.queryForObject("SELECT hold_packages FROM ll_inventory_position WHERE id=101",Long.class));
|
||||
var retry=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(101L,1,"RL-OWN",null,
|
||||
"RELABEL:RL-OWN","LINKED-RETRY",null);
|
||||
tx.executeWithoutResult(status->ReflectionTestUtils.invokeMethod(relabel,"holdRelabelInventory",
|
||||
"7","operator",retry,null,application));
|
||||
assertEquals(1L,jdbc.queryForObject("SELECT hold_packages FROM ll_inventory_position WHERE id=101",Long.class));
|
||||
var independent=new com.baiyue.lastleg.relabel.entity.RelabelApplication();
|
||||
independent.setId(999L); independent.setLastlegOrderId(999L); independent.setRelabelNo("RL-OTHER");
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->tx.executeWithoutResult(status->ReflectionTestUtils.invokeMethod(relabel,"holdRelabelInventory",
|
||||
"7","operator",new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(101L,1,
|
||||
"RL-OTHER",null,"RELABEL:RL-OTHER","OTHER-HOLD",null),null,independent)));
|
||||
}
|
||||
|
||||
@Test void realReservationBlocksNormalConsumersAndWrongInternalOwner() {
|
||||
var request=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(101L,1,"WT-ORIGINAL","WT-ORIGINAL",
|
||||
"WAREHOUSE_TRANSFER_OUTBOUND:WT-ORIGINAL","WAREHOUSE_TRANSFER:FORGED:ALLOCATE",null);
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->tx.executeWithoutResult(status->inventory.allocate("7","operator",request)));
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->tx.executeWithoutResult(status->inventory.hold("7","operator",request)));
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->tx.executeWithoutResult(status->inventory.allocateWarehouseTransfer("7","operator",2L,request,null)));
|
||||
assertEquals(2L,jdbc.queryForObject("SELECT available_packages FROM ll_inventory_position WHERE id=101",Long.class));
|
||||
assertEquals("RESERVED",jdbc.queryForObject("SELECT status FROM ll_warehouse_transfer_inventory_allocation WHERE id=13",String.class));
|
||||
assertEquals(0L,jdbc.queryForObject("SELECT COUNT(*) FROM ll_inventory_ledger",Long.class));
|
||||
}
|
||||
|
||||
@Test void confirmsMovedCartonIntoNewSkuAndPreservesOtherHoldWithRealCommandsAndMappers() {
|
||||
tx.executeWithoutResult(s->completion.complete(transfer,application,List.of(item),"operator",LocalDateTime.now()));
|
||||
assertEquals(4L,jdbc.queryForObject("SELECT SUM(available_packages+hold_packages+allocated_packages+picked_packages) FROM ll_inventory_position",Long.class));
|
||||
@@ -121,12 +165,14 @@ class WarehouseTransferRelabelPersistenceTest {
|
||||
var allocate=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(actual.getInventoryPositionId(),1,"WT-ORIGINAL","WT-ORIGINAL","WAREHOUSE_TRANSFER_OUTBOUND:WT-ORIGINAL","WAREHOUSE_TRANSFER:WT-ORIGINAL:ALLOCATE","");
|
||||
var pick=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(actual.getInventoryPositionId(),1,"WT-ORIGINAL","WT-ORIGINAL","WAREHOUSE_TRANSFER_OUTBOUND:WT-ORIGINAL","WAREHOUSE_TRANSFER:WT-ORIGINAL:PICK","");
|
||||
var ship=new com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move(actual.getInventoryPositionId(),1,"WT-ORIGINAL","WT-ORIGINAL","WAREHOUSE_TRANSFER_OUTBOUND:WT-ORIGINAL","WAREHOUSE_TRANSFER:WT-ORIGINAL:SHIP","");
|
||||
tx.executeWithoutResult(s->{inventory.allocateTransferSnapshot("7","operator",allocate,actual.getSkuCode());inventory.pickTransferSnapshot("7","operator",pick,actual.getSkuCode());inventory.shipTransferSnapshot("7","operator",ship,actual.getSkuCode());});
|
||||
tx.executeWithoutResult(s->{assertTrue(inventory.allocateTransferSnapshot("7","operator",allocate,"NEW").replayed());assertTrue(inventory.pickTransferSnapshot("7","operator",pick,"NEW").replayed());assertTrue(inventory.shipTransferSnapshot("7","operator",ship,"NEW").replayed());});
|
||||
tx.executeWithoutResult(s->{inventory.allocateWarehouseTransfer("7","operator",1L,allocate,actual.getSkuCode());inventory.pickWarehouseTransfer("7","operator",1L,pick,actual.getSkuCode());inventory.shipWarehouseTransfer("7","operator",1L,ship,actual.getSkuCode());});
|
||||
tx.executeWithoutResult(s->{assertTrue(inventory.allocateWarehouseTransfer("7","operator",1L,allocate,"NEW").replayed());assertTrue(inventory.pickWarehouseTransfer("7","operator",1L,pick,"NEW").replayed());assertTrue(inventory.shipWarehouseTransfer("7","operator",1L,ship,"NEW").replayed());});
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
()->tx.executeWithoutResult(status->inventory.allocateWarehouseTransfer("7","operator",2L,allocate,"NEW")));
|
||||
assertEquals(3L,jdbc.queryForObject("SELECT SUM(available_packages+hold_packages+allocated_packages+picked_packages) FROM ll_inventory_position",Long.class));
|
||||
assertEquals(1L,jdbc.queryForObject("SELECT COUNT(*) FROM ll_inventory_ledger WHERE business_type='SHIP' AND sku_code='NEW'",Long.class));
|
||||
assertEquals(0L,jdbc.queryForObject("SELECT COUNT(*) FROM ll_inventory_ledger WHERE business_type IN ('SHIP','PICK','ALLOCATE') AND sku_code<>'NEW'",Long.class));
|
||||
assertThrows(RuntimeException.class,()->tx.executeWithoutResult(s->inventory.shipTransferSnapshot("7","operator",ship,"OLD")));
|
||||
assertThrows(RuntimeException.class,()->tx.executeWithoutResult(s->inventory.shipWarehouseTransfer("7","operator",1L,ship,"OLD")));
|
||||
assertEquals(1L,jdbc.queryForObject("SELECT hold_packages FROM ll_inventory_position WHERE id=99",Long.class));
|
||||
}
|
||||
@Test void cartonOnlyConfirmationKeepsSamePositionAndRetainsOriginalBindingHistory(){
|
||||
|
||||
+5
-5
@@ -793,9 +793,9 @@ class WarehouseTransferServiceTest {
|
||||
var ordered = inOrder(inventory);
|
||||
ArgumentCaptor<com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move> move =
|
||||
ArgumentCaptor.forClass(com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests.Move.class);
|
||||
ordered.verify(inventory).allocate(eq("TENANT-A"), eq("USER-1"), move.capture());
|
||||
ordered.verify(inventory).pick(eq("TENANT-A"), eq("USER-1"), move.capture());
|
||||
ordered.verify(inventory).ship(eq("TENANT-A"), eq("USER-1"), move.capture());
|
||||
ordered.verify(inventory).allocateWarehouseTransfer(eq("TENANT-A"), eq("USER-1"), anyLong(), move.capture(), org.mockito.ArgumentMatchers.isNull());
|
||||
ordered.verify(inventory).pickWarehouseTransfer(eq("TENANT-A"), eq("USER-1"), anyLong(), move.capture(), org.mockito.ArgumentMatchers.isNull());
|
||||
ordered.verify(inventory).shipWarehouseTransfer(eq("TENANT-A"), eq("USER-1"), anyLong(), move.capture(), org.mockito.ArgumentMatchers.isNull());
|
||||
assertTrue(move.getAllValues().stream().allMatch(value -> value.positionId() == 501L && value.packages() == 5));
|
||||
assertEquals(WarehouseTransferService.OUTBOUNDED, transfer.getStatus());
|
||||
assertEquals("SHIPPED", allocation.getStatus());
|
||||
@@ -958,7 +958,7 @@ class WarehouseTransferServiceTest {
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
service.outbound("TENANT-A","WTR-1","USER-1",new WarehouseTransferRequests.Outbound("OUT-NEW","departed"));
|
||||
service.outbound("TENANT-A","WTR-1","USER-1",new WarehouseTransferRequests.Outbound("OUT-NEW","departed"));
|
||||
verify(inventory).shipTransferSnapshot(eq("TENANT-A"),eq("USER-1"),any(),eq("NEW"));
|
||||
verify(inventory).shipWarehouseTransfer(eq("TENANT-A"),eq("USER-1"),anyLong(),any(),eq("NEW"));
|
||||
verify(inventory,never()).ship(anyString(),anyString(),any());assertEquals("OUTBOUNDED",app.getFulfillmentStatus());
|
||||
var mixed=balance(601,101,"IN-1");mixed.setSkuCode("MIXED");when(inventoryCommands.lockBalance("TENANT-A",601L)).thenReturn(mixed);
|
||||
when(inventory.stockIn(eq("TENANT-A"),eq("USER-1"),any())).thenReturn(new InventoryCommandResponse(1L,"STOCK_IN",801L,901L,5,0,0,0,false,false));
|
||||
@@ -984,7 +984,7 @@ class WarehouseTransferServiceTest {
|
||||
when(transfers.lockNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
when(inventoryAllocations.lockTransfer("TENANT-A", 21L)).thenReturn(List.of(allocation));
|
||||
doThrow(new ResponseStatusException(org.springframework.http.HttpStatus.CONFLICT, "insufficient"))
|
||||
.when(inventory).pick(eq("TENANT-A"), eq("USER-1"), any());
|
||||
.when(inventory).pickWarehouseTransfer(eq("TENANT-A"), eq("USER-1"), anyLong(), any(), org.mockito.ArgumentMatchers.isNull());
|
||||
|
||||
assertThrows(ResponseStatusException.class, () -> service.outbound("TENANT-A", "WTR-1", "USER-1",
|
||||
new WarehouseTransferRequests.Outbound("OUT-1", null)));
|
||||
|
||||
Reference in New Issue
Block a user