fix: enforce dropship pallet count for inbound plans

This commit is contained in:
2026-09-14 16:38:50 +08:00
parent 99f2c730e0
commit 26c37deb55
5 changed files with 82 additions and 5 deletions
@@ -75,6 +75,10 @@ public interface InboundPlanOrderMapper {
String findSourceContainerBookingId(@Param("customerId") String customerId,
@Param("orderId") Long orderId);
@Select("SELECT order_type FROM ll_order WHERE customer_id=#{customerId} AND id=#{orderId} LIMIT 1")
String findOrderType(@Param("customerId") String customerId,
@Param("orderId") Long orderId);
@Select("SELECT o.id AS orderId,o.customer_id AS customerId,o.container_no AS containerNo," +
"o.inbound_code AS inboundCode,o.current_status AS currentStatus,o.inbound_order_no AS inboundOrderNo," +
"COALESCE(o.volume_cbm,0) AS volumeCbm,COALESCE(o.package_count,0) AS packageCount," +
@@ -130,10 +130,23 @@ public class InboundPlanService {
WarehouseResourceGateway.WarehouseReference receivingWarehouse =
requiredReceivingWarehouse(containerWarehouseId);
validateOrders(snapshots);
int minimumPalletCount = suggestedPalletCount(order);
int sourcePalletCount = Objects.requireNonNullElse(
sourcePalletMapper.palletNos(customerId, request.orderId()), List.<String>of()).size();
minimumPalletCount = Math.max(minimumPalletCount, sourcePalletCount);
String orderType = trimToNull(orderMapper.findOrderType(customerId, request.orderId()));
int sourcePalletCount = "ONE_CLICK_DROPSHIP".equals(orderType)
? dropshipOrders.palletSnapshots(customerId, request.orderId()).size()
: Objects.requireNonNullElse(
sourcePalletMapper.palletNos(customerId, request.orderId()), List.<String>of()).size();
if ("ONE_CLICK_DROPSHIP".equals(orderType)) {
if (sourcePalletCount <= 0) {
throw new ResponseStatusException(HttpStatus.CONFLICT,
"一件代发订单缺少不可变来源托盘快照,不能生成入库计划");
}
if (request.palletCount() != sourcePalletCount) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"一件代发人工计划托数必须与头程封托托盘数一致:" + sourcePalletCount);
}
}
int minimumPalletCount = "ONE_CLICK_DROPSHIP".equals(orderType)
? sourcePalletCount : Math.max(suggestedPalletCount(order), sourcePalletCount);
if (request.palletCount() < minimumPalletCount) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"人工计划托数不能少于柜级预览建议托数 " + minimumPalletCount);
@@ -272,6 +285,10 @@ public class InboundPlanService {
int targetPalletCount = Objects.requireNonNullElse(row.plannedPalletCount(),
Objects.requireNonNullElse(suggested, 0));
int supplementPalletCount = Math.max(0, targetPalletCount - sourcePalletCount);
if (planned && "ONE_CLICK_DROPSHIP".equals(row.orderType())
&& targetPalletCount != sourcePalletCount) {
blockers.add("DROPSHIP_PALLET_COUNT_MISMATCH");
}
if (!planned && (suggested == null || suggested <= 0)) blockers.add("PALLET_COUNT_NOT_READY");
String destinationType = destinationType(row);
String fbaWarehouseCode = isFbaDestination(row) ? trimToNull(row.fbaWarehouseCode()) : null;