Commit 57f0ea04f72fb4ebe68d4bc1d7a3bee38e3aca09
1 parent
c023209a
mall-order: 完善活动商品库存扣减逻辑(并发更新库存下一提交实现)
Showing
10 changed files
with
104 additions
and
121 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java
| @@ -10,9 +10,9 @@ public interface BargainActivityApi { | @@ -10,9 +10,9 @@ public interface BargainActivityApi { | ||
| 10 | /** | 10 | /** |
| 11 | * 更新砍价活动库存 | 11 | * 更新砍价活动库存 |
| 12 | * | 12 | * |
| 13 | - * @param activityId 砍价活动编号 | 13 | + * @param id 砍价活动编号 |
| 14 | * @param count 购买数量 | 14 | * @param count 购买数量 |
| 15 | */ | 15 | */ |
| 16 | - void updateBargainActivityStock(Long activityId, Integer count); | 16 | + void updateBargainActivityStock(Long id, Integer count); |
| 17 | 17 | ||
| 18 | } | 18 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
| @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto; | @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto; | ||
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | 4 | ||
| 5 | -import java.util.List; | 5 | +import javax.validation.constraints.NotNull; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | * 更新秒杀库存 request DTO | 8 | * 更新秒杀库存 request DTO |
| @@ -12,37 +12,25 @@ import java.util.List; | @@ -12,37 +12,25 @@ import java.util.List; | ||
| 12 | @Data | 12 | @Data |
| 13 | public class SeckillActivityUpdateStockReqDTO { | 13 | public class SeckillActivityUpdateStockReqDTO { |
| 14 | 14 | ||
| 15 | - // TODO @puhui999:参数校验 | ||
| 16 | - | ||
| 17 | - // TODO @puhui999:秒杀的话,一次只能购买一种商品哈;不能多个哈; | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | - * 活动编号 | ||
| 21 | - */ | 15 | + @NotNull(message = "活动编号不能为空") |
| 22 | private Long activityId; | 16 | private Long activityId; |
| 23 | - /** | ||
| 24 | - * 总购买数量 | ||
| 25 | - */ | 17 | + |
| 18 | + @NotNull(message = "购买数量不能为空") | ||
| 26 | private Integer count; | 19 | private Integer count; |
| 27 | - /** | ||
| 28 | - * 活动商品 | ||
| 29 | - */ | ||
| 30 | - private List<Item> items; | 20 | + |
| 21 | + @NotNull(message = "活动商品不能为空") | ||
| 22 | + private Item item; | ||
| 31 | 23 | ||
| 32 | @Data | 24 | @Data |
| 33 | public static class Item { | 25 | public static class Item { |
| 34 | 26 | ||
| 35 | - /** | ||
| 36 | - * SPU 编号 | ||
| 37 | - */ | 27 | + @NotNull(message = "SPU 编号不能为空") |
| 38 | private Long spuId; | 28 | private Long spuId; |
| 39 | - /** | ||
| 40 | - * SKU 编号 | ||
| 41 | - */ | 29 | + |
| 30 | + @NotNull(message = "SKU 编号活动商品不能为空") | ||
| 42 | private Long skuId; | 31 | private Long skuId; |
| 43 | - /** | ||
| 44 | - * 购买数量 | ||
| 45 | - */ | 32 | + |
| 33 | + @NotNull(message = "购买数量不能为空") | ||
| 46 | private Integer count; | 34 | private Integer count; |
| 47 | 35 | ||
| 48 | } | 36 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApiImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.api.bargain; | 1 | package cn.iocoder.yudao.module.promotion.api.bargain; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO; | ||
| 4 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | ||
| 5 | import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; | 3 | import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; |
| 6 | import org.springframework.stereotype.Service; | 4 | import org.springframework.stereotype.Service; |
| 7 | 5 | ||
| 8 | import javax.annotation.Resource; | 6 | import javax.annotation.Resource; |
| 9 | 7 | ||
| 10 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 11 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.BARGAIN_ACTIVITY_NOT_EXISTS; | ||
| 12 | - | ||
| 13 | /** | 8 | /** |
| 14 | * 砍价活动 Api 接口实现类 | 9 | * 砍价活动 Api 接口实现类 |
| 15 | * | 10 | * |
| @@ -22,20 +17,8 @@ public class BargainActivityApiImpl implements BargainActivityApi { | @@ -22,20 +17,8 @@ public class BargainActivityApiImpl implements BargainActivityApi { | ||
| 22 | private BargainActivityService bargainActivityService; | 17 | private BargainActivityService bargainActivityService; |
| 23 | 18 | ||
| 24 | @Override | 19 | @Override |
| 25 | - public void updateBargainActivityStock(Long activityId, Integer count) { | ||
| 26 | - // TODO @puhui999:可以整个实现到 bargainActivityService 中 | ||
| 27 | - // 查询砍价活动 | ||
| 28 | - BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); | ||
| 29 | - if (activity == null) { | ||
| 30 | - throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); | ||
| 31 | - } | ||
| 32 | - | ||
| 33 | - // 更新砍价库存 | ||
| 34 | - // TODO @puhui999:考虑下并发更新问题 | ||
| 35 | - BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); | ||
| 36 | - reqVO.setId(activityId); | ||
| 37 | - reqVO.setStock(activity.getStock() - count); | ||
| 38 | - bargainActivityService.updateBargainActivity(reqVO); | 20 | + public void updateBargainActivityStock(Long id, Integer count) { |
| 21 | + bargainActivityService.updateBargainActivityStock(id, count); | ||
| 39 | } | 22 | } |
| 40 | 23 | ||
| 41 | } | 24 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.api.seckill; | 1 | package cn.iocoder.yudao.module.promotion.api.seckill; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 4 | import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | 3 | import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; |
| 5 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; | ||
| 6 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; | 4 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; |
| 8 | import org.springframework.stereotype.Service; | 5 | import org.springframework.stereotype.Service; |
| 9 | 6 | ||
| 10 | import javax.annotation.Resource; | 7 | import javax.annotation.Resource; |
| 11 | -import java.util.ArrayList; | ||
| 12 | -import java.util.HashMap; | ||
| 13 | -import java.util.List; | ||
| 14 | -import java.util.Map; | ||
| 15 | - | ||
| 16 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 17 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_UPDATE_STOCK_FAIL; | ||
| 18 | 8 | ||
| 19 | /** | 9 | /** |
| 20 | * 秒杀活动接口 Api 接口实现类 | 10 | * 秒杀活动接口 Api 接口实现类 |
| @@ -27,58 +17,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | @@ -27,58 +17,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | ||
| 27 | @Resource | 17 | @Resource |
| 28 | private SeckillActivityService activityService; | 18 | private SeckillActivityService activityService; |
| 29 | 19 | ||
| 30 | - // TODO @puhui:建议这块弄到 activityService 实现哈; | ||
| 31 | - // TODO @puhui:这个方法,要考虑事务性 | ||
| 32 | @Override | 20 | @Override |
| 33 | public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { | 21 | public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { |
| 34 | - // TODO @puhui999:长方法,最好有 1.1 1.2 2.1 这种步骤哈; | ||
| 35 | - SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); | ||
| 36 | - if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { | ||
| 37 | - throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||
| 38 | - } | ||
| 39 | - // 获取活动商品 | ||
| 40 | - // TODO @puhui999:在一个方法里,dos 和 dolist 最好保持一致,要么用 s,要么用 list 哈; | ||
| 41 | - List<SeckillProductDO> productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); | ||
| 42 | - // TODO @puhui999:这个是不是搞成 CollectionUtils.convertMultiMap() | ||
| 43 | - List<SeckillActivityUpdateStockReqDTO.Item> items = updateStockReqDTO.getItems(); | ||
| 44 | - Map<Long, List<Long>> map = new HashMap<>(); | ||
| 45 | - items.forEach(item -> { | ||
| 46 | - if (map.containsKey(item.getSpuId())) { | ||
| 47 | - List<Long> skuIds = map.get(item.getSpuId()); | ||
| 48 | - skuIds.add(item.getSkuId()); | ||
| 49 | - map.put(item.getSpuId(), skuIds); | ||
| 50 | - } else { | ||
| 51 | - List<Long> list = new ArrayList<>(); | ||
| 52 | - list.add(item.getSkuId()); | ||
| 53 | - map.put(item.getSpuId(), list); | ||
| 54 | - } | ||
| 55 | - }); | ||
| 56 | - // 过滤出购买的商品 | ||
| 57 | - // TODO @puhui999:productDOList 可以简化成 productList;一般来说,do 之类不用带着哈,在变量里; | ||
| 58 | - List<SeckillProductDO> productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); | ||
| 59 | - Map<Long, SeckillActivityUpdateStockReqDTO.Item> productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); | ||
| 60 | - // 检查活动商品库存是否充足 | ||
| 61 | - // TODO @puhui999:避免 b 这种无业务含义的变量; | ||
| 62 | - boolean b = CollectionUtils.anyMatch(productDOList, item -> { | ||
| 63 | - SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); | ||
| 64 | - return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; | ||
| 65 | - }); | ||
| 66 | - if (b) { | ||
| 67 | - throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||
| 68 | - } | ||
| 69 | - // TODO @puhui999:类似 doList,应该和下面的 update 逻辑粘的更紧密一点;so 在空行的时候,应该挪到 74 之后里去;甚至更合理,应该是 79 之后;说白了,逻辑要分块,每个模块涉及的代码要紧密在一起; | ||
| 70 | - List<SeckillProductDO> doList = CollectionUtils.convertList(productDOList, item -> { | ||
| 71 | - item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); | ||
| 72 | - return item; | ||
| 73 | - }); | ||
| 74 | - | ||
| 75 | - // 更新活动库存 | ||
| 76 | - // TODO @puhui999:考虑下并发更新 | ||
| 77 | - seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); | ||
| 78 | - seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); | ||
| 79 | - activityService.updateSeckillActivity(seckillActivity); | ||
| 80 | - // 更新活动商品库存 | ||
| 81 | - activityService.updateSeckillActivityProductList(doList); | 22 | + activityService.updateSeckillStock(updateStockReqDTO); |
| 82 | } | 23 | } |
| 83 | 24 | ||
| 84 | } | 25 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java
| @@ -31,6 +31,14 @@ public interface BargainActivityService { | @@ -31,6 +31,14 @@ public interface BargainActivityService { | ||
| 31 | void updateBargainActivity(@Valid BargainActivityUpdateReqVO updateReqVO); | 31 | void updateBargainActivity(@Valid BargainActivityUpdateReqVO updateReqVO); |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | + * 更新砍价活动库存 | ||
| 35 | + * | ||
| 36 | + * @param id 砍价活动编号 | ||
| 37 | + * @param count 购买数量 | ||
| 38 | + */ | ||
| 39 | + void updateBargainActivityStock(Long id, Integer count); | ||
| 40 | + | ||
| 41 | + /** | ||
| 34 | * 删除砍价活动 | 42 | * 删除砍价活动 |
| 35 | * | 43 | * |
| 36 | * @param id 编号 | 44 | * @param id 编号 |
| @@ -53,5 +61,4 @@ public interface BargainActivityService { | @@ -53,5 +61,4 @@ public interface BargainActivityService { | ||
| 53 | */ | 61 | */ |
| 54 | PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO); | 62 | PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO); |
| 55 | 63 | ||
| 56 | - | ||
| 57 | } | 64 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
| @@ -39,6 +39,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -39,6 +39,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 39 | private ProductSkuApi productSkuApi; | 39 | private ProductSkuApi productSkuApi; |
| 40 | 40 | ||
| 41 | @Override | 41 | @Override |
| 42 | + @Transactional(rollbackFor = Exception.class) | ||
| 42 | public Long createBargainActivity(BargainActivityCreateReqVO createReqVO) { | 43 | public Long createBargainActivity(BargainActivityCreateReqVO createReqVO) { |
| 43 | // 校验商品 SPU 是否存在是否参加的别的活动 | 44 | // 校验商品 SPU 是否存在是否参加的别的活动 |
| 44 | validateBargainConflict(createReqVO.getSpuId(), null); | 45 | validateBargainConflict(createReqVO.getSpuId(), null); |
| @@ -53,6 +54,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -53,6 +54,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | @Override | 56 | @Override |
| 57 | + @Transactional(rollbackFor = Exception.class) | ||
| 56 | public void updateBargainActivity(BargainActivityUpdateReqVO updateReqVO) { | 58 | public void updateBargainActivity(BargainActivityUpdateReqVO updateReqVO) { |
| 57 | // 校验存在 | 59 | // 校验存在 |
| 58 | BargainActivityDO activityDO = validateBargainActivityExists(updateReqVO.getId()); | 60 | BargainActivityDO activityDO = validateBargainActivityExists(updateReqVO.getId()); |
| @@ -70,6 +72,23 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -70,6 +72,23 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 70 | bargainActivityMapper.updateById(updateObj); | 72 | bargainActivityMapper.updateById(updateObj); |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 75 | + @Override | ||
| 76 | + @Transactional(rollbackFor = Exception.class) | ||
| 77 | + public void updateBargainActivityStock(Long id, Integer count) { | ||
| 78 | + // 查询砍价活动 | ||
| 79 | + BargainActivityDO activity = getBargainActivity(id); | ||
| 80 | + if (activity == null) { | ||
| 81 | + throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + // 更新砍价库存 | ||
| 85 | + // TODO @puhui999:考虑下并发更新问题 | ||
| 86 | + BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); | ||
| 87 | + reqVO.setId(id); | ||
| 88 | + reqVO.setStock(activity.getStock() - count); | ||
| 89 | + //bargainActivityService.updateBargainActivity(reqVO); | ||
| 90 | + } | ||
| 91 | + | ||
| 73 | private void validateBargainConflict(Long spuId, Long activityId) { | 92 | private void validateBargainConflict(Long spuId, Long activityId) { |
| 74 | // 查询所有开启的砍价活动 | 93 | // 查询所有开启的砍价活动 |
| 75 | List<BargainActivityDO> activityList = bargainActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); | 94 | List<BargainActivityDO> activityList = bargainActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
| 1 | package cn.iocoder.yudao.module.promotion.service.seckill; | 1 | package cn.iocoder.yudao.module.promotion.service.seckill; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | ||
| 4 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; |
| @@ -41,6 +42,12 @@ public interface SeckillActivityService { | @@ -41,6 +42,12 @@ public interface SeckillActivityService { | ||
| 41 | void updateSeckillActivity(SeckillActivityDO activityDO); | 42 | void updateSeckillActivity(SeckillActivityDO activityDO); |
| 42 | 43 | ||
| 43 | /** | 44 | /** |
| 45 | + * 更新秒杀库存 | ||
| 46 | + * | ||
| 47 | + * @param updateStockReqDTO 更新信息 | ||
| 48 | + */ | ||
| 49 | + void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO); | ||
| 50 | + /** | ||
| 44 | * 更新秒杀活动商品 | 51 | * 更新秒杀活动商品 |
| 45 | * | 52 | * |
| 46 | * @param productList 活动商品列表 | 53 | * @param productList 活动商品列表 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 7 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 7 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 8 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | 8 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; |
| 9 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | 9 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 10 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO; | ||
| 10 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; | 11 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; |
| 11 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; | 12 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; |
| 12 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; | 13 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; |
| @@ -150,6 +151,40 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -150,6 +151,40 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 150 | } | 151 | } |
| 151 | 152 | ||
| 152 | @Override | 153 | @Override |
| 154 | + @Transactional(rollbackFor = Exception.class) | ||
| 155 | + public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { | ||
| 156 | + // 1、校验秒杀活动是否存在 | ||
| 157 | + SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId()); | ||
| 158 | + // 1.1、校验库存是否充足 | ||
| 159 | + if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { | ||
| 160 | + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + // 2、更新活动库存 | ||
| 164 | + // TODO @puhui999:考虑下并发更新 | ||
| 165 | + seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); | ||
| 166 | + seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); | ||
| 167 | + updateSeckillActivity(seckillActivity); | ||
| 168 | + | ||
| 169 | + // 3、获取活动商品 | ||
| 170 | + List<SeckillProductDO> products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); | ||
| 171 | + // 3.1、过滤出购买的商品 | ||
| 172 | + SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId())); | ||
| 173 | + // 3.2、检查活动商品库存是否充足 | ||
| 174 | + boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0); | ||
| 175 | + if (isSufficient) { | ||
| 176 | + throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + // 4、更新活动商品库存 | ||
| 180 | + SeckillProductDO updateProduct = new SeckillProductDO(); | ||
| 181 | + updateProduct.setId(product.getId()); | ||
| 182 | + updateProduct.setStock(product.getStock() - updateStockReqDTO.getItem().getCount()); | ||
| 183 | + // TODO @puhui999:考虑下并发更新 | ||
| 184 | + | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + @Override | ||
| 153 | public void updateSeckillActivityProductList(List<SeckillProductDO> productList) { | 188 | public void updateSeckillActivityProductList(List<SeckillProductDO> productList) { |
| 154 | seckillProductMapper.updateBatch(productList); | 189 | seckillProductMapper.updateBatch(productList); |
| 155 | } | 190 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| @@ -81,10 +81,9 @@ public class AppTradeOrderController { | @@ -81,10 +81,9 @@ public class AppTradeOrderController { | ||
| 81 | public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) { | 81 | public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) { |
| 82 | // 查询订单 | 82 | // 查询订单 |
| 83 | TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); | 83 | TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); |
| 84 | - // TODO @puhui999:这里建议改成,如果为 null,直接返回 success null;主要查询操作,尽量不要有非空的提示哈;交给前端处理; | ||
| 85 | -// if (order == null) { | ||
| 86 | -// return success(null, ORDER_NOT_FOUND.getMsg()); | ||
| 87 | -// } | 84 | + if (order == null) { |
| 85 | + return success(null); | ||
| 86 | + } | ||
| 88 | 87 | ||
| 89 | // 查询订单项 | 88 | // 查询订单项 |
| 90 | List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); | 89 | List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -313,17 +313,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -313,17 +313,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 313 | Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); | 313 | Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum); |
| 314 | // 1)如果是秒杀商品:额外扣减秒杀的库存; | 314 | // 1)如果是秒杀商品:额外扣减秒杀的库存; |
| 315 | if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { | 315 | if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) { |
| 316 | - SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); | ||
| 317 | - updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); | ||
| 318 | - updateStockReqDTO.setCount(count); | ||
| 319 | - updateStockReqDTO.setItems(CollectionUtils.convertList(orderItems, item -> { | ||
| 320 | - SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); | ||
| 321 | - item1.setSpuId(item.getSpuId()); | ||
| 322 | - item1.setSkuId(item.getSkuId()); | ||
| 323 | - item1.setCount(item.getCount()); | ||
| 324 | - return item1; | ||
| 325 | - })); | ||
| 326 | - seckillActivityApi.updateSeckillStock(updateStockReqDTO); | 316 | + seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count)); |
| 327 | } | 317 | } |
| 328 | // 2)如果是砍价活动:额外扣减砍价的库存; | 318 | // 2)如果是砍价活动:额外扣减砍价的库存; |
| 329 | bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); | 319 | bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count); |
| @@ -351,6 +341,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -351,6 +341,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 351 | // 增加订单日志 TODO 芋艿:待实现 | 341 | // 增加订单日志 TODO 芋艿:待实现 |
| 352 | } | 342 | } |
| 353 | 343 | ||
| 344 | + private SeckillActivityUpdateStockReqDTO getSeckillActivityUpdateStockReqDTO(AppTradeOrderCreateReqVO createReqVO, List<TradeOrderItemDO> orderItems, Integer count) { | ||
| 345 | + SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO(); | ||
| 346 | + updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId()); | ||
| 347 | + updateStockReqDTO.setCount(count); | ||
| 348 | + // 秒杀活动只能选择一个商品 | ||
| 349 | + TradeOrderItemDO item = orderItems.get(0); | ||
| 350 | + SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item(); | ||
| 351 | + item1.setSpuId(item.getSpuId()); | ||
| 352 | + item1.setSkuId(item.getSkuId()); | ||
| 353 | + item1.setCount(item.getCount()); | ||
| 354 | + updateStockReqDTO.setItem(item1); | ||
| 355 | + return updateStockReqDTO; | ||
| 356 | + } | ||
| 357 | + | ||
| 354 | private void createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems, TradePriceCalculateRespBO calculateRespBO) { | 358 | private void createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems, TradePriceCalculateRespBO calculateRespBO) { |
| 355 | // 创建支付单,用于后续的支付 | 359 | // 创建支付单,用于后续的支付 |
| 356 | PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( | 360 | PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( |