From 245f14b8f1f4e6b5f1cf38db55a6f81505da11c7 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 10 Oct 2023 10:25:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=92=E6=9D=80=E6=B4=BB=E5=8A=A8=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E8=AE=A2=E5=8D=95=E5=8F=96=E6=B6=88=E6=97=B6?= =?UTF-8?q?=E6=81=A2=E5=A4=8D=E6=B4=BB=E5=8A=A8=E5=BA=93=E5=AD=98=E5=92=8C?= =?UTF-8?q?=E5=95=86=E5=93=81=E5=BA=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/seckill/SeckillActivityApi.java | 23 ++++++++++++------ .../api/seckill/SeckillActivityApiImpl.java | 9 +++++-- .../dataobject/seckill/SeckillActivityDO.java | 3 ++- .../SeckillActivityMapper.java | 24 ++++++++++++++++--- .../seckillactivity/SeckillProductMapper.java | 22 ++++++++++++++--- .../seckill/SeckillActivityService.java | 19 +++++++++++---- .../seckill/SeckillActivityServiceImpl.java | 16 ++++++++++--- .../order/handler/TradeSeckillHandler.java | 10 +++++++- 8 files changed, 101 insertions(+), 25 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java index 11b75e03c..0d65919d1 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java @@ -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); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java index 239cdf4ba..45e2d4698 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java @@ -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 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/SeckillActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/SeckillActivityDO.java index 76a08ac70..67d074903 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/SeckillActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/SeckillActivityDO.java @@ -77,7 +77,8 @@ public class SeckillActivityDO extends BaseDO { private Integer singleLimitCount; /** - * 秒杀库存(剩余库存秒杀时扣减) + * 秒杀库存-秒杀下单时怎加,恢复库存是减少 + * 也就是说这个是记录当前秒杀活动用户购买的商品数量和 */ private Integer stock; /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java index 75c26119f..e2d33991c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java @@ -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 { } /** - * 更新活动库存 + * 更新活动库存(减少) * * @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() .eq(SeckillActivityDO::getId, id) .gt(SeckillActivityDO::getTotalStock, 0) @@ -53,6 +55,21 @@ public interface SeckillActivityMapper extends BaseMapperX { .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() + .eq(SeckillActivityDO::getId, id) + .setSql("stock = stock - " + count) + .setSql("total_stock = total_stock + " + count)); + } + default PageResult selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eqIfPresent(SeckillActivityDO::getStatus, status) @@ -62,6 +79,7 @@ public interface SeckillActivityMapper extends BaseMapperX { /** * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 + * * @param spuIds spu 编号 * @param status 状态 * @return 包含 spuId 和 activityId 的 map 对象列表 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java index 35ea110ce..8e1692415 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java @@ -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 { } /** - * 更新活动库存 + * 更新活动库存(减少) * * @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() .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() + .eq(SeckillProductDO::getId, id) + .setSql("stock = stock + " + count)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index f71c538a8..36074fd56 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -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); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 4b35161a5..6d86bd517 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -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); + } + /** * 更新秒杀商品 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java index b9bd3e4bd..77934cb17 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java @@ -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()); } }