拼团活动同一店铺同一时间限制一个活动取消。
积分订单库存扣减,积分返还处理。 其他促销相关优化
This commit is contained in:
parent
42e9ee06f4
commit
fb006e13a0
57
consumer/src/main/java/cn/lili/event/impl/PointExecute.java
Normal file
57
consumer/src/main/java/cn/lili/event/impl/PointExecute.java
Normal file
@ -0,0 +1,57 @@
|
||||
package cn.lili.event.impl;
|
||||
|
||||
import cn.lili.event.OrderStatusChangeEvent;
|
||||
import cn.lili.modules.member.entity.enums.PointTypeEnum;
|
||||
import cn.lili.modules.member.service.MemberService;
|
||||
import cn.lili.modules.order.order.entity.dos.Order;
|
||||
import cn.lili.modules.order.order.entity.dto.OrderMessage;
|
||||
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
|
||||
import cn.lili.modules.order.order.service.OrderService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 积分
|
||||
*
|
||||
* @author Chopper
|
||||
* @since 2021-03-13 16:58
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PointExecute implements OrderStatusChangeEvent {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@Override
|
||||
public void orderChange(OrderMessage orderMessage) {
|
||||
|
||||
switch (orderMessage.getNewStatus()) {
|
||||
case CANCELLED:
|
||||
Order order = orderService.getBySn(orderMessage.getOrderSn());
|
||||
Long point = order.getPriceDetailDTO().getPayPoint();
|
||||
if (point <= 0) {
|
||||
return;
|
||||
}
|
||||
//如果未付款,则不去要退回相关代码执行
|
||||
if (order.getPayStatus().equals(PayStatusEnum.UNPAID.name())) {
|
||||
return;
|
||||
}
|
||||
//如果他不处于连续赠送阶段,则只赠送签到积分数
|
||||
String content = "订单取消,积分返还:" + point + "分";
|
||||
//赠送会员积分
|
||||
memberService.updateMemberPoint(point, PointTypeEnum.INCREASE.name(), order.getMemberId(), content);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -15,10 +15,7 @@ import cn.lili.modules.promotion.entity.dos.KanjiaActivity;
|
||||
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
|
||||
import cn.lili.modules.promotion.entity.dto.KanjiaActivityGoodsDTO;
|
||||
import cn.lili.modules.promotion.entity.vos.PointsGoodsVO;
|
||||
import cn.lili.modules.promotion.service.KanjiaActivityGoodsService;
|
||||
import cn.lili.modules.promotion.service.KanjiaActivityService;
|
||||
import cn.lili.modules.promotion.service.PointsGoodsService;
|
||||
import cn.lili.modules.promotion.service.PromotionGoodsService;
|
||||
import cn.lili.modules.promotion.service.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
@ -65,11 +62,17 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
*/
|
||||
@Autowired
|
||||
private PromotionGoodsService promotionGoodsService;
|
||||
/**
|
||||
* 促销商品
|
||||
*/
|
||||
@Autowired
|
||||
private SeckillApplyService seckillApplyService;
|
||||
/**
|
||||
* 缓存
|
||||
*/
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private KanjiaActivityService kanjiaActivityService;
|
||||
@Autowired
|
||||
@ -95,6 +98,11 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
values.add(Integer.toString(i));
|
||||
setPromotionStock(keys, values, orderItem);
|
||||
}
|
||||
|
||||
List<Integer> stocks = cache.multiGet(keys);
|
||||
//如果缓存中不存在存在等量的库存值,则重新写入缓存,防止缓存击穿导致无法下单
|
||||
checkStocks(stocks, order);
|
||||
|
||||
//库存扣除结果
|
||||
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
|
||||
//如果库存扣减都成功,则记录成交订单
|
||||
@ -142,6 +150,75 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验库存是否有效
|
||||
*
|
||||
* @param stocks
|
||||
*/
|
||||
private void checkStocks(List<Integer> stocks, OrderDetailVO order) {
|
||||
for (int i = 0; i < stocks.size(); i++) {
|
||||
if (null == stocks.get(i)) {
|
||||
initSkuCache(order.getOrderItems());
|
||||
initPromotionCache(order.getOrderItems());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存中sku库存值不存在时,将不存在的信息重新写入一边
|
||||
*
|
||||
* @param orderItems
|
||||
*/
|
||||
private void initSkuCache(List<OrderItem> orderItems) {
|
||||
orderItems.forEach(orderItem -> {
|
||||
//如果不存在
|
||||
if (!cache.hasKey(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()))) {
|
||||
//内部会自动写入,这里不需要进行二次处理
|
||||
goodsSkuService.getStock(orderItem.getSkuId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化促销商品缓存
|
||||
*
|
||||
* @param orderItems
|
||||
*/
|
||||
private void initPromotionCache(List<OrderItem> orderItems) {
|
||||
|
||||
//如果促销类型需要库存判定,则做对应处理
|
||||
orderItems.forEach(orderItem -> {
|
||||
if (orderItem.getPromotionType() != null) {
|
||||
//如果此促销有库存概念,则计入
|
||||
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
|
||||
|
||||
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
|
||||
|
||||
String cacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
|
||||
|
||||
switch (promotionTypeEnum) {
|
||||
case KANJIA:
|
||||
cache.put(cacheKey, kanjiaActivityGoodsService.getKanJiaGoodsBySku(orderItem.getSkuId()).getStock().intValue());
|
||||
return;
|
||||
case POINTS_GOODS:
|
||||
cache.put(cacheKey, pointsGoodsService.getPointsGoodsVOByMongo(orderItem.getSkuId()).getActiveStock().intValue());
|
||||
return;
|
||||
case SECKILL:
|
||||
case PINTUAN:
|
||||
cache.put(cacheKey, promotionGoodsService.getPromotionGoodsStock(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId()));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单出库失败
|
||||
*
|
||||
@ -208,13 +285,12 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
|
||||
List promotionStocks = cache.multiGet(promotionKey);
|
||||
//修改砍价商品库存
|
||||
if (promotionTypeEnum.equals(PromotionTypeEnum.KANJIA)) {
|
||||
KanjiaActivity kanjiaActivity=kanjiaActivityService.getById(orderItem.getPromotionId());
|
||||
KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO=kanjiaActivityGoodsService.getKanjiaGoodsDetail(kanjiaActivity.getKanjiaActivityGoodsId());
|
||||
KanjiaActivity kanjiaActivity = kanjiaActivityService.getById(orderItem.getPromotionId());
|
||||
KanjiaActivityGoodsDTO kanjiaActivityGoodsDTO = kanjiaActivityGoodsService.getKanjiaGoodsDetail(kanjiaActivity.getKanjiaActivityGoodsId());
|
||||
kanjiaActivityGoodsDTO.setStock(Convert.toInt(promotionStocks.get(0).toString()));
|
||||
kanjiaActivityGoodsService.updateById(kanjiaActivityGoodsDTO);
|
||||
this.mongoTemplate.save(kanjiaActivityGoodsDTO);
|
||||
orderItem.getPromotionId();
|
||||
//修改积分商品库存
|
||||
//修改积分商品库存
|
||||
} else if (promotionTypeEnum.equals(PromotionTypeEnum.POINTS_GOODS)) {
|
||||
PointsGoodsVO pointsGoodsVO = pointsGoodsService.getPointsGoodsDetail(orderItem.getPromotionId());
|
||||
pointsGoodsVO.setActiveStock(Convert.toLong(promotionStocks.get(0).toString()));
|
||||
|
@ -178,15 +178,15 @@ public class GoodsMessageListener implements RocketMQListener<MessageExt> {
|
||||
*/
|
||||
private void updateGoodsNum(MessageExt messageExt) {
|
||||
|
||||
Goods goods = null;
|
||||
Goods goods;
|
||||
try {
|
||||
goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class);
|
||||
//更新店铺商品数量
|
||||
assert goods != null;
|
||||
storeService.updateStoreGoodsNum(goods.getStoreId());
|
||||
} catch (Exception e) {
|
||||
log.error("商品传输信息错误-{}", messageExt.toString());
|
||||
log.error("商品MQ信息错误:{}", messageExt.toString());
|
||||
}
|
||||
//更新店铺商品数量
|
||||
assert goods != null;
|
||||
storeService.updateStoreGoodsNum(goods.getStoreId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.lili.timetask.handler.impl.coupon;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
|
||||
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
|
||||
import cn.lili.modules.promotion.service.MemberCouponService;
|
||||
@ -18,6 +17,11 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class CouponExecute implements EveryDayExecute {
|
||||
|
||||
/**
|
||||
* 过期常量,过期后或者使用后一定时间内,删除无效的优惠券,物理删除
|
||||
*/
|
||||
static final int EXPIRATION_DAY = 7;
|
||||
|
||||
@Autowired
|
||||
private MemberCouponService memberCouponService;
|
||||
|
||||
@ -27,12 +31,19 @@ public class CouponExecute implements EveryDayExecute {
|
||||
*/
|
||||
@Override
|
||||
public void execute() {
|
||||
//将过期优惠券变更为过期状体
|
||||
LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
|
||||
.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
|
||||
.le(MemberCoupon::getEndTime, DateUtil.date())
|
||||
.le(MemberCoupon::getEndTime, System.currentTimeMillis())
|
||||
.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
|
||||
this.memberCouponService.update(updateWrapper);
|
||||
|
||||
//删除过期/已使用的优惠券
|
||||
LambdaUpdateWrapper<MemberCoupon> deleteWrapper = new LambdaUpdateWrapper<MemberCoupon>()
|
||||
//如果结束时间小于 当前时间增加指定删除日期,则删除
|
||||
.le(MemberCoupon::getEndTime, System.currentTimeMillis() + 24 * 60 * 60 * 1000 * EXPIRATION_DAY);
|
||||
this.memberCouponService.remove(deleteWrapper);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public enum PromotionTypeEnum {
|
||||
/**
|
||||
* 有促销库存的活动类型
|
||||
*/
|
||||
static PromotionTypeEnum[] haveStockPromotion = new PromotionTypeEnum[]{SECKILL, KANJIA, POINTS_GOODS};
|
||||
static PromotionTypeEnum[] haveStockPromotion = new PromotionTypeEnum[]{PINTUAN, SECKILL, KANJIA, POINTS_GOODS};
|
||||
|
||||
private final String description;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.lili.modules.order.cart.render;
|
||||
|
||||
import cn.lili.common.exception.ServiceException;
|
||||
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
|
||||
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
|
||||
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
|
||||
@ -125,6 +126,8 @@ public class TradeBuilder {
|
||||
if (render.step().equals(step)) {
|
||||
render.render(tradeDTO);
|
||||
}
|
||||
} catch (ServiceException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("购物车{}渲染异常:", render.getClass(), e);
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ public class CartPriceRender implements CartRenderStep {
|
||||
List<CartVO> cartVOS = tradeDTO.getCartList();
|
||||
|
||||
cartVOS.forEach(cartVO -> {
|
||||
|
||||
List<PriceDetailDTO> skuPrices = cartVO.getSkuList().stream().filter(CartSkuVO::getChecked)
|
||||
.map(CartSkuVO::getPriceDetailDTO).collect(Collectors.toList());
|
||||
cartVO.getPriceDetailDTO().accumulationPriceDTO(
|
||||
cartVO.getSkuList().stream().filter(CartSkuVO::getChecked)
|
||||
.map(CartSkuVO::getPriceDetailDTO).collect(Collectors.toList())
|
||||
|
@ -85,6 +85,13 @@ public class CheckDataRender implements CartRenderStep {
|
||||
private void checkData(TradeDTO tradeDTO) {
|
||||
//循环购物车中的商品
|
||||
for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
|
||||
|
||||
//如果失效,确认sku为未选中状态
|
||||
if (cartSkuVO.getInvalid()) {
|
||||
//设置购物车未选中
|
||||
cartSkuVO.setChecked(false);
|
||||
}
|
||||
|
||||
//缓存中的商品信息
|
||||
GoodsSku dataSku = goodsSkuService.getGoodsSkuByIdFromCache(cartSkuVO.getGoodsSku().getId());
|
||||
//商品有效性判定
|
||||
|
@ -86,7 +86,7 @@ public class SkuPromotionRender implements CartRenderStep {
|
||||
for (CartVO cartVO : tradeDTO.getCartList()) {
|
||||
for (CartSkuVO cartSkuVO : cartVO.getSkuList()) {
|
||||
cartSkuVO.getPriceDetailDTO().setPayPoint(cartSkuVO.getPoint());
|
||||
PromotionSkuVO promotionSkuVO = new PromotionSkuVO(PromotionTypeEnum.PINTUAN.name(), cartSkuVO.getPointsId());
|
||||
PromotionSkuVO promotionSkuVO = new PromotionSkuVO(PromotionTypeEnum.POINTS_GOODS.name(), cartSkuVO.getPointsId());
|
||||
cartSkuVO.getPriceDetailDTO().getJoinPromotion().add(promotionSkuVO);
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,6 @@ public class PintuanServiceImpl extends ServiceImpl<PintuanMapper, Pintuan> impl
|
||||
@Override
|
||||
public boolean addPintuan(PintuanVO pintuan) {
|
||||
PromotionTools.checkPromotionTime(pintuan.getStartTime().getTime(), pintuan.getEndTime().getTime());
|
||||
this.checkSamePromotion(pintuan.getStartTime(), pintuan.getEndTime(), pintuan.getStoreId(), null);
|
||||
pintuan.setPromotionStatus(PromotionStatusEnum.NEW.name());
|
||||
//保存到MYSQL中
|
||||
boolean result = this.save(pintuan);
|
||||
@ -224,8 +223,6 @@ public class PintuanServiceImpl extends ServiceImpl<PintuanMapper, Pintuan> impl
|
||||
}
|
||||
//检查促销时间
|
||||
PromotionTools.checkPromotionTime(pintuan.getStartTime().getTime(), pintuan.getEndTime().getTime());
|
||||
//检查同一时间,同一店铺,同一类型的促销活动
|
||||
this.checkSamePromotion(pintuan.getStartTime(), pintuan.getEndTime(), pintuan.getStoreId(), pintuan.getId());
|
||||
boolean result = this.updateById(pintuan);
|
||||
if (pintuan.getPromotionGoodsList() != null) {
|
||||
this.updatePintuanPromotionGoods(pintuan);
|
||||
@ -393,14 +390,10 @@ public class PintuanServiceImpl extends ServiceImpl<PintuanMapper, Pintuan> impl
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSamePromotion(Date startTime, Date endTime, String storeId, String pintuanId) {
|
||||
QueryWrapper<Pintuan> queryWrapper = PromotionTools.checkActiveTime(startTime, endTime, PromotionTypeEnum.PINTUAN, storeId, pintuanId);
|
||||
List<Pintuan> list = this.list(queryWrapper);
|
||||
if (!list.isEmpty()) {
|
||||
throw new ServiceException(ResultCode.PROMOTION_SAME_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加拼团定时任务
|
||||
* @param pintuan
|
||||
*/
|
||||
private void addPintuanStartTask(PintuanVO pintuan) {
|
||||
PromotionMessage promotionMessage = new PromotionMessage(pintuan.getId(), PromotionTypeEnum.PINTUAN.name(), PromotionStatusEnum.START.name(), pintuan.getStartTime(), pintuan.getEndTime());
|
||||
TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.PROMOTION_EXECUTOR,
|
||||
|
@ -2,6 +2,8 @@ package cn.lili.modules.promotion.serviceimpl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.lili.common.enums.ResultCode;
|
||||
import cn.lili.common.security.context.UserContext;
|
||||
import cn.lili.common.security.enums.UserEnums;
|
||||
import cn.lili.trigger.util.DelayQueueTools;
|
||||
import cn.lili.trigger.enums.DelayTypeEnums;
|
||||
import cn.lili.trigger.message.PromotionMessage;
|
||||
@ -226,6 +228,9 @@ public class PointsGoodsServiceImpl extends ServiceImpl<PointsGoodsMapper, Point
|
||||
@Override
|
||||
public IPage<PointsGoodsVO> getPointsGoodsByPage(PointsGoodsSearchParams searchParams, PageVO page) {
|
||||
IPage<PointsGoodsVO> pointsGoodsPage = new Page<>();
|
||||
if (UserContext.getCurrentUser().getRole().equals(UserEnums.MEMBER)) {
|
||||
searchParams.setPromotionStatus(PromotionStatusEnum.START.name());
|
||||
}
|
||||
Query query = searchParams.mongoQuery();
|
||||
if (page != null) {
|
||||
PromotionTools.mongoQueryPageParam(query, page);
|
||||
|
Loading…
x
Reference in New Issue
Block a user