!136 增加检测促销商品库存

Merge pull request !136 from OceansDeep/feature/pg
This commit is contained in:
OceansDeep 2022-03-02 12:41:01 +00:00 committed by Gitee
commit b9b2c10ca0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 121 additions and 48 deletions

View File

@ -332,7 +332,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
Integer num = promotionGoods.get(i).getNum(); Integer num = promotionGoods.get(i).getNum();
promotionGoods.get(i).setNum((num != null ? num : 0) + order.getOrder().getGoodsNum()); promotionGoods.get(i).setNum((num != null ? num : 0) + order.getOrder().getGoodsNum());
} }
promotionGoodsService.updateBatchById(promotionGoods); promotionGoodsService.updatePromotionGoodsStock(promotionGoods);
} }
//商品库存包含sku库存集合批量更新商品库存相关 //商品库存包含sku库存集合批量更新商品库存相关
goodsSkuService.updateGoodsStuck(goodsSkus); goodsSkuService.updateGoodsStuck(goodsSkus);

View File

@ -246,6 +246,7 @@ public enum ResultCode {
* 活动 * 活动
*/ */
PROMOTION_GOODS_NOT_EXIT(40000, "当前促销商品不存在!"), PROMOTION_GOODS_NOT_EXIT(40000, "当前促销商品不存在!"),
PROMOTION_GOODS_QUANTITY_NOT_EXIT(40020, "当前促销商品库存不足!"),
PROMOTION_SAME_ACTIVE_EXIST(40001, "活动时间内已存在同类活动,请选择关闭、删除当前时段的活动"), PROMOTION_SAME_ACTIVE_EXIST(40001, "活动时间内已存在同类活动,请选择关闭、删除当前时段的活动"),
PROMOTION_START_TIME_ERROR(40002, "活动起始时间不能小于当前时间"), PROMOTION_START_TIME_ERROR(40002, "活动起始时间不能小于当前时间"),
PROMOTION_END_TIME_ERROR(40003, "活动结束时间不能小于当前时间"), PROMOTION_END_TIME_ERROR(40003, "活动结束时间不能小于当前时间"),

View File

@ -139,7 +139,6 @@ public class TradeDTO implements Serializable {
this.cartList = new ArrayList<>(); this.cartList = new ArrayList<>();
this.skuPromotionDetail = new HashMap<>(); this.skuPromotionDetail = new HashMap<>();
this.storeCoupons = new HashMap<>(); this.storeCoupons = new HashMap<>();
this.storeCoupons = new HashMap<>();
this.priceDetailDTO = new PriceDetailDTO(); this.priceDetailDTO = new PriceDetailDTO();
this.cantUseCoupons = new ArrayList<>(); this.cantUseCoupons = new ArrayList<>();
this.canUseCoupons = new ArrayList<>(); this.canUseCoupons = new ArrayList<>();

View File

@ -193,7 +193,7 @@ public class CheckDataRender implements CartRenderStep {
} }
} }
//积分商品判断用户积分是否满足 //积分商品判断用户积分是否满足
} else if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS) && tradeDTO.getSkuList().get(0).getPromotionMap() != null && !tradeDTO.getSkuList().get(0).getPromotionMap().isEmpty()) { } else if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS) && tradeDTO.getSkuList().get(0).getPromotionMap() != null && !tradeDTO.getSkuList().get(0).getPromotionMap().isEmpty()) {
//获取积分商品VO //获取积分商品VO
Optional<Map.Entry<String, Object>> pointsPromotions = tradeDTO.getSkuList().get(0).getPromotionMap().entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.POINTS_GOODS.name())).findFirst(); Optional<Map.Entry<String, Object>> pointsPromotions = tradeDTO.getSkuList().get(0).getPromotionMap().entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.POINTS_GOODS.name())).findFirst();
if (pointsPromotions.isPresent()) { if (pointsPromotions.isPresent()) {

View File

@ -2,6 +2,7 @@ package cn.lili.modules.order.cart.render.impl;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException; import cn.lili.common.exception.ServiceException;
@ -19,10 +20,14 @@ import cn.lili.modules.promotion.entity.dto.search.KanjiaActivitySearchParams;
import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum; import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum;
import cn.lili.modules.promotion.entity.vos.PromotionSkuVO; import cn.lili.modules.promotion.entity.vos.PromotionSkuVO;
import cn.lili.modules.promotion.entity.vos.kanjia.KanjiaActivityVO; import cn.lili.modules.promotion.entity.vos.kanjia.KanjiaActivityVO;
import cn.lili.modules.promotion.service.KanjiaActivityGoodsService;
import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.KanjiaActivityService;
import cn.lili.modules.promotion.service.PointsGoodsService;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -39,9 +44,24 @@ public class SkuPromotionRender implements CartRenderStep {
@Autowired @Autowired
private KanjiaActivityService kanjiaActivityService; private KanjiaActivityService kanjiaActivityService;
@Autowired
private KanjiaActivityGoodsService kanjiaActivityGoodsService;
@Autowired
private PointsGoodsService pointsGoodsService;
/**
* 促销商品
*/
@Autowired
private PromotionGoodsService promotionGoodsService;
@Autowired @Autowired
private MemberService memberService; private MemberService memberService;
@Autowired
private Cache cache;
@Override @Override
public RenderStepEnums step() { public RenderStepEnums step() {
return RenderStepEnums.SKU_PROMOTION; return RenderStepEnums.SKU_PROMOTION;
@ -54,6 +74,10 @@ public class SkuPromotionRender implements CartRenderStep {
renderBasePrice(tradeDTO); renderBasePrice(tradeDTO);
//渲染单品促销 //渲染单品促销
renderSkuPromotion(tradeDTO); renderSkuPromotion(tradeDTO);
checkPromotionQuantity(tradeDTO);
} }
/** /**
@ -155,6 +179,54 @@ public class SkuPromotionRender implements CartRenderStep {
} }
} }
/**
* 检查促销库存
*
* @param tradeDTO 购物车视图
*/
private void checkPromotionQuantity(TradeDTO tradeDTO) {
for (CartSkuVO cartSkuVO : tradeDTO.getCheckedSkuList()) {
cartSkuVO.getPromotionMap();
List<PromotionSkuVO> joinPromotion = cartSkuVO.getPriceDetailDTO().getJoinPromotion();
if (!joinPromotion.isEmpty()) {
for (PromotionSkuVO promotionSkuVO : joinPromotion) {
this.checkPromotionGoodsQuantity(cartSkuVO, promotionSkuVO);
}
}
}
}
private void checkPromotionGoodsQuantity(CartSkuVO cartSkuVO, PromotionSkuVO promotionSkuVO) {
String promotionGoodsStockCacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(PromotionTypeEnum.valueOf(promotionSkuVO.getPromotionType()), promotionSkuVO.getActivityId(), cartSkuVO.getGoodsSku().getId());
Object quantity = cache.get(promotionGoodsStockCacheKey);
if (quantity == null) {
//如果促销有库存信息
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(promotionSkuVO.getPromotionType());
switch (promotionTypeEnum) {
case KANJIA:
quantity = kanjiaActivityGoodsService.getKanjiaGoodsBySkuId(cartSkuVO.getGoodsSku().getId()).getStock();
break;
case POINTS_GOODS:
quantity = pointsGoodsService.getPointsGoodsDetailBySkuId(cartSkuVO.getGoodsSku().getId()).getActiveStock();
break;
case SECKILL:
case PINTUAN:
quantity = promotionGoodsService.getPromotionGoodsStock(PromotionTypeEnum.valueOf(promotionSkuVO.getPromotionType()), promotionSkuVO.getActivityId(), cartSkuVO.getGoodsSku().getId());
break;
default:
return;
}
}
if (quantity != null && cartSkuVO.getNum() > (Integer) quantity) {//设置购物车未选中
cartSkuVO.setChecked(false);
//设置失效消息
cartSkuVO.setErrorMessage("促销商品库存不足,现有库存数量[" + quantity + "]");
}
}
/** /**
* 购物车促销类型 * 购物车促销类型
*/ */

View File

@ -185,6 +185,7 @@ public class CartServiceImpl implements CartService {
//购物车中不存在此商品则新建立一个 //购物车中不存在此商品则新建立一个
CartSkuVO cartSkuVO = new CartSkuVO(dataSku, promotionMap); CartSkuVO cartSkuVO = new CartSkuVO(dataSku, promotionMap);
this.checkSetGoodsQuantity(cartSkuVO, skuId, num);
cartSkuVO.setCartType(cartTypeEnum); cartSkuVO.setCartType(cartTypeEnum);
//检测购物车数据 //检测购物车数据
checkCart(cartTypeEnum, cartSkuVO, skuId, num); checkCart(cartTypeEnum, cartSkuVO, skuId, num);

View File

@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
/** /**
* 发票 * 发票
* *
@ -12,8 +14,10 @@ import lombok.Data;
*/ */
@Data @Data
@ApiModel(value = "发票") @ApiModel(value = "发票")
public class ReceiptVO { public class ReceiptVO implements Serializable {
private static final long serialVersionUID = -8402457457074092957L;
@ApiModelProperty(value = "发票抬头") @ApiModelProperty(value = "发票抬头")
private String receiptTitle; private String receiptTitle;

View File

@ -11,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.Field;
@ -30,6 +31,7 @@ import java.util.Date;
@TableName("li_seckill") @TableName("li_seckill")
@ApiModel(value = "秒杀活动活动") @ApiModel(value = "秒杀活动活动")
@NoArgsConstructor @NoArgsConstructor
@ToString(callSuper = true)
public class Seckill extends BasePromotions { public class Seckill extends BasePromotions {
private static final long serialVersionUID = -9116425737163730836L; private static final long serialVersionUID = -9116425737163730836L;

View File

@ -121,12 +121,9 @@ public interface PromotionGoodsService extends IService<PromotionGoods> {
/** /**
* 更新促销活动商品库存 * 更新促销活动商品库存
* *
* @param typeEnum 促销商品类型 * @param promotionGoodsList 更新促销活动商品信息
* @param promotionId 促销活动id
* @param skuId 商品skuId
* @param quantity 更新后的库存数量
*/ */
void updatePromotionGoodsStock(PromotionTypeEnum typeEnum, String promotionId, String skuId, Integer quantity); void updatePromotionGoodsStock(List<PromotionGoods> promotionGoodsList);
/** /**
* 更新促销活动商品索引 * 更新促销活动商品索引

View File

@ -90,13 +90,13 @@ public interface SeckillApplyService extends IService<SeckillApply> {
void removeSeckillApply(String seckillId, String id); void removeSeckillApply(String seckillId, String id);
/** /**
* 更新秒杀商品库存 * 更新秒杀商品出售数量
* *
* @param seckillId 秒杀活动id * @param seckillId 秒杀活动id
* @param skuId 商品skuId * @param skuId 商品skuId
* @param quantity 库存 * @param saleNum 出售数量
*/ */
void updateSeckillApplyQuantity(String seckillId, String skuId, Integer quantity); void updateSeckillApplySaleNum(String seckillId, String skuId, Integer saleNum);
/** /**
* 更新秒杀活动时间 * 更新秒杀活动时间

View File

@ -3,8 +3,6 @@ package cn.lili.modules.promotion.serviceimpl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.PageVO; import cn.lili.common.vo.PageVO;
import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.goods.service.GoodsSkuService;
@ -27,6 +25,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -209,31 +208,32 @@ public class PromotionGoodsServiceImpl extends ServiceImpl<PromotionGoodsMapper,
/** /**
* 更新促销活动商品库存 * 更新促销活动商品库存
* *
* @param typeEnum 促销商品类型 * @param promotionGoodsList 更新促销活动商品信息
* @param promotionId 促销活动id
* @param skuId 商品skuId
* @param quantity 更新后的库存数量
*/ */
@Override @Override
public void updatePromotionGoodsStock(PromotionTypeEnum typeEnum, String promotionId, String skuId, Integer quantity) { @Transactional(rollbackFor = Exception.class)
String promotionStockKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(typeEnum, promotionId, skuId); public void updatePromotionGoodsStock(List<PromotionGoods> promotionGoodsList) {
if (typeEnum.equals(PromotionTypeEnum.SECKILL)) { for (PromotionGoods promotionGoods : promotionGoodsList) {
SeckillSearchParams searchParams = new SeckillSearchParams(); String promotionStockKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(PromotionTypeEnum.valueOf(promotionGoods.getPromotionType()), promotionGoods.getPromotionId(), promotionGoods.getSkuId());
searchParams.setSeckillId(promotionId); if (promotionGoods.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())) {
searchParams.setSkuId(skuId); SeckillSearchParams searchParams = new SeckillSearchParams();
SeckillApply seckillApply = this.seckillApplyService.getSeckillApply(searchParams); searchParams.setSeckillId(promotionGoods.getPromotionId());
if (seckillApply == null) { searchParams.setSkuId(promotionGoods.getSkuId());
throw new ServiceException(ResultCode.SECKILL_NOT_EXIST_ERROR); SeckillApply seckillApply = this.seckillApplyService.getSeckillApply(searchParams);
if (seckillApply != null) {
seckillApplyService.updateSeckillApplySaleNum(promotionGoods.getPromotionId(), promotionGoods.getSkuId(), promotionGoods.getNum());
}
} }
seckillApplyService.updateSeckillApplyQuantity(promotionId, skuId, quantity);
} else {
LambdaUpdateWrapper<PromotionGoods> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<PromotionGoods> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(PromotionGoods::getPromotionType, typeEnum.name()).eq(PromotionGoods::getPromotionId, promotionId).eq(PromotionGoods::getSkuId, skuId); updateWrapper.eq(PromotionGoods::getPromotionType, promotionGoods.getPromotionType()).eq(PromotionGoods::getPromotionId, promotionGoods.getPromotionId()).eq(PromotionGoods::getSkuId, promotionGoods.getSkuId());
updateWrapper.set(PromotionGoods::getQuantity, quantity); updateWrapper.set(PromotionGoods::getQuantity, promotionGoods.getQuantity()).set(PromotionGoods::getNum, promotionGoods.getNum());
this.update(updateWrapper); this.update(updateWrapper);
stringRedisTemplate.opsForValue().set(promotionStockKey, promotionGoods.getQuantity().toString());
} }
stringRedisTemplate.opsForValue().set(promotionStockKey, quantity.toString());
} }
/** /**

View File

@ -105,7 +105,7 @@ public class PromotionServiceImpl implements PromotionService {
/** /**
* 根据商品索引获取当前商品索引的所有促销活动信息 * 根据商品索引获取当前商品索引的所有促销活动信息
* *
* @param storeId 店铺id * @param storeId 店铺id
* @param goodsSkuId 商品skuId * @param goodsSkuId 商品skuId
* @return 当前促销活动集合 * @return 当前促销活动集合
*/ */
@ -129,7 +129,7 @@ public class PromotionServiceImpl implements PromotionService {
promotionMap.put(esPromotionKey, fullDiscount); promotionMap.put(esPromotionKey, fullDiscount);
break; break;
case SECKILL: case SECKILL:
this.getGoodsCurrentSeckill(promotionGoods, promotionMap); this.getGoodsCurrentSeckill(esPromotionKey, promotionGoods, promotionMap);
break; break;
case POINTS_GOODS: case POINTS_GOODS:
PointsGoods pointsGoods = pointsGoodsService.getById(promotionGoods.getPromotionId()); PointsGoods pointsGoods = pointsGoodsService.getById(promotionGoods.getPromotionId());
@ -143,7 +143,7 @@ public class PromotionServiceImpl implements PromotionService {
} }
private void getGoodsCurrentSeckill(PromotionGoods promotionGoods, Map<String, Object> promotionMap) { private void getGoodsCurrentSeckill(String esPromotionKey, PromotionGoods promotionGoods, Map<String, Object> promotionMap) {
Seckill seckill = seckillService.getById(promotionGoods.getPromotionId()); Seckill seckill = seckillService.getById(promotionGoods.getPromotionId());
SeckillSearchParams searchParams = new SeckillSearchParams(); SeckillSearchParams searchParams = new SeckillSearchParams();
searchParams.setSeckillId(promotionGoods.getPromotionId()); searchParams.setSeckillId(promotionGoods.getPromotionId());
@ -151,19 +151,12 @@ public class PromotionServiceImpl implements PromotionService {
List<SeckillApply> seckillApplyList = seckillApplyService.getSeckillApplyList(searchParams); List<SeckillApply> seckillApplyList = seckillApplyService.getSeckillApplyList(searchParams);
if (seckillApplyList != null && !seckillApplyList.isEmpty()) { if (seckillApplyList != null && !seckillApplyList.isEmpty()) {
SeckillApply seckillApply = seckillApplyList.get(0); SeckillApply seckillApply = seckillApplyList.get(0);
int nextHour = 23;
String[] split = seckill.getHours().split(","); String[] split = seckill.getHours().split(",");
int[] hoursSored = Arrays.stream(split).mapToInt(Integer::parseInt).toArray(); int[] hoursSored = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
Arrays.sort(hoursSored); Arrays.sort(hoursSored);
for (int i : hoursSored) {
if (seckillApply.getTimeLine() < i) {
nextHour = i;
}
}
String seckillKey = promotionGoods.getPromotionType() + "-" + nextHour;
seckill.setStartTime(promotionGoods.getStartTime()); seckill.setStartTime(promotionGoods.getStartTime());
seckill.setEndTime(promotionGoods.getEndTime()); seckill.setEndTime(promotionGoods.getEndTime());
promotionMap.put(seckillKey, seckill); promotionMap.put(esPromotionKey, seckill);
} }
} }

View File

@ -231,17 +231,17 @@ public class SeckillApplyServiceImpl extends ServiceImpl<SeckillApplyMapper, Sec
} }
/** /**
* 更新秒杀商品库存 * 更新秒杀商品出售数量
* *
* @param seckillId 秒杀活动id * @param seckillId 秒杀活动id
* @param skuId 商品skuId * @param skuId 商品skuId
* @param quantity 库存 * @param saleNum 库存
*/ */
@Override @Override
public void updateSeckillApplyQuantity(String seckillId, String skuId, Integer quantity) { public void updateSeckillApplySaleNum(String seckillId, String skuId, Integer saleNum) {
LambdaUpdateWrapper<SeckillApply> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SeckillApply> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(SeckillApply::getSeckillId, seckillId).eq(SeckillApply::getSkuId, skuId); updateWrapper.eq(SeckillApply::getSeckillId, seckillId).eq(SeckillApply::getSkuId, skuId);
updateWrapper.set(SeckillApply::getQuantity, quantity); updateWrapper.set(SeckillApply::getSalesNum, saleNum);
this.update(updateWrapper); this.update(updateWrapper);
} }
@ -424,7 +424,11 @@ public class SeckillApplyServiceImpl extends ServiceImpl<SeckillApplyMapper, Sec
//设置单独每个促销商品的结束时间 //设置单独每个促销商品的结束时间
DateTime startTime = DateUtil.offsetHour(DateUtil.beginOfDay(seckill.getStartTime()), seckillApply.getTimeLine()); DateTime startTime = DateUtil.offsetHour(DateUtil.beginOfDay(seckill.getStartTime()), seckillApply.getTimeLine());
promotionGoods.setStartTime(startTime); promotionGoods.setStartTime(startTime);
promotionGoods.setEndTime(seckill.getEndTime()); if (seckill.getEndTime() == null) {
promotionGoods.setEndTime(DateUtil.endOfDay(startTime));
} else {
promotionGoods.setEndTime(seckill.getEndTime());
}
return promotionGoods; return promotionGoods;
} }