fix: settle whole dropship pallets by sku

This commit is contained in:
2026-09-02 00:27:04 +08:00
parent 7e6c7a4b9d
commit fd9a070efc
3 changed files with 63 additions and 7 deletions
@@ -22,6 +22,9 @@ public interface InboundSplitSettlementMapper {
@Select("SELECT container_booking_id FROM fl_loading_plan WHERE id=#{loadingPlanId}")
Long containerBookingId(@Param("loadingPlanId") long loadingPlanId);
@Select("SELECT fulfillment_type FROM fl_inbound_order WHERE id=#{inboundId} AND tenant_id=#{accountId} AND deleted=0")
String fulfillmentType(@Param("accountId") long accountId, @Param("inboundId") long inboundId);
@Select("""
SELECT id, tenant_id AS tenantId, order_id AS orderId, order_no AS orderNo,
inbound_code AS inboundCode, inbound_role AS inboundRole,
@@ -180,7 +180,14 @@ public class PdaPickSettlementService {
if (pickedByMeasurement != pickedPackageCount) {
throw conflict("PDA 已拣明细与入库单已拣箱数不一致");
}
List<MeasurementSplitLine> measurementLines = measurementLines(measurements, pickedByDetail);
boolean dropshipWholePallet = "ONE_CLICK_DROPSHIP".equals(
splits.fulfillmentType(parent.tenantId(), parentInboundId));
if (dropshipWholePallet && childPackageCount != 0) {
throw conflict("一件代发现场托盘必须整票装柜,不能生成余量分片");
}
List<MeasurementSplitLine> measurementLines = dropshipWholePallet
? wholePalletMeasurementLines(measurements, pickedPackageCount, parentAvailable)
: measurementLines(measurements, pickedByDetail);
int measuredRemaining = measurementLines.stream().mapToInt(MeasurementSplitLine::remainingPackageCount).sum();
if (measuredRemaining != childPackageCount) {
throw conflict("主入库单测量明细剩余箱数与未装柜箱数不一致");
@@ -191,7 +198,9 @@ public class PdaPickSettlementService {
}
if (root == null || !"MASTER".equals(root.inboundRole())) throw conflict("根主入库单不存在");
OrderFulfillmentSplitClient.Response orderSplit = createOrderSplit(parent, root, measurementLines,
Map<Long, Integer> orderQuantities = dropshipWholePallet
? new LinkedHashMap<>(pickedByDetail) : measurementQuantities(measurementLines);
OrderFulfillmentSplitClient.Response orderSplit = createOrderSplit(parent, root, orderQuantities,
pickedPackageCount, childPackageCount, loadingPlanId, containerBookingId, operationId,
"pda-task-" + taskId, operatorId, operatorName);
String settlementKey = "PDA-SETTLE-" + taskId + '-' + parentInboundId;
@@ -282,17 +291,14 @@ public class PdaPickSettlementService {
}
private OrderFulfillmentSplitClient.Response createOrderSplit(
ParentRow source, ParentRow root, List<MeasurementSplitLine> lines,
ParentRow source, ParentRow root, Map<Long, Integer> quantitiesByDetail,
int loadedPackageCount, int remainingPackageCount, long loadingPlanId,
long containerBookingId, String operationId, String idempotencyKey,
long operatorId, String operatorName) {
if (root.orderId() == null || source.orderId() == null) {
throw conflict("入仓单缺少真实订单引用");
}
List<OrderFulfillmentSplitClient.QuantityLine> quantities = lines.stream()
.collect(Collectors.groupingBy(line -> line.item().inboundDetailId(), LinkedHashMap::new,
Collectors.summingInt(line -> count(line.item().packageCount(), "测量明细箱数"))))
.entrySet().stream()
List<OrderFulfillmentSplitClient.QuantityLine> quantities = quantitiesByDetail.entrySet().stream()
.map(entry -> new OrderFulfillmentSplitClient.QuantityLine(entry.getKey(), entry.getValue()))
.toList();
OrderFulfillmentSplitClient.CreateRequest request = new OrderFulfillmentSplitClient.CreateRequest(
@@ -386,6 +392,24 @@ public class PdaPickSettlementService {
return result;
}
/** 一件代发逐箱封托已经冻结 SKU 归属;测量批次只承担整票体积重量,不再冒充 SKU 明细。 */
private static List<MeasurementSplitLine> wholePalletMeasurementLines(List<MeasurementItemRow> measurements,
int pickedPackageCount,
int parentAvailable) {
int measuredPackages = measurements.stream()
.mapToInt(item -> count(item.packageCount(), "测量明细箱数")).sum();
if (pickedPackageCount != parentAvailable || measuredPackages != parentAvailable) {
throw conflict("一件代发整托箱数与入库单、测量批次不守恒");
}
return measurements.stream().map(item -> new MeasurementSplitLine(item,
count(item.packageCount(), "测量明细箱数"), 0)).toList();
}
private static Map<Long, Integer> measurementQuantities(List<MeasurementSplitLine> lines) {
return lines.stream().collect(Collectors.groupingBy(line -> line.item().inboundDetailId(),
LinkedHashMap::new, Collectors.summingInt(line -> count(line.item().packageCount(), "测量明细箱数"))));
}
private void consumePickedAllocations(long accountId, long inboundId,
List<InboundPalletAllocationEntity> confirmed, int pickedCount) {
int toConsume = pickedCount;