yuan
6 天以前 15f7555b9f9d3e3ae2cdaa82d89bc7ea5160f62c
src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
@@ -9,6 +9,7 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
import com.ruoyi.production.bean.vo.AutoPickResultVo;
import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
import com.ruoyi.production.mapper.ProductionOrderMapper;
@@ -16,6 +17,7 @@
import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
import com.ruoyi.production.pojo.ProductionOrder;
import com.ruoyi.production.pojo.ProductionOrderPick;
import com.ruoyi.production.service.ProductionOrderService;
import com.ruoyi.production.pojo.ProductionOrderPickRecord;
import com.ruoyi.production.service.ProductionOrderPickService;
import com.ruoyi.stock.dto.StockInventoryDto;
@@ -51,6 +53,7 @@
    private static final String FEED_RETURN_IN_RECORD_TYPE = StockInQualifiedRecordTypeEnum.FEED_RETURN_IN.getCode();
    private final ProductionOrderMapper productionOrderMapper;
    private final ProductionOrderService productionOrderService;
    private final ProductionOperationTaskMapper productionOperationTaskMapper;
    private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
    private final StockInventoryMapper stockInventoryMapper;
@@ -192,6 +195,147 @@
        fillBatchNoList(detailList);
        fillSelectableBatchNoList(detailList);
        return detailList;
    }
    @Override
    public AutoPickResultVo autoPick(List<Long> orderIds) {
        // 自动领料总流程:
        // 1) 遍历目标订单,读取BOM需求清单;
        // 2) 按 订单ID+规格ID+工序ID 去重判断是否已领料;
        // 3) 对未领料且有需求的物料,逐笔执行 savePick 领料;
        // 4) 汇总成功/跳过/失败明细并返回。
        AutoPickResultVo result = new AutoPickResultVo();
        if (orderIds == null || orderIds.isEmpty()) {
            return result;
        }
        result.setOrderTotal(orderIds.size());
        for (Long orderId : orderIds) {
            ProductionOrder order = productionOrderMapper.selectById(orderId);
            if (order == null) {
                result.setOrderFail(result.getOrderFail() + 1);
                AutoPickResultVo.ItemDetail failItem = new AutoPickResultVo.ItemDetail();
                failItem.setProductionOrderId(orderId);
                failItem.setReason("生产订单不存在");
                result.getFailList().add(failItem);
                continue;
            }
            // 获取BOM需求清单
            List<ProductionOrderPickVo> demandList = productionOrderService.pick(orderId);
            if (demandList == null || demandList.isEmpty()) {
                result.setOrderFail(result.getOrderFail() + 1);
                AutoPickResultVo.ItemDetail failItem = new AutoPickResultVo.ItemDetail();
                failItem.setProductionOrderId(orderId);
                failItem.setProductionOrderNo(order.getNpsNo());
                failItem.setReason("无BOM物料需求");
                result.getFailList().add(failItem);
                continue;
            }
            // 查询已领料记录(按 工序ID#规格ID 去重)
            Set<String> pickedKeys = list(Wrappers.<ProductionOrderPick>lambdaQuery()
                    .eq(ProductionOrderPick::getProductionOrderId, orderId)
                    .eq(ProductionOrderPick::getReturned, false)).stream()
                    .map(p -> (p.getTechnologyOperationId() == null ? "null" : p.getTechnologyOperationId())
                            + "#" + p.getProductModelId())
                    .collect(Collectors.toSet());
            boolean orderHasSuccess = false;
            boolean orderHasFail = false;
            for (ProductionOrderPickVo demand : demandList) {
                result.setMaterialTotal(result.getMaterialTotal() + 1);
                String key = (demand.getTechnologyOperationId() == null ? "null" : demand.getTechnologyOperationId())
                        + "#" + demand.getProductModelId();
                // 已领料的跳过
                if (pickedKeys.contains(key)) {
                    result.setMaterialSkip(result.getMaterialSkip() + 1);
                    AutoPickResultVo.ItemDetail skipItem = new AutoPickResultVo.ItemDetail();
                    skipItem.setProductionOrderId(orderId);
                    skipItem.setProductionOrderNo(order.getNpsNo());
                    skipItem.setProductModelId(demand.getProductModelId());
                    skipItem.setTechnologyOperationId(demand.getTechnologyOperationId());
                    skipItem.setOperationName(demand.getOperationName());
                    skipItem.setDemandedQuantity(demand.getDemandedQuantity());
                    skipItem.setReason("已领料");
                    result.getSkipList().add(skipItem);
                    continue;
                }
                BigDecimal demandQty = demand.getDemandedQuantity();
                if (demandQty == null || demandQty.compareTo(BigDecimal.ZERO) <= 0) {
                    result.setMaterialSkip(result.getMaterialSkip() + 1);
                    AutoPickResultVo.ItemDetail skipItem = new AutoPickResultVo.ItemDetail();
                    skipItem.setProductionOrderId(orderId);
                    skipItem.setProductionOrderNo(order.getNpsNo());
                    skipItem.setProductModelId(demand.getProductModelId());
                    skipItem.setTechnologyOperationId(demand.getTechnologyOperationId());
                    skipItem.setOperationName(demand.getOperationName());
                    skipItem.setDemandedQuantity(demandQty);
                    skipItem.setReason("需求数量为0或空");
                    result.getSkipList().add(skipItem);
                    continue;
                }
                // 执行领料
                try {
                    ProductionOrderPickDto dto = new ProductionOrderPickDto();
                    dto.setProductionOrderId(orderId);
                    dto.setProductModelId(demand.getProductModelId());
                    dto.setPickQuantity(demandQty);
                    dto.setPickType((byte) 1); // 1=正常领料
                    dto.setBatchNoList(demand.getBatchNoList());
                    dto.setTechnologyOperationId(demand.getTechnologyOperationId());
                    dto.setOperationName(demand.getOperationName());
                    dto.setDemandedQuantity(demand.getDemandedQuantity());
                    dto.setBom(demand.getBom());
                    dto.setRemark("自动领料");
                    savePick(dto);
                    result.setMaterialSuccess(result.getMaterialSuccess() + 1);
                    orderHasSuccess = true;
                    AutoPickResultVo.ItemDetail successItem = new AutoPickResultVo.ItemDetail();
                    successItem.setProductionOrderId(orderId);
                    successItem.setProductionOrderNo(order.getNpsNo());
                    successItem.setProductModelId(demand.getProductModelId());
                    successItem.setTechnologyOperationId(demand.getTechnologyOperationId());
                    successItem.setOperationName(demand.getOperationName());
                    successItem.setDemandedQuantity(demandQty);
                    successItem.setPickQuantity(demandQty);
                    result.getSuccessList().add(successItem);
                } catch (Exception e) {
                    result.setMaterialFail(result.getMaterialFail() + 1);
                    orderHasFail = true;
                    AutoPickResultVo.ItemDetail failItem = new AutoPickResultVo.ItemDetail();
                    failItem.setProductionOrderId(orderId);
                    failItem.setProductionOrderNo(order.getNpsNo());
                    failItem.setProductModelId(demand.getProductModelId());
                    failItem.setTechnologyOperationId(demand.getTechnologyOperationId());
                    failItem.setOperationName(demand.getOperationName());
                    failItem.setDemandedQuantity(demandQty);
                    failItem.setReason(e.getMessage());
                    result.getFailList().add(failItem);
                }
            }
            if (orderHasSuccess) {
                result.setOrderSuccess(result.getOrderSuccess() + 1);
            }
            if (orderHasFail) {
                result.setOrderFail(result.getOrderFail() + 1);
            }
            // 如果既没有成功也没有失败(全跳过),订单不算失败也不算成功
            if (!orderHasSuccess && !orderHasFail) {
                result.setOrderSuccess(result.getOrderSuccess() + 1);
            }
        }
        return result;
    }
    private void processDeletePickIds(ProductionOrderPickDto rootDto,
@@ -430,7 +574,7 @@
        BigDecimal totalReturnQty = oldReturnQty.add(currentReturnQty);
        if (currentReturnQty.compareTo(BigDecimal.ZERO) > 0) {
            String returnBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo());
            addInventory(oldPick.getId(), oldPick.getProductModelId(), returnBatchNo, currentReturnQty, FEED_RETURN_IN_RECORD_TYPE);
            addInventoryRecordOnly(oldPick.getId(), oldPick.getProductModelId(), returnBatchNo, currentReturnQty, FEED_RETURN_IN_RECORD_TYPE);
        }
        BigDecimal actualQty = defaultDecimal(oldPick.getQuantity())
@@ -737,6 +881,31 @@
        }
    }
    private void addInventoryRecordOnly(Long recordId,
                                        Long productModelId,
                                        String batchNo,
                                        BigDecimal quantity,
                                        String stockInRecordType) {
        // 仅记录入库申请,不做审核通过。
        BigDecimal addQuantity = defaultDecimal(quantity);
        if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        try {
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setProductModelId(productModelId);
            stockInventoryDto.setBatchNo(batchNo);
            stockInventoryDto.setQualitity(addQuantity);
            stockInventoryDto.setRecordType(stockInRecordType);
            stockInventoryDto.setRecordId(recordId == null ? 0L : recordId);
            stockInventoryService.addStockInRecordOnly(stockInventoryDto);
        } catch (ServiceException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new ServiceException("退料入库记录保存失败:" + ex.getMessage());
        }
    }
    private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) {
        // 解析新增场景的领料明细集合。
        if (dto == null) {