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 BigDecimal materialNum; // 单产品所需配料数量
private Long sort; // 配料排序 private Long sort; // 配料排序
private String remark; 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查询问题 * 避免N+1查询问题
*/ */
private Map<Long, MaterialInventoryVo> batchQueryMaterialInventory(List<Long> materialIds) { public Map<Long, MaterialInventoryVo> batchQueryMaterialInventory(List<Long> materialIds) {
if (materialIds == null || materialIds.isEmpty()) { if (materialIds == null || materialIds.isEmpty()) {
return Collections.emptyMap(); return Collections.emptyMap();
} }

View File

@@ -73,6 +73,9 @@ public class MatProductMaterialRelationServiceImpl implements IMatProductMateria
*/ */
@Override @Override
public Boolean insertByBo(MatProductMaterialRelationBo bo) { public Boolean insertByBo(MatProductMaterialRelationBo bo) {
// 校验是否已存在相同的绑定关系
validBindingExists(bo);
MatProductMaterialRelation add = BeanUtil.toBean(bo, MatProductMaterialRelation.class); MatProductMaterialRelation add = BeanUtil.toBean(bo, MatProductMaterialRelation.class);
validEntityBeforeSave(add); validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0; boolean flag = baseMapper.insert(add) > 0;
@@ -82,6 +85,26 @@ public class MatProductMaterialRelationServiceImpl implements IMatProductMateria
return flag; 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.bo.MatProductBo;
import com.gear.mat.domain.vo.MatProductVo; import com.gear.mat.domain.vo.MatProductVo;
import com.gear.mat.domain.vo.MatProductWithMaterialsVo; import com.gear.mat.domain.vo.MatProductWithMaterialsVo;
import com.gear.mat.domain.vo.MaterialInventoryVo;
import com.gear.mat.domain.MatProduct; import com.gear.mat.domain.MatProduct;
import com.gear.mat.mapper.MatProductMapper; import com.gear.mat.mapper.MatProductMapper;
import com.gear.mat.service.IMatProductService; import com.gear.mat.service.IMatProductService;
@@ -40,6 +41,7 @@ public class MatProductServiceImpl implements IMatProductService {
private final MatProductMapper baseMapper; private final MatProductMapper baseMapper;
private final IMatMaterialService matMaterialService; private final IMatMaterialService matMaterialService;
private final IMatProductMaterialRelationService productMaterialRelationService; 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); productWithMaterialsVo.setMaterials(materials);
return productWithMaterialsVo; return productWithMaterialsVo;