gongchunyi
5 天以前 d5e8cbc39a363ec8a6cdc80360e2112fb3b2a9c0
src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
@@ -31,6 +31,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -189,11 +190,110 @@
            return Collections.emptyList();
        }
        List<ProductionOrderPickVo> detailList = baseMapper.listPickedDetailByOrderId(productionOrderId);
        fillStockQuantity(detailList);
        fillBatchNoList(detailList);
        fillSelectableBatchNoList(detailList);
        return detailList;
    }
    @Override
    public List<ProductionOrderPickVo> listPickedRecordDetail(Long productionOrderId) {
        // 领料详情:按 production_order_pick_record 一条一行,展示每次领取量,而不是主单汇总。
        if (productionOrderId == null) {
            return Collections.emptyList();
        }
        List<ProductionOrderPickVo> detailList =
                productionOrderPickRecordMapper.listPickedDetailByOrderId(productionOrderId);
        allocateRecordReturnQuantity(detailList);
        fillStockQuantity(detailList);
        return detailList;
    }
    private void allocateRecordReturnQuantity(List<ProductionOrderPickVo> detailList) {
        // 退料数量按领料主单汇总存储,详情按流水拆分展示时按领取量分摊到每条流水,
        // 保证“实际数量 = 领取数量 - 分摊退料”且同一主单各流水合计与主单一致。
        if (detailList == null || detailList.isEmpty()) {
            return;
        }
        Map<Long, List<ProductionOrderPickVo>> pickGroupMap = new LinkedHashMap<>();
        for (ProductionOrderPickVo detail : detailList) {
            if (detail == null || detail.getId() == null) {
                continue;
            }
            pickGroupMap.computeIfAbsent(detail.getId(), key -> new ArrayList<>()).add(detail);
        }
        for (List<ProductionOrderPickVo> pickGroup : pickGroupMap.values()) {
            BigDecimal totalReturnQty = BigDecimal.ZERO;
            BigDecimal totalRecordQuantity = BigDecimal.ZERO;
            for (ProductionOrderPickVo detail : pickGroup) {
                totalReturnQty = defaultDecimal(detail.getReturnQty());
                totalRecordQuantity = totalRecordQuantity.add(recordQuantity(detail));
            }
            if (totalRecordQuantity.compareTo(BigDecimal.ZERO) <= 0) {
                for (ProductionOrderPickVo detail : pickGroup) {
                    detail.setReturnQty(BigDecimal.ZERO);
                    detail.setActualQty(BigDecimal.ZERO);
                }
                continue;
            }
            BigDecimal effectiveReturnQty = totalReturnQty.min(totalRecordQuantity);
            BigDecimal allocatedReturnQty = BigDecimal.ZERO;
            for (int i = 0; i < pickGroup.size(); i++) {
                ProductionOrderPickVo detail = pickGroup.get(i);
                BigDecimal rowQuantity = recordQuantity(detail);
                BigDecimal returnQty;
                if (i == pickGroup.size() - 1) {
                    returnQty = effectiveReturnQty.subtract(allocatedReturnQty);
                } else {
                    returnQty = effectiveReturnQty.multiply(rowQuantity)
                            .divide(totalRecordQuantity, 4, RoundingMode.HALF_UP)
                            .setScale(2, RoundingMode.HALF_UP);
                }
                if (returnQty.compareTo(rowQuantity) > 0) {
                    returnQty = rowQuantity;
                }
                if (returnQty.compareTo(BigDecimal.ZERO) < 0) {
                    returnQty = BigDecimal.ZERO;
                }
                detail.setReturnQty(returnQty);
                detail.setActualQty(rowQuantity.subtract(returnQty));
                allocatedReturnQty = allocatedReturnQty.add(returnQty);
            }
        }
    }
    private BigDecimal recordQuantity(ProductionOrderPickVo detail) {
        return defaultDecimal(detail.getPickQuantity()).add(defaultDecimal(detail.getFeedingQty()));
    }
    private void fillStockQuantity(List<ProductionOrderPickVo> detailList) {
        // 批量查询明细中涉及规格的当前库存数量,供前端领料台账展示。
        if (detailList == null || detailList.isEmpty()) {
            return;
        }
        Set<Long> productModelIdSet = detailList.stream()
                .map(ProductionOrderPickVo::getProductModelId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        if (productModelIdSet.isEmpty()) {
            return;
        }
        List<StockInventory> stockList = stockInventoryMapper.selectList(
                Wrappers.<StockInventory>lambdaQuery()
                        .in(StockInventory::getProductModelId, productModelIdSet));
        Map<Long, BigDecimal> stockQuantityMap = new HashMap<>();
        for (StockInventory stockItem : stockList) {
            if (stockItem == null || stockItem.getProductModelId() == null) {
                continue;
            }
            stockQuantityMap.merge(stockItem.getProductModelId(),
                    defaultDecimal(stockItem.getQualitity()), BigDecimal::add);
        }
        for (ProductionOrderPickVo detail : detailList) {
            detail.setStockQuantity(stockQuantityMap.getOrDefault(detail.getProductModelId(), BigDecimal.ZERO));
        }
    }
    private void processDeletePickIds(ProductionOrderPickDto rootDto,
                                      Map<Long, ProductionOrderPick> existingPickMap,
                                      Long productionOrderId) {