fix: 按物理箱贯通一件代发履约箱数

This commit is contained in:
2026-09-16 20:49:35 +08:00
parent 8797c0bef9
commit 545ad2083d
34 changed files with 779 additions and 132 deletions
@@ -7,9 +7,12 @@ import com.baiyue.lastleg.discard.entity.CargoDiscardItem;
import com.baiyue.lastleg.discard.mapper.CargoDiscardInventoryMapper;
import com.baiyue.lastleg.dropship.entity.DropshipCarton;
import com.baiyue.lastleg.dropship.entity.DropshipCartonLedger;
import com.baiyue.lastleg.dropship.entity.DropshipCartonSku;
import com.baiyue.lastleg.dropship.entity.DropshipSkuInventory;
import com.baiyue.lastleg.dropship.mapper.DropshipCartonLedgerMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipCartonSkuMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipOrderProfileMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipSkuInventoryMapper;
import com.baiyue.lastleg.inventory.mapper.InventoryPositionMapper;
import com.baiyue.lastleg.inventory.mapper.InventoryBalanceMapper;
import jakarta.annotation.Resource;
@@ -21,6 +24,7 @@ import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.LinkedHashMap;
import java.util.Map;
/** Final inventory mutation for a warehouse-approved cargo discard. */
@@ -28,6 +32,8 @@ import java.util.Map;
public class CargoDiscardInventoryAdjustmentService {
@Resource private CargoDiscardInventoryMapper inventory;
@Resource private DropshipCartonLedgerMapper cartonLedgers;
@Resource private DropshipCartonSkuMapper cartonSkus;
@Resource private DropshipSkuInventoryMapper skuInventories;
@Resource private DropshipOrderProfileMapper profiles;
@Resource private InventoryPositionMapper positions;
@Resource private InventoryBalanceMapper balances;
@@ -40,8 +46,25 @@ public class CargoDiscardInventoryAdjustmentService {
DropshipSkuInventory sku = inventory.lockSkuInventory(customerId, item.getSkuInventoryId());
if (sku == null) throw conflict("托盘 SKU 库存不存在: " + item.getSkuCode());
long before = value(sku.getPackageCount());
if (before < actualPackages || inventory.deductSkuInventory(customerId, sku.getId(), actualPackages) != 1) {
throw conflict("托盘 SKU 库存不足: " + item.getSkuCode());
Map<String, SkuDiscard> discardedSkus = new LinkedHashMap<>();
for (int index = 0; index < actualPackages; index++) {
CargoDiscardCarton link = links.get(index);
DropshipCarton carton = inventory.lockCarton(customerId, link.getCartonId());
if (carton == null) throw conflict("托盘预留箱不存在");
List<DropshipCartonSku> facts = cartonSkus.listCarton(customerId, carton.getId());
if (facts.isEmpty()) {
discardedSkus.merge(carton.getSkuCode(), new SkuDiscard(1, value(carton.getProductQuantity())), SkuDiscard::add);
} else {
for (DropshipCartonSku fact : facts) {
discardedSkus.merge(fact.getSkuCode(), new SkuDiscard(1, value(fact.getProductQuantity())), SkuDiscard::add);
}
}
}
for (Map.Entry<String, SkuDiscard> discarded : discardedSkus.entrySet()) {
if (skuInventories.deduct(customerId, item.getProfileId(), discarded.getKey(),
discarded.getValue().packages(), discarded.getValue().quantity()) != 1) {
throw conflict("托盘 SKU 库存不足: " + discarded.getKey());
}
}
var profile = profiles.selectById(item.getProfileId());
var position = profile == null || profile.getInventoryPositionId() == null ? null
@@ -120,6 +143,11 @@ public class CargoDiscardInventoryAdjustmentService {
}
private static long value(Long value) { return value == null ? 0L : value; }
private record SkuDiscard(long packages, long quantity) {
private SkuDiscard add(SkuDiscard other) {
return new SkuDiscard(Math.addExact(packages, other.packages), Math.addExact(quantity, other.quantity));
}
}
private static String remarkSuffix(String value) {
return value == null || value.isBlank() ? "" : "; " + value.trim();
}
@@ -75,7 +75,9 @@ public class CargoDiscardService {
CandidateAccumulator value = grouped.computeIfAbsent(row.getOrderId(), ignored -> new CandidateAccumulator(row));
value.add(row);
}
return grouped.values().stream().map(CandidateAccumulator::response).toList();
return grouped.values().stream()
.map(value -> value.response(inventory.countAvailableOrder(customerId, value.first.getOrderId())))
.toList();
}
@Transactional
@@ -396,12 +398,11 @@ public class CargoDiscardService {
skus.computeIfAbsent(row.getSkuCode(), ignored -> new CandidateSkuAccumulator(row.getSkuCode(), row.getProductName()))
.packages += row.getAvailablePackages() == null ? 0 : row.getAvailablePackages();
}
private CargoDiscardResponses.Candidate response() {
private CargoDiscardResponses.Candidate response(long physicalPackages) {
List<CargoDiscardResponses.CandidateSku> skuViews = skus.values().stream()
.map(value -> new CargoDiscardResponses.CandidateSku(value.skuCode, value.productName, value.packages)).toList();
long packages = skuViews.stream().mapToLong(CargoDiscardResponses.CandidateSku::availablePackages).sum();
return new CargoDiscardResponses.Candidate(first.getOrderId(), first.getInboundCode(), first.getInboundOrderNo(),
first.getOverseasWarehouseId(), first.getOverseasWarehouseName(), first.getCreatedAt(), packages, skuViews);
first.getOverseasWarehouseId(), first.getOverseasWarehouseName(), first.getCreatedAt(), physicalPackages, skuViews);
}
}
private static final class CandidateSkuAccumulator {