mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	✨ ERP:增加库存变更记录
This commit is contained in:
		@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.stock;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
@@ -56,25 +57,25 @@ public class ErpStockRecordDO extends BaseDO {
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务类型
 | 
			
		||||
     *
 | 
			
		||||
     * 枚举 {@link cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum}
 | 
			
		||||
     * 枚举 {@link ErpStockRecordBizTypeEnum}
 | 
			
		||||
     */
 | 
			
		||||
    private Integer bizType;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务编号
 | 
			
		||||
     *
 | 
			
		||||
     * 例如说:TODO
 | 
			
		||||
     * 例如说:{@link ErpStockInDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private Long bizId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务项编号
 | 
			
		||||
     *
 | 
			
		||||
     * 例如说:TODO
 | 
			
		||||
     * 例如说:{@link ErpStockInItemDO#getId()}
 | 
			
		||||
     */
 | 
			
		||||
    private Long bizItemId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务单号
 | 
			
		||||
     *
 | 
			
		||||
     * 例如说:TODO
 | 
			
		||||
     * 例如说:{@link ErpStockInDO#getNo()}
 | 
			
		||||
     */
 | 
			
		||||
    private String bizNo;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
 | 
			
		||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 | 
			
		||||
import org.apache.ibatis.annotations.Mapper;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ERP 产品库存 Mapper
 | 
			
		||||
 *
 | 
			
		||||
@@ -27,4 +30,18 @@ public interface ErpStockMapper extends BaseMapperX<ErpStockDO> {
 | 
			
		||||
                ErpStockDO::getWarehouseId, warehouseId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default int updateCountIncrement(Long id, BigDecimal count, boolean negativeEnable) {
 | 
			
		||||
        LambdaUpdateWrapper<ErpStockDO> updateWrapper = new LambdaUpdateWrapper<ErpStockDO>()
 | 
			
		||||
                .eq(ErpStockDO::getId, id);
 | 
			
		||||
        if (count.compareTo(BigDecimal.ZERO) > 0) {
 | 
			
		||||
            updateWrapper.setSql("count = count + " + count);
 | 
			
		||||
        } else if (count.compareTo(BigDecimal.ZERO) < 0) {
 | 
			
		||||
            if (!negativeEnable) {
 | 
			
		||||
                updateWrapper.gt(ErpStockDO::getCount, count.abs());
 | 
			
		||||
            }
 | 
			
		||||
            updateWrapper.setSql("count = count - " + count.abs());
 | 
			
		||||
        }
 | 
			
		||||
        return update(null, updateWrapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -13,8 +13,10 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO;
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
@@ -54,6 +56,8 @@ public class ErpStockInServiceImpl implements ErpStockInService {
 | 
			
		||||
    private ErpWarehouseService warehouseService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ErpSupplierService supplierService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ErpStockRecordService stockRecordService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
@@ -102,23 +106,31 @@ public class ErpStockInServiceImpl implements ErpStockInService {
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public void updateStockInStatus(Long id, Integer status) {
 | 
			
		||||
        boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
 | 
			
		||||
        // 1.1 校验存在
 | 
			
		||||
        ErpStockInDO stockIn = validateStockInExists(id);
 | 
			
		||||
        // 1.2 校验状态
 | 
			
		||||
        if (stockIn.getStatus().equals(status)) {
 | 
			
		||||
            throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ?
 | 
			
		||||
                    STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL);
 | 
			
		||||
            throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. 更新状态
 | 
			
		||||
        int updateCount = stockInMapper.updateByIdAndStatus(id, stockIn.getStatus(),
 | 
			
		||||
                new ErpStockInDO().setStatus(status));
 | 
			
		||||
        if (updateCount == 0) {
 | 
			
		||||
            throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ?
 | 
			
		||||
                    STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL);
 | 
			
		||||
            throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. TODO 芋艿:调整库存记录
 | 
			
		||||
        // 3. 变更库存
 | 
			
		||||
        List<ErpStockInItemDO> stockInItems = stockInItemMapper.selectListByInId(id);
 | 
			
		||||
        Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_IN.getType()
 | 
			
		||||
                : ErpStockRecordBizTypeEnum.OTHER_IN_CANCEL.getType();
 | 
			
		||||
        stockInItems.forEach(stockInItem -> {
 | 
			
		||||
            BigDecimal count = approve ? stockInItem.getCount() : stockInItem.getCount().negate();
 | 
			
		||||
            stockRecordService.createStockRecord(new ErpStockInCreateReqBO(
 | 
			
		||||
                    stockInItem.getProductId(), stockInItem.getWarehouseId(), count,
 | 
			
		||||
                    bizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo()));
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<ErpStockInItemDO> validateStockInItems(List<ErpStockInSaveReqVO.Item> list) {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.erp.service.stock;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO;
 | 
			
		||||
import jakarta.validation.Valid;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ERP 产品库存明细 Service 接口
 | 
			
		||||
@@ -27,4 +29,11 @@ public interface ErpStockRecordService {
 | 
			
		||||
     */
 | 
			
		||||
    PageResult<ErpStockRecordDO> getStockRecordPage(ErpStockRecordPageReqVO pageReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建库存明细
 | 
			
		||||
     *
 | 
			
		||||
     * @param createReqBO 创建库存明细 BO
 | 
			
		||||
     */
 | 
			
		||||
    void createStockRecord(@Valid ErpStockInCreateReqBO createReqBO);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,18 @@
 | 
			
		||||
package cn.iocoder.yudao.module.erp.service.stock;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO;
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ERP 产品库存明细 Service 实现类
 | 
			
		||||
 *
 | 
			
		||||
@@ -20,6 +25,9 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ErpStockRecordMapper stockRecordMapper;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ErpStockService stockService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ErpStockRecordDO getStockRecord(Long id) {
 | 
			
		||||
        return stockRecordMapper.selectById(id);
 | 
			
		||||
@@ -30,4 +38,16 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService {
 | 
			
		||||
        return stockRecordMapper.selectPage(pageReqVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public void createStockRecord(ErpStockInCreateReqBO createReqBO) {
 | 
			
		||||
        // 1. 更新库存
 | 
			
		||||
        BigDecimal totalCount = stockService.updateStockCountIncrement(
 | 
			
		||||
                createReqBO.getProductId(), createReqBO.getWarehouseId(), createReqBO.getCount());
 | 
			
		||||
        // 2. 创建库存明细
 | 
			
		||||
        ErpStockRecordDO stockRecord = BeanUtils.toBean(createReqBO, ErpStockRecordDO.class)
 | 
			
		||||
                .setTotalCount(totalCount);
 | 
			
		||||
        stockRecordMapper.insert(stockRecord);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ERP 产品库存 Service 接口
 | 
			
		||||
 *
 | 
			
		||||
@@ -36,4 +38,14 @@ public interface ErpStockService {
 | 
			
		||||
     */
 | 
			
		||||
    PageResult<ErpStockDO> getStockPage(ErpStockPageReqVO pageReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 增量更新产品库存数量
 | 
			
		||||
     *
 | 
			
		||||
     * @param productId 产品编号
 | 
			
		||||
     * @param warehouseId 仓库编号
 | 
			
		||||
     * @param count 增量数量:正数,表示增加;负数,表示减少
 | 
			
		||||
     * @return 更新后的库存
 | 
			
		||||
     */
 | 
			
		||||
    BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -8,6 +8,12 @@ import jakarta.annotation.Resource;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE;
 | 
			
		||||
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE2;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ERP 产品库存 Service 实现类
 | 
			
		||||
 *
 | 
			
		||||
@@ -17,6 +23,13 @@ import org.springframework.validation.annotation.Validated;
 | 
			
		||||
@Validated
 | 
			
		||||
public class ErpStockServiceImpl implements ErpStockService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 允许库存为负数
 | 
			
		||||
     *
 | 
			
		||||
     * TODO 芋艿:后续做成 db 配置
 | 
			
		||||
     */
 | 
			
		||||
    private static final Boolean NEGATIVE_STOCK_COUNT_ENABLE = false;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ErpStockMapper stockMapper;
 | 
			
		||||
 | 
			
		||||
@@ -35,4 +48,27 @@ public class ErpStockServiceImpl implements ErpStockService {
 | 
			
		||||
        return stockMapper.selectPage(pageReqVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count) {
 | 
			
		||||
        // 1.1 查询当前库存
 | 
			
		||||
        ErpStockDO stock = stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId);
 | 
			
		||||
        if (stock == null) {
 | 
			
		||||
            stock = new ErpStockDO().setProductId(productId).setWarehouseId(warehouseId).setCount(BigDecimal.ZERO);
 | 
			
		||||
            stockMapper.insert(stock);
 | 
			
		||||
        }
 | 
			
		||||
        // 1.2 校验库存是否充足
 | 
			
		||||
        if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) {
 | 
			
		||||
            throw exception(STOCK_COUNT_NEGATIVE, stock.getCount(), count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. 库存变更
 | 
			
		||||
        int updateCount = stockMapper.updateCountIncrement(stock.getId(), count, NEGATIVE_STOCK_COUNT_ENABLE);
 | 
			
		||||
        if (updateCount == 0) {
 | 
			
		||||
            throw exception(STOCK_COUNT_NEGATIVE2); // 此时不好去查询最新库存,所以直接抛出该提示,不提供具体库存数字
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. 返回最新库存
 | 
			
		||||
        return stock.getCount().add(count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,59 @@
 | 
			
		||||
package cn.iocoder.yudao.module.erp.service.stock.bo;
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.math.BigDecimal;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 库存明细的创建 Request BO
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class ErpStockInCreateReqBO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 产品编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "产品编号不能为空")
 | 
			
		||||
    private Long productId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 仓库编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "仓库编号不能为空")
 | 
			
		||||
    private Long warehouseId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 出入库数量
 | 
			
		||||
     *
 | 
			
		||||
     * 正数,表示入库;负数,表示出库
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "出入库数量不能为空")
 | 
			
		||||
    private BigDecimal count;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务类型
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "业务类型不能为空")
 | 
			
		||||
    private Integer bizType;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "业务编号不能为空")
 | 
			
		||||
    private Long bizId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务项编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "业务项编号不能为空")
 | 
			
		||||
    private Long bizItemId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 业务单号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "业务单号不能为空")
 | 
			
		||||
    private String bizNo;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user