fix(inventory): enforce warehouse transfer reservation ownership
This commit is contained in:
+34
-8
@@ -58,6 +58,7 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class PdaPalletOperationService {
|
||||
@Resource private PdaPalletOperationMapper mapper;
|
||||
@Resource private com.baiyue.lastleg.inventory.command.mapper.InventoryCommandMapper inventoryCommands;
|
||||
@Resource private InventoryPositionMapper positions;
|
||||
@Resource private InventoryBalanceMapper balances;
|
||||
@Resource private InventoryLedgerMapper ledgers;
|
||||
@@ -465,14 +466,33 @@ public class PdaPalletOperationService {
|
||||
|
||||
List<PalletPhysicalGateway.Transition> transitions = new ArrayList<>();
|
||||
try {
|
||||
for (PalletChange change : plan.changes()) {
|
||||
transitions.add(physical.apply(identity.overseasWarehouseId(), change.pallet(), change.targetStatus(),
|
||||
change.targetLocationId(), transitionKey(identity.operatorKey(), normalizedKey,
|
||||
change.pallet().palletId()), reason));
|
||||
}
|
||||
saveTransitions(operation.getId(), transitions);
|
||||
PalletOperationResponses.Operation result = transaction.execute(status ->
|
||||
mutate(identity, operation, plan, normalizedKey, requestHash, reason));
|
||||
PalletOperationResponses.Operation result = transaction.execute(status -> {
|
||||
if (plan.relabelMutation() != null) lockRelabelMutation(plan.relabelMutation(), identity.overseasWarehouseId());
|
||||
Long relabelOwner = plan.relabelMutation() == null ? null : inventoryCommands.relabelTransfer(
|
||||
plan.relabelMutation().application().getCustomerId(), plan.relabelMutation().application().getId());
|
||||
// Allocation also locks the position first: preserve mutual exclusion until commit.
|
||||
for (PlannedMove move : plan.moves()) {
|
||||
PalletInventoryRow source = mapper.lockPosition(String.valueOf(identity.overseasWarehouseId()), move.positionId());
|
||||
if (source == null || !Objects.equals(source.getPalletId(), move.sourcePalletId())
|
||||
|| value(source.getVersion()) != move.expectedVersion()) throw conflict("Inventory source changed");
|
||||
requirePalletReservation(source.getCustomerId(), move.positionId(),
|
||||
move.bucket() == InventoryBucket.HOLD ? relabelOwner : null);
|
||||
}
|
||||
if (plan.relabelMutation() != null) {
|
||||
for (Long anchorId : plan.relabelMutation().anchors().keySet()) {
|
||||
PalletInventoryRow anchor = mapper.lockPosition(String.valueOf(identity.overseasWarehouseId()), anchorId);
|
||||
if (anchor == null) throw conflict("Relabel inventory anchor disappeared");
|
||||
requirePalletReservation(anchor.getCustomerId(), anchorId, relabelOwner);
|
||||
}
|
||||
}
|
||||
for (PalletChange change : plan.changes()) {
|
||||
transitions.add(physical.apply(identity.overseasWarehouseId(), change.pallet(), change.targetStatus(),
|
||||
change.targetLocationId(), transitionKey(identity.operatorKey(), normalizedKey,
|
||||
change.pallet().palletId()), reason));
|
||||
}
|
||||
saveTransitions(operation.getId(), transitions);
|
||||
return mutate(identity, operation, plan, normalizedKey, requestHash, reason);
|
||||
});
|
||||
if (result == null) throw new IllegalStateException("托盘作业事务没有返回结果");
|
||||
return result;
|
||||
} catch (RuntimeException failure) {
|
||||
@@ -482,6 +502,12 @@ public class PdaPalletOperationService {
|
||||
}
|
||||
}
|
||||
|
||||
private void requirePalletReservation(String customerId, Long positionId, Long owner) {
|
||||
var reservation = inventoryCommands.transferReservation(customerId, positionId);
|
||||
if (reservation != null && (owner == null || !owner.equals(reservation.transferOrderId())))
|
||||
throw conflict("Inventory is reserved by a warehouse transfer");
|
||||
}
|
||||
|
||||
private PalletOperationResponses.Operation mutate(PdaWarehouseIdentity identity, PdaPalletOperation operation,
|
||||
Plan plan, String key, String requestHash, String reason) {
|
||||
if (plan.relabelMutation() != null) lockRelabelMutation(plan.relabelMutation(), identity.overseasWarehouseId());
|
||||
|
||||
Reference in New Issue
Block a user