diff --git a/gear-mat/src/main/java/com/gear/mat/controller/MatMaterialController.java b/gear-mat/src/main/java/com/gear/mat/controller/MatMaterialController.java index 2ee2b16..cf72e41 100644 --- a/gear-mat/src/main/java/com/gear/mat/controller/MatMaterialController.java +++ b/gear-mat/src/main/java/com/gear/mat/controller/MatMaterialController.java @@ -21,7 +21,6 @@ import com.gear.common.core.validate.QueryGroup; import com.gear.common.enums.BusinessType; import com.gear.common.utils.poi.ExcelUtil; import com.gear.mat.domain.vo.MatMaterialVo; -import com.gear.mat.domain.vo.MatMaterialWithInventoryVo; import com.gear.mat.domain.bo.MatMaterialBo; import com.gear.mat.service.IMatMaterialService; import com.gear.common.core.page.TableDataInfo; @@ -44,7 +43,7 @@ public class MatMaterialController extends BaseController { * 查询配料配件基础信息列表 */ @GetMapping("/list") - public TableDataInfo list(MatMaterialBo bo, PageQuery pageQuery) { + public TableDataInfo list(MatMaterialBo bo, PageQuery pageQuery) { return iMatMaterialService.queryPageListWithInventory(bo, pageQuery); } @@ -55,8 +54,8 @@ public class MatMaterialController extends BaseController { @PostMapping("/export") public void export(MatMaterialBo bo, HttpServletResponse response) { // 使用增强的服务方法获取带库存信息的物料列表 - List list = iMatMaterialService.queryListWithInventory(bo); - ExcelUtil.exportExcel(list, "配料配件基础信息", MatMaterialWithInventoryVo.class, response); + List list = iMatMaterialService.queryListWithInventory(bo); + ExcelUtil.exportExcel(list, "配料配件基础信息", MatMaterialVo.class, response); } /** diff --git a/gear-mat/src/main/java/com/gear/mat/domain/vo/MatMaterialVo.java b/gear-mat/src/main/java/com/gear/mat/domain/vo/MatMaterialVo.java index e444269..75dfd5f 100644 --- a/gear-mat/src/main/java/com/gear/mat/domain/vo/MatMaterialVo.java +++ b/gear-mat/src/main/java/com/gear/mat/domain/vo/MatMaterialVo.java @@ -71,5 +71,19 @@ public class MatMaterialVo { @ExcelProperty(value = "备注") private String remark; + /** + * 在途数量(未完成入库的采购数量) + */ + private transient BigDecimal inTransitNum; + + /** + * 计划采购总数量 + */ + private transient BigDecimal planNum; + + /** + * 已入库数量 + */ + private transient BigDecimal receivedNum; } diff --git a/gear-mat/src/main/java/com/gear/mat/service/IMatMaterialService.java b/gear-mat/src/main/java/com/gear/mat/service/IMatMaterialService.java index eba0853..9f6a12f 100644 --- a/gear-mat/src/main/java/com/gear/mat/service/IMatMaterialService.java +++ b/gear-mat/src/main/java/com/gear/mat/service/IMatMaterialService.java @@ -2,7 +2,6 @@ package com.gear.mat.service; import com.gear.mat.domain.MatMaterial; import com.gear.mat.domain.vo.MatMaterialVo; -import com.gear.mat.domain.vo.MatMaterialWithInventoryVo; import com.gear.mat.domain.bo.MatMaterialBo; import com.gear.common.core.page.TableDataInfo; import com.gear.common.core.domain.PageQuery; @@ -36,7 +35,7 @@ public interface IMatMaterialService { /** * 查询配料配件基础信息列表(包含库存信息) */ - List queryListWithInventory(MatMaterialBo bo); + List queryListWithInventory(MatMaterialBo bo); /** * 新增配料配件基础信息 @@ -56,5 +55,5 @@ public interface IMatMaterialService { /** * 查询配料配件基础信息列表(包含库存信息) */ - TableDataInfo queryPageListWithInventory(MatMaterialBo bo, PageQuery pageQuery); + TableDataInfo queryPageListWithInventory(MatMaterialBo bo, PageQuery pageQuery); } diff --git a/gear-mat/src/main/java/com/gear/mat/service/impl/MatMaterialServiceImpl.java b/gear-mat/src/main/java/com/gear/mat/service/impl/MatMaterialServiceImpl.java index 34c6dad..0db0da5 100644 --- a/gear-mat/src/main/java/com/gear/mat/service/impl/MatMaterialServiceImpl.java +++ b/gear-mat/src/main/java/com/gear/mat/service/impl/MatMaterialServiceImpl.java @@ -124,139 +124,156 @@ public class MatMaterialServiceImpl implements IMatMaterialService { } @Override - public TableDataInfo queryPageListWithInventory(MatMaterialBo bo, PageQuery pageQuery) { + public TableDataInfo queryPageListWithInventory(MatMaterialBo bo, PageQuery pageQuery) { // 先查询物料基本信息 TableDataInfo materialTable = queryPageList(bo, pageQuery); + List materialList = materialTable.getRows(); - // 将MatMaterialVo转换为MatMaterialWithInventoryVo - List inventoryList = materialTable.getRows().stream() - .map(material -> { - MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material); + if (materialList.isEmpty()) { + return materialTable; + } - // 查询该物料的库存信息 - List materialInventoryList = queryMaterialInventory(material.getMaterialId()); - - if (!materialInventoryList.isEmpty()) { - MaterialInventoryVo inventoryInfo = materialInventoryList.get(0); - inventoryVo.setInTransitNum(inventoryInfo.getInTransitNum()); - inventoryVo.setPlanNum(inventoryInfo.getPlanNum()); - inventoryVo.setReceivedNum(inventoryInfo.getReceivedNum()); - } - - return inventoryVo; - }) + // 批量查询所有物料的库存信息 + List materialIds = materialList.stream() + .map(MatMaterialVo::getMaterialId) + .distinct() .collect(Collectors.toList()); + Map inventoryMap = batchQueryMaterialInventory(materialIds); - // 构建返回结果 - Page resultPage = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize(), materialTable.getTotal()); - resultPage.setRecords(inventoryList); + // 填充库存信息到MatMaterialVo + materialList.forEach(material -> { + MaterialInventoryVo inventory = inventoryMap.get(material.getMaterialId()); + if (inventory != null) { + material.setInTransitNum(inventory.getInTransitNum()); + material.setPlanNum(inventory.getPlanNum()); + material.setReceivedNum(inventory.getReceivedNum()); + } + }); - return TableDataInfo.build(resultPage); + return materialTable; } @Override - public List queryListWithInventory(MatMaterialBo bo) { + public List queryListWithInventory(MatMaterialBo bo) { // 先查询物料基本信息 List materialList = queryList(bo); - // 将MatMaterialVo转换为MatMaterialWithInventoryVo - return materialList.stream() - .map(material -> { - MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material); + if (materialList.isEmpty()) { + return materialList; + } - // 查询该物料的库存信息 - List materialInventoryList = queryMaterialInventory(material.getMaterialId()); - - if (!materialInventoryList.isEmpty()) { - MaterialInventoryVo inventoryInfo = materialInventoryList.get(0); - inventoryVo.setInTransitNum(inventoryInfo.getInTransitNum()); - inventoryVo.setPlanNum(inventoryInfo.getPlanNum()); - inventoryVo.setReceivedNum(inventoryInfo.getReceivedNum()); - } - - return inventoryVo; - }) + // 批量查询所有物料的库存信息 + List materialIds = materialList.stream() + .map(MatMaterialVo::getMaterialId) + .distinct() .collect(Collectors.toList()); + Map inventoryMap = batchQueryMaterialInventory(materialIds); + + // 填充库存信息到MatMaterialVo + materialList.forEach(material -> { + MaterialInventoryVo inventory = inventoryMap.get(material.getMaterialId()); + if (inventory != null) { + material.setInTransitNum(inventory.getInTransitNum()); + material.setPlanNum(inventory.getPlanNum()); + material.setReceivedNum(inventory.getReceivedNum()); + } + }); + + return materialList; } - public List queryMaterialInventory(Long materialId) { - // 创建结果列表 - List result = new ArrayList<>(); - - // 物料ID,先做非空校验 - if (materialId == null) { - return result; + /** + * 批量查询物料库存信息 + * 避免N+1查询问题 + */ + private Map batchQueryMaterialInventory(List materialIds) { + if (materialIds == null || materialIds.isEmpty()) { + return Collections.emptyMap(); } - // 构建采购单查询条件(materialId + 过滤删除标记) + Map resultMap = new HashMap<>(); + + // 批量查询所有采购单(按materialId过滤) QueryWrapper purchaseQw = new QueryWrapper<>(); - purchaseQw.eq("material_id", materialId); + purchaseQw.in("material_id", materialIds); purchaseQw.eq("del_flag", 0); - // 直接查采购单PO List purchaseListPo = matPurchaseMapper.selectList(purchaseQw); - // 将PO转换为VO - List purchaseList = purchaseListPo.stream() - .map(purchase -> { - MatPurchaseVo vo = new MatPurchaseVo(); - BeanUtils.copyProperties(purchase, vo); - return vo; - }) + // 按materialId分组 + Map> purchaseByMaterial = purchaseListPo.stream() + .collect(Collectors.groupingBy(MatPurchase::getMaterialId)); + + // 查询物料基本信息 + Map materialInfoMap = baseMapper.selectVoBatchIds(materialIds).stream() + .collect(Collectors.toMap(MatMaterialVo::getMaterialId, m -> m)); + + // 按采购单ID分组,用于批量查询入库详情 + List purchaseIds = purchaseListPo.stream() + .map(MatPurchase::getPurchaseId) + .distinct() .collect(Collectors.toList()); - // 1. 查询当前物料的详细信息 - MatMaterialVo material = baseMapper.selectVoById(materialId); - // 2. 初始化物料库存VO - MaterialInventoryVo inventory = new MaterialInventoryVo(); - inventory.setMaterialId(materialId); - if (material != null) { - inventory.setMaterialName(material.getMaterialName()); - inventory.setSpec(material.getSpec()); - inventory.setModel(material.getModel()); - inventory.setUnit(material.getUnit()); - inventory.setCurrentStock(material.getCurrentStock()); + Map> detailsByPurchaseId = Collections.emptyMap(); + if (!purchaseIds.isEmpty()) { + MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo(); + Map params = new HashMap<>(); + params.put("purchaseIds", purchaseIds); + detailBo.setParams(params); + List allDetails = matPurchaseInDetailService.queryList(detailBo); + detailsByPurchaseId = allDetails.stream() + .collect(Collectors.groupingBy(MatPurchaseInDetailVo::getPurchaseId)); } - // 3. 计算该物料的计划总数、已入库总数、在途总数 - BigDecimal planTotal = BigDecimal.ZERO; - BigDecimal receivedTotal = BigDecimal.ZERO; - BigDecimal inTransitTotal = BigDecimal.ZERO; + // 计算每个物料的库存信息 + for (Long materialId : materialIds) { + MaterialInventoryVo inventory = new MaterialInventoryVo(); + inventory.setMaterialId(materialId); - for (MatPurchaseVo purchase : purchaseList) { - // 累加计划总数 - BigDecimal planNum = Optional.ofNullable(purchase.getPlanNum()).orElse(BigDecimal.ZERO); - planTotal = planTotal.add(planNum); + // 填充物料基本信息 + MatMaterialVo material = materialInfoMap.get(materialId); + if (material != null) { + inventory.setMaterialName(material.getMaterialName()); + inventory.setSpec(material.getSpec()); + inventory.setModel(material.getModel()); + inventory.setUnit(material.getUnit()); + inventory.setCurrentStock(material.getCurrentStock()); + } - // 查询该采购单下的入库详情 - MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo(); - detailBo.setPurchaseId(purchase.getPurchaseId()); - List details = matPurchaseInDetailService.queryList(detailBo); + // 计算采购相关数据 + List purchases = purchaseByMaterial.getOrDefault(materialId, Collections.emptyList()); + BigDecimal planTotal = BigDecimal.ZERO; + BigDecimal receivedTotal = BigDecimal.ZERO; + BigDecimal inTransitTotal = BigDecimal.ZERO; - // 计算该采购单的已入库数量 - BigDecimal receivedInPurchase = details.stream() - .map(MatPurchaseInDetailVo::getInNum) - .filter(Objects::nonNull) - .reduce(BigDecimal.ZERO, BigDecimal::add); - receivedTotal = receivedTotal.add(receivedInPurchase); + for (MatPurchase purchase : purchases) { + BigDecimal planNum = Optional.ofNullable(purchase.getPlanNum()).orElse(BigDecimal.ZERO); + planTotal = planTotal.add(planNum); - // 计算该采购单的在途数量 - if (purchase.getStatus() != null && (purchase.getStatus() == 1 || purchase.getStatus() == 4)) { - BigDecimal pending = planNum.subtract(receivedInPurchase); - if (pending.compareTo(BigDecimal.ZERO) > 0) { - inTransitTotal = inTransitTotal.add(pending); + // 计算该采购单的已入库数量 + List details = detailsByPurchaseId.getOrDefault(purchase.getPurchaseId(), Collections.emptyList()); + BigDecimal receivedInPurchase = details.stream() + .map(MatPurchaseInDetailVo::getInNum) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + receivedTotal = receivedTotal.add(receivedInPurchase); + + // 计算该采购单的在途数量 + if (purchase.getStatus() != null && (purchase.getStatus() == 1 || purchase.getStatus() == 4)) { + BigDecimal pending = planNum.subtract(receivedInPurchase); + if (pending.compareTo(BigDecimal.ZERO) > 0) { + inTransitTotal = inTransitTotal.add(pending); + } } } + + inventory.setPlanNum(planTotal); + inventory.setReceivedNum(receivedTotal); + inventory.setInTransitNum(inTransitTotal); + + resultMap.put(materialId, inventory); } - // 4. 设置库存VO的数值字段 - inventory.setPlanNum(planTotal); - inventory.setReceivedNum(receivedTotal); - inventory.setInTransitNum(inTransitTotal); - - // 5. 添加到结果列表 - result.add(inventory); - - return result; + return resultMap; } }