| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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, |
| | | Map<Long, ProductionOrderPick> existingPickMap, |
| | | Long productionOrderId) { |