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.enums.BusinessType;
|
||||||
import com.gear.common.utils.poi.ExcelUtil;
|
import com.gear.common.utils.poi.ExcelUtil;
|
||||||
import com.gear.mat.domain.vo.MatPurchaseVo;
|
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.domain.bo.MatPurchaseBo;
|
||||||
import com.gear.mat.service.IMatPurchaseService;
|
import com.gear.mat.service.IMatPurchaseService;
|
||||||
import com.gear.common.core.page.TableDataInfo;
|
import com.gear.common.core.page.TableDataInfo;
|
||||||
@@ -99,4 +101,35 @@ public class MatPurchaseController extends BaseController {
|
|||||||
@PathVariable Long[] purchaseIds) {
|
@PathVariable Long[] purchaseIds) {
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.MatPurchase;
|
||||||
import com.gear.mat.domain.vo.MatPurchaseVo;
|
import com.gear.mat.domain.vo.MatPurchaseVo;
|
||||||
|
import com.gear.mat.domain.vo.MaterialInventoryVo;
|
||||||
import com.gear.mat.domain.bo.MatPurchaseBo;
|
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||||
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.gear.mat.domain.vo.PurchasePlanMaterialInventoryVo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -46,4 +48,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,23 @@ 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.*;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.gear.mat.domain.bo.MatPurchaseBo;
|
import com.gear.mat.domain.bo.MatPurchaseBo;
|
||||||
import com.gear.mat.domain.vo.MatPurchaseVo;
|
|
||||||
import com.gear.mat.domain.MatPurchase;
|
import com.gear.mat.domain.MatPurchase;
|
||||||
import com.gear.mat.mapper.MatPurchaseMapper;
|
import com.gear.mat.mapper.MatPurchaseMapper;
|
||||||
import com.gear.mat.service.IMatPurchaseService;
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 采购单主(管理在途库存)Service业务层处理
|
* 采购单主(管理在途库存)Service业务层处理
|
||||||
@@ -31,6 +37,8 @@ import java.util.Collection;
|
|||||||
public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
public class MatPurchaseServiceImpl implements IMatPurchaseService {
|
||||||
|
|
||||||
private final MatPurchaseMapper baseMapper;
|
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;
|
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