feat(product): 添加产品配料库存信息展示功能

- 将batchQueryMaterialInventory方法从私有改为公共以支持外部调用
- 在产品-配料关联服务中新增重复绑定校验逻辑
- 实现产品详情页面显示配料的在途、计划和已入库数量信息
- 扩展MatProductWithMaterialsVo数据传输对象增加库存相关字段
- 在产品服务中集成物料库存批量查询并填充到响应结果中
This commit is contained in:
2026-01-31 16:10:44 +08:00
parent 570c597fae
commit 89a67aaf20
4 changed files with 48 additions and 1 deletions

View File

@@ -77,5 +77,8 @@ public class MatProductWithMaterialsVo {
private BigDecimal materialNum; // 单产品所需配料数量
private Long sort; // 配料排序
private String remark;
private BigDecimal inTransitNum; // 在途数量(未完成入库的采购数量)
private BigDecimal planNum; // 计划采购总数量
private BigDecimal receivedNum; // 已入库数量
}
}

View File

@@ -189,7 +189,7 @@ public class MatMaterialServiceImpl implements IMatMaterialService {
* 批量查询物料库存信息
* 避免N+1查询问题
*/
private Map<Long, MaterialInventoryVo> batchQueryMaterialInventory(List<Long> materialIds) {
public Map<Long, MaterialInventoryVo> batchQueryMaterialInventory(List<Long> materialIds) {
if (materialIds == null || materialIds.isEmpty()) {
return Collections.emptyMap();
}

View File

@@ -73,6 +73,9 @@ public class MatProductMaterialRelationServiceImpl implements IMatProductMateria
*/
@Override
public Boolean insertByBo(MatProductMaterialRelationBo bo) {
// 校验是否已存在相同的绑定关系
validBindingExists(bo);
MatProductMaterialRelation add = BeanUtil.toBean(bo, MatProductMaterialRelation.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
@@ -82,6 +85,26 @@ public class MatProductMaterialRelationServiceImpl implements IMatProductMateria
return flag;
}
/**
* 校验绑定关系是否存在
*/
private void validBindingExists(MatProductMaterialRelationBo bo) {
if (bo.getProductId() == null || bo.getMaterialId() == null) {
throw new RuntimeException("产品ID和物料ID不能为空");
}
// 查询是否已存在相同的绑定关系
LambdaQueryWrapper<MatProductMaterialRelation> lqw = Wrappers.lambdaQuery();
lqw.eq(MatProductMaterialRelation::getProductId, bo.getProductId())
.eq(MatProductMaterialRelation::getMaterialId, bo.getMaterialId())
.eq(MatProductMaterialRelation::getDelFlag, 0); // 只查询未删除的记录
MatProductMaterialRelation existing = baseMapper.selectOne(lqw);
if (existing != null) {
throw new RuntimeException("该产品已绑定此配料,不能重复绑定");
}
}
/**
* 修改产品-配料关联中间
*/

View File

@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
import com.gear.mat.domain.bo.MatProductBo;
import com.gear.mat.domain.vo.MatProductVo;
import com.gear.mat.domain.vo.MatProductWithMaterialsVo;
import com.gear.mat.domain.vo.MaterialInventoryVo;
import com.gear.mat.domain.MatProduct;
import com.gear.mat.mapper.MatProductMapper;
import com.gear.mat.service.IMatProductService;
@@ -40,6 +41,7 @@ public class MatProductServiceImpl implements IMatProductService {
private final MatProductMapper baseMapper;
private final IMatMaterialService matMaterialService;
private final IMatProductMaterialRelationService productMaterialRelationService;
private final MatMaterialServiceImpl matMaterialServiceImpl;
/**
* 查询产品基础信息
@@ -137,6 +139,25 @@ public class MatProductServiceImpl implements IMatProductService {
}
}
// 批量查询所有物料的库存信息
if (!materials.isEmpty()) {
List<Long> materialIds = materials.stream()
.map(MatProductWithMaterialsVo.MaterialInfo::getMaterialId)
.distinct()
.collect(Collectors.toList());
Map<Long, MaterialInventoryVo> inventoryMap = matMaterialServiceImpl.batchQueryMaterialInventory(materialIds);
// 填充库存信息到MaterialInfo
materials.forEach(material -> {
MaterialInventoryVo inventory = inventoryMap.get(material.getMaterialId());
if (inventory != null) {
material.setInTransitNum(inventory.getInTransitNum());
material.setPlanNum(inventory.getPlanNum());
material.setReceivedNum(inventory.getReceivedNum());
}
});
}
productWithMaterialsVo.setMaterials(materials);
return productWithMaterialsVo;