mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	秒杀活动:完成订单取消时恢复活动库存和商品库存
This commit is contained in:
		| @@ -10,13 +10,22 @@ import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinResp | ||||
| public interface SeckillActivityApi { | ||||
|  | ||||
|     /** | ||||
|      * 更新秒杀库存 | ||||
|      * 更新秒杀库存(减少) | ||||
|      * | ||||
|      * @param id 活动编号 | ||||
|      * @param skuId      sku 编号 | ||||
|      * @param count      数量 | ||||
|      * @param id    活动编号 | ||||
|      * @param skuId sku 编号 | ||||
|      * @param count 数量(正数) | ||||
|      */ | ||||
|     void updateSeckillStock(Long id, Long skuId, Integer count); | ||||
|     void updateSeckillStockDecr(Long id, Long skuId, Integer count); | ||||
|  | ||||
|     /** | ||||
|      * 更新秒杀库存(增加) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param skuId sku 编号 | ||||
|      * @param count 数量(正数) | ||||
|      */ | ||||
|     void updateSeckillStockIncr(Long id, Long skuId, Integer count); | ||||
|  | ||||
|     /** | ||||
|      * 【下单前】校验是否参与秒杀活动 | ||||
| @@ -24,8 +33,8 @@ public interface SeckillActivityApi { | ||||
|      * 如果校验失败,则抛出业务异常 | ||||
|      * | ||||
|      * @param activityId 活动编号 | ||||
|      * @param skuId SKU 编号 | ||||
|      * @param count 数量 | ||||
|      * @param skuId      SKU 编号 | ||||
|      * @param count      数量 | ||||
|      * @return 秒杀信息 | ||||
|      */ | ||||
|     SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); | ||||
|   | ||||
| @@ -18,8 +18,13 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | ||||
|     private SeckillActivityService activityService; | ||||
|  | ||||
|     @Override | ||||
|     public void updateSeckillStock(Long id, Long skuId, Integer count) { | ||||
|         activityService.updateSeckillStock(id, skuId, count); | ||||
|     public void updateSeckillStockDecr(Long id, Long skuId, Integer count) { | ||||
|         activityService.updateSeckillStockDecr(id, skuId, count); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { | ||||
|         activityService.updateSeckillStockIncr(id, skuId, count); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -77,7 +77,8 @@ public class SeckillActivityDO extends BaseDO { | ||||
|     private Integer singleLimitCount; | ||||
|  | ||||
|     /** | ||||
|      * 秒杀库存(剩余库存秒杀时扣减) | ||||
|      * 秒杀库存-秒杀下单时怎加,恢复库存是减少 | ||||
|      * 也就是说这个是记录当前秒杀活动用户购买的商品数量和 | ||||
|      */ | ||||
|     private Integer stock; | ||||
|     /** | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; | ||||
|  | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| @@ -39,13 +40,14 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 更新活动库存 | ||||
|      * 更新活动库存(减少) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param count 扣减的库存数量 | ||||
|      * @param count 扣减的库存数量(正数) | ||||
|      * @return 影响的行数 | ||||
|      */ | ||||
|     default int updateStock(Long id, int count) { | ||||
|     default int updateStockDecr(Long id, int count) { | ||||
|         Assert.isTrue(count > 0); | ||||
|         return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() | ||||
|                 .eq(SeckillActivityDO::getId, id) | ||||
|                 .gt(SeckillActivityDO::getTotalStock, 0) | ||||
| @@ -53,6 +55,21 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||||
|                 .setSql("total_stock = total_stock - " + count)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 更新活动库存(增加) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param count 增加的库存数量(正数) | ||||
|      * @return 影响的行数 | ||||
|      */ | ||||
|     default int updateStockIncr(Long id, int count) { | ||||
|         Assert.isTrue(count > 0); | ||||
|         return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() | ||||
|                 .eq(SeckillActivityDO::getId, id) | ||||
|                 .setSql("stock = stock - " + count) | ||||
|                 .setSql("total_stock = total_stock + " + count)); | ||||
|     } | ||||
|  | ||||
|     default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) { | ||||
|         return selectPage(pageReqVO, new LambdaQueryWrapperX<SeckillActivityDO>() | ||||
|                 .eqIfPresent(SeckillActivityDO::getStatus, status) | ||||
| @@ -62,6 +79,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||||
|  | ||||
|     /** | ||||
|      * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 | ||||
|      * | ||||
|      * @param spuIds spu 编号 | ||||
|      * @param status 状态 | ||||
|      * @return 包含 spuId 和 activityId 的 map 对象列表 | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; | ||||
|  | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; | ||||
| import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||||
| @@ -30,17 +31,32 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 更新活动库存 | ||||
|      * 更新活动库存(减少) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param count 扣减的库存数量 | ||||
|      * @param count 扣减的库存数量(减少库存) | ||||
|      * @return 影响的行数 | ||||
|      */ | ||||
|     default int updateStock(Long id, int count) { | ||||
|     default int updateStockDecr(Long id, int count) { | ||||
|         Assert.isTrue(count > 0); | ||||
|         return update(null, new LambdaUpdateWrapper<SeckillProductDO>() | ||||
|                 .eq(SeckillProductDO::getId, id) | ||||
|                 .gt(SeckillProductDO::getStock, count) | ||||
|                 .setSql("stock = stock - " + count)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 更新活动库存(增加) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param count 需要增加的库存(增加库存) | ||||
|      * @return 影响的行数 | ||||
|      */ | ||||
|     default int updateStockIncr(Long id, int count) { | ||||
|         Assert.isTrue(count > 0); | ||||
|         return update(null, new LambdaUpdateWrapper<SeckillProductDO>() | ||||
|                 .eq(SeckillProductDO::getId, id) | ||||
|                 .setSql("stock = stock + " + count)); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -36,13 +36,22 @@ public interface SeckillActivityService { | ||||
|     void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 更新秒杀库存 | ||||
|      * 更新秒杀库存(减少) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param skuId sku 编号 | ||||
|      * @param count 数量 | ||||
|      * @param count 数量(正数) | ||||
|      */ | ||||
|     void updateSeckillStock(Long id, Long skuId, Integer count); | ||||
|     void updateSeckillStockDecr(Long id, Long skuId, Integer count); | ||||
|  | ||||
|     /** | ||||
|      * 更新秒杀库存(增加) | ||||
|      * | ||||
|      * @param id    活动编号 | ||||
|      * @param skuId sku 编号 | ||||
|      * @param count 数量(正数) | ||||
|      */ | ||||
|     void updateSeckillStockIncr(Long id, Long skuId, Integer count); | ||||
|  | ||||
|     /** | ||||
|      * 关闭秒杀活动 | ||||
| @@ -113,8 +122,8 @@ public interface SeckillActivityService { | ||||
|      * 如果校验失败,则抛出业务异常 | ||||
|      * | ||||
|      * @param activityId 活动编号 | ||||
|      * @param skuId SKU 编号 | ||||
|      * @param count 数量 | ||||
|      * @param skuId      SKU 编号 | ||||
|      * @param count      数量 | ||||
|      * @return 秒杀信息 | ||||
|      */ | ||||
|     SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); | ||||
|   | ||||
| @@ -157,7 +157,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void updateSeckillStock(Long id, Long skuId, Integer count) { | ||||
|     public void updateSeckillStockDecr(Long id, Long skuId, Integer count) { | ||||
|         // 1.1 校验活动库存是否充足 | ||||
|         SeckillActivityDO seckillActivity = validateSeckillActivityExists(id); | ||||
|         if (count > seckillActivity.getTotalStock()) { | ||||
| @@ -170,18 +170,28 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||||
|         } | ||||
|  | ||||
|         // 2.1 更新活动商品库存 | ||||
|         int updateCount = seckillProductMapper.updateStock(product.getId(), count); | ||||
|         int updateCount = seckillProductMapper.updateStockDecr(product.getId(), count); | ||||
|         if (updateCount == 0) { | ||||
|             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||||
|         } | ||||
|  | ||||
|         // 2.2 更新活动库存 | ||||
|         updateCount = seckillActivityMapper.updateStock(seckillActivity.getId(), count); | ||||
|         updateCount = seckillActivityMapper.updateStockDecr(seckillActivity.getId(), count); | ||||
|         if (updateCount == 0) { | ||||
|             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { | ||||
|         SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); | ||||
|         // 更新活动商品库存 | ||||
|         seckillProductMapper.updateStockIncr(product.getId(), count); | ||||
|         // 更新活动库存 | ||||
|         seckillActivityMapper.updateStockIncr(id, count); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 更新秒杀商品 | ||||
|      * | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.trade.service.order.handler; | ||||
|  | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; | ||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||||
| @@ -25,9 +26,11 @@ public class TradeSeckillHandler implements TradeOrderHandler { | ||||
|         if (TradeOrderTypeEnum.isSeckill(order.getType())) { | ||||
|             return; | ||||
|         } | ||||
|         // 明确校验一下 | ||||
|         Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); | ||||
|  | ||||
|         // 扣减秒杀活动的库存 | ||||
|         seckillActivityApi.updateSeckillStock(order.getSeckillActivityId(), | ||||
|         seckillActivityApi.updateSeckillStockDecr(order.getSeckillActivityId(), | ||||
|                 orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); | ||||
|     } | ||||
|  | ||||
| @@ -36,7 +39,12 @@ public class TradeSeckillHandler implements TradeOrderHandler { | ||||
|         if (TradeOrderTypeEnum.isSeckill(order.getType())) { | ||||
|             return; | ||||
|         } | ||||
|         // 明确校验一下 | ||||
|         Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); | ||||
|  | ||||
|         // 恢复秒杀活动的库存 | ||||
|         seckillActivityApi.updateSeckillStockIncr(order.getSeckillActivityId(), | ||||
|                 orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 puhui999
					puhui999