feat(mat-purchase): 采购对应配料的在库和在途
- 在 IMatPurchaseService 中添加 queryMaterialInventory 和 queryPurchasePlanMaterialInventory 方法 - 在 MatPurchaseController 中新增库存查询接口,包括按物料ID查询、查询所有物料库存、查询采购计划库存 - 在 MatPurchaseServiceImpl 中实现库存信息查询逻辑,计算当前库存、在途数量、已入库数量等 - 新增 MaterialInventoryVo 和 PurchasePlanMaterialInventoryVo 视图对象用于库存信息展示 - 集成 matMaterialService 和 matPurchaseInDetailService 来获取完整的库存数据
This commit is contained in:
@@ -21,6 +21,8 @@ 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.MatPurchaseVo;
|
||||
import com.gear.mat.domain.vo.MaterialInventoryVo;
|
||||
import com.gear.mat.domain.vo.PurchasePlanMaterialInventoryVo;
|
||||
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||
import com.gear.mat.service.IMatPurchaseService;
|
||||
import com.gear.common.core.page.TableDataInfo;
|
||||
@@ -99,4 +101,35 @@ public class MatPurchaseController extends BaseController {
|
||||
@PathVariable Long[] purchaseIds) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.gear.mat.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 物料库存信息视图对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Data
|
||||
public class MaterialInventoryVo {
|
||||
|
||||
/**
|
||||
* 物料ID
|
||||
*/
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 规格
|
||||
*/
|
||||
private String spec;
|
||||
|
||||
/**
|
||||
* 型号
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 当前库存数量
|
||||
*/
|
||||
private BigDecimal currentStock;
|
||||
|
||||
/**
|
||||
* 在途数量(未完成入库的采购数量)
|
||||
*/
|
||||
private BigDecimal inTransitNum;
|
||||
|
||||
/**
|
||||
* 计划采购总数量
|
||||
*/
|
||||
private BigDecimal planNum;
|
||||
|
||||
/**
|
||||
* 已入库数量
|
||||
*/
|
||||
private BigDecimal receivedNum;
|
||||
|
||||
public MaterialInventoryVo() {
|
||||
this.currentStock = BigDecimal.ZERO;
|
||||
this.inTransitNum = BigDecimal.ZERO;
|
||||
this.planNum = BigDecimal.ZERO;
|
||||
this.receivedNum = BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.gear.mat.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 采购计划物料库存信息视图对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-30
|
||||
*/
|
||||
@Data
|
||||
public class PurchasePlanMaterialInventoryVo {
|
||||
|
||||
/**
|
||||
* 采购单ID
|
||||
*/
|
||||
private Long purchaseId;
|
||||
|
||||
/**
|
||||
* 采购单号
|
||||
*/
|
||||
private String purchaseNo;
|
||||
|
||||
/**
|
||||
* 物料ID
|
||||
*/
|
||||
private Long materialId;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
private String materialName;
|
||||
|
||||
/**
|
||||
* 规格
|
||||
*/
|
||||
private String spec;
|
||||
|
||||
/**
|
||||
* 型号
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 计划采购数量
|
||||
*/
|
||||
private BigDecimal planNum;
|
||||
|
||||
/**
|
||||
* 当前库存数量
|
||||
*/
|
||||
private BigDecimal currentStock;
|
||||
|
||||
/**
|
||||
* 在途数量(未完成入库的采购数量)
|
||||
*/
|
||||
private BigDecimal inTransitNum;
|
||||
|
||||
/**
|
||||
* 已入库数量
|
||||
*/
|
||||
private BigDecimal receivedNum;
|
||||
|
||||
public PurchasePlanMaterialInventoryVo() {
|
||||
this.planNum = BigDecimal.ZERO;
|
||||
this.currentStock = BigDecimal.ZERO;
|
||||
this.inTransitNum = BigDecimal.ZERO;
|
||||
this.receivedNum = BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package com.gear.mat.service;
|
||||
|
||||
import com.gear.mat.domain.MatPurchase;
|
||||
import com.gear.mat.domain.vo.MatPurchaseVo;
|
||||
import com.gear.mat.domain.vo.MaterialInventoryVo;
|
||||
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||
import com.gear.common.core.page.TableDataInfo;
|
||||
import com.gear.common.core.domain.PageQuery;
|
||||
import com.gear.mat.domain.vo.PurchasePlanMaterialInventoryVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -46,4 +48,14 @@ public interface IMatPurchaseService {
|
||||
* 校验并批量删除采购单主(管理在途库存)信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 查询物料库存信息(当前库存和在途数量)
|
||||
*/
|
||||
List<MaterialInventoryVo> queryMaterialInventory(Long materialId);
|
||||
|
||||
/**
|
||||
* 查询采购计划中所有物料的库存信息(当前库存和在途数量)
|
||||
*/
|
||||
List<PurchasePlanMaterialInventoryVo> queryPurchasePlanMaterialInventory(Long purchaseId);
|
||||
}
|
||||
|
||||
@@ -8,17 +8,23 @@ 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.toolkit.Wrappers;
|
||||
import com.gear.mat.domain.vo.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||
import com.gear.mat.domain.vo.MatPurchaseVo;
|
||||
import com.gear.mat.domain.MatPurchase;
|
||||
import com.gear.mat.mapper.MatPurchaseMapper;
|
||||
import com.gear.mat.service.IMatPurchaseService;
|
||||
import com.gear.mat.service.IMatMaterialService;
|
||||
import com.gear.mat.service.IMatPurchaseInDetailService;
|
||||
import com.gear.mat.domain.bo.MatPurchaseInDetailBo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 采购单主(管理在途库存)Service业务层处理
|
||||
@@ -31,6 +37,8 @@ import java.util.Collection;
|
||||
public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
||||
|
||||
private final MatPurchaseMapper baseMapper;
|
||||
private final IMatMaterialService matMaterialService;
|
||||
private final IMatPurchaseInDetailService matPurchaseInDetailService;
|
||||
|
||||
/**
|
||||
* 查询采购单主(管理在途库存)
|
||||
@@ -134,4 +142,154 @@ public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@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