| | |
| | | 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; |
| | |
| | | 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) { |