fix: keep dropship pallets atomic in smart loading

This commit is contained in:
2026-09-14 14:35:29 +08:00
parent de9516d19e
commit 1d258ab27b
3 changed files with 88 additions and 6 deletions
@@ -273,15 +273,19 @@ public class SmartLoadingService {
String goods = details.stream().map(Candidate::goodsName).filter(StringUtils::hasText)
.map(String::trim).distinct().collect(java.util.stream.Collectors.joining("、"));
List<PalletCandidate> pallets=dropshipPallets.palletCandidates(first.inboundId());
if(!pallets.isEmpty()) return pallets.stream().map(pallet -> new InboundCandidate(first.accountId(), first.inboundId(), first.orderId(), first.orderNo(),
if(!pallets.isEmpty()) return pallets.stream().map(pallet -> {
String palletBlock = StringUtils.hasText(first.blockReason()) ? first.blockReason()
: pallet.cartonCount() == null || pallet.cartonCount() <= 0 ? "托盘没有可加入的箱数" : null;
return new InboundCandidate(first.accountId(), first.inboundId(), first.orderId(), first.orderNo(),
first.inboundCode(), first.warehouseId(), first.channelCode(), first.channelName(),
first.destinationWarehouseId(), first.destinationWarehouseCode(), first.destinationWarehouseName(),
first.customerName(), goods, pallet.cartonCount(),
pallet.cartonCount()==null||pallet.cartonCount()==0?null:pallet.weightKg().divide(BigDecimal.valueOf(pallet.cartonCount()),6,RoundingMode.HALF_UP),
first.unitNetWeightKg(), pallet.cartonCount()==null||pallet.cartonCount()==0?null:pallet.volumeCbm().divide(BigDecimal.valueOf(pallet.cartonCount()),6,RoundingMode.HALF_UP),
pallet.volumeCbm(),"SEALED_PALLET",pallet.palletId(),pallet.palletNo(),true,
first.coLoadGroupId(), first.groupNo(), first.memberCount(),first.groupTotalBoxes(), first.locked(), canAssign(first), capabilityBlock(first),
first.orderStatusSnapshot(),first.expectedArrivalAt(),List.of())).toList();
first.coLoadGroupId(), first.groupNo(), first.memberCount(),first.groupTotalBoxes(), false, !StringUtils.hasText(palletBlock), palletBlock,
first.orderStatusSnapshot(),first.expectedArrivalAt(),List.of());
}).toList();
return List.of(new InboundCandidate(first.accountId(), first.inboundId(), first.orderId(), first.orderNo(),
first.inboundCode(), first.warehouseId(), first.channelCode(), first.channelName(),
first.destinationWarehouseId(), first.destinationWarehouseCode(), first.destinationWarehouseName(),
@@ -903,6 +907,7 @@ public class SmartLoadingService {
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
Set<Long> visitedGroups = new HashSet<>();
Set<Long> visitedPallets = new HashSet<>();
for (InboundCandidate candidate : recommendationCandidates(booking)) {
if (candidate.coLoadGroupId() != null) {
if (!visitedGroups.add(candidate.coLoadGroupId()) || StringUtils.hasText(candidate.blockReason())) {
@@ -923,6 +928,18 @@ public class SmartLoadingService {
}
if (StringUtils.hasText(booking.getDestinationWarehouseCode())
&& !Objects.equals(booking.getDestinationWarehouseCode(), candidate.destinationWarehouseCode())) continue;
if ("SEALED_PALLET".equals(candidate.unitType())) {
if (candidate.palletId() == null || !visitedPallets.add(candidate.palletId())
|| !Boolean.TRUE.equals(candidate.canAssign())) continue;
int fitting = fittingBoxes(booking, repository.items(planId), candidate.availablePackageCount(),
candidate.averageUnitVolumeCbm(), candidate.unitGrossWeightKg());
if (fitting != candidate.availablePackageCount()) continue;
plan = repository.plan(planId);
assignPallet(planId, new AssignPalletRequest(candidate.palletId(), plan.getVersion(),
"REC-PAL-" + sha256(operation + '|' + candidate.palletId()).substring(0, 48)),
operatorId, operatorName);
continue;
}
int count = fittingBoxes(booking, repository.items(planId), candidate.availablePackageCount(),
candidate.averageUnitVolumeCbm(), candidate.unitGrossWeightKg());
if (count > 0) {