diff --git a/gear-mat/src/main/java/com/gear/mat/controller/MatPurchaseController.java b/gear-mat/src/main/java/com/gear/mat/controller/MatPurchaseController.java index e13bec3..68118c6 100644 --- a/gear-mat/src/main/java/com/gear/mat/controller/MatPurchaseController.java +++ b/gear-mat/src/main/java/com/gear/mat/controller/MatPurchaseController.java @@ -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> getMaterialInventory(@PathVariable Long materialId) { + List inventoryList = iMatPurchaseService.queryMaterialInventory(materialId); + return R.ok(inventoryList); + } + + /** + * 获取所有物料库存信息(当前库存和在途数量) + */ + @GetMapping("/inventory") + public R> getAllMaterialInventory() { + List inventoryList = iMatPurchaseService.queryMaterialInventory(null); + return R.ok(inventoryList); + } + + /** + * 获取采购计划中所有物料的库存信息(当前库存和在途数量) + * + * @param purchaseId 采购单ID + */ + @GetMapping("/plan-inventory/{purchaseId}") + public R> getPurchasePlanMaterialInventory(@PathVariable Long purchaseId) { + List inventoryList = iMatPurchaseService.queryPurchasePlanMaterialInventory(purchaseId); + return R.ok(inventoryList); + } } diff --git a/gear-mat/src/main/java/com/gear/mat/domain/vo/MaterialInventoryVo.java b/gear-mat/src/main/java/com/gear/mat/domain/vo/MaterialInventoryVo.java new file mode 100644 index 0000000..42aea88 --- /dev/null +++ b/gear-mat/src/main/java/com/gear/mat/domain/vo/MaterialInventoryVo.java @@ -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; + } +} \ No newline at end of file diff --git a/gear-mat/src/main/java/com/gear/mat/domain/vo/PurchasePlanMaterialInventoryVo.java b/gear-mat/src/main/java/com/gear/mat/domain/vo/PurchasePlanMaterialInventoryVo.java new file mode 100644 index 0000000..ba6d1fc --- /dev/null +++ b/gear-mat/src/main/java/com/gear/mat/domain/vo/PurchasePlanMaterialInventoryVo.java @@ -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; + } +} \ No newline at end of file diff --git a/gear-mat/src/main/java/com/gear/mat/service/IMatPurchaseService.java b/gear-mat/src/main/java/com/gear/mat/service/IMatPurchaseService.java index 717122f..c378ca8 100644 --- a/gear-mat/src/main/java/com/gear/mat/service/IMatPurchaseService.java +++ b/gear-mat/src/main/java/com/gear/mat/service/IMatPurchaseService.java @@ -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 ids, Boolean isValid); + + /** + * 查询物料库存信息(当前库存和在途数量) + */ + List queryMaterialInventory(Long materialId); + + /** + * 查询采购计划中所有物料的库存信息(当前库存和在途数量) + */ + List queryPurchasePlanMaterialInventory(Long purchaseId); } diff --git a/gear-mat/src/main/java/com/gear/mat/service/impl/MatPurchaseServiceImpl.java b/gear-mat/src/main/java/com/gear/mat/service/impl/MatPurchaseServiceImpl.java index 70f8085..031443d 100644 --- a/gear-mat/src/main/java/com/gear/mat/service/impl/MatPurchaseServiceImpl.java +++ b/gear-mat/src/main/java/com/gear/mat/service/impl/MatPurchaseServiceImpl.java @@ -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 queryMaterialInventory(Long materialId) { + // 创建结果列表 + List result = new ArrayList<>(); + + // 构建查询条件 + MatPurchaseBo purchaseBo = new MatPurchaseBo(); + if (materialId != null) { + purchaseBo.setMaterialId(materialId); + } + + // 查询所有相关的采购单 + List purchaseList = queryList(purchaseBo); + + // 按物料ID分组 + Map> 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 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 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 queryPurchasePlanMaterialInventory(Long purchaseId) { + List 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 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; + } }