修改提交

This commit is contained in:
2026-08-22 10:16:45 +08:00
parent af8724dd70
commit 93feb7da67
16 changed files with 150 additions and 44 deletions
@@ -7,7 +7,7 @@ import lombok.Data;
import java.time.LocalDateTime;
/** 本柜在国内冻结、由海外首次扫码确权的箱级作业事实。 */
/** 头程装柜完成时冻结并关联尾程订单、由海外扫码补充托盘归属的箱级事实。 */
@Data
@TableName("ll_inbound_plan_carton")
public class InboundPlanCarton {
@@ -48,7 +48,7 @@ public class InventoryCommandService {
balance.setInTransitPackages(before + request.packages());
touch(balance);
balances.updateById(balance);
ledger(customerId, operatorId, operation.getId(), balance, null, "IN_TRANSIT",
ledger(customerId, operatorId, operation.getId(), balance, null, sku(request.skuCode()), "IN_TRANSIT",
"OUTSIDE", "IN_TRANSIT", before, request.packages(), before + request.packages(),
request.businessOrderNo(), request.inboundOrderNo(), null, request.sourceEventId(),
request.idempotencyKey(), request.remark());
@@ -74,7 +74,7 @@ public class InventoryCommandService {
balance.setAvailablePackages(value(balance.getAvailablePackages()) + request.packages());
touch(balance);
balances.updateById(balance);
ledger(customerId, operatorId, operation.getId(), balance, position, "STOCK_IN",
ledger(customerId, operatorId, operation.getId(), balance, position, sku(request.skuCode()), "STOCK_IN",
transferred == request.packages() ? "IN_TRANSIT" : "OUTSIDE", "AVAILABLE",
before, request.packages(), before + request.packages(),
request.businessOrderNo(), request.inboundOrderNo(), null, request.sourceEventId(),
@@ -138,7 +138,7 @@ public class InventoryCommandService {
balances.updateById(balance);
boolean palletEmpty = commands.palletPackages(customerId, position.getPalletId()) == 0;
if (palletEmpty) warehouseGateway.scrapPallet(customerId, position.getPalletId());
ledger(customerId, operatorId, operation.getId(), balance, position, "SHIP",
ledger(customerId, operatorId, operation.getId(), balance, position, balance.getSkuCode(), "SHIP",
"PICKED", "SHIPPED", before, -request.packages(), before - request.packages(),
request.businessOrderNo(), null, request.outboundOrderNo(), request.sourceEventId(),
request.idempotencyKey(), request.remark());
@@ -170,7 +170,7 @@ public class InventoryCommandService {
balance.setAvailablePackages(balanceAfter);
touch(balance);
balances.updateById(balance);
ledger(customerId, operatorId, operation.getId(), balance, position, "ADJUST",
ledger(customerId, operatorId, operation.getId(), balance, position, balance.getSkuCode(), "ADJUST",
"AVAILABLE", "AVAILABLE", before, request.packageDelta(), after,
request.businessOrderNo(), null, null, null, request.idempotencyKey(),
request.reason() + remarkSuffix(request.remark()));
@@ -202,7 +202,7 @@ public class InventoryCommandService {
packages(balance, to, packages(balance, to) + request.packages());
touch(balance);
balances.updateById(balance);
ledger(customerId, operatorId, operation.getId(), balance, position, operationType,
ledger(customerId, operatorId, operation.getId(), balance, position, balance.getSkuCode(), operationType,
from.name(), to.name(), beforeTarget, request.packages(), beforeTarget + request.packages(),
request.businessOrderNo(), null, request.outboundOrderNo(), request.sourceEventId(),
request.idempotencyKey(), request.remark());
@@ -234,8 +234,11 @@ public class InventoryCommandService {
String productNameEn) {
String skuCode = sku(requestedSkuCode);
InventoryBalance balance = balances.lockDimension(customerId, overseasWarehouseId,
destinationWarehouseCode, inboundOrderId, inboundCode, skuCode);
if (balance != null) return balance;
destinationWarehouseCode, inboundOrderId, inboundCode);
if (balance != null) {
mergeSkuSnapshot(balance, skuCode);
return balance;
}
balance = new InventoryBalance();
balance.setId(IdWorker.getId());
balance.setCustomerId(customerId);
@@ -261,8 +264,11 @@ public class InventoryCommandService {
return balance;
} catch (DuplicateKeyException exception) {
InventoryBalance concurrent = balances.lockDimension(customerId, overseasWarehouseId,
destinationWarehouseCode, inboundOrderId, inboundCode, skuCode);
if (concurrent != null) return concurrent;
destinationWarehouseCode, inboundOrderId, inboundCode);
if (concurrent != null) {
mergeSkuSnapshot(concurrent, skuCode);
return concurrent;
}
throw exception;
}
}
@@ -365,7 +371,7 @@ public class InventoryCommandService {
}
private void ledger(String customerId, String operatorId, Long operationId, InventoryBalance balance,
InventoryPosition position, String businessType, String from, String to,
InventoryPosition position, String skuCode, String businessType, String from, String to,
long beforePackages, long deltaPackages, long afterPackages,
String businessOrderNo, String inboundOrderNo, String outboundOrderNo,
String sourceEventId, String idempotencyKey, String remark) {
@@ -381,7 +387,7 @@ public class InventoryCommandService {
ledger.setPalletNo(position == null ? null : position.getPalletNo());
ledger.setBatchNo(position == null ? null : position.getBatchNo());
ledger.setWarehouseLocationCode(position == null ? null : position.getWarehouseLocationCode());
ledger.setSkuCode(balance.getSkuCode());
ledger.setSkuCode(skuCode);
ledger.setBusinessType(businessType);
ledger.setBusinessOrderId(balance.getInboundOrderId());
ledger.setBusinessOrderNo(trim(businessOrderNo));
@@ -406,6 +412,17 @@ public class InventoryCommandService {
ledgers.insert(ledger);
}
private static void mergeSkuSnapshot(InventoryBalance balance, String skuCode) {
String existing = trim(balance.getSkuCode());
if (existing == null) {
balance.setSkuCode(skuCode);
} else if (!existing.equals(skuCode) && !"MIXED".equals(existing)) {
balance.setSkuCode("MIXED");
balance.setProductNameZh(null);
balance.setProductNameEn(null);
}
}
private InventoryCommandResponse response(InventoryOperation operation, InventoryBalance balance,
InventoryPosition position, boolean palletEmpty) {
return new InventoryCommandResponse(operation.getId(), operation.getOperationType(), balance.getId(),
@@ -12,24 +12,22 @@ public interface InventoryBalanceMapper extends BaseMapper<InventoryBalance> {
@Select("SELECT * FROM ll_inventory_balance WHERE customer_id=#{customerId} " +
"AND overseas_warehouse_id=#{overseasWarehouseId} " +
"AND destination_warehouse_code=#{destinationWarehouseCode} " +
"AND inbound_order_id=#{inboundOrderId} AND inbound_code=#{inboundCode} AND sku_code=#{skuCode} LIMIT 1")
"AND inbound_order_id=#{inboundOrderId} AND inbound_code=#{inboundCode} LIMIT 1")
InventoryBalance findDimension(@Param("customerId") String customerId,
@Param("overseasWarehouseId") String overseasWarehouseId,
@Param("destinationWarehouseCode") String destinationWarehouseCode,
@Param("inboundOrderId") Long inboundOrderId,
@Param("inboundCode") String inboundCode,
@Param("skuCode") String skuCode);
@Param("inboundCode") String inboundCode);
@Select("SELECT * FROM ll_inventory_balance WHERE customer_id=#{customerId} " +
"AND overseas_warehouse_id=#{overseasWarehouseId} " +
"AND destination_warehouse_code=#{destinationWarehouseCode} " +
"AND inbound_order_id=#{inboundOrderId} AND inbound_code=#{inboundCode} AND sku_code=#{skuCode} LIMIT 1 FOR UPDATE")
"AND inbound_order_id=#{inboundOrderId} AND inbound_code=#{inboundCode} LIMIT 1 FOR UPDATE")
InventoryBalance lockDimension(@Param("customerId") String customerId,
@Param("overseasWarehouseId") String overseasWarehouseId,
@Param("destinationWarehouseCode") String destinationWarehouseCode,
@Param("inboundOrderId") Long inboundOrderId,
@Param("inboundCode") String inboundCode,
@Param("skuCode") String skuCode);
@Param("inboundCode") String inboundCode);
@Select("<script>SELECT * FROM ll_inventory_balance WHERE customer_id=#{customerId}" +
"<if test='overseasWarehouseId != null and overseasWarehouseId != \"\"'> AND overseas_warehouse_id=#{overseasWarehouseId}</if>" +
@@ -118,8 +118,8 @@ public class LoadingCompletedConsumer {
throw new IllegalArgumentException("V2 尾程交接事件的箱唛映射缺少 SKU");
}
List<String> marks = cartonMarks == null ? List.of() : cartonMarks;
if (marks.size() < loadedPackages) {
throw new IllegalArgumentException("V2 尾程交接事件的 SKU 箱唛数量少于实装箱数: " + skuCode);
if (marks.size() != loadedPackages) {
throw new IllegalArgumentException("V2 尾程交接事件的 SKU 箱唛数量必须等于实装箱数: " + skuCode);
}
for (String mark : marks) {
if (mark == null || mark.isBlank() || !orderCartonMarks.add(mark)) {
@@ -183,7 +183,7 @@ public class LoadingCompletedConsumer {
detail.setDestinationWarehouseId(item.destinationWarehouseId()); detail.setDestinationWarehouseCode(item.destinationWarehouseCode());
detail.setDestinationWarehouseName(item.destinationWarehouseName()); detail.setFbaTrackingNo(item.fbaTrackingNo());
detail.setShipmentNo(item.shipmentNo()); detail.setShippingMark(item.shippingMark()); detailMapper.insert(detail);
createCartonLabelPool(customerId, item);
createCartonLabels(customerId, order.getId(), item);
}
LastlegOrderStatusHistory history=new LastlegOrderStatusHistory();
history.setOrderId(order.getId()); history.setToStatus("PENDING_ASSIGNMENT"); history.setEventId(event.eventId());
@@ -218,7 +218,7 @@ public class LoadingCompletedConsumer {
}
}
private void createCartonLabelPool(String customerId, FirstLegLoadingPlanCompletedV1.Item item) {
private void createCartonLabels(String customerId, Long orderId, FirstLegLoadingPlanCompletedV1.Item item) {
List<String> marks = item.cartonMarks() == null ? List.of() : item.cartonMarks();
if (marks.isEmpty()) return; // 历史 V1 事件保持原有按箱数入库路径。
if (marks.stream().anyMatch(mark -> mark == null || mark.isBlank()) || marks.stream().distinct().count() != marks.size()) {
@@ -226,7 +226,7 @@ public class LoadingCompletedConsumer {
}
for (String mark : marks) {
InboundPlanCarton carton = new InboundPlanCarton();
carton.setId(IdWorker.getId()); carton.setCustomerId(customerId);
carton.setId(IdWorker.getId()); carton.setCustomerId(customerId); carton.setOrderId(orderId);
carton.setSourceInboundDetailId(item.sourceInboundDetailId()); carton.setSkuCode(item.skuCode());
carton.setCartonMark(mark); carton.setDestinationWarehouseId(item.destinationWarehouseId());
carton.setDestinationWarehouseCode(item.destinationWarehouseCode());