From fb006e13a0ea8351965209655f92282f367db11a Mon Sep 17 00:00:00 2001 From: Chopper Date: Wed, 1 Sep 2021 19:10:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8=E5=90=8C?= =?UTF-8?q?=E4=B8=80=E5=BA=97=E9=93=BA=E5=90=8C=E4=B8=80=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=99=90=E5=88=B6=E4=B8=80=E4=B8=AA=E6=B4=BB=E5=8A=A8=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E3=80=82=20=E7=A7=AF=E5=88=86=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=BA=93=E5=AD=98=E6=89=A3=E5=87=8F=EF=BC=8C=E7=A7=AF=E5=88=86?= =?UTF-8?q?=E8=BF=94=E8=BF=98=E5=A4=84=E7=90=86=E3=80=82=20=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E4=BF=83=E9=94=80=E7=9B=B8=E5=85=B3=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/lili/event/impl/PointExecute.java | 57 ++++++++++++ .../lili/event/impl/StockUpdateExecute.java | 92 +++++++++++++++++-- .../lili/listener/GoodsMessageListener.java | 10 +- .../handler/impl/coupon/CouponExecute.java | 15 ++- .../lili/common/enums/PromotionTypeEnum.java | 2 +- .../order/cart/render/TradeBuilder.java | 3 + .../cart/render/impl/CartPriceRender.java | 3 + .../cart/render/impl/CheckDataRender.java | 7 ++ .../cart/render/impl/SkuPromotionRender.java | 2 +- .../serviceimpl/PintuanServiceImpl.java | 15 +-- .../serviceimpl/PointsGoodsServiceImpl.java | 5 + 11 files changed, 183 insertions(+), 28 deletions(-) create mode 100644 consumer/src/main/java/cn/lili/event/impl/PointExecute.java diff --git a/consumer/src/main/java/cn/lili/event/impl/PointExecute.java b/consumer/src/main/java/cn/lili/event/impl/PointExecute.java new file mode 100644 index 00000000..be034348 --- /dev/null +++ b/consumer/src/main/java/cn/lili/event/impl/PointExecute.java @@ -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; + } + + + } + + +} diff --git a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java index b94cbbad..25bc98a6 100644 --- a/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/StockUpdateExecute.java @@ -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 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 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 orderItems) { + orderItems.forEach(orderItem -> { + //如果不存在 + if (!cache.hasKey(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()))) { + //内部会自动写入,这里不需要进行二次处理 + goodsSkuService.getStock(orderItem.getSkuId()); + } + }); + } + + /** + * 初始化促销商品缓存 + * + * @param orderItems + */ + private void initPromotionCache(List 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())); diff --git a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java index e0955456..5a5975d4 100644 --- a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java @@ -178,15 +178,15 @@ public class GoodsMessageListener implements RocketMQListener { */ 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()); } /** diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java index bb56133c..d1245fc5 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/coupon/CouponExecute.java @@ -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 updateWrapper = new LambdaUpdateWrapper() .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 deleteWrapper = new LambdaUpdateWrapper() + //如果结束时间小于 当前时间增加指定删除日期,则删除 + .le(MemberCoupon::getEndTime, System.currentTimeMillis() + 24 * 60 * 60 * 1000 * EXPIRATION_DAY); + this.memberCouponService.remove(deleteWrapper); + } } diff --git a/framework/src/main/java/cn/lili/common/enums/PromotionTypeEnum.java b/framework/src/main/java/cn/lili/common/enums/PromotionTypeEnum.java index 0066632d..68006dac 100644 --- a/framework/src/main/java/cn/lili/common/enums/PromotionTypeEnum.java +++ b/framework/src/main/java/cn/lili/common/enums/PromotionTypeEnum.java @@ -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; diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java b/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java index 4e08d8a2..75cfa3bd 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java @@ -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); } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CartPriceRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CartPriceRender.java index d704192d..a6508cf2 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CartPriceRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CartPriceRender.java @@ -58,6 +58,9 @@ public class CartPriceRender implements CartRenderStep { List cartVOS = tradeDTO.getCartList(); cartVOS.forEach(cartVO -> { + + List 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()) diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java index 676ee916..a6aa65b0 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java @@ -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()); //商品有效性判定 diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java index 31f137fd..9e74a528 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuPromotionRender.java @@ -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); } } diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java index 9b1675fd..474bb4ec 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PintuanServiceImpl.java @@ -206,7 +206,6 @@ public class PintuanServiceImpl extends ServiceImpl 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 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 impl } } - private void checkSamePromotion(Date startTime, Date endTime, String storeId, String pintuanId) { - QueryWrapper queryWrapper = PromotionTools.checkActiveTime(startTime, endTime, PromotionTypeEnum.PINTUAN, storeId, pintuanId); - List 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, diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java index 126af0b3..acee95ac 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PointsGoodsServiceImpl.java @@ -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 getPointsGoodsByPage(PointsGoodsSearchParams searchParams, PageVO page) { IPage 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);