feat: freeze and propagate first-leg pallet labels
This commit is contained in:
+10
-3
@@ -142,13 +142,20 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT,
|
||||
"Reserved pallet customer binding is invalid");
|
||||
}
|
||||
WarehousePalletData pallet = lookupPallet(palletCode).data();
|
||||
if (pallet.id() != palletId || pallet.warehouseId() != warehouseId || pallet.locationId() != locationId
|
||||
WarehousePalletReference pallet;
|
||||
try {
|
||||
pallet = reference(lookupPallet(palletCode).data());
|
||||
} catch (ResponseStatusException exception) {
|
||||
if (exception.getStatusCode().value() != 404) throw exception;
|
||||
// 已生成计划可能保留早期展示码;确认过的资源绑定仍是唯一可信物理身份。
|
||||
pallet = resolvePallet(palletId);
|
||||
}
|
||||
if (pallet.palletId() != palletId || pallet.warehouseId() != warehouseId || pallet.locationId() != locationId
|
||||
|| !"OCCUPIED".equals(pallet.status())) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT,
|
||||
"Scanned pallet does not match the reserved inbound plan resource");
|
||||
}
|
||||
return reference(pallet);
|
||||
return pallet;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ public interface WarehouseResourceGateway {
|
||||
java.math.BigDecimal maxLoadKg, String status) { }
|
||||
record PalletBatchEnsure(long warehouseId, String batchKey, List<PalletBatchItemRequest> items) { }
|
||||
record PalletBatchItemRequest(long customerId, String businessKey, String inboundPlanNo,
|
||||
int sequenceNo, String palletType, String fbaWarehouseCode) { }
|
||||
int sequenceNo, String palletType, String fbaWarehouseCode,
|
||||
String palletCode) { }
|
||||
record PalletBatchCommand(long warehouseId, String batchKey, String commandKey) { }
|
||||
record PalletBatchCompensation(long warehouseId, String batchKey, String commandKey, String reason) { }
|
||||
record PalletBatchResponse(long batchId, String batchKey, String status, int attemptNo,
|
||||
|
||||
+8
-3
@@ -117,7 +117,7 @@ public class ContainerInboundPlanConversionCoordinator {
|
||||
preparation.warehouseId(), command.getBatchKey(), preparation.items().stream().map(item ->
|
||||
new WarehouseResourceGateway.PalletBatchItemRequest(Long.parseLong(item.customerId()),
|
||||
item.businessKey(), item.planNo(), item.globalSequenceNo(), "STANDARD",
|
||||
item.fbaWarehouseCode())).toList());
|
||||
item.fbaWarehouseCode(), item.palletCode())).toList());
|
||||
WarehouseResourceGateway.PalletBatchResponse reservation;
|
||||
try {
|
||||
reservation = warehouse.ensurePalletBatch(ensure);
|
||||
@@ -207,10 +207,15 @@ public class ContainerInboundPlanConversionCoordinator {
|
||||
.flatMap(group -> group.orders().stream()).filter(item -> "READY".equals(item.readiness())).toList()) {
|
||||
long planId = IdWorker.getId();
|
||||
String planNo = numbers.next("INBOUND_PLAN", order.destinationWarehouseCode(), planId);
|
||||
List<String> sourcePalletNos = plans.sourcePalletNos(
|
||||
order.customerId(), Long.parseLong(order.orderId()), order.orderType());
|
||||
if (sourcePalletNos.size() != order.suggestedPalletCount()) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "头程托盘码数量与柜级预览不一致");
|
||||
}
|
||||
for (int localSequence = 1; localSequence <= order.suggestedPalletCount(); localSequence++) {
|
||||
items.add(new PreparedItem(order.customerId(), Long.parseLong(order.orderId()), planId, planNo,
|
||||
localSequence, ++globalSequence, "CIP:" + generationId + ":" + globalSequence,
|
||||
trimToNull(order.fbaWarehouseCode())));
|
||||
trimToNull(order.fbaWarehouseCode()), sourcePalletNos.get(localSequence - 1)));
|
||||
}
|
||||
}
|
||||
Preparation preparation = new Preparation(warehouseId, List.copyOf(items));
|
||||
@@ -373,5 +378,5 @@ public class ContainerInboundPlanConversionCoordinator {
|
||||
public record Preparation(long warehouseId, List<PreparedItem> items) { }
|
||||
public record PreparedItem(String customerId, long orderId, long planId, String planNo,
|
||||
int localSequenceNo, int globalSequenceNo, String businessKey,
|
||||
String fbaWarehouseCode) { }
|
||||
String fbaWarehouseCode, String palletCode) { }
|
||||
}
|
||||
|
||||
+20
-1
@@ -27,6 +27,7 @@ import com.baiyue.lastleg.dropship.service.DropshipOrderService;
|
||||
import com.baiyue.common.event.ContainerNumbers;
|
||||
import com.baiyue.lastleg.entity.LastlegOrderCommandRecord;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderCommandRecordMapper;
|
||||
import com.baiyue.lastleg.mapper.LastlegSourcePalletMapper;
|
||||
import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -65,8 +66,16 @@ public class InboundPlanService {
|
||||
@Resource private DropshipOrderService dropshipOrders;
|
||||
@Resource private WarehouseResourceGateway warehouseGateway;
|
||||
@Resource private LastlegOrderCommandRecordMapper commandMapper;
|
||||
@Resource private LastlegSourcePalletMapper sourcePalletMapper;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
|
||||
public List<String> sourcePalletNos(String customerId, long orderId, String orderType) {
|
||||
return "ONE_CLICK_DROPSHIP".equals(orderType)
|
||||
? dropshipOrders.palletSnapshots(customerId, orderId).stream()
|
||||
.map(DropshipPalletSnapshot::sourcePalletNo).toList()
|
||||
: sourcePalletMapper.palletNos(customerId, orderId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public InboundPlanResponse convertManual(ManualInboundPlanRequest request, String idempotencyKey,
|
||||
String operatorId) {
|
||||
@@ -393,6 +402,10 @@ public class InboundPlanService {
|
||||
PalletAllocator.Result allocation = wholePallets == null && manual == null ? PalletAllocator.allocate(orders.stream()
|
||||
.map(order -> new PalletAllocator.LineInput(order.orderId(), warehouseKey(order), volume(order),
|
||||
order.packageCount(), order.recommendedPalletCount())).toList()) : null;
|
||||
if (allocation != null && sourcePalletNos != null && !sourcePalletNos.isEmpty()
|
||||
&& sourcePalletNos.size() != allocation.pallets().size()) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "头程托盘码数量与尾程计划托盘数不一致");
|
||||
}
|
||||
if (wholePallets != null) validateWholePallets(orders, wholePallets);
|
||||
plan.setPalletCount(manual != null ? manual.palletCount()
|
||||
: wholePallets == null ? allocation.pallets().size() : wholePallets.size());
|
||||
@@ -479,6 +492,7 @@ public class InboundPlanService {
|
||||
List<Integer> pendingIndexes = new ArrayList<>();
|
||||
List<List<SourceOrderSnapshot>> snapshots = new ArrayList<>();
|
||||
List<List<WholePalletInput>> wholePallets = new ArrayList<>();
|
||||
List<List<String>> standardPalletNos = new ArrayList<>();
|
||||
for (int index = 0; index < refs.size(); index++) {
|
||||
InboundPlanOrderMapper.ContainerOrderRef ref = refs.get(index);
|
||||
InboundPlan existing = existingPlans.get(index);
|
||||
@@ -517,6 +531,11 @@ public class InboundPlanService {
|
||||
validateWholePallets(orders, sourcePallets);
|
||||
}
|
||||
wholePallets.add(sourcePallets);
|
||||
List<String> standardNos = "ONE_CLICK_DROPSHIP".equals(ref.orderType()) ? List.of()
|
||||
: sourcePalletMapper.palletNos(ref.customerId(), ref.orderId());
|
||||
if (sourcePallets == null && standardNos.isEmpty()) throw new ResponseStatusException(
|
||||
HttpStatus.CONFLICT, "散货订单缺少头程托盘码快照");
|
||||
standardPalletNos.add(standardNos);
|
||||
}
|
||||
requireSingleWarehouseId(warehouseIds);
|
||||
|
||||
@@ -531,7 +550,7 @@ public class InboundPlanService {
|
||||
Map<Integer, WarehouseResourceGateway.PalletBatchItem> reserved = prepared == null ? Map.of()
|
||||
: prepared.pallets().stream().collect(Collectors.toMap(PreparedPallet::sequenceNo,
|
||||
PreparedPallet::reservation));
|
||||
created.put(refIndex, createPlan(ref.customerId(), ref.orderId(), snapshots.get(pendingIndex), List.of(),
|
||||
created.put(refIndex, createPlan(ref.customerId(), ref.orderId(), snapshots.get(pendingIndex), standardPalletNos.get(pendingIndex),
|
||||
wholePallets.get(pendingIndex), null, null, prepared, reserved));
|
||||
}
|
||||
List<InboundPlanResponse> result = new ArrayList<>(refs.size());
|
||||
|
||||
Reference in New Issue
Block a user