mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10: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
	 YunaiV
					YunaiV