This commit is contained in:
wujinliang
2026-09-18 11:41:13 +08:00
68 changed files with 819 additions and 383 deletions
@@ -126,7 +126,7 @@ public interface InboundPlanOrderMapper {
@Update("UPDATE ll_order SET inbound_order_no=#{planNo},current_status='INBOUND_PLANNED'," +
"pallet_merge_flag=CASE WHEN #{mergeRequired}=1 THEN 'MERGE_REQUIRED' ELSE NULL END," +
"pallet_count=#{palletCount},version=version+1,updated_at=#{updatedAt} " +
"WHERE customer_id=#{customerId} AND id=#{orderId} AND version=#{expectedVersion} AND detained=0 " +
"WHERE customer_id=#{customerId} AND id=#{orderId} AND version=#{expectedVersion} " +
"AND current_status IN ('PENDING_ASSIGNMENT','DESTINATION_ASSIGNED') AND inbound_order_no IS NULL")
int markPlannedManual(@Param("customerId") String customerId, @Param("orderId") Long orderId,
@Param("planNo") String planNo, @Param("palletCount") int palletCount,
@@ -2,6 +2,7 @@ package com.baiyue.lastleg.inboundplan.pda.dto;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;
@@ -23,7 +24,8 @@ public final class ReceivingContainerRequests {
public record PalletResolve(@NotBlank String palletCode, @NotBlank String inboundCode) { }
/** packageCount 是该托当前累计实收箱数,不是本次增量。 */
public record BulkReceive(@NotBlank String inboundCode, @NotBlank String palletCode,
@Positive int packageCount, Integer expectedPalletVersion,
@Positive @Max(value = 66, message = "一个托盘最多只能收66箱,请拆分到其他托盘") int packageCount,
Integer expectedPalletVersion,
@NotBlank @Size(max = 255) String idempotencyKey) {
public BulkReceive(String inboundCode, String palletCode, int packageCount, String idempotencyKey) {
this(inboundCode, palletCode, packageCount, null, idempotencyKey);
@@ -73,6 +73,9 @@ public class ReceivingContainerService {
"/api/pda/v1/last-leg/receiving-containers/current/domestic-loading-photos/{type}/content";
private static final String PALLET_MERGE_HINT =
"该入库计划可选择合托:合托时扫描同目的仓已使用的托盘码,独立收货时扫描新托盘码;不强制合托";
private static final int MAX_PACKAGES_PER_PALLET = 66;
private static final String PALLET_CAPACITY_MESSAGE =
"一个托盘最多只能收66箱,请拆分到其他托盘";
@Resource private InboundPlanMapper plans;
@Resource private InboundPlanLineMapper lines;
@@ -364,6 +367,7 @@ public class ReceivingContainerService {
ReceivingContainerRequests.BulkReceive request) {
ReceivingContainerOperation replay = replay(operatorKey, "BULK_RECEIVE", request.idempotencyKey(), request);
if (replay != null) return read(replay, ReceivingContainerResponses.Receipt.class);
requirePalletCapacity(request.packageCount());
ReceivingContainerSession session = requireSigned(operatorKey);
InboundRef ref = requireInbound(session.getContainerNo(), request.inboundCode());
if ("ONE_CLICK_DROPSHIP".equals(ref.order().getOrderType())) {
@@ -463,6 +467,10 @@ public class ReceivingContainerService {
PalletSelection selection = resolveReceivingPallet(ref, request.palletCode(), true);
WarehouseResourceGateway.WarehousePalletReference resource = selection.resource();
InboundPlanPallet pallet = selection.pallet();
long packagesOnPallet = cartons.selectCount(new LambdaQueryWrapper<InboundPlanCarton>()
.eq(InboundPlanCarton::getWarehousePalletId, resource.palletId())
.eq(InboundPlanCarton::getStatus, "ON_PALLET"));
requirePalletCapacity(packagesOnPallet + 1);
workflow.validateCartonResolved(customerId, ref.plan(), ref.line(), pallet, request.cartonMark());
Long resourceLockId = workflow.assignResolvedPallet(customerId, ref.plan(), pallet, resource);
try {
@@ -492,6 +500,8 @@ public class ReceivingContainerService {
if (sourcePalletNo == null) throw notFound("DP or carton is not part of the current container");
requireCompleteManifest(session.getContainerNo(), sourcePalletNo);
List<DropshipPalletRef> matches = dropshipPalletRefs(session.getContainerNo(), sourcePalletNo);
int total = matches.stream().mapToInt(value -> value(value.allocation().getPlannedPackageCount())).sum();
requirePalletCapacity(total);
boolean alreadyReceived = matches.stream().allMatch(match ->
value(match.allocation().getPickedPackageCount()) == value(match.allocation().getPlannedPackageCount()));
int accepted = 0;
@@ -511,7 +521,6 @@ public class ReceivingContainerService {
}
List<InboundRef> group = matches.stream().map(DropshipPalletRef::ref).distinct().toList();
List<String> inboundCodes = group.stream().map(value -> value.line().getInboundCode()).distinct().sorted().toList();
int total = matches.stream().mapToInt(value -> value(value.allocation().getPlannedPackageCount())).sum();
int received = matches.stream().mapToInt(value -> value(value.allocation().getPickedPackageCount())).sum();
InboundRef first = group.get(0);
ReceivingContainerResponses.Inbound inbound = inbound(first);
@@ -885,6 +894,10 @@ public class ReceivingContainerService {
|| "LOCKED".equals(pallet.getAssignmentStatus()));
}
private void requirePalletCapacity(long packageCount) {
if (packageCount > MAX_PACKAGES_PER_PALLET) throw conflict(PALLET_CAPACITY_MESSAGE);
}
private void requireMaterializedPlans(List<InboundPlan> containerPlans) {
for (InboundPlan plan : containerPlans) {
int expected = plan.getPalletCount() == null ? 0 : plan.getPalletCount();
@@ -126,7 +126,6 @@ public class InboundPlanService {
if (order.version() != request.expectedOrderVersion()) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "尾程订单版本已变化,请刷新后重试");
}
if (order.detained()) throw new ResponseStatusException(HttpStatus.CONFLICT, "暂扣尾程订单不能生成入库计划");
if (!Objects.equals(containerWarehouseId, trimToNull(order.overseasWarehouseId()))) {
throw new ResponseStatusException(HttpStatus.CONFLICT, "来源柜接柜仓冻结事实已变化,请刷新后重试");
}
@@ -280,7 +279,6 @@ public class InboundPlanService {
boolean planned = trimToNull(row.planNo()) != null;
if (!planned) {
if (trimToNull(row.inboundCode()) == null) blockers.add("MISSING_INBOUND_CODE");
if (row.detained()) blockers.add("ORDER_DETAINED");
if (!("PENDING_ASSIGNMENT".equals(row.currentStatus())
|| "DESTINATION_ASSIGNED".equals(row.currentStatus()))) blockers.add("ORDER_STATUS_NOT_READY");
if (containerNo == null || !Objects.equals(containerNo, trimToNull(row.containerNo()))) {