refactor(purchase): 解决循环依赖问题
- 从 IMatPurchaseService 接口中移除 queryMaterialInventory 和 queryPurchasePlanMaterialInventory 方法 - 将库存查询实现从 MatPurchaseServiceImpl 迁移到 MatMaterialServiceImpl - 修改 MatMaterialServiceImpl 中的依赖注入,使用 MatPurchaseMapper 替代 IMatPurchaseService - 更新控制器 MatPurchaseController,移除库存相关 API 端点 - 优化 MatPurchaseServiceImpl 中的查询逻辑,改用批量查询减少 N+1 问题 - 在 MatMaterialServiceImpl 中实现完整的物料库存查询功能,包括当前库存、在途数量等信息
This commit is contained in:
@@ -102,34 +102,4 @@ public class MatPurchaseController extends BaseController {
|
|||||||
return toAjax(iMatPurchaseService.deleteWithValidByIds(Arrays.asList(purchaseIds), true));
|
return toAjax(iMatPurchaseService.deleteWithValidByIds(Arrays.asList(purchaseIds), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取物料库存信息(当前库存和在途数量)
|
|
||||||
*
|
|
||||||
* @param materialId 物料ID
|
|
||||||
*/
|
|
||||||
@GetMapping("/inventory/{materialId}")
|
|
||||||
public R<List<MaterialInventoryVo>> getMaterialInventory(@PathVariable Long materialId) {
|
|
||||||
List<MaterialInventoryVo> inventoryList = iMatPurchaseService.queryMaterialInventory(materialId);
|
|
||||||
return R.ok(inventoryList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有物料库存信息(当前库存和在途数量)
|
|
||||||
*/
|
|
||||||
@GetMapping("/inventory")
|
|
||||||
public R<List<MaterialInventoryVo>> getAllMaterialInventory() {
|
|
||||||
List<MaterialInventoryVo> inventoryList = iMatPurchaseService.queryMaterialInventory(null);
|
|
||||||
return R.ok(inventoryList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取采购计划中所有物料的库存信息(当前库存和在途数量)
|
|
||||||
*
|
|
||||||
* @param purchaseId 采购单ID
|
|
||||||
*/
|
|
||||||
@GetMapping("/plan-inventory/{purchaseId}")
|
|
||||||
public R<List<PurchasePlanMaterialInventoryVo>> getPurchasePlanMaterialInventory(@PathVariable Long purchaseId) {
|
|
||||||
List<PurchasePlanMaterialInventoryVo> inventoryList = iMatPurchaseService.queryPurchasePlanMaterialInventory(purchaseId);
|
|
||||||
return R.ok(inventoryList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,13 +48,4 @@ public interface IMatPurchaseService {
|
|||||||
*/
|
*/
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询物料库存信息(当前库存和在途数量)
|
|
||||||
*/
|
|
||||||
List<MaterialInventoryVo> queryMaterialInventory(Long materialId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询采购计划中所有物料的库存信息(当前库存和在途数量)
|
|
||||||
*/
|
|
||||||
List<PurchasePlanMaterialInventoryVo> queryPurchasePlanMaterialInventory(Long purchaseId);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,32 @@
|
|||||||
package com.gear.mat.service.impl;
|
package com.gear.mat.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.gear.common.utils.StringUtils;
|
import com.gear.common.utils.StringUtils;
|
||||||
import com.gear.common.core.page.TableDataInfo;
|
import com.gear.common.core.page.TableDataInfo;
|
||||||
import com.gear.common.core.domain.PageQuery;
|
import com.gear.common.core.domain.PageQuery;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.gear.mat.domain.vo.MaterialInventoryVo;
|
import com.gear.mat.domain.MatPurchase;
|
||||||
|
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||||
|
import com.gear.mat.domain.bo.MatPurchaseInDetailBo;
|
||||||
|
import com.gear.mat.domain.vo.*;
|
||||||
|
import com.gear.mat.mapper.MatPurchaseMapper;
|
||||||
|
import com.gear.mat.service.IMatPurchaseInDetailService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.gear.mat.domain.bo.MatMaterialBo;
|
import com.gear.mat.domain.bo.MatMaterialBo;
|
||||||
import com.gear.mat.domain.vo.MatMaterialVo;
|
|
||||||
import com.gear.mat.domain.vo.MatMaterialWithInventoryVo;
|
|
||||||
import com.gear.mat.domain.MatMaterial;
|
import com.gear.mat.domain.MatMaterial;
|
||||||
import com.gear.mat.mapper.MatMaterialMapper;
|
import com.gear.mat.mapper.MatMaterialMapper;
|
||||||
import com.gear.mat.service.IMatMaterialService;
|
import com.gear.mat.service.IMatMaterialService;
|
||||||
import com.gear.mat.service.IMatPurchaseService;
|
import com.gear.mat.service.IMatPurchaseService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配料配件基础信息Service业务层处理
|
* 配料配件基础信息Service业务层处理
|
||||||
@@ -34,7 +39,8 @@ import java.util.stream.Collectors;
|
|||||||
public class MatMaterialServiceImpl implements IMatMaterialService {
|
public class MatMaterialServiceImpl implements IMatMaterialService {
|
||||||
|
|
||||||
private final MatMaterialMapper baseMapper;
|
private final MatMaterialMapper baseMapper;
|
||||||
private final IMatPurchaseService matPurchaseService;
|
private final MatPurchaseMapper matPurchaseMapper;
|
||||||
|
private final IMatPurchaseInDetailService matPurchaseInDetailService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询配料配件基础信息
|
* 查询配料配件基础信息
|
||||||
@@ -128,7 +134,7 @@ public class MatMaterialServiceImpl implements IMatMaterialService {
|
|||||||
MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material);
|
MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material);
|
||||||
|
|
||||||
// 查询该物料的库存信息
|
// 查询该物料的库存信息
|
||||||
List<MaterialInventoryVo> materialInventoryList = matPurchaseService.queryMaterialInventory(material.getMaterialId());
|
List<MaterialInventoryVo> materialInventoryList = queryMaterialInventory(material.getMaterialId());
|
||||||
|
|
||||||
if (!materialInventoryList.isEmpty()) {
|
if (!materialInventoryList.isEmpty()) {
|
||||||
MaterialInventoryVo inventoryInfo = materialInventoryList.get(0);
|
MaterialInventoryVo inventoryInfo = materialInventoryList.get(0);
|
||||||
@@ -159,7 +165,7 @@ public class MatMaterialServiceImpl implements IMatMaterialService {
|
|||||||
MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material);
|
MatMaterialWithInventoryVo inventoryVo = new MatMaterialWithInventoryVo(material);
|
||||||
|
|
||||||
// 查询该物料的库存信息
|
// 查询该物料的库存信息
|
||||||
List<MaterialInventoryVo> materialInventoryList = matPurchaseService.queryMaterialInventory(material.getMaterialId());
|
List<MaterialInventoryVo> materialInventoryList = queryMaterialInventory(material.getMaterialId());
|
||||||
|
|
||||||
if (!materialInventoryList.isEmpty()) {
|
if (!materialInventoryList.isEmpty()) {
|
||||||
MaterialInventoryVo inventoryInfo = materialInventoryList.get(0);
|
MaterialInventoryVo inventoryInfo = materialInventoryList.get(0);
|
||||||
@@ -172,4 +178,95 @@ public class MatMaterialServiceImpl implements IMatMaterialService {
|
|||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<MaterialInventoryVo> queryMaterialInventory(Long materialId) {
|
||||||
|
// 创建结果列表
|
||||||
|
List<MaterialInventoryVo> result = new ArrayList<>();
|
||||||
|
|
||||||
|
// 构建采购单查询条件(直接用QueryWrapper,和Service层逻辑保持一致)
|
||||||
|
QueryWrapper<MatPurchase> purchaseQw = new QueryWrapper<>();
|
||||||
|
if (materialId != null) {
|
||||||
|
purchaseQw.eq("material_id", materialId);
|
||||||
|
}
|
||||||
|
// 直接查采购单PO
|
||||||
|
List<MatPurchase> purchaseListPo = matPurchaseMapper.selectList(purchaseQw);
|
||||||
|
|
||||||
|
// 将PO转换为VO,以便后续处理
|
||||||
|
List<MatPurchaseVo> purchaseList = purchaseListPo.stream()
|
||||||
|
.map(purchase -> {
|
||||||
|
MatPurchaseVo vo = new MatPurchaseVo();
|
||||||
|
BeanUtils.copyProperties(purchase, vo);
|
||||||
|
return vo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 按物料ID分组
|
||||||
|
Map<Long, List<MatPurchaseVo>> purchaseMap = purchaseList.stream()
|
||||||
|
.collect(Collectors.groupingBy(MatPurchaseVo::getMaterialId));
|
||||||
|
|
||||||
|
for (Long matId : purchaseMap.keySet()) {
|
||||||
|
|
||||||
|
// 通过采购单中的物料ID查询物料详细信息
|
||||||
|
MatMaterialVo material = baseMapper.selectVoById(matId);
|
||||||
|
|
||||||
|
MaterialInventoryVo inventory = new MaterialInventoryVo();
|
||||||
|
inventory.setMaterialId(matId);
|
||||||
|
|
||||||
|
if (material != null) {
|
||||||
|
inventory.setMaterialName(material.getMaterialName());
|
||||||
|
inventory.setSpec(material.getSpec());
|
||||||
|
inventory.setModel(material.getModel());
|
||||||
|
inventory.setUnit(material.getUnit());
|
||||||
|
inventory.setCurrentStock(material.getCurrentStock());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MatPurchaseVo> purchases = purchaseMap.get(matId);
|
||||||
|
|
||||||
|
// 计算计划总数
|
||||||
|
BigDecimal planTotal = purchases.stream()
|
||||||
|
.map(MatPurchaseVo::getPlanNum)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
inventory.setPlanNum(planTotal);
|
||||||
|
|
||||||
|
// 计算已入库数量和在途数量
|
||||||
|
BigDecimal receivedTotal = BigDecimal.ZERO;
|
||||||
|
BigDecimal inTransitTotal = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (MatPurchaseVo purchase : purchases) {
|
||||||
|
// 查询该采购单下的入库详情
|
||||||
|
MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo();
|
||||||
|
detailBo.setPurchaseId(purchase.getPurchaseId());
|
||||||
|
|
||||||
|
List<MatPurchaseInDetailVo> details = matPurchaseInDetailService.queryList(detailBo);
|
||||||
|
|
||||||
|
// 计算该采购单的已入库数量
|
||||||
|
BigDecimal receivedInPurchase = details.stream()
|
||||||
|
.map(MatPurchaseInDetailVo::getInNum)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
receivedTotal = receivedTotal.add(receivedInPurchase);
|
||||||
|
|
||||||
|
// 根据采购单状态判断在途数量
|
||||||
|
// 1-待入(在途) 2-已完成(全部入库) 3-已取消(归零) 4-部分入库
|
||||||
|
if (purchase.getStatus() != null && (purchase.getStatus() == 1 || purchase.getStatus() == 4)) {
|
||||||
|
// 在途或部分入库,计算未入库数量
|
||||||
|
BigDecimal pending = purchase.getPlanNum().subtract(receivedInPurchase);
|
||||||
|
if (pending.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
inTransitTotal = inTransitTotal.add(pending);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.setReceivedNum(receivedTotal);
|
||||||
|
inventory.setInTransitNum(inTransitTotal);
|
||||||
|
|
||||||
|
result.add(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,30 @@
|
|||||||
package com.gear.mat.service.impl;
|
package com.gear.mat.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.gear.common.utils.StringUtils;
|
|
||||||
import com.gear.common.core.page.TableDataInfo;
|
|
||||||
import com.gear.common.core.domain.PageQuery;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import lombok.RequiredArgsConstructor;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import org.springframework.stereotype.Service;
|
import com.gear.common.utils.StringUtils;
|
||||||
import com.gear.mat.domain.bo.MatPurchaseInDetailBo;
|
import com.gear.common.core.domain.PageQuery;
|
||||||
import com.gear.mat.domain.vo.MatPurchaseInDetailVo;
|
import com.gear.common.core.page.TableDataInfo;
|
||||||
|
import com.gear.mat.domain.MatMaterial;
|
||||||
|
import com.gear.mat.domain.MatPriceHistory;
|
||||||
import com.gear.mat.domain.MatPurchaseInDetail;
|
import com.gear.mat.domain.MatPurchaseInDetail;
|
||||||
|
import com.gear.mat.domain.bo.*;
|
||||||
|
import com.gear.mat.domain.vo.*;
|
||||||
|
import com.gear.mat.mapper.MatMaterialMapper;
|
||||||
|
import com.gear.mat.mapper.MatPriceHistoryMapper;
|
||||||
import com.gear.mat.mapper.MatPurchaseInDetailMapper;
|
import com.gear.mat.mapper.MatPurchaseInDetailMapper;
|
||||||
import com.gear.mat.service.IMatPurchaseInDetailService;
|
|
||||||
import com.gear.mat.service.IMatMaterialService;
|
import com.gear.mat.service.IMatMaterialService;
|
||||||
import com.gear.mat.service.IMatPriceHistoryService;
|
import com.gear.mat.service.IMatPriceHistoryService;
|
||||||
import com.gear.mat.domain.vo.MatMaterialVo;
|
import com.gear.mat.service.IMatPurchaseInDetailService;
|
||||||
import com.gear.mat.domain.vo.MatPriceHistoryVo;
|
import lombok.RequiredArgsConstructor;
|
||||||
import com.gear.mat.domain.bo.MatMaterialBo;
|
import org.springframework.stereotype.Service;
|
||||||
import com.gear.mat.domain.bo.MatPriceHistoryBo;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,7 +38,8 @@ import java.util.stream.Collectors;
|
|||||||
public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailService {
|
public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailService {
|
||||||
|
|
||||||
private final MatPurchaseInDetailMapper baseMapper;
|
private final MatPurchaseInDetailMapper baseMapper;
|
||||||
private final IMatMaterialService matMaterialService;
|
private final MatMaterialMapper matMaterialMapper; // 使用Mapper代替Service避免循环依赖
|
||||||
|
private final MatPriceHistoryMapper matPriceHistoryMapper; // 添加PriceHistory的Mapper
|
||||||
private final IMatPriceHistoryService matPriceHistoryService;
|
private final IMatPriceHistoryService matPriceHistoryService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,16 +190,13 @@ public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailServi
|
|||||||
* 更新库存数量
|
* 更新库存数量
|
||||||
*/
|
*/
|
||||||
private void updateInventory(Long materialId, BigDecimal quantity) {
|
private void updateInventory(Long materialId, BigDecimal quantity) {
|
||||||
MatMaterialVo material = matMaterialService.queryById(materialId);
|
MatMaterial material = matMaterialMapper.selectById(materialId);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
MatMaterialBo materialBo = new MatMaterialBo();
|
|
||||||
materialBo.setMaterialId(materialId);
|
|
||||||
|
|
||||||
// 计算新的库存数量
|
// 计算新的库存数量
|
||||||
BigDecimal newStock = material.getCurrentStock().add(quantity);
|
BigDecimal newStock = material.getCurrentStock().add(quantity);
|
||||||
materialBo.setCurrentStock(newStock);
|
material.setCurrentStock(newStock);
|
||||||
|
|
||||||
matMaterialService.updateByBo(materialBo);
|
matMaterialMapper.updateById(material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +205,7 @@ public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailServi
|
|||||||
*/
|
*/
|
||||||
private void insertPriceHistory(Long materialId, BigDecimal price, BigDecimal quantity, Long detailId) {
|
private void insertPriceHistory(Long materialId, BigDecimal price, BigDecimal quantity, Long detailId) {
|
||||||
// 获取当前库存和平均价格信息
|
// 获取当前库存和平均价格信息
|
||||||
MatMaterialVo material = matMaterialService.queryById(materialId);
|
MatMaterial material = matMaterialMapper.selectById(materialId);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
// 计算新的平均价格
|
// 计算新的平均价格
|
||||||
BigDecimal avgPrice = calculateAveragePrice(materialId, price, quantity);
|
BigDecimal avgPrice = calculateAveragePrice(materialId, price, quantity);
|
||||||
@@ -244,7 +241,7 @@ public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailServi
|
|||||||
MatPriceHistoryVo lastHistory = historyList.get(0); // 最近的一条记录
|
MatPriceHistoryVo lastHistory = historyList.get(0); // 最近的一条记录
|
||||||
|
|
||||||
// 获取当前物料的现有库存
|
// 获取当前物料的现有库存
|
||||||
MatMaterialVo material = matMaterialService.queryById(materialId);
|
MatMaterial material = matMaterialMapper.selectById(materialId);
|
||||||
if (material == null) {
|
if (material == null) {
|
||||||
return newPrice;
|
return newPrice;
|
||||||
}
|
}
|
||||||
@@ -273,7 +270,7 @@ public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailServi
|
|||||||
* 还原库存数量(减少库存)
|
* 还原库存数量(减少库存)
|
||||||
*/
|
*/
|
||||||
private void revertInventory(Long materialId, BigDecimal quantity) {
|
private void revertInventory(Long materialId, BigDecimal quantity) {
|
||||||
MatMaterialVo material = matMaterialService.queryById(materialId);
|
MatMaterial material = matMaterialMapper.selectById(materialId);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
// 验证要减少的数量不能大于当前库存
|
// 验证要减少的数量不能大于当前库存
|
||||||
if (quantity.compareTo(material.getCurrentStock()) > 0) {
|
if (quantity.compareTo(material.getCurrentStock()) > 0) {
|
||||||
@@ -281,17 +278,14 @@ public class MatPurchaseInDetailServiceImpl implements IMatPurchaseInDetailServi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MatMaterialBo materialBo = new MatMaterialBo();
|
|
||||||
materialBo.setMaterialId(materialId);
|
|
||||||
|
|
||||||
// 计算还原后的库存数量(减去本次入库的数量)
|
// 计算还原后的库存数量(减去本次入库的数量)
|
||||||
BigDecimal newStock = material.getCurrentStock().subtract(quantity);
|
BigDecimal newStock = material.getCurrentStock().subtract(quantity);
|
||||||
if (newStock.compareTo(BigDecimal.ZERO) < 0) {
|
if (newStock.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
newStock = BigDecimal.ZERO; // 库存不能为负数
|
newStock = BigDecimal.ZERO; // 库存不能为负数
|
||||||
}
|
}
|
||||||
materialBo.setCurrentStock(newStock);
|
material.setCurrentStock(newStock);
|
||||||
|
|
||||||
matMaterialService.updateByBo(materialBo);
|
matMaterialMapper.updateById(material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import com.gear.mat.service.IMatPurchaseService;
|
|||||||
import com.gear.mat.service.IMatMaterialService;
|
import com.gear.mat.service.IMatMaterialService;
|
||||||
import com.gear.mat.service.IMatPurchaseInDetailService;
|
import com.gear.mat.service.IMatPurchaseInDetailService;
|
||||||
import com.gear.mat.domain.bo.MatPurchaseInDetailBo;
|
import com.gear.mat.domain.bo.MatPurchaseInDetailBo;
|
||||||
|
import com.gear.mat.mapper.MatMaterialMapper;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购单主(管理在途库存)Service业务层处理
|
* 采购单主(管理在途库存)Service业务层处理
|
||||||
@@ -36,7 +38,7 @@ import java.util.stream.Collectors;
|
|||||||
public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
||||||
|
|
||||||
private final MatPurchaseMapper baseMapper;
|
private final MatPurchaseMapper baseMapper;
|
||||||
private final IMatMaterialService matMaterialService;
|
private final MatMaterialMapper matMaterialMapper;
|
||||||
private final IMatPurchaseInDetailService matPurchaseInDetailService;
|
private final IMatPurchaseInDetailService matPurchaseInDetailService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,98 +147,51 @@ public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
|||||||
return baseMapper.deleteBatchIds(ids) > 0;
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MaterialInventoryVo> queryMaterialInventory(Long materialId) {
|
|
||||||
// 创建结果列表
|
|
||||||
List<MaterialInventoryVo> result = new ArrayList<>();
|
|
||||||
|
|
||||||
// 构建查询条件
|
|
||||||
MatPurchaseBo purchaseBo = new MatPurchaseBo();
|
|
||||||
if (materialId != null) {
|
|
||||||
purchaseBo.setMaterialId(materialId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询所有相关的采购单
|
|
||||||
List<MatPurchaseVo> purchaseList = queryList(purchaseBo);
|
|
||||||
|
|
||||||
// 按物料ID分组
|
|
||||||
Map<Long, List<MatPurchaseVo>> purchaseMap = purchaseList.stream()
|
|
||||||
.collect(Collectors.groupingBy(MatPurchaseVo::getMaterialId));
|
|
||||||
|
|
||||||
for (Long matId : purchaseMap.keySet()) {
|
|
||||||
// 获取物料信息
|
|
||||||
MatMaterialVo material = matMaterialService.queryById(matId);
|
|
||||||
|
|
||||||
MaterialInventoryVo inventory = new MaterialInventoryVo();
|
|
||||||
inventory.setMaterialId(matId);
|
|
||||||
|
|
||||||
if (material != null) {
|
|
||||||
inventory.setMaterialName(material.getMaterialName());
|
|
||||||
inventory.setSpec(material.getSpec());
|
|
||||||
inventory.setModel(material.getModel());
|
|
||||||
inventory.setUnit(material.getUnit());
|
|
||||||
inventory.setCurrentStock(material.getCurrentStock());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MatPurchaseVo> purchases = purchaseMap.get(matId);
|
|
||||||
|
|
||||||
// 计算计划总数
|
|
||||||
BigDecimal planTotal = purchases.stream()
|
|
||||||
.map(MatPurchaseVo::getPlanNum)
|
|
||||||
.filter(num -> num != null)
|
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
||||||
|
|
||||||
inventory.setPlanNum(planTotal);
|
|
||||||
|
|
||||||
// 计算已入库数量和在途数量
|
|
||||||
BigDecimal receivedTotal = BigDecimal.ZERO;
|
|
||||||
BigDecimal inTransitTotal = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
for (MatPurchaseVo purchase : purchases) {
|
|
||||||
// 查询该采购单下的入库详情
|
|
||||||
MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo();
|
|
||||||
detailBo.setPurchaseId(purchase.getPurchaseId());
|
|
||||||
|
|
||||||
List<MatPurchaseInDetailVo> details = matPurchaseInDetailService.queryList(detailBo);
|
|
||||||
|
|
||||||
// 计算该采购单的已入库数量
|
|
||||||
BigDecimal receivedInPurchase = details.stream()
|
|
||||||
.map(MatPurchaseInDetailVo::getInNum)
|
|
||||||
.filter(num -> num != null)
|
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
||||||
|
|
||||||
receivedTotal = receivedTotal.add(receivedInPurchase);
|
|
||||||
|
|
||||||
// 根据采购单状态判断在途数量
|
|
||||||
// 1-待入(在途) 2-已完成(全部入库) 3-已取消(归零) 4-部分入库
|
|
||||||
if (purchase.getStatus() != null && (purchase.getStatus() == 1 || purchase.getStatus() == 4)) {
|
|
||||||
// 在途或部分入库,计算未入库数量
|
|
||||||
BigDecimal pending = purchase.getPlanNum().subtract(receivedInPurchase);
|
|
||||||
if (pending.compareTo(BigDecimal.ZERO) > 0) {
|
|
||||||
inTransitTotal = inTransitTotal.add(pending);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inventory.setReceivedNum(receivedTotal);
|
|
||||||
inventory.setInTransitNum(inTransitTotal);
|
|
||||||
|
|
||||||
result.add(inventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MatPurchaseVo> convertToPurchaseWithInventoryVo(List<MatPurchaseVo> purchaseList) {
|
public List<MatPurchaseVo> convertToPurchaseWithInventoryVo(List<MatPurchaseVo> purchaseList) {
|
||||||
List<MatPurchaseVo> result = new ArrayList<>();
|
List<MatPurchaseVo> result = new ArrayList<>();
|
||||||
|
|
||||||
|
// 批量获取所有物料ID
|
||||||
|
Set<Long> materialIds = purchaseList.stream()
|
||||||
|
.map(MatPurchaseVo::getMaterialId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// 批量查询物料信息,避免N+1查询问题
|
||||||
|
Map<Long, MatMaterialVo> materialMap = new HashMap<>();
|
||||||
|
if (!materialIds.isEmpty()) {
|
||||||
|
List<MatMaterialVo> materials = new ArrayList<>();
|
||||||
|
for (Long materialId : materialIds) {
|
||||||
|
MatMaterialVo material = matMaterialMapper.selectVoById(materialId);
|
||||||
|
if (material != null) {
|
||||||
|
materialMap.put(materialId, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量获取所有采购单ID
|
||||||
|
List<Long> purchaseIds = purchaseList.stream()
|
||||||
|
.map(MatPurchaseVo::getPurchaseId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 批量查询所有入库详情,避免N+1查询问题
|
||||||
|
Map<Long, List<MatPurchaseInDetailVo>> detailMap = new HashMap<>();
|
||||||
|
if (!purchaseIds.isEmpty()) {
|
||||||
|
for (Long purchaseId : purchaseIds) {
|
||||||
|
MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo();
|
||||||
|
detailBo.setPurchaseId(purchaseId);
|
||||||
|
List<MatPurchaseInDetailVo> details = matPurchaseInDetailService.queryList(detailBo);
|
||||||
|
detailMap.put(purchaseId, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (MatPurchaseVo purchase : purchaseList) {
|
for (MatPurchaseVo purchase : purchaseList) {
|
||||||
MatPurchaseVo vo = new MatPurchaseVo();
|
MatPurchaseVo vo = new MatPurchaseVo();
|
||||||
|
|
||||||
// 复制基本采购信息
|
// 复制基本采购信息
|
||||||
BeanUtils.copyProperties(purchase, vo);
|
BeanUtils.copyProperties(purchase, vo);
|
||||||
// 获取物料信息
|
|
||||||
MatMaterialVo material = matMaterialService.queryById(purchase.getMaterialId());
|
// 获取物料信息 - 从预加载的Map中获取
|
||||||
|
MatMaterialVo material = materialMap.get(purchase.getMaterialId());
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
vo.setMaterialName(material.getMaterialName());
|
vo.setMaterialName(material.getMaterialName());
|
||||||
vo.setSpec(material.getSpec());
|
vo.setSpec(material.getSpec());
|
||||||
@@ -245,15 +200,17 @@ public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
|||||||
vo.setCurrentStock(material.getCurrentStock());
|
vo.setCurrentStock(material.getCurrentStock());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算已入库数量
|
// 获取入库详情 - 从预加载的Map中获取
|
||||||
MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo();
|
List<MatPurchaseInDetailVo> details = detailMap.get(purchase.getPurchaseId());
|
||||||
detailBo.setPurchaseId(purchase.getPurchaseId());
|
|
||||||
List<MatPurchaseInDetailVo> details = matPurchaseInDetailService.queryList(detailBo);
|
|
||||||
|
|
||||||
BigDecimal receivedTotal = details.stream()
|
// 计算已入库数量
|
||||||
.map(MatPurchaseInDetailVo::getInNum)
|
BigDecimal receivedTotal = BigDecimal.ZERO;
|
||||||
.filter(Objects::nonNull)
|
if (details != null && !details.isEmpty()) {
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
receivedTotal = details.stream()
|
||||||
|
.map(MatPurchaseInDetailVo::getInNum)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
}
|
||||||
|
|
||||||
vo.setReceivedNum(receivedTotal);
|
vo.setReceivedNum(receivedTotal);
|
||||||
|
|
||||||
@@ -278,71 +235,4 @@ public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<PurchasePlanMaterialInventoryVo> queryPurchasePlanMaterialInventory(Long purchaseId) {
|
|
||||||
List<PurchasePlanMaterialInventoryVo> result = new ArrayList<>();
|
|
||||||
|
|
||||||
if (purchaseId == null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询采购单信息
|
|
||||||
MatPurchaseVo purchase = queryById(purchaseId);
|
|
||||||
if (purchase == null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取物料信息
|
|
||||||
MatMaterialVo material = matMaterialService.queryById(purchase.getMaterialId());
|
|
||||||
|
|
||||||
// 创建库存信息对象
|
|
||||||
PurchasePlanMaterialInventoryVo inventory = new PurchasePlanMaterialInventoryVo();
|
|
||||||
inventory.setPurchaseId(purchase.getPurchaseId());
|
|
||||||
inventory.setPurchaseNo(purchase.getPurchaseNo());
|
|
||||||
inventory.setMaterialId(purchase.getMaterialId());
|
|
||||||
|
|
||||||
if (material != null) {
|
|
||||||
inventory.setMaterialName(material.getMaterialName());
|
|
||||||
inventory.setSpec(material.getSpec());
|
|
||||||
inventory.setModel(material.getModel());
|
|
||||||
inventory.setUnit(material.getUnit());
|
|
||||||
inventory.setCurrentStock(material.getCurrentStock());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置计划采购数量
|
|
||||||
inventory.setPlanNum(purchase.getPlanNum());
|
|
||||||
|
|
||||||
// 查询该采购单下的入库详情
|
|
||||||
MatPurchaseInDetailBo detailBo = new MatPurchaseInDetailBo();
|
|
||||||
detailBo.setPurchaseId(purchase.getPurchaseId());
|
|
||||||
|
|
||||||
List<MatPurchaseInDetailVo> details = matPurchaseInDetailService.queryList(detailBo);
|
|
||||||
|
|
||||||
// 计算已入库数量
|
|
||||||
BigDecimal receivedTotal = details.stream()
|
|
||||||
.map(MatPurchaseInDetailVo::getInNum)
|
|
||||||
.filter(num -> num != null)
|
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
||||||
|
|
||||||
inventory.setReceivedNum(receivedTotal);
|
|
||||||
|
|
||||||
// 根据采购单状态判断在途数量
|
|
||||||
// 1-待入(在途) 2-已完成(全部入库) 3-已取消(归零) 4-部分入库
|
|
||||||
if (purchase.getStatus() != null && (purchase.getStatus() == 1 || purchase.getStatus() == 4)) {
|
|
||||||
// 在途或部分入库,计算未入库数量
|
|
||||||
BigDecimal pending = purchase.getPlanNum().subtract(receivedTotal);
|
|
||||||
if (pending.compareTo(BigDecimal.ZERO) > 0) {
|
|
||||||
inventory.setInTransitNum(pending);
|
|
||||||
} else {
|
|
||||||
inventory.setInTransitNum(BigDecimal.ZERO);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 已完成或已取消,没有在途数量
|
|
||||||
inventory.setInTransitNum(BigDecimal.ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.add(inventory);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user