package cn.iocoder.yudao.module.mes.service.wm.stockreserve;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stockreserve.MesWmStockReserveDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.wm.stockreserve.MesWmStockReserveMapper;
|
import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockReserveStatusEnum;
|
import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.math.BigDecimal;
|
import java.util.List;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
|
/**
|
* MES 库存占用 Service 实现类
|
*/
|
@Service
|
@Validated
|
@Slf4j
|
public class MesWmStockReserveServiceImpl implements MesWmStockReserveService {
|
|
@Resource
|
private MesWmStockReserveMapper stockReserveMapper;
|
|
@Resource
|
private MesWmMaterialStockMapper materialStockMapper;
|
|
@Resource
|
private MesWmMaterialStockService materialStockService;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void createReserve(Long materialStockId, Integer bizType, Long bizId, String bizCode, Long bizLineId, Long itemId, BigDecimal quantity) {
|
// 1. 校验库存记录存在
|
MesWmMaterialStockDO stock = materialStockService.getMaterialStock(materialStockId);
|
if (stock == null) {
|
throw exception(WM_MATERIAL_STOCK_NOT_EXISTS);
|
}
|
|
// 2. 校验可用量充足(在库数量 - 冻结数量 - 已占用量 >= 本次占用数量)
|
BigDecimal availableQty = stock.getQuantity()
|
.subtract(stock.getFrozenQuantity() != null ? stock.getFrozenQuantity() : BigDecimal.ZERO)
|
.subtract(stock.getReservedQuantity() != null ? stock.getReservedQuantity() : BigDecimal.ZERO);
|
if (availableQty.compareTo(quantity) < 0) {
|
throw exception(WM_MATERIAL_STOCK_INSUFFICIENT);
|
}
|
|
// 3. 创建占用记录
|
MesWmStockReserveDO reserve = MesWmStockReserveDO.builder()
|
.materialStockId(materialStockId)
|
.bizType(bizType)
|
.bizId(bizId)
|
.bizCode(bizCode)
|
.bizLineId(bizLineId)
|
.itemId(itemId)
|
.quantity(quantity)
|
.status(MesWmStockReserveStatusEnum.RESERVING.getStatus())
|
.build();
|
stockReserveMapper.insert(reserve);
|
|
// 4. 更新库存占用量字段(累加)
|
int updatedRows = materialStockMapper.updateReservedQuantity(materialStockId, quantity, true);
|
if (updatedRows == 0) {
|
throw exception(WM_MATERIAL_STOCK_INSUFFICIENT);
|
}
|
|
log.info("[createReserve] 创建库存占用成功,materialStockId={}, bizType={}, bizId={}, quantity={}",
|
materialStockId, bizType, bizId, quantity);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void createReserveBatch(List<ReserveInfo> reserves) {
|
if (CollUtil.isEmpty(reserves)) {
|
return;
|
}
|
for (ReserveInfo reserve : reserves) {
|
createReserve(reserve.materialStockId(), reserve.bizType(), reserve.bizId(),
|
reserve.bizCode(), reserve.bizLineId(), reserve.itemId(), reserve.quantity());
|
}
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void releaseReserve(Integer bizType, Long bizId) {
|
// 1. 查询占用中的记录
|
List<MesWmStockReserveDO> reserveList = stockReserveMapper.selectReservingListByBiz(bizType, bizId);
|
if (CollUtil.isEmpty(reserveList)) {
|
log.warn("[releaseReserve] 未找到占用记录,bizType={}, bizId={}", bizType, bizId);
|
return;
|
}
|
|
// 2. 更新占用记录状态为已释放,并扣减库存占用量字段
|
for (MesWmStockReserveDO reserve : reserveList) {
|
// 2.1 更新占用记录状态
|
stockReserveMapper.updateById(new MesWmStockReserveDO()
|
.setId(reserve.getId())
|
.setStatus(MesWmStockReserveStatusEnum.RELEASED.getStatus()));
|
|
// 2.2 扣减库存占用量(负数表示减少)
|
materialStockMapper.updateReservedQuantity(reserve.getMaterialStockId(), reserve.getQuantity().negate(), false);
|
}
|
|
log.info("[releaseReserve] 释放库存占用成功,bizType={}, bizId={}, count={}", bizType, bizId, reserveList.size());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void confirmReserveToOutbound(Integer bizType, Long bizId) {
|
// 1. 查询占用中的记录
|
List<MesWmStockReserveDO> reserveList = stockReserveMapper.selectReservingListByBiz(bizType, bizId);
|
if (CollUtil.isEmpty(reserveList)) {
|
log.warn("[confirmReserveToOutbound] 未找到占用记录,bizType={}, bizId={}", bizType, bizId);
|
return;
|
}
|
|
// 2. 更新占用记录状态为已出库,并扣减库存占用量字段
|
for (MesWmStockReserveDO reserve : reserveList) {
|
// 2.1 更新占用记录状态
|
stockReserveMapper.updateById(new MesWmStockReserveDO()
|
.setId(reserve.getId())
|
.setStatus(MesWmStockReserveStatusEnum.OUTBOUND.getStatus()));
|
|
// 2.2 扣减库存占用量(负数表示减少)
|
materialStockMapper.updateReservedQuantity(reserve.getMaterialStockId(), reserve.getQuantity().negate(), false);
|
}
|
|
log.info("[confirmReserveToOutbound] 确认占用转出库成功,bizType={}, bizId={}, count={}", bizType, bizId, reserveList.size());
|
}
|
|
@Override
|
public List<MesWmStockReserveDO> getReserveListByBiz(Integer bizType, Long bizId) {
|
return stockReserveMapper.selectListByBiz(bizType, bizId);
|
}
|
|
@Override
|
public BigDecimal sumReservedQuantity(Long itemId, Long warehouseId) {
|
if (warehouseId != null) {
|
return stockReserveMapper.sumReservedQuantityByItemAndWarehouse(itemId, warehouseId);
|
}
|
return stockReserveMapper.sumReservedQuantityByItem(itemId);
|
}
|
|
}
|