This commit is contained in:
2026-10-15 15:42:10 +08:00
parent 095a95e64a
commit c6bd6af5ce
43 changed files with 1153 additions and 92 deletions
@@ -77,6 +77,21 @@ public class PdaWarehouseTransferController {
.contentType(MediaType.parseMediaType(file.contentType())).body(file.content());
}
@GetMapping("/{transferNo}/carton-label")
public ApiResponse<WarehouseTransferResponses.Label> cartonLabel(
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String transferNo) {
PdaWarehouseIdentity identity = PdaWarehouseIdentity.require(user);
return ApiResponse.success(service.pdaCartonLabel(identity.overseasWarehouseId(), transferNo));
}
@PostMapping("/{transferNo}/cartons/count")
public ApiResponse<WarehouseTransferResponses.Detail> countCartons(
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String transferNo,
@Valid @RequestBody WarehouseTransferRequests.CountCartons request) {
PdaWarehouseIdentity identity = PdaWarehouseIdentity.require(user);
return ApiResponse.success(service.countCartons(identity.operatorKey(), identity.overseasWarehouseId(), transferNo, request));
}
@PostMapping("/{transferNo}/palletize")
public ApiResponse<WarehouseTransferResponses.Detail> palletize(
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String transferNo,
@@ -97,6 +97,24 @@ public final class WarehouseTransferRequests {
public record Outbound(@NotBlank @Size(max = 255) String idempotencyKey,
@Size(max = 1000) String remark) {}
public record CountCartons(
@NotBlank @Size(max = 255) String idempotencyKey,
@NotEmpty @Size(max = 5000) List<@Valid @NotNull CountCarton> boxes,
@Size(max = 1000) String discrepancyReason
) {}
public record CountCarton(
@Size(max = 255) String cartonMark,
Long transferItemId,
@NotNull Long transferPalletId,
@NotNull @DecimalMin("0.01") BigDecimal length,
@NotNull @DecimalMin("0.01") BigDecimal width,
@NotNull @DecimalMin("0.01") BigDecimal height,
@NotNull @DecimalMin("0.01") BigDecimal weight,
@NotBlank @Size(max = 255) String skuCode,
@Positive @Max(2147483647) long quantity
) {}
public record Palletize(
@NotBlank @Size(max = 255) String idempotencyKey,
@NotEmpty @Size(max = 20) List<@NotNull Long> photoFileIds
@@ -104,13 +122,7 @@ public final class WarehouseTransferRequests {
public record PalletDraft(
Long palletId,
@NotBlank @Size(max = 255) String idempotencyKey,
@Positive int cartonCount,
@NotNull @DecimalMin("0.01") BigDecimal lengthCm,
@NotNull @DecimalMin("0.01") BigDecimal widthCm,
@NotNull @DecimalMin("0.01") BigDecimal heightCm,
@NotNull @DecimalMin("0.000001") BigDecimal volumeCbm,
@NotNull @DecimalMin("0.01") BigDecimal grossWeightKg
@NotBlank @Size(max = 255) String idempotencyKey
) {}
public record PalletAction(@NotBlank @Size(max = 255) String idempotencyKey) {}
@@ -151,8 +163,13 @@ public final class WarehouseTransferRequests {
@Size(max = 128) String skuCode,
@Size(max = 255) String productNameZh,
@Positive int packageCount,
@Size(max = 255) String shippingMark
) {}
@Size(max = 255) String shippingMark,
@Positive Long quantity
) {
public Item(String skuCode, String productNameZh, int packageCount, String shippingMark) {
this(skuCode, productNameZh, packageCount, shippingMark, null);
}
}
public record RelabelItem(
@NotBlank @Size(max = 32) String operationType,
@@ -6,8 +6,10 @@ import java.util.List;
public final class WarehouseTransferResponses {
private WarehouseTransferResponses() {}
public record Item(Long id, String skuCode, String productNameZh, int packageCount, String shippingMark) {}
public record Carton(String cartonMark, String customerCartonMark, int cartonIndex, int totalCartons, String status) {}
public record Item(Long id, String skuCode, String productNameZh, int packageCount, String shippingMark, Long quantity) {}
public record Carton(String cartonMark, String customerCartonMark, int cartonIndex, int totalCartons, String status,
Long transferItemId, Long transferPalletId, BigDecimal length, BigDecimal width, BigDecimal height,
BigDecimal weight, Long quantity, String discrepancyReason, String countedBy, LocalDateTime countedAt) {}
public record Label(String transferNo, List<Carton> cartons, String printableHtml) {}
public record DestinationResult(String customerId, String transferNo) {}
public record PalletItem(Long transferItemId, String skuCode, int packageCount) {}
@@ -13,12 +13,23 @@ public class WarehouseTransferCarton {
@TableId(type = IdType.INPUT) private Long id;
private Long transferOrderId;
private Long transferItemId;
private Long transferPalletId;
private String customerId;
private String cartonMark;
private String customerCartonMark;
private Integer cartonIndex;
private Integer totalCartons;
private String status;
private java.math.BigDecimal lengthCm;
private java.math.BigDecimal widthCm;
private java.math.BigDecimal heightCm;
private java.math.BigDecimal grossWeightKg;
private Long countedQuantity;
private String countIdempotencyKey;
private String countRequestHash;
private String discrepancyReason;
private String countedBy;
private LocalDateTime countedAt;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
@@ -15,6 +15,7 @@ public class WarehouseTransferItem {
private String skuCode;
private String productNameZh;
private Integer packageCount;
private Long declaredQuantity;
private String shippingMark;
private LocalDateTime createdAt;
}
@@ -525,7 +525,7 @@ public class WarehouseTransferService {
new LambdaQueryWrapper<WarehouseTransferItem>().eq(WarehouseTransferItem::getCustomerId, customerId)
.eq(WarehouseTransferItem::getTransferOrderId, transfer.getId()).orderByAsc(WarehouseTransferItem::getId))
.stream().map(value -> new WarehouseTransferResponses.Item(value.getId(), value.getSkuCode(), value.getProductNameZh(),
value.getPackageCount(), value.getShippingMark())).toList();
value.getPackageCount(), value.getShippingMark(), value.getDeclaredQuantity())).toList();
Map<Long, WarehouseTransferResponses.Item> itemById = items.stream()
.collect(Collectors.toMap(WarehouseTransferResponses.Item::id, Function.identity()));
List<WarehouseTransferResponses.SourceOrder> sources = sourceOrders.selectList(
@@ -535,7 +535,7 @@ public class WarehouseTransferService {
value.getSourceLastlegOrderNo(), value.getInboundOrderId(), value.getInboundCode())).toList();
List<WarehouseTransferResponses.Carton> cartons = transferCartons.listOrder(customerId, transfer.getId())
.stream().map(value -> new WarehouseTransferResponses.Carton(value.getCartonMark(), value.getCustomerCartonMark(),
value.getCartonIndex(), value.getTotalCartons(), value.getStatus())).toList();
value.getCartonIndex(), value.getTotalCartons(), value.getStatus(), value.getTransferItemId(), value.getTransferPalletId(), value.getLengthCm(), value.getWidthCm(), value.getHeightCm(), value.getGrossWeightKg(), value.getCountedQuantity(), value.getDiscrepancyReason(), value.getCountedBy(), value.getCountedAt())).toList();
List<WarehouseTransferPalletItem> palletItemRows = transferPalletItems == null
? List.of() : transferPalletItems.listOrder(customerId, transfer.getId());
Map<Long, List<WarehouseTransferPalletItem>> palletItemsByPallet = palletItemRows.stream()
@@ -607,13 +607,21 @@ public class WarehouseTransferService {
transfer.getCustomerConfirmedAt(), transfer.getOutboundAt(), transfer.getCreatedAt());
}
@Transactional(readOnly = true)
public WarehouseTransferResponses.Label pdaCartonLabel(long warehouseId, String transferNo) {
var transfer = transfers.findNoByWarehouse(transferNo, String.valueOf(warehouseId));
if (transfer == null) throw notFound("当前仓没有该转运单");
return cartonLabel(transfer.getCustomerId(), transferNo);
}
@Transactional(readOnly = true)
public WarehouseTransferResponses.Label cartonLabel(String customerId, String transferNo) {
WarehouseTransferOrder transfer = transfers.findNo(customerId, transferNo);
if (transfer == null) throw notFound("Warehouse transfer order not found");
if (DRAFT.equals(transfer.getStatus())) throw conflict("Submit the warehouse transfer order before printing carton labels");
List<WarehouseTransferResponses.Carton> cartons = transferCartons.listOrder(customerId, transfer.getId()).stream()
.map(value -> new WarehouseTransferResponses.Carton(value.getCartonMark(), value.getCustomerCartonMark(), value.getCartonIndex(), value.getTotalCartons(), value.getStatus())).toList();
.filter(value -> !"NOT_RECEIVED".equals(value.getStatus()))
.map(value -> new WarehouseTransferResponses.Carton(value.getCartonMark(), value.getCustomerCartonMark(), value.getCartonIndex(), value.getTotalCartons(), value.getStatus(), value.getTransferItemId(), value.getTransferPalletId(), value.getLengthCm(), value.getWidthCm(), value.getHeightCm(), value.getGrossWeightKg(), value.getCountedQuantity(), value.getDiscrepancyReason(), value.getCountedBy(), value.getCountedAt())).toList();
StringBuilder labels = new StringBuilder();
for (WarehouseTransferResponses.Carton carton : cartons) {
labels.append("<section class=label><div class=title>仓储转运箱唛</div><div class=mark>")
@@ -689,9 +697,10 @@ public class WarehouseTransferService {
WarehouseTransferRequests.PalletDraft request) {
WarehouseTransferOrder transfer = requirePdaMeasuringTransfer(warehouseId, transferNo);
String customerId = transfer.getCustomerId();
validatePalletMeasurement(request.lengthCm(), request.widthCm(), request.heightCm(), request.volumeCbm());
String requestHash = hash(request);
List<WarehouseTransferPallet> existing = transferPallets.listOrder(customerId, transfer.getId());
if (transferCartons.listOrder(customerId, transfer.getId()).stream().anyMatch(box -> box.getCountedAt() != null))
throw conflict("箱子清点已确认,不能再新增或修改托盘");
WarehouseTransferPallet pallet;
if (request.palletId() == null) {
pallet = existing.stream().filter(value -> request.idempotencyKey().equals(value.getDraftIdempotencyKey()))
@@ -710,9 +719,9 @@ public class WarehouseTransferService {
if (pallet == null) throw notFound("Warehouse transfer pallet draft not found");
if (!"DRAFT".equals(pallet.getStatus())) throw conflict("Generated pallet measurements are locked");
}
pallet.setCartonCount(request.cartonCount()); pallet.setLengthCm(request.lengthCm());
pallet.setWidthCm(request.widthCm()); pallet.setHeightCm(request.heightCm());
pallet.setVolumeCbm(request.volumeCbm()); pallet.setGrossWeightKg(request.grossWeightKg());
pallet.setCartonCount(0); pallet.setLengthCm(BigDecimal.ZERO);
pallet.setWidthCm(BigDecimal.ZERO); pallet.setHeightCm(BigDecimal.ZERO);
pallet.setVolumeCbm(BigDecimal.ZERO); pallet.setGrossWeightKg(BigDecimal.ZERO);
pallet.setDraftIdempotencyKey(request.idempotencyKey()); pallet.setDraftRequestHash(requestHash);
pallet.setUpdatedAt(LocalDateTime.now()); transferPallets.insertOrUpdate(pallet);
fleetPool.receiving(customerId, transferNo, pdaOperatorId());
@@ -782,6 +791,94 @@ public class WarehouseTransferService {
return detail(transfer.getCustomerId(), transferNo);
}
@Transactional
public WarehouseTransferResponses.Detail countCartons(String operatorId, long warehouseId, String transferNo,
WarehouseTransferRequests.CountCartons request) {
WarehouseTransferOrder transfer = transfers.lockForPda(transferNo, String.valueOf(warehouseId));
if (transfer == null) throw notFound("当前仓没有该转运单");
String customerId = transfer.getCustomerId();
List<WarehouseTransferCarton> cartons = transferCartons.listOrder(customerId, transfer.getId());
String requestHash = hash(request);
boolean sameKey = cartons.stream().anyMatch(box -> request.idempotencyKey().equals(box.getCountIdempotencyKey()));
if (sameKey) {
if (cartons.stream().anyMatch(box -> !request.idempotencyKey().equals(box.getCountIdempotencyKey())
|| !requestHash.equals(box.getCountRequestHash()))) throw conflict("幂等键已用于其他清点内容");
return detail(customerId, transferNo);
}
if (!WAIT_PDA_RECEIVING.equals(transfer.getStatus())) throw conflict("转运单已结束入库测量");
if (cartons.stream().anyMatch(box -> box.getCountedAt() != null)) throw conflict("本单已完成清点,请刷新查看结果");
if (cartons.isEmpty()) throw conflict("转运单缺少箱号预报");
if (request.boxes().size() != transfer.getPackageCount() && !StringUtils.hasText(request.discrepancyReason()))
throw badRequest("实收箱数与预报不一致时必须填写差异原因");
Map<String, WarehouseTransferCarton> byMark = cartons.stream().collect(Collectors.toMap(WarehouseTransferCarton::getCartonMark, Function.identity()));
Map<Long, WarehouseTransferItem> byItem = transferItems.selectList(new LambdaQueryWrapper<WarehouseTransferItem>()
.eq(WarehouseTransferItem::getCustomerId, customerId).eq(WarehouseTransferItem::getTransferOrderId, transfer.getId()))
.stream().collect(Collectors.toMap(WarehouseTransferItem::getId, Function.identity()));
List<WarehouseTransferPallet> countedPallets = transferPallets.listOrder(customerId, transfer.getId());
if (countedPallets.stream().anyMatch(pallet -> request.boxes().stream().noneMatch(box -> pallet.getId().equals(box.transferPalletId()))))
throw badRequest("每个托盘必须至少分配一个实收箱,请核对箱子所属托盘");
Map<Long, WarehouseTransferPallet> byPallet = countedPallets.stream().collect(Collectors.toMap(WarehouseTransferPallet::getId, Function.identity()));
Set<String> seen = new java.util.HashSet<>();
for (var input : request.boxes()) {
var targetPallet = byPallet.get(input.transferPalletId());
if (targetPallet == null || targetPallet.getWarehousePalletId() == null
|| !Set.of("GENERATED", "BOUND").contains(targetPallet.getStatus()))
throw badRequest("请先创建本单托盘号,再选择箱子所属托盘");
var carton = byMark.get(input.cartonMark());
if (StringUtils.hasText(input.cartonMark()) && (carton == null || !seen.add(input.cartonMark())))
throw badRequest("箱号不属于本单或重复填写");
if (carton == null && input.transferItemId() == null) throw badRequest("新增实收箱必须选择本单申报明细");
var item = byItem.get(carton == null ? input.transferItemId() : carton.getTransferItemId());
if (item == null || !item.getSkuCode().equals(input.skuCode())) throw badRequest("箱内 SKU 必须与该箱申报明细一致");
if (input.quantity() <= 0 || input.quantity() > Integer.MAX_VALUE || input.length() == null || input.width() == null
|| input.height() == null || input.weight() == null || input.length().signum() <= 0 || input.width().signum() <= 0
|| input.height().signum() <= 0 || input.weight().signum() <= 0) throw badRequest("每箱必须填写有效尺寸、重量和实点件数");
}
LocalDateTime now = LocalDateTime.now();
for (var carton : cartons) {
if (seen.contains(carton.getCartonMark())) continue;
carton.setStatus("NOT_RECEIVED"); carton.setCountedAt(now); carton.setCountedBy(operatorId);
carton.setCountIdempotencyKey(request.idempotencyKey()); carton.setCountRequestHash(requestHash);
carton.setDiscrepancyReason(trim(request.discrepancyReason())); carton.setUpdatedAt(now); transferCartons.updateById(carton);
}
int nextIndex = cartons.stream().mapToInt(WarehouseTransferCarton::getCartonIndex).max().orElse(0);
for (var input : request.boxes()) {
var carton = byMark.get(input.cartonMark());
boolean added = carton == null;
if (added) {
carton = new WarehouseTransferCarton(); carton.setId(IdWorker.getId());
carton.setTransferOrderId(transfer.getId()); carton.setTransferItemId(input.transferItemId()); carton.setCustomerId(customerId);
carton.setCartonIndex(++nextIndex); carton.setTotalCartons(transfer.getPackageCount());
carton.setCartonMark(transferNo + "#EX-" + nextIndex); carton.setCreatedAt(now);
}
carton.setTransferPalletId(input.transferPalletId());
carton.setLengthCm(input.length()); carton.setWidthCm(input.width()); carton.setHeightCm(input.height());
carton.setGrossWeightKg(input.weight()); carton.setCountedQuantity(input.quantity());
carton.setCountedBy(operatorId); carton.setCountedAt(now); carton.setStatus("COUNTED");
carton.setCountIdempotencyKey(request.idempotencyKey()); carton.setCountRequestHash(requestHash); carton.setUpdatedAt(now);
carton.setDiscrepancyReason(trim(request.discrepancyReason()));
if (added) transferCartons.insert(carton); else transferCartons.updateById(carton);
}
// Aggregate only the submitted, physically assigned boxes; never infer SKU placement from declaration order.
for (var pallet : countedPallets) {
var assigned = request.boxes().stream().filter(box -> pallet.getId().equals(box.transferPalletId())).toList();
pallet.setCartonCount(assigned.size());
pallet.setVolumeCbm(assigned.stream().map(box -> box.length().multiply(box.width()).multiply(box.height())
.movePointLeft(6)).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(6, java.math.RoundingMode.HALF_UP));
pallet.setGrossWeightKg(assigned.stream().map(WarehouseTransferRequests.CountCarton::weight).reduce(BigDecimal.ZERO, BigDecimal::add));
pallet.setUpdatedAt(now); transferPallets.updateById(pallet);
}
return detail(customerId, transferNo);
}
private List<WarehouseTransferCarton> requireCountedCartons(WarehouseTransferOrder transfer) {
var cartons = transferCartons.listOrder(transfer.getCustomerId(), transfer.getId());
if (cartons.isEmpty() || cartons.stream().anyMatch(box -> box.getCountedAt() == null)
|| cartons.stream().noneMatch(box -> "COUNTED".equals(box.getStatus())))
throw conflict("请先完成全部箱子的尺寸测量和箱内清点");
return cartons.stream().filter(box -> "COUNTED".equals(box.getStatus())).toList();
}
private WarehouseTransferOrder requirePdaMeasuringTransfer(long warehouseId, String transferNo) {
WarehouseTransferOrder transfer = transfers.lockForPda(transferNo, String.valueOf(warehouseId));
if (transfer == null) throw notFound("Warehouse transfer order not found");
@@ -818,6 +915,7 @@ public class WarehouseTransferService {
if (!WAIT_PDA_RECEIVING.equals(transfer.getStatus())) {
throw conflict("Warehouse transfer is not awaiting PDA receiving");
}
List<WarehouseTransferCarton> countedCartons = requireCountedCartons(transfer);
List<WarehouseTransferItem> items = transferItems.selectList(new LambdaQueryWrapper<WarehouseTransferItem>()
.eq(WarehouseTransferItem::getCustomerId, customerId)
.eq(WarehouseTransferItem::getTransferOrderId, transfer.getId()).orderByAsc(WarehouseTransferItem::getId));
@@ -838,8 +936,10 @@ public class WarehouseTransferService {
if (persistedPallets.isEmpty() || persistedPallets.stream().anyMatch(value -> !"BOUND".equals(value.getStatus()))) {
throw conflict("Every pallet must be generated and scan-bound before completing palletization");
}
if (persistedPallets.stream().anyMatch(pallet -> pallet.getCartonCount() == null || pallet.getCartonCount() <= 0)) throw conflict("每个托盘必须至少分配一个实收箱");
int palletCartons = persistedPallets.stream().mapToInt(WarehouseTransferPallet::getCartonCount).sum();
List<DerivedPalletAllocation> derivedAllocations = derivePersistedPalletAllocations(items, persistedPallets);
if (palletCartons != countedCartons.size()) throw conflict("打托箱数必须与已清点实收箱数一致");
List<DerivedPalletAllocation> derivedAllocations = deriveCountedPalletAllocations(countedCartons, persistedPallets);
LocalDateTime now = LocalDateTime.now();
List<WarehouseTransferPalletItem> completedPalletItems = new ArrayList<>();
for (int index = 0; index < persistedPallets.size(); index++) {
@@ -1452,29 +1552,20 @@ public class WarehouseTransferService {
return result;
}
static List<DerivedPalletAllocation> derivePersistedPalletAllocations(List<WarehouseTransferItem> items,
List<WarehouseTransferPallet> pallets) {
if (items == null || items.isEmpty()) throw conflict("Warehouse transfer declared cargo is incomplete");
static List<DerivedPalletAllocation> deriveCountedPalletAllocations(List<WarehouseTransferCarton> cartons,
List<WarehouseTransferPallet> pallets) {
List<DerivedPalletAllocation> result = new ArrayList<>();
int itemIndex = 0;
int itemRemaining = items.get(0).getPackageCount();
for (int palletIndex = 0; palletIndex < pallets.size(); palletIndex++) {
int palletRemaining = pallets.get(palletIndex).getCartonCount();
while (palletRemaining > 0) {
WarehouseTransferItem item = items.get(itemIndex);
if (itemIndex + 1 == items.size()) {
result.add(new DerivedPalletAllocation(palletIndex, item.getId(), palletRemaining));
break;
}
int allocated = Math.min(palletRemaining, itemRemaining);
result.add(new DerivedPalletAllocation(palletIndex, item.getId(), allocated));
palletRemaining -= allocated;
itemRemaining -= allocated;
if (itemRemaining == 0 && itemIndex + 1 < items.size()) {
itemIndex++;
itemRemaining = items.get(itemIndex).getPackageCount();
}
}
Set<Long> palletIds = pallets.stream().map(WarehouseTransferPallet::getId).collect(Collectors.toSet());
if (cartons.stream().anyMatch(box -> box.getTransferPalletId() == null || !palletIds.contains(box.getTransferPalletId())))
throw conflict("每个实收箱必须分配到本单托盘");
for (int index = 0; index < pallets.size(); index++) {
var pallet = pallets.get(index);
Map<Long, Integer> quantities = new java.util.LinkedHashMap<>();
cartons.stream().filter(box -> pallet.getId().equals(box.getTransferPalletId()))
.forEach(box -> quantities.merge(box.getTransferItemId(), 1, Integer::sum));
if (quantities.values().stream().mapToInt(Integer::intValue).sum() != pallet.getCartonCount())
throw conflict("托盘箱数与分配的实收箱不一致");
for (var entry : quantities.entrySet()) result.add(new DerivedPalletAllocation(index, entry.getKey(), entry.getValue()));
}
return result;
}
@@ -1796,18 +1887,17 @@ public class WarehouseTransferService {
pallet.setWarehouseResourceLockId(source.getWarehouseResourceLockId()); pallet.setAssignmentStatus("ASSIGNED");
pallet.setLockedAt(source.getCompletedAt()); pallet.setActualVolumeCbm(source.getVolumeCbm());
pallet.setActualPackageCount(source.getCartonCount()); inboundPlanPallets.insert(pallet);
for (WarehouseTransferPalletItem sourceItem : palletItems.stream()
.filter(row -> row.getTransferPalletId().equals(source.getId())).toList()) {
InboundPlanPalletAllocation allocation = new InboundPlanPalletAllocation(); allocation.setId(IdWorker.getId());
allocation.setCustomerId(customerId); allocation.setPlanId(plan.getId()); allocation.setLineId(line.getId());
allocation.setPalletId(pallet.getId()); allocation.setAllocatedVolumeCbm(BigDecimal.ZERO);
allocation.setPlannedPackageCount(sourceItem.getPackageCount()); allocation.setCountedPackageCount(sourceItem.getPackageCount());
// PDA 已完成测量、打托并确认了本托箱数;入仓计划列表的“实际拣货数”
// 直接汇总该字段,不能再保留初始化时的 0。
allocation.setPickedPackageCount(sourceItem.getPackageCount());
allocation.setActualVolumeCbm(source.getVolumeCbm());
allocation.setStatus("COMPLETED"); allocation.setVersion(0); inboundPlanAllocations.insert(allocation);
}
// Plan allocations are unique by inbound line + pallet. SKU breakdown
// belongs to transfer pallet items and must not duplicate that allocation.
int receivedPackages = palletItems.stream().filter(row -> row.getTransferPalletId().equals(source.getId()))
.mapToInt(WarehouseTransferPalletItem::getPackageCount).sum();
if (receivedPackages != source.getCartonCount()) throw conflict("托盘明细箱数与实收不一致");
InboundPlanPalletAllocation allocation = new InboundPlanPalletAllocation(); allocation.setId(IdWorker.getId());
allocation.setCustomerId(customerId); allocation.setPlanId(plan.getId()); allocation.setLineId(line.getId());
allocation.setPalletId(pallet.getId()); allocation.setAllocatedVolumeCbm(BigDecimal.ZERO);
allocation.setPlannedPackageCount(receivedPackages); allocation.setCountedPackageCount(receivedPackages);
allocation.setPickedPackageCount(receivedPackages); allocation.setActualVolumeCbm(source.getVolumeCbm());
allocation.setStatus("COMPLETED"); allocation.setVersion(0); inboundPlanAllocations.insert(allocation);
}
plan.setAssignedFlag(true); plan.setStatus("COMPLETED"); plan.setPalletCount(pallets.size());
plan.setTotalVolumeCbm(pallets.stream().map(WarehouseTransferPallet::getVolumeCbm)
@@ -1879,6 +1969,7 @@ public class WarehouseTransferService {
item.setId(IdWorker.getId()); item.setTransferOrderId(transferId); item.setCustomerId(customerId);
item.setSkuCode(Objects.toString(trim(source.skuCode()), "UNSPECIFIED"));
item.setProductNameZh(Objects.toString(trim(source.productNameZh()), "仓储转运货物"));
item.setDeclaredQuantity(source.quantity());
item.setPackageCount(source.packageCount()); item.setShippingMark(trim(source.shippingMark())); item.setCreatedAt(now);
transferItems.insert(item);
return item.getId();