Files
klp-oa/klp-wms/src/main/java/com/klp/service/impl/WmsStockServiceImpl.java
2025-11-11 23:01:18 +08:00

291 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.klp.common.core.page.TableDataInfo;
import com.klp.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.klp.common.utils.StringUtils;
import com.klp.domain.WmsActualWarehouse;
import com.klp.mapper.WmsActualWarehouseMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsStockBo;
import com.klp.domain.vo.WmsStockVo;
import com.klp.domain.WmsStock;
import com.klp.domain.WmsWarehouse;
import com.klp.mapper.WmsStockMapper;
import com.klp.mapper.WmsWarehouseMapper;
import com.klp.service.IWmsStockService;
import java.math.BigDecimal;
import java.util.*;
/**
* 库存:原材料/产品与库区/库位的存放关系Service业务层处理
*
* @author Joshi
* @date 2025-07-18
*/
@RequiredArgsConstructor
@Service
public class WmsStockServiceImpl implements IWmsStockService {
private final WmsStockMapper baseMapper;
private final WmsWarehouseMapper warehouseMapper;
private final WmsActualWarehouseMapper actualWarehouseMapper;
/**
* 查询库存:原材料/产品与库区/库位的存放关系
*/
@Override
public WmsStockVo queryById(Long stockId){
return baseMapper.selectVoById(stockId);
}
/**
* 查询库存:原材料/产品与库区/库位的存放关系列表
*/
@Override
public TableDataInfo<WmsStockVo> queryPageList(WmsStockBo bo, PageQuery pageQuery) {
QueryWrapper<WmsStock> lqw = buildQueryWrapperPlus(bo);
Page<WmsStockVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public TableDataInfo<WmsStockVo> queryPageListActual(WmsStockBo bo, PageQuery pageQuery) {
QueryWrapper<WmsStock> lqw = buildQueryWrapperPlusActual(bo);
Page<WmsStockVo> result = baseMapper.selectVoPagePlusActual(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
private QueryWrapper<WmsStock> buildQueryWrapperPlusActual(WmsStockBo bo) { // 注意:这里改用 QueryWrapper 而非 LambdaQueryWrapper
QueryWrapper<WmsStock> qw = Wrappers.query(); // 使用普通 QueryWrapper
// 固定条件:未删除的现存数据
qw.eq("mc.del_flag", 0);
qw.eq("mc.data_type", 1);
qw.eq("mc.status", 0);
qw.eq("mc.material_type", "成品").or().eq("mc.product_type", "原料");
// 处理仓库ID查询支持递归查询子节点
if (bo.getActualWarehouseId() != null) {
List<Long> warehouseIds = getActualWarehouseIdsWithChildren(bo.getActualWarehouseId());
if (warehouseIds.size() == 1) {
qw.eq("mc.actual_warehouse_id", warehouseIds.get(0));
} else {
qw.in("mc.actual_warehouse_id", warehouseIds);
}
}
qw.eq(StringUtils.isNotBlank(bo.getItemType()), "mc.item_type", bo.getItemType());
qw.eq(bo.getItemId() != null, "mc.item_id", bo.getItemId());
qw.like(StringUtils.isNotBlank(bo.getBatchNo()), "mc.enter_coil_no", bo.getBatchNo());
// 使用 groupBy 进行分组
qw.groupBy(
"mc.actual_warehouse_id",
"mc.item_type",
"mc.item_id",
"w.actual_warehouse_name",
"CASE WHEN mc.item_type = 'product' THEN p.product_name WHEN mc.item_type = 'raw_material' THEN r.raw_material_name ELSE NULL END",
"CASE WHEN mc.item_type = 'product' THEN p.product_code WHEN mc.item_type = 'raw_material' THEN r.raw_material_code ELSE NULL END"
);
return qw;
}
private List<Long> getActualWarehouseIdsWithChildren(Long actualWarehouseId) {
List<Long> actualWarehouseIds = new ArrayList<>();
actualWarehouseIds.add(actualWarehouseId); // 添加当前仓库ID
// 递归获取所有子仓库ID
getChildActualWarehouseIds(actualWarehouseId,actualWarehouseIds);
return actualWarehouseIds;
}
private void getChildActualWarehouseIds(Long parentId, List<Long> actualWarehouseIds) {
// 查询直接子仓库
List<WmsActualWarehouse> children = actualWarehouseMapper.selectList(
Wrappers.<WmsActualWarehouse>lambdaQuery()
.eq(WmsActualWarehouse::getActualParentId, parentId)
.eq(WmsActualWarehouse::getDelFlag, 0)
);
// 递归处理每个子仓库
for (WmsActualWarehouse child : children) {
actualWarehouseIds.add(child.getActualWarehouseId());
getChildActualWarehouseIds(child.getActualWarehouseId(), actualWarehouseIds);
}
}
/**
* 查询库存:原材料/产品与库区/库位的存放关系列表
*/
@Override
public List<WmsStockVo> queryList(WmsStockBo bo) {
LambdaQueryWrapper<WmsStock> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsStock> buildQueryWrapper(WmsStockBo bo) {
LambdaQueryWrapper<WmsStock> lqw = new LambdaQueryWrapper<>();
lqw.eq(StringUtils.isNotBlank(bo.getItemType()), WmsStock::getItemType, bo.getItemType());
lqw.eq(bo.getItemId() != null, WmsStock::getItemId, bo.getItemId());
lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), WmsStock::getBatchNo, bo.getBatchNo());
return lqw;
}
private QueryWrapper<WmsStock> buildQueryWrapperPlus(WmsStockBo bo) { // 注意:这里改用 QueryWrapper 而非 LambdaQueryWrapper
QueryWrapper<WmsStock> qw = Wrappers.query(); // 使用普通 QueryWrapper
// 固定条件:未删除的现存数据
qw.eq("mc.del_flag", 0);
qw.eq("mc.data_type", 1);
// 处理仓库ID查询支持递归查询子节点
if (bo.getWarehouseId() != null) {
List<Long> warehouseIds = getWarehouseIdsWithChildren(bo.getWarehouseId());
if (warehouseIds.size() == 1) {
qw.eq("mc.warehouse_id", warehouseIds.get(0));
} else {
qw.in("mc.warehouse_id", warehouseIds);
}
}
qw.eq(StringUtils.isNotBlank(bo.getItemType()), "mc.item_type", bo.getItemType());
qw.eq(bo.getItemId() != null, "mc.item_id", bo.getItemId());
qw.like(StringUtils.isNotBlank(bo.getBatchNo()), "mc.enter_coil_no", bo.getBatchNo());
// 使用 groupBy 进行分组
qw.groupBy(
"mc.warehouse_id",
"mc.item_type",
"mc.item_id",
"w.warehouse_name",
"CASE WHEN mc.item_type = 'product' THEN p.product_name WHEN mc.item_type = 'raw_material' THEN r.raw_material_name ELSE NULL END",
"CASE WHEN mc.item_type = 'product' THEN p.product_code WHEN mc.item_type = 'raw_material' THEN r.raw_material_code ELSE NULL END"
);
return qw;
}
/**
* 新增库存:原材料/产品与库区/库位的存放关系
*/
@Override
public Boolean insertByBo(WmsStockBo bo) {
WmsStock add = BeanUtil.toBean(bo, WmsStock.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setStockId(add.getStockId());
}
return flag;
}
/**
* 修改库存:原材料/产品与库区/库位的存放关系
*/
@Override
public Boolean updateByBo(WmsStockBo bo) {
WmsStock update = BeanUtil.toBean(bo, WmsStock.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsStock entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除库存:原材料/产品与库区/库位的存放关系
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public BigDecimal getStockByItemId(Long rawMaterialId) {
return baseMapper.getStockByItemId(rawMaterialId);
}
/**
* 查询库存分布(按仓库统计)
*/
@Override
public WmsStockVo queryStockDistribution(WmsStockBo bo) {
if (bo.getItemType() == null || bo.getItemId() == null) {
throw new RuntimeException("物品类型和物品ID不能为空");
}
// 1. 计算总库存量
BigDecimal totalQuantity = BigDecimal.ZERO;
// 2. 按仓库统计库存分布
List<WmsStockVo> distributionList = baseMapper.selectStockDistribution(bo.getItemType(), bo.getItemId());
// 计算总量
for (WmsStockVo vo : distributionList) {
if (vo.getTotalQuantity() != null) {
totalQuantity = totalQuantity.add(vo.getTotalQuantity());
}
}
// 构建返回对象
WmsStockVo result = new WmsStockVo();
result.setItemType(bo.getItemType());
result.setItemId(bo.getItemId());
result.setTotalQuantity(totalQuantity);
result.setStockDistribution(distributionList);
return result;
}
/**
* 获取指定仓库ID及其所有子仓库ID
* @param warehouseId 仓库ID
* @return 包含当前仓库ID和所有子仓库ID的列表
*/
private List<Long> getWarehouseIdsWithChildren(Long warehouseId) {
List<Long> warehouseIds = new ArrayList<>();
warehouseIds.add(warehouseId); // 添加当前仓库ID
// 递归获取所有子仓库ID
getChildWarehouseIds(warehouseId, warehouseIds);
return warehouseIds;
}
/**
* 递归获取子仓库ID
* @param parentId 父仓库ID
* @param warehouseIds 仓库ID列表用于收集结果
*/
private void getChildWarehouseIds(Long parentId, List<Long> warehouseIds) {
// 查询直接子仓库
List<WmsWarehouse> children = warehouseMapper.selectList(
Wrappers.<WmsWarehouse>lambdaQuery()
.eq(WmsWarehouse::getParentId, parentId)
.eq(WmsWarehouse::getDelFlag, 0)
);
// 递归处理每个子仓库
for (WmsWarehouse child : children) {
warehouseIds.add(child.getWarehouseId());
getChildWarehouseIds(child.getWarehouseId(), warehouseIds);
}
}
}