fix: persist PDA movement state semantics
This commit is contained in:
+2
-1
@@ -264,7 +264,8 @@ public class PdaPalletOperationService {
|
||||
ledger.setBusinessType(operation.getOperationType()); ledger.setBusinessOrderId(operation.getId());
|
||||
ledger.setBusinessOrderNo(String.valueOf(operation.getId())); ledger.setInboundCode(balance.getInboundCode());
|
||||
ledger.setInboundOrderNo(balance.getInboundOrderNo()); ledger.setIdempotencyKey(idempotencyKey);
|
||||
ledger.setStatusFrom("PALLET:" + sourcePallet); ledger.setStatusTo("PALLET:" + targetPallet);
|
||||
ledger.setStatusFrom("OCCUPIED");
|
||||
ledger.setStatusTo("UNBOUND".equals(targetPallet) ? "UNBOUND" : "OCCUPIED");
|
||||
ledger.setBeforePackages(before); ledger.setDeltaPackages(delta); ledger.setAfterPackages(after);
|
||||
ledger.setOperatorId(identity.operatorKey()); ledger.setRemark(trim(reason));
|
||||
ledger.setOccurredAt(LocalDateTime.now()); ledger.setCreatedAt(ledger.getOccurredAt()); ledgers.insert(ledger);
|
||||
|
||||
+5
-6
@@ -117,8 +117,7 @@ public class PdaInventoryMoveService {
|
||||
position.setWarehouseLocationId(target.locationId()); position.setWarehouseLocationCode(target.locationCode());
|
||||
position.setVersion(value(position.getVersion()) + 1); position.setUpdatedAt(completedAt);
|
||||
positions.updateById(position);
|
||||
ledger(operation, position, balance, operatorKey, key, request.reason(), source.locationCode(),
|
||||
target.locationCode(), completedAt);
|
||||
ledger(operation, position, balance, operatorKey, key, request.reason(), completedAt);
|
||||
}
|
||||
operation.setPalletVersionAfter(relocated.afterVersion()); operation.setStatus("COMPLETED");
|
||||
operation.setCompletedAt(completedAt);
|
||||
@@ -150,18 +149,18 @@ public class PdaInventoryMoveService {
|
||||
}
|
||||
|
||||
private void ledger(PdaInventoryMove operation, InventoryPosition position, InventoryBalance balance,
|
||||
String operator, String key, String reason, String source, String target,
|
||||
LocalDateTime now) {
|
||||
String operator, String key, String reason, LocalDateTime now) {
|
||||
InventoryLedger row = new InventoryLedger(); row.setId(IdWorker.getId()); row.setCustomerId(position.getCustomerId());
|
||||
row.setBalanceId(balance.getId()); row.setPositionId(position.getId());
|
||||
row.setOverseasWarehouseId(String.valueOf(operation.getOverseasWarehouseId()));
|
||||
row.setDestinationWarehouseCode(balance.getDestinationWarehouseCode()); row.setInboundOrderId(balance.getInboundOrderId());
|
||||
row.setPalletId(position.getPalletId()); row.setPalletNo(position.getPalletNo()); row.setBatchNo(position.getBatchNo());
|
||||
row.setSkuCode(balance.getSkuCode()); row.setWarehouseLocationCode(target); row.setBusinessType("INTERNAL_MOVE");
|
||||
row.setSkuCode(balance.getSkuCode()); row.setWarehouseLocationCode(position.getWarehouseLocationCode());
|
||||
row.setBusinessType("INTERNAL_MOVE");
|
||||
row.setBusinessOrderId(operation.getId()); row.setBusinessOrderNo(operation.getMoveNo());
|
||||
row.setInboundCode(balance.getInboundCode()); row.setInboundOrderNo(balance.getInboundOrderNo());
|
||||
row.setIdempotencyKey("MOVE:" + operation.getId() + ":" + position.getId());
|
||||
row.setStatusFrom(source); row.setStatusTo(target); long packages = physical(position);
|
||||
row.setStatusFrom("OCCUPIED"); row.setStatusTo("OCCUPIED"); long packages = physical(position);
|
||||
row.setBeforePackages(packages); row.setDeltaPackages(0L); row.setAfterPackages(packages);
|
||||
row.setOperatorId(operator); row.setRemark(reason.trim()); row.setOccurredAt(now); row.setCreatedAt(now);
|
||||
ledgers.insert(row);
|
||||
|
||||
+25
@@ -3,6 +3,9 @@ package com.baiyue.lastleg.palletops.service;
|
||||
import com.baiyue.lastleg.inventory.mapper.InventoryBalanceMapper;
|
||||
import com.baiyue.lastleg.inventory.mapper.InventoryLedgerMapper;
|
||||
import com.baiyue.lastleg.inventory.mapper.InventoryPositionMapper;
|
||||
import com.baiyue.lastleg.inventory.entity.InventoryBalance;
|
||||
import com.baiyue.lastleg.inventory.entity.InventoryLedger;
|
||||
import com.baiyue.lastleg.inventory.entity.InventoryPosition;
|
||||
import com.baiyue.lastleg.palletops.dto.PalletOperationRequests;
|
||||
import com.baiyue.lastleg.palletops.entity.PdaPalletOperation;
|
||||
import com.baiyue.lastleg.palletops.gateway.PalletPhysicalGateway;
|
||||
@@ -15,6 +18,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
@@ -94,6 +98,27 @@ class PdaPalletOperationServiceTest {
|
||||
verifyNoInteractions(ledgers, history);
|
||||
}
|
||||
|
||||
@Test void inventoryLedgerStoresStateSemanticsInsteadOfLongPalletCodes() {
|
||||
InventoryBalance balance = new InventoryBalance(); balance.setId(200L); balance.setCustomerId("100");
|
||||
balance.setOverseasWarehouseId("88"); balance.setInboundOrderId(300L); balance.setInboundCode("IN-1");
|
||||
InventoryPosition position = new InventoryPosition(); position.setId(100L); position.setPalletId(20L);
|
||||
position.setPalletNo("PDAOPS-ADMIN-API-20260825095854036-SWAP-TARGET");
|
||||
position.setBatchNo("DEFAULT"); position.setWarehouseLocationCode("PDAOPS-LONG-LOCATION-CODE");
|
||||
PdaPalletOperation operation = new PdaPalletOperation(); operation.setId(400L);
|
||||
operation.setOperationType("PALLET_SWAP");
|
||||
|
||||
ReflectionTestUtils.invokeMethod(service, "ledger", identity(), operation, balance, position,
|
||||
"idem:out", 5L, -5L, 0L,
|
||||
"PDAOPS-ADMIN-API-20260825095854036-SOURCE",
|
||||
"PDAOPS-ADMIN-API-20260825095854036-TARGET", "swap");
|
||||
|
||||
ArgumentCaptor<InventoryLedger> ledger = ArgumentCaptor.forClass(InventoryLedger.class);
|
||||
verify(ledgers).insert(ledger.capture());
|
||||
assertEquals("OCCUPIED", ledger.getValue().getStatusFrom());
|
||||
assertEquals("OCCUPIED", ledger.getValue().getStatusTo());
|
||||
assertEquals("PDAOPS-LONG-LOCATION-CODE", ledger.getValue().getWarehouseLocationCode());
|
||||
}
|
||||
|
||||
private static PdaWarehouseIdentity identity() { return new PdaWarehouseIdentity("7", "picker", 88L); }
|
||||
private static PalletPhysicalGateway.PalletReference pallet(long id, String code, long warehouse, int version) {
|
||||
return new PalletPhysicalGateway.PalletReference(id, code, warehouse, 1000L + id,
|
||||
|
||||
+10
-4
@@ -60,9 +60,10 @@ class PdaInventoryMoveServiceTest {
|
||||
|
||||
@Test
|
||||
void atomicallyRelocatesPhysicalPalletAndEveryWarehouseScopedPosition() {
|
||||
String targetLocationCode = "PDAOPS-ADMIN-API-20260825095854036-MOVE";
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(pallet(900L, 20L, 2));
|
||||
when(warehouse.resolveLocation(900L, 20L)).thenReturn(location(20L, "A-01"));
|
||||
when(warehouse.resolveLocation(900L, "B-01")).thenReturn(location(21L, "B-01"));
|
||||
when(warehouse.resolveLocation(900L, targetLocationCode)).thenReturn(location(21L, targetLocationCode));
|
||||
InventoryPosition position = new InventoryPosition(); position.setId(11L); position.setCustomerId("100");
|
||||
position.setBalanceId(10L); position.setOverseasWarehouseId("900"); position.setPalletId(30L);
|
||||
position.setPalletNo("PAL-1"); position.setWarehouseLocationId(20L); position.setWarehouseLocationCode("A-01");
|
||||
@@ -76,7 +77,7 @@ class PdaInventoryMoveServiceTest {
|
||||
eq(21L), anyString(), eq("库位优化"))).thenReturn(transition(false));
|
||||
|
||||
var response = service.move(900L, "operator-1",
|
||||
new PdaInventoryMoveRequest("PAL-1", "B-01", 2, "move-1", "库位优化"));
|
||||
new PdaInventoryMoveRequest("PAL-1", targetLocationCode, 2, "move-1", "库位优化"));
|
||||
|
||||
verify(physical).apply(eq(900L), argThat(value -> value.palletId() == 30L
|
||||
&& value.locationId() == 20L && value.version() == 2), eq("OCCUPIED"),
|
||||
@@ -84,11 +85,16 @@ class PdaInventoryMoveServiceTest {
|
||||
ArgumentCaptor<InventoryPosition> updated = ArgumentCaptor.forClass(InventoryPosition.class);
|
||||
verify(positions).updateById(updated.capture());
|
||||
assertThat(updated.getValue().getWarehouseLocationId()).isEqualTo(21L);
|
||||
assertThat(updated.getValue().getWarehouseLocationCode()).isEqualTo("B-01");
|
||||
assertThat(updated.getValue().getWarehouseLocationCode()).isEqualTo(targetLocationCode);
|
||||
assertThat(response.packageCount()).isEqualTo(6L);
|
||||
assertThat(response.palletVersion()).isEqualTo(3);
|
||||
assertThat(response.status()).isEqualTo("COMPLETED");
|
||||
verify(ledgers).insert(any(InventoryLedger.class)); verify(moves).updateById(any(PdaInventoryMove.class));
|
||||
ArgumentCaptor<InventoryLedger> ledger = ArgumentCaptor.forClass(InventoryLedger.class);
|
||||
verify(ledgers).insert(ledger.capture());
|
||||
assertThat(ledger.getValue().getStatusFrom()).isEqualTo("OCCUPIED");
|
||||
assertThat(ledger.getValue().getStatusTo()).isEqualTo("OCCUPIED");
|
||||
assertThat(ledger.getValue().getWarehouseLocationCode()).isEqualTo(targetLocationCode);
|
||||
verify(moves).updateById(any(PdaInventoryMove.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user