修复尾程货主快照与短单号合同

This commit is contained in:
2026-09-01 11:06:26 +08:00
parent 4991536065
commit de0eddeee8
7 changed files with 97 additions and 47 deletions
@@ -58,6 +58,7 @@ public class LoadingCompletedConsumer {
String containerNo = ContainerNumbers.requireCanonical(payload.containerNo());
String sourceContainerBookingId = sourceContainerBookingId(envelope, payload);
if(payload.orders()==null||payload.orders().isEmpty()) throw new IllegalArgumentException("事件没有入仓单");
OwnerSnapshot owner = requireOwnerSnapshot(payload.orders(), envelope.tenantId());
if (envelope.eventVersion() == 2) validateCartonSkuMappings(payload);
freezeContainerIdentity(envelope, sourceContainerBookingId, containerNo);
LastlegEventInbox existing=inboxMapper.selectById(envelope.eventId());
@@ -87,7 +88,8 @@ public class LoadingCompletedConsumer {
for (int index = 0; index < payload.orders().size(); index++) {
var source = payload.orders().get(index);
JsonNode rawSource = rawOrders.isArray() && index < rawOrders.size() ? rawOrders.get(index) : objectMapper.createObjectNode();
createOrder(envelope, payload, source, orderNo, rawSource, containerNo, sourceContainerBookingId);
createOrder(envelope, payload, source, orderNo, rawSource, containerNo,
sourceContainerBookingId, owner);
}
inbox.setStatus("PROCESSED"); inbox.setProcessedAt(LocalDateTime.now()); inboxMapper.updateById(inbox);
return payload.orders().size();
@@ -136,6 +138,33 @@ public class LoadingCompletedConsumer {
return value.trim();
}
private OwnerSnapshot requireOwnerSnapshot(List<FirstLegLoadingPlanCompletedV1.Order> orders,
String trustedCustomerId) {
String customerId = requiredOwnerValue(orders.get(0).customerId(), "customerId");
String customerName = requiredOwnerValue(orders.get(0).customerName(), "customerName");
if (!trustedCustomerId.equals(customerId)) {
throw new IllegalArgumentException("Order customerId does not match the trusted event customer");
}
for (FirstLegLoadingPlanCompletedV1.Order order : orders) {
if (!customerId.equals(requiredOwnerValue(order.customerId(), "customerId"))
|| !customerName.equals(requiredOwnerValue(order.customerName(), "customerName"))) {
throw new IllegalArgumentException("同一装柜完成事件的货主快照不一致");
}
}
return new OwnerSnapshot(customerId, customerName);
}
private String requiredOwnerValue(String value, String field) {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException("尾程事件缺少不可变货主快照 " + field);
}
String normalized = value.trim();
if (normalized.length() > 128) {
throw new IllegalArgumentException("尾程事件货主快照过长 " + field);
}
return normalized;
}
private void validateCartonSkuMappings(FirstLegLoadingPlanCompletedV1 payload) {
for (FirstLegLoadingPlanCompletedV1.Order order : payload.orders()) {
Set<String> orderCartonMarks = new HashSet<>();
@@ -186,7 +215,7 @@ public class LoadingCompletedConsumer {
private void createOrder(EventEnvelope event,FirstLegLoadingPlanCompletedV1 payload,
FirstLegLoadingPlanCompletedV1.Order source,String orderNo, JsonNode rawSource,
String containerNo, String sourceContainerBookingId) {
String containerNo, String sourceContainerBookingId, OwnerSnapshot owner) {
String orderHash=EventPayloadHash.sha256(EventPayloadCanonicalizer.canonicalize(rawSource));
LastlegOrder existing=orderMapper.findSource(event.tenantId(),event.sourceRegion().name(),source.sourceInboundId());
if(existing!=null) {
@@ -196,11 +225,8 @@ public class LoadingCompletedConsumer {
LastlegOrder order=new LastlegOrder();
String orderType = source.orderType();
String destinationType = destinationType(payload, source);
String customerId = source.customerId() == null || source.customerId().isBlank()
? event.tenantId() : source.customerId();
if (!event.tenantId().equals(customerId)) {
throw new IllegalArgumentException("Order customerId does not match the trusted event customer");
}
String customerId = owner.customerId();
String customerName = owner.customerName();
List<DropshipRequests.Pallet> dropshipPallets = "ONE_CLICK_DROPSHIP".equals(orderType)
? pallets(source, rawSource) : List.of();
if ("ONE_CLICK_DROPSHIP".equals(orderType) && dropshipPallets.isEmpty()) {
@@ -211,7 +237,7 @@ public class LoadingCompletedConsumer {
order.setInboundCode(source.inboundCode()); order.setSourceRegion(event.sourceRegion().name());
order.setSourceInboundId(source.sourceInboundId()); order.setRootInboundId(source.rootInboundId());
order.setSourceOrderId(source.sourceOrderId()); order.setSourceOrderNo(source.sourceOrderNo()); order.setRootOrderId(source.rootOrderId());
order.setCustomerName(source.customerName());
order.setCustomerName(customerName);
order.setSourceWarehouseId(payload.warehouseId()); order.setSourceWarehouseName(payload.warehouseName());
order.setOverseasWarehouseId(null); order.setOverseasWarehouseName(null);
order.setFbaWarehouseCode(source.destinationWarehouseCode()); order.setContainerNo(containerNo);
@@ -423,4 +449,6 @@ public class LoadingCompletedConsumer {
}
return result;
}
private record OwnerSnapshot(String customerId, String customerName) { }
}