商城活动: 完善活动商品并发库存扣减逻辑

This commit is contained in:
puhui999 2023-09-11 00:13:45 +08:00
parent 3976011af0
commit 7fb455096c
6 changed files with 66 additions and 21 deletions

View File

@ -55,7 +55,7 @@ public interface ErrorCodeConstants {
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "更新秒杀活动库存失败,原因秒杀库存不足"); ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
// ========== 秒杀时段 1013009000 ========== // ========== 秒杀时段 1013009000 ==========
ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
@ -83,6 +83,7 @@ public interface ErrorCodeConstants {
ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动"); ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改"); ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除"); ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
// ========== 砍价记录 1013013000 ========== // ========== 砍价记录 1013013000 ==========
ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在"); ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在");

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -28,4 +29,18 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
return selectList(BargainActivityDO::getStatus, status); return selectList(BargainActivityDO::getStatus, status);
} }
/**
* 更新活动库存
*
* @param id 活动编号
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<BargainActivityDO>()
.eq(BargainActivityDO::getId, id)
.gt(BargainActivityDO::getStock, 0)
.setSql("stock = stock - " + count));
}
} }

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -32,4 +33,19 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
.eqIfPresent(SeckillActivityDO::getStatus, status)); .eqIfPresent(SeckillActivityDO::getStatus, status));
} }
/**
* 更新活动库存
*
* @param id 活动编号
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<SeckillActivityDO>()
.eq(SeckillActivityDO::getId, id)
.gt(SeckillActivityDO::getTotalStock, 0)
.setSql("stock = stock + " + count)
.setSql("totalStock = totalStock - " + count));
}
} }

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Collection; import java.util.Collection;
@ -23,4 +24,18 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
return selectList(SeckillProductDO::getActivityId, ids); return selectList(SeckillProductDO::getActivityId, ids);
} }
/**
* 更新活动库存
*
* @param id 活动编号
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<SeckillProductDO>()
.eq(SeckillProductDO::getId, id)
.gt(SeckillProductDO::getStock, 0)
.setSql("stock = stock - " + count));
}
} }

View File

@ -82,11 +82,10 @@ public class BargainActivityServiceImpl implements BargainActivityService {
} }
// 更新砍价库存 // 更新砍价库存
// TODO @puhui999考虑下并发更新问题 int row = bargainActivityMapper.updateActivityStock(id, count);
BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); if (row == 0) {
reqVO.setId(id); throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
reqVO.setStock(activity.getStock() - count); }
//bargainActivityService.updateBargainActivity(reqVO);
} }
private void validateBargainConflict(Long spuId, Long activityId) { private void validateBargainConflict(Long spuId, Long activityId) {

View File

@ -156,32 +156,31 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
// 1校验秒杀活动是否存在 // 1校验秒杀活动是否存在
SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId()); SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId());
// 1.1校验库存是否充足 // 1.1校验库存是否充足
if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { if (seckillActivity.getTotalStock() < updateStockReqDTO.getCount()) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
} }
// 2更新活动库存 // 2获取活动商品
// TODO @puhui999考虑下并发更新
seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount());
seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount());
updateSeckillActivity(seckillActivity);
// 3获取活动商品
List<SeckillProductDO> products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); List<SeckillProductDO> products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId());
// 3.1过滤出购买的商品 // 2.1过滤出购买的商品
SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId())); SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId()));
// 3.2检查活动商品库存是否充足 // 2.2检查活动商品库存是否充足
boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0); boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0);
if (isSufficient) { if (isSufficient) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
} }
// 4更新活动商品库存 // 3更新活动商品库存
SeckillProductDO updateProduct = new SeckillProductDO(); int itemRow = seckillProductMapper.updateActivityStock(product.getId(), updateStockReqDTO.getItem().getCount());
updateProduct.setId(product.getId()); if (itemRow == 0) {
updateProduct.setStock(product.getStock() - updateStockReqDTO.getItem().getCount()); throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
// TODO @puhui999考虑下并发更新 }
// 4更新活动库存
int row = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), updateStockReqDTO.getCount());
if (row == 0) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}
} }
@Override @Override