优化
This commit is contained in:
@@ -216,12 +216,19 @@ public interface DropshipPalletizationMapper {
|
||||
""") List<CartonRow> cartons(@Param("palletId") long palletId);
|
||||
@Select("SELECT c.*,p.pallet_no FROM fl_dropship_pallet_carton c LEFT JOIN fl_dropship_pallet p ON p.id=c.pallet_id WHERE c.task_id=#{taskId} AND c.pallet_id IS NULL ORDER BY c.counted_at,c.id") List<CartonRow> unboundCartons(@Param("taskId") long taskId);
|
||||
@Select("""
|
||||
SELECT COALESCE(SUM(o.actual_gross_weight_kg/NULLIF(o.total_package_count,0)),0) weight_kg,
|
||||
COALESCE(SUM(o.actual_volume_cbm/NULLIF(o.total_package_count,0)),0) volume_cbm
|
||||
FROM fl_dropship_pallet_carton c
|
||||
JOIN fl_inbound_order o ON o.id=c.inbound_id AND o.tenant_id=c.tenant_id
|
||||
WHERE c.pallet_id=#{palletId}""")
|
||||
PalletMetrics metrics(@Param("palletId") long palletId);
|
||||
<script>
|
||||
SELECT c.pallet_id,COUNT(DISTINCT c.id) carton_count,
|
||||
COALESCE(SUM(o.actual_gross_weight_kg/NULLIF(o.total_package_count,0)),0) gross_weight_kg,
|
||||
COALESCE(SUM(o.actual_net_weight_kg/NULLIF(o.total_package_count,0)),0) net_weight_kg,
|
||||
COALESCE(SUM(o.actual_volume_cbm/NULLIF(o.total_package_count,0)),0) volume_cbm
|
||||
FROM fl_dropship_pallet_carton c
|
||||
JOIN fl_inbound_order o ON o.id=c.inbound_id AND o.tenant_id=c.tenant_id
|
||||
WHERE c.pallet_id IN
|
||||
<foreach collection="palletIds" item="palletId" open="(" separator="," close=")">#{palletId}</foreach>
|
||||
GROUP BY c.pallet_id
|
||||
</script>
|
||||
""")
|
||||
List<PalletMetrics> physicalMetricsByPalletIds(@Param("palletIds") Collection<Long> palletIds);
|
||||
|
||||
@Select("""
|
||||
SELECT c.tenant_id,c.inbound_id,o.inbound_code,
|
||||
@@ -340,7 +347,8 @@ public interface DropshipPalletizationMapper {
|
||||
@Getter @Setter class LabelSkuRow { private Long inboundDetailId; private String skuCode,cargoName; private Integer expectedQuantity,lineNo; }
|
||||
@Getter @Setter class CartonRow { private Long id,taskId,palletId,inboundId,inboundDetailId; private String palletNo,inboundCode,skuCode,cargoName,boxCode,discrepancyStatus,discrepancyRemark; private Integer expectedSkuQuantity,actualSkuQuantity; }
|
||||
@Getter @Setter class CartonSkuRow { private Long inboundDetailId; private String skuCode,cargoName,discrepancyStatus,discrepancyRemark; private Integer expectedQuantity,actualQuantity,lineNo; }
|
||||
record PalletMetrics(BigDecimal weightKg,BigDecimal volumeCbm) {}
|
||||
record PalletMetrics(Long palletId,Integer cartonCount,BigDecimal grossWeightKg,
|
||||
BigDecimal netWeightKg,BigDecimal volumeCbm) {}
|
||||
@Getter @Setter class PrintInboundRow { private Long tenantId,inboundId; private String inboundCode,destinationWarehouse; private Integer cartonCount,itemQuantity; }
|
||||
@Getter @Setter class PrintSkuRow { private String skuCode; private Integer cartonCount,itemQuantity,minUnitsPerCarton,maxUnitsPerCarton; }
|
||||
@Getter @Setter class PalletLine { private Long palletId,tenantId,accountId,inboundId,orderId,warehouseId,destinationWarehouseId,inboundDetailId; private String palletNo,palletStatus,orderNo,inboundCode,channelCode,channelName,destinationWarehouseCode,destinationWarehouseName,customerName,skuCode,cargoName; private Integer cartonCount,actualSkuQuantity; private BigDecimal unitGrossWeightKg,unitNetWeightKg,unitVolumeCbm; }
|
||||
|
||||
@@ -45,10 +45,33 @@ public interface LoadingListQueryMapper {
|
||||
(SELECT pick_task.task_status FROM fl_loading_pick_task pick_task
|
||||
WHERE pick_task.loading_plan_id = p.id LIMIT 1) AS pda_task_status,
|
||||
COUNT(DISTINCT NULLIF(i.sku_code, '')) AS sku_count,
|
||||
COALESCE(SUM(i.package_count), 0) AS total_package_count,
|
||||
COALESCE(SUM(i.gross_weight_kg), 0) AS total_gross_weight_kg,
|
||||
COALESCE(SUM(i.net_weight_kg), 0) AS total_net_weight_kg,
|
||||
COALESCE(SUM(i.volume_cbm), 0) AS total_volume_cbm,
|
||||
COALESCE(SUM(CASE WHEN i.pallet_id IS NULL THEN i.package_count ELSE 0 END), 0)
|
||||
+ COALESCE((SELECT COUNT(DISTINCT carton.id)
|
||||
FROM fl_dropship_pallet_carton carton
|
||||
WHERE EXISTS (SELECT 1 FROM fl_loading_plan_item pallet_item
|
||||
WHERE pallet_item.loading_plan_id=p.id AND pallet_item.deleted=0
|
||||
AND pallet_item.pallet_id=carton.pallet_id)), 0) AS total_package_count,
|
||||
COALESCE(SUM(CASE WHEN i.pallet_id IS NULL THEN i.gross_weight_kg ELSE 0 END), 0)
|
||||
+ COALESCE((SELECT SUM(inbound.actual_gross_weight_kg/NULLIF(inbound.total_package_count,0))
|
||||
FROM fl_dropship_pallet_carton carton
|
||||
JOIN fl_inbound_order inbound ON inbound.id=carton.inbound_id AND inbound.tenant_id=carton.tenant_id
|
||||
WHERE EXISTS (SELECT 1 FROM fl_loading_plan_item pallet_item
|
||||
WHERE pallet_item.loading_plan_id=p.id AND pallet_item.deleted=0
|
||||
AND pallet_item.pallet_id=carton.pallet_id)), 0) AS total_gross_weight_kg,
|
||||
COALESCE(SUM(CASE WHEN i.pallet_id IS NULL THEN i.net_weight_kg ELSE 0 END), 0)
|
||||
+ COALESCE((SELECT SUM(inbound.actual_net_weight_kg/NULLIF(inbound.total_package_count,0))
|
||||
FROM fl_dropship_pallet_carton carton
|
||||
JOIN fl_inbound_order inbound ON inbound.id=carton.inbound_id AND inbound.tenant_id=carton.tenant_id
|
||||
WHERE EXISTS (SELECT 1 FROM fl_loading_plan_item pallet_item
|
||||
WHERE pallet_item.loading_plan_id=p.id AND pallet_item.deleted=0
|
||||
AND pallet_item.pallet_id=carton.pallet_id)), 0) AS total_net_weight_kg,
|
||||
COALESCE(SUM(CASE WHEN i.pallet_id IS NULL THEN i.volume_cbm ELSE 0 END), 0)
|
||||
+ COALESCE((SELECT SUM(inbound.actual_volume_cbm/NULLIF(inbound.total_package_count,0))
|
||||
FROM fl_dropship_pallet_carton carton
|
||||
JOIN fl_inbound_order inbound ON inbound.id=carton.inbound_id AND inbound.tenant_id=carton.tenant_id
|
||||
WHERE EXISTS (SELECT 1 FROM fl_loading_plan_item pallet_item
|
||||
WHERE pallet_item.loading_plan_id=p.id AND pallet_item.deleted=0
|
||||
AND pallet_item.pallet_id=carton.pallet_id)), 0) AS total_volume_cbm,
|
||||
COALESCE(SUM(i.product_quantity), 0) AS total_quantity
|
||||
""";
|
||||
|
||||
|
||||
@@ -158,11 +158,12 @@ public class LoadingListRepository {
|
||||
java.util.ArrayList<String> blockers = new java.util.ArrayList<>();
|
||||
if (!editing) blockers.add("LOADING_PLAN_NOT_EDITING");
|
||||
if (linkCount == 0) blockers.add("PRELOAD_LINK_MISSING");
|
||||
if (!containerReady) blockers.add("CONTAINER_NO_MISSING");
|
||||
if (!oceanLinked) blockers.add("OCEAN_BOOKING_NOT_LINKED");
|
||||
else if (!released) blockers.add("OCEAN_BOOKING_NOT_RELEASED");
|
||||
if (taskCreated) blockers.add("PDA_TASK_ALREADY_CREATED");
|
||||
boolean allConfirmed = linkCount > 0 && confirmedCount == linkCount;
|
||||
boolean prerequisitesReady = editing && linkCount > 0 && released;
|
||||
boolean prerequisitesReady = editing && linkCount > 0 && containerReady && released;
|
||||
boolean canConfirm = prerequisitesReady && !taskCreated && !allConfirmed;
|
||||
if (allConfirmed) blockers.add("PRELOAD_ALREADY_CONFIRMED");
|
||||
String confirmationStatus = allConfirmed ? "CONFIRMED"
|
||||
|
||||
+2
-2
@@ -231,10 +231,10 @@ public class DropshipPalletizationService {
|
||||
values.stream().mapToInt(v->v.line().getActualQuantity()==null?0:v.line().getActualQuantity()).sum(),
|
||||
values.stream().map(v->v.carton().getBoxCode()).toList());}).toList();
|
||||
int discrepancies=(int)cartons.stream().filter(c->"ACCEPTED_VARIANCE".equals(c.getDiscrepancyStatus())).count();
|
||||
PalletMetrics metrics=mapper.metrics(row.getId());
|
||||
PalletMetrics metrics=mapper.physicalMetricsByPalletIds(List.of(row.getId())).stream().findFirst().orElse(null);
|
||||
int skuCount=(int)items.stream().map(SkuItem::skuCode).distinct().count();
|
||||
return new Pallet(row.getId(),row.getPalletNo(),row.getPalletStatus(),cartons.size(),skuCount,discrepancies,
|
||||
metrics==null?BigDecimal.ZERO:metrics.weightKg(),metrics==null?BigDecimal.ZERO:metrics.volumeCbm(),row.getVersion(),items,
|
||||
metrics==null?BigDecimal.ZERO:metrics.grossWeightKg(),metrics==null?BigDecimal.ZERO:metrics.volumeCbm(),row.getVersion(),items,
|
||||
cartons.stream().map(c->cartonView(c,c.getInboundCode(),false,null)).toList(),row.getCompletedAt());
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ public class LoadingPickService {
|
||||
public void beginIfReady(long containerBookingId, long operatorId, String operatorName) {
|
||||
var booking = smartLoadingRepository.booking(containerBookingId);
|
||||
if (booking == null) return;
|
||||
if (!StringUtils.hasText(booking.getContainerNo())) return;
|
||||
var plan = smartLoadingRepository.planByBooking(containerBookingId);
|
||||
if (plan == null || !"EDITING".equals(plan.getPlanStatus())) return;
|
||||
inboundHoldGuard.requirePlanNotHeld(plan.getId());
|
||||
@@ -137,6 +138,10 @@ public class LoadingPickService {
|
||||
if (!Set.of("PENDING", "CONFIRMING").contains(link.preloadStatus())) {
|
||||
throw conflict("预装清单已确认或当前状态不允许确认");
|
||||
}
|
||||
var booking = smartLoadingRepository.booking(link.containerBookingId());
|
||||
if (booking == null || !StringUtils.hasText(booking.getContainerNo())) {
|
||||
throw conflict("确认预装前必须录入真实集装箱号");
|
||||
}
|
||||
var allocation = oceanBookingRepository.allocationByContainer(link.containerBookingId());
|
||||
if (allocation == null) throw conflict("确认预装前必须关联真实订舱柜");
|
||||
var oceanBooking = oceanBookingRepository.find(allocation.getOceanBookingId());
|
||||
|
||||
@@ -476,19 +476,28 @@ public class SmartLoadingService {
|
||||
var first = lines.get(0);
|
||||
inboundHoldGuard.requireInboundNotHeld(first.getAccountId(), first.getInboundId());
|
||||
if (!repository.activeItemsByPallet(request.palletId()).isEmpty()) throw conflict("托盘已被有效柜次占用");
|
||||
com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PalletMetrics physical =
|
||||
dropshipPallets.physicalMetricsByPalletIds(List.of(request.palletId())).stream().findFirst()
|
||||
.orElseThrow(() -> conflict("托盘缺少物理箱明细,不能加入预装清单"));
|
||||
int sequence = 0;
|
||||
for (var line : lines) {
|
||||
boolean primaryPalletLine = sequence == 0;
|
||||
BigDecimal lineBoxes = BigDecimal.valueOf(line.getCartonCount());
|
||||
LoadingPlanEntity current = repository.plan(planId);
|
||||
Candidate candidate = new Candidate(line.getAccountId(), line.getInboundId(), line.getInboundDetailId(),
|
||||
line.getOrderId(), line.getOrderNo(), line.getInboundCode(), line.getWarehouseId(), line.getChannelCode(),
|
||||
line.getChannelName(), line.getDestinationWarehouseId(), line.getDestinationWarehouseCode(),
|
||||
line.getDestinationWarehouseName(), line.getCustomerName(), line.getCargoName(), line.getCartonCount(),
|
||||
line.getUnitGrossWeightKg(), line.getUnitNetWeightKg(), line.getUnitVolumeCbm(), null, null, null, null,
|
||||
primaryPalletLine ? unit(physical.grossWeightKg()).divide(lineBoxes, 6, RoundingMode.HALF_UP) : BigDecimal.ZERO,
|
||||
primaryPalletLine ? unit(physical.netWeightKg()).divide(lineBoxes, 6, RoundingMode.HALF_UP) : BigDecimal.ZERO,
|
||||
primaryPalletLine ? unit(physical.volumeCbm()).divide(lineBoxes, 6, RoundingMode.HALF_UP) : BigDecimal.ZERO,
|
||||
null, null, null, null,
|
||||
false, null, "WAIT_SPLIT", null);
|
||||
String childOperation = "PAL-" + sha256(operation + '|' + line.getInboundDetailId()).substring(0, 48);
|
||||
assign(planId, new AssignRequest(line.getInboundId(), line.getInboundDetailId(), line.getCartonCount(),
|
||||
current.getVersion(), childOperation), operatorId, operatorName, true, request.palletId(),
|
||||
line.getPalletNo(), line.getActualSkuQuantity(), sequence++ == 0, candidate, false);
|
||||
line.getPalletNo(), line.getActualSkuQuantity(), primaryPalletLine, candidate, false);
|
||||
sequence++;
|
||||
}
|
||||
LoadingPlanEntity assigned = repository.plan(planId);
|
||||
history(planId, null, "ADD_PALLET", original.getPlanStatus(), assigned.getPlanStatus(), operation,
|
||||
@@ -1689,19 +1698,26 @@ public class SmartLoadingService {
|
||||
Map<Long,List<LoadingPlanItemEntity>> pallets = items.stream().filter(i -> i.getPalletId() != null)
|
||||
.collect(java.util.stream.Collectors.groupingBy(LoadingPlanItemEntity::getPalletId,
|
||||
LinkedHashMap::new, java.util.stream.Collectors.toList()));
|
||||
Map<Long,com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PalletMetrics> physicalByPallet =
|
||||
pallets.isEmpty() ? Map.of() : dropshipPallets.physicalMetricsByPalletIds(pallets.keySet()).stream()
|
||||
.collect(java.util.stream.Collectors.toMap(
|
||||
com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PalletMetrics::palletId,
|
||||
java.util.function.Function.identity()));
|
||||
items.stream().filter(i -> i.getPalletId() == null).forEach(result::add);
|
||||
for (List<LoadingPlanItemEntity> lines : pallets.values()) {
|
||||
LoadingPlanItemEntity unit = lines.get(0);
|
||||
unit.setPackageCount(lines.stream().map(LoadingPlanItemEntity::getPackageCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
|
||||
var physical = physicalByPallet.get(unit.getPalletId());
|
||||
if (physical == null) throw conflict("托盘缺少物理箱明细,不能汇总预装清单");
|
||||
unit.setPackageCount(physical.cartonCount());
|
||||
unit.setProductQuantity(lines.stream().map(LoadingPlanItemEntity::getProductQuantity)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
|
||||
unit.setPalletCount(1);
|
||||
unit.setGrossWeightKg(sumDecimal(lines, LoadingPlanItemEntity::getGrossWeightKg));
|
||||
unit.setNetWeightKg(sumDecimal(lines, LoadingPlanItemEntity::getNetWeightKg));
|
||||
unit.setVolumeCbm(sumDecimal(lines, LoadingPlanItemEntity::getVolumeCbm));
|
||||
unit.setPickedPackageCount(lines.stream().map(LoadingPlanItemEntity::getPickedPackageCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum());
|
||||
unit.setGrossWeightKg(physical.grossWeightKg());
|
||||
unit.setNetWeightKg(physical.netWeightKg());
|
||||
unit.setVolumeCbm(physical.volumeCbm());
|
||||
unit.setPickedPackageCount(Math.min(physical.cartonCount(), lines.stream()
|
||||
.map(LoadingPlanItemEntity::getPickedPackageCount).filter(Objects::nonNull)
|
||||
.mapToInt(Integer::intValue).sum()));
|
||||
unit.setTotalPackageCount(unit.getPackageCount());
|
||||
unit.setRemainingPackageCount(0);
|
||||
unit.setCanAdjust(false);
|
||||
@@ -1713,10 +1729,6 @@ public class SmartLoadingService {
|
||||
.thenComparing(LoadingPlanItemEntity::getId, Comparator.nullsLast(Long::compareTo)))
|
||||
.toList();
|
||||
}
|
||||
private static BigDecimal sumDecimal(List<LoadingPlanItemEntity> lines,
|
||||
java.util.function.Function<LoadingPlanItemEntity,BigDecimal> getter) {
|
||||
return lines.stream().map(getter).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
private int adjustmentTotal(LoadingPlanItemEntity item) {
|
||||
int current = item.getPackageCount() == null ? 0 : item.getPackageCount();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user