Merge origin/dev into test preserving warehouse and PDA workflows

This commit is contained in:
2026-09-14 11:03:47 +08:00
103 changed files with 3033 additions and 225 deletions
@@ -116,6 +116,30 @@ public class WarehouseResourceService {
}
}
@Transactional
public WarehousePalletResolveResponse ensureRelabelPallet(long warehouseId, String businessId) {
String normalizedBusinessId = businessId == null ? null : businessId.trim();
WarehousePalletBindingEntity existing = repository.findPalletBinding(PUBLIC_RESOURCE_SCOPE, warehouseId,
"RELABEL_PDA_NEW", normalizedBusinessId);
if (existing != null) return resolvePublicPallet(existing.getPalletId());
Long palletId = createPallet(PUBLIC_RESOURCE_SCOPE, warehouseId,
new PalletRequests.SaveRequest(null, "STANDARD", null, java.math.BigDecimal.ZERO, "IDLE", null,
"PDA换标拆托新托盘"));
WarehousePalletBindingEntity binding = new WarehousePalletBindingEntity();
binding.setId(IdWorker.getId()); binding.setCustomerId(PUBLIC_RESOURCE_SCOPE); binding.setWarehouseId(warehouseId);
binding.setBusinessType("RELABEL_PDA_NEW"); binding.setBusinessId(normalizedBusinessId); binding.setPalletId(palletId);
binding.setCreatedAt(java.time.LocalDateTime.now());
try {
repository.insertPalletBinding(binding);
return resolvePublicPallet(palletId);
} catch (org.springframework.dao.DuplicateKeyException duplicate) {
WarehousePalletBindingEntity winner = repository.findPalletBinding(PUBLIC_RESOURCE_SCOPE, warehouseId,
"RELABEL_PDA_NEW", normalizedBusinessId);
if (winner == null) throw duplicate;
return resolvePublicPallet(winner.getPalletId());
}
}
/**
* Returns the warehouse-scoped virtual location used only as a pallet/inventory reference.
* It is deliberately never made IDLE/OCCUPIED by resource locking.
@@ -186,7 +210,6 @@ public class WarehouseResourceService {
if (matches.isEmpty()) throw new BizException(ResultCode.NOT_FOUND, "托盘码不存在");
if (matches.size() != 1) throw new BizException(ResultCode.CONFLICT, "托盘码在多个仓库重复,无法解析");
WarehousePalletEntity pallet = matches.get(0);
if (pallet.getLocationId() == null) throw new BizException(ResultCode.CONFLICT, "托盘未绑定库位");
if ("SCRAPPED".equals(pallet.getStatus())) throw new BizException(ResultCode.CONFLICT, "托盘已报废");
return palletReference(pallet);
}
@@ -200,7 +223,6 @@ public class WarehouseResourceService {
public WarehousePalletResolveResponse resolvePublicPallet(long palletId) {
WarehousePalletEntity pallet = repository.findPublicPallet(palletId);
if (pallet == null) throw new BizException(ResultCode.NOT_FOUND, "托盘不存在");
if (pallet.getLocationId() == null) throw new BizException(ResultCode.CONFLICT, "托盘未绑定库位");
return palletReference(pallet);
}
@@ -224,8 +246,8 @@ public class WarehouseResourceService {
}
private WarehousePalletResolveResponse palletReference(WarehousePalletEntity pallet) {
WarehouseLocationEntity location = repository.findLocation(PUBLIC_RESOURCE_SCOPE,
pallet.getWarehouseId(), pallet.getLocationId());
WarehouseLocationEntity location = pallet.getLocationId() == null ? null
: repository.findLocation(PUBLIC_RESOURCE_SCOPE, pallet.getWarehouseId(), pallet.getLocationId());
String blockReason = reservationBlockReason(pallet, location);
return new WarehousePalletResolveResponse(pallet.getId(), pallet.getPalletCode(), pallet.getWarehouseId(),
pallet.getLocationId(), pallet.getStatus(), pallet.getFbaWarehouseCode(), pallet.getUnitPrice(),
@@ -236,7 +258,7 @@ public class WarehouseResourceService {
private static String reservationBlockReason(WarehousePalletEntity pallet, WarehouseLocationEntity location) {
if (!"IDLE".equals(pallet.getStatus())) return "PALLET_NOT_IDLE";
if (location == null) return "LOCATION_NOT_FOUND";
if (location == null) return pallet.getLocationId() == null ? "LOCATION_NOT_REQUIRED" : "LOCATION_NOT_FOUND";
if ("VIRTUAL".equals(location.getLocationType())) {
return "ACTIVE".equals(location.getStatus()) ? null : "VIRTUAL_LOCATION_NOT_ACTIVE";
}