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

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_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
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 ==========
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_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
// ========== 砍价记录 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.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
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 java.util.List;
@ -28,4 +29,18 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
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.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
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 java.util.List;
@ -32,4 +33,19 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
.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.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
@ -23,4 +24,18 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
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考虑下并发更新问题
BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO();
reqVO.setId(id);
reqVO.setStock(activity.getStock() - count);
//bargainActivityService.updateBargainActivity(reqVO);
int row = bargainActivityMapper.updateActivityStock(id, count);
if (row == 0) {
throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
}
}
private void validateBargainConflict(Long spuId, Long activityId) {

View File

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