diff --git a/consumer/src/main/java/cn/lili/event/impl/MemberWalletExecute.java b/consumer/src/main/java/cn/lili/event/impl/MemberWalletExecute.java index 49274773..79713ce2 100644 --- a/consumer/src/main/java/cn/lili/event/impl/MemberWalletExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/MemberWalletExecute.java @@ -21,6 +21,7 @@ public class MemberWalletExecute implements MemberRegisterEvent { @Override public void memberRegister(Member member) { - memberWalletService.save(member.getId(),member.getUsername()); + // 有些情况下,会同时创建一个member_id的两条数据 +// memberWalletService.save(member.getId(),member.getUsername()); } } diff --git a/consumer/src/main/java/cn/lili/event/impl/OrderCreateReceiptExecute.java b/consumer/src/main/java/cn/lili/event/impl/OrderCreateReceiptExecute.java index 36826a60..a7126774 100644 --- a/consumer/src/main/java/cn/lili/event/impl/OrderCreateReceiptExecute.java +++ b/consumer/src/main/java/cn/lili/event/impl/OrderCreateReceiptExecute.java @@ -8,7 +8,6 @@ import cn.lili.modules.order.order.entity.dos.Receipt; import cn.lili.modules.order.order.entity.vo.OrderVO; import cn.lili.modules.order.order.entity.vo.ReceiptVO; import cn.lili.modules.order.order.service.ReceiptService; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,25 +33,23 @@ public class OrderCreateReceiptExecute implements TradeEvent { //获取发票信息 ReceiptVO receiptVO = tradeDTO.getReceiptVO(); //如果需要获取发票则保存发票信息 - if (tradeDTO.getNeedReceipt()) { - if (orderList.size() > 0) { - List receipts = new ArrayList<>(); - for (OrderVO orderVO : orderList) { - Receipt receipt = new Receipt(); - BeanUtil.copyProperties(receiptVO, receipt); - receipt.setMemberId(orderVO.getMemberId()); - receipt.setMemberName(orderVO.getMemberName()); - receipt.setStoreId(orderVO.getStoreId()); - receipt.setStoreName(orderVO.getStoreName()); - receipt.setOrderSn(orderVO.getSn()); - receipt.setReceiptDetail(JSONUtil.toJsonStr(orderVO.getOrderItems())); - receipt.setReceiptPrice(orderVO.getFlowPrice()); - receipt.setReceiptStatus(0); - receipts.add(receipt); - } - //保存发票 - receiptService.saveBatch(receipts); + if (Boolean.TRUE.equals(tradeDTO.getNeedReceipt()) && !orderList.isEmpty()) { + List receipts = new ArrayList<>(); + for (OrderVO orderVO : orderList) { + Receipt receipt = new Receipt(); + BeanUtil.copyProperties(receiptVO, receipt); + receipt.setMemberId(orderVO.getMemberId()); + receipt.setMemberName(orderVO.getMemberName()); + receipt.setStoreId(orderVO.getStoreId()); + receipt.setStoreName(orderVO.getStoreName()); + receipt.setOrderSn(orderVO.getSn()); + receipt.setReceiptDetail(JSONUtil.toJsonStr(orderVO.getOrderItems())); + receipt.setReceiptPrice(orderVO.getFlowPrice()); + receipt.setReceiptStatus(0); + receipts.add(receipt); } + //保存发票 + receiptService.saveBatch(receipts); } } } diff --git a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java index 3900de1f..a18c3d03 100644 --- a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java @@ -186,12 +186,28 @@ public class GoodsMessageListener implements RocketMQListener { break; //审核商品 case GOODS_AUDIT: - updateGoodsNum(messageExt); + Goods goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class); + updateGoodsNum(goods); break; //删除商品 case GOODS_DELETE: - deleteGoods(messageExt); - updateGoodsNum(messageExt); + try { + String goodsIdsJsonStr = new String(messageExt.getBody()); + for (String goodsId : JSONUtil.toList(goodsIdsJsonStr, String.class)) { + Goods goodsById = this.goodsService.getById(goodsId); + if (goodsById != null) { + this.deleteGoods(goodsById); + this.updateGoodsNum(goodsById); + List skuIdsByGoodsId = this.goodsSkuService.getSkuIdsByGoodsId(goodsId); + if (skuIdsByGoodsId != null && !skuIdsByGoodsId.isEmpty()) { + this.goodsIndexService.deleteIndexByIds(skuIdsByGoodsId); + } + } + } + + } catch (Exception e) { + log.error("删除商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody())); + } break; //规格删除 case SKU_DELETE: @@ -380,10 +396,9 @@ public class GoodsMessageListener implements RocketMQListener { * 2.删除分销员-分销商品绑定关系 * 3.删除分销商品 * - * @param messageExt 消息 + * @param goods 消息 */ - private void deleteGoods(MessageExt messageExt) { - Goods goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class); + private void deleteGoods(Goods goods) { DistributionGoodsSearchParams searchParams = new DistributionGoodsSearchParams(); searchParams.setGoodsId(goods.getId()); @@ -403,17 +418,15 @@ public class GoodsMessageListener implements RocketMQListener { /** * 修改商品数量 * - * @param messageExt 信息体 + * @param goods 信息体 */ - private void updateGoodsNum(MessageExt messageExt) { - + private void updateGoodsNum(Goods goods) { try { - Goods goods = JSONUtil.toBean(new String(messageExt.getBody()), Goods.class); //更新店铺商品数量 assert goods != null; storeService.updateStoreGoodsNum(goods.getStoreId()); } catch (Exception e) { - log.error("商品MQ信息错误:{}", messageExt.toString()); + log.error("修改商品数量错误"); } } diff --git a/consumer/src/main/java/cn/lili/listener/OrderMessageListener.java b/consumer/src/main/java/cn/lili/listener/OrderMessageListener.java index 29f5bda7..d72ff5fd 100644 --- a/consumer/src/main/java/cn/lili/listener/OrderMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/OrderMessageListener.java @@ -62,7 +62,7 @@ public class OrderMessageListener implements RocketMQListener { //订单创建 case ORDER_CREATE: String key = new String(messageExt.getBody()); - TradeDTO tradeDTO = (TradeDTO) cache.get(key); + TradeDTO tradeDTO = JSONUtil.toBean(cache.getString(key), TradeDTO.class); boolean result = true; for (TradeEvent event : tradeEvent) { try { diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java index bad47e54..c996005a 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java @@ -44,7 +44,7 @@ public class PromotionEverydayExecute implements EveryDayExecute { */ @Override public void execute() { - //查询条件 + //清除所以商品索引的无效促销活动 this.esGoodsIndexService.cleanInvalidPromotion(); //定时创建活动 addSeckill(); diff --git a/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java b/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java index 478470d2..22a709ad 100644 --- a/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java +++ b/framework/src/main/java/cn/lili/elasticsearch/config/ElasticsearchConfig.java @@ -71,7 +71,7 @@ public class ElasticsearchConfig extends AbstractElasticsearchConfiguration { @Bean("elasticsearchRestTemplate") public ElasticsearchRestTemplate elasticsearchRestTemplate() { - return new ElasticsearchRestTemplate(elasticsearchClient()); + return new ElasticsearchRestTemplate(this.client); } private HttpHost[] getHttpHosts() { diff --git a/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java b/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java index 304b8cd9..62f65589 100644 --- a/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java +++ b/framework/src/main/java/cn/lili/modules/goods/mapper/GoodsSkuMapper.java @@ -2,6 +2,9 @@ package cn.lili.modules.goods.mapper; import cn.lili.modules.goods.entity.dos.GoodsSku; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; /** * 规格项数据处理层 @@ -11,4 +14,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface GoodsSkuMapper extends BaseMapper { + /** + * 根据商品id获取全部skuId的集合 + * + * @param goodsId goodsId + * @return 全部skuId的集合 + */ + @Select("SELECT id FROM li_goods_sku WHERE goods_id = #{goodsId}") + List getGoodsSkuIdByGoodsId(String goodsId); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java index 03bd3276..c300a39b 100644 --- a/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java +++ b/framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java @@ -202,4 +202,12 @@ public interface GoodsSkuService extends IService { * @param promotionPrice 促销价格 */ void updateGoodsSkuPromotion(String skuId, Double promotionPrice); + + /** + * 根据商品id获取全部skuId的集合 + * + * @param goodsId goodsId + * @return 全部skuId的集合 + */ + List getSkuIdsByGoodsId(String goodsId); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java index a8887da8..101ad3ee 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java @@ -304,6 +304,14 @@ public class GoodsServiceImpl extends ServiceImpl implements for (Goods goods : goodsList) { goodsSkuService.updateGoodsSkuStatus(goods); } + + if (GoodsStatusEnum.DOWN.equals(goodsStatusEnum)) { + + //商品删除消息 + String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name(); + //发送mq消息 + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIds), RocketmqSendCallbackBuilder.commonCallback()); + } return result; } @@ -351,12 +359,13 @@ public class GoodsServiceImpl extends ServiceImpl implements for (Goods goods : goodsList) { //修改SKU状态 goodsSkuService.updateGoodsSkuStatus(goods); - //商品删除消息 - String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name(); - //发送mq消息 - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goods), RocketmqSendCallbackBuilder.commonCallback()); } + //商品删除消息 + String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name(); + //发送mq消息 + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIds), RocketmqSendCallbackBuilder.commonCallback()); + return true; } diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java index 37d3268c..77526c48 100644 --- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java @@ -2,6 +2,7 @@ package cn.lili.modules.goods.serviceimpl; import cn.hutool.core.convert.Convert; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; @@ -13,7 +14,6 @@ import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.context.UserContext; -import cn.lili.common.utils.StringUtils; import cn.lili.modules.goods.entity.dos.Goods; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.dto.GoodsSearchParams; @@ -221,7 +221,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl i //获取商品VO GoodsVO goodsVO = goodsService.getGoodsVO(goodsId); //如果skuid为空,则使用商品VO中sku信息获取 - if (StringUtils.isEmpty(skuId) || "undefined".equals(skuId)) { + if (CharSequenceUtil.isEmpty(skuId) || "undefined".equals(skuId)) { skuId = goodsVO.getSkuList().get(0).getId(); } //从缓存拿商品Sku @@ -532,6 +532,17 @@ public class GoodsSkuServiceImpl extends ServiceImpl i cache.remove(GoodsSkuService.getCacheKeys(skuId)); } + /** + * 根据商品id获取全部skuId的集合 + * + * @param goodsId goodsId + * @return 全部skuId的集合 + */ + @Override + public List getSkuIdsByGoodsId(String goodsId) { + return this.baseMapper.getGoodsSkuIdByGoodsId(goodsId); + } + /** * 发送生成ES商品索引 * @@ -539,6 +550,10 @@ public class GoodsSkuServiceImpl extends ServiceImpl i */ @Override public void generateEs(Goods goods) { + // 不生成没有审核通过且没有上架的商品 + if (!GoodsStatusEnum.UPPER.name().equals(goods.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) { + return; + } ThreadUtil.execAsync(() -> { try { // 延时执行,防止商品未保存完成就去生成商品索引导致生成索引时找不到商品问题 diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java index 342a36ed..213264bc 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/TradeServiceImpl.java @@ -1 +1 @@ -package cn.lili.modules.order.order.serviceimpl; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; 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.vo.CartVO; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.entity.dos.KanjiaActivity; import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @date 2020/11/17 7:39 下午 */ @Service @Transactional(rollbackFor = Exception.class) public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, tradeDTO); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO */ private void createTradeCheck(TradeDTO tradeDTO) { //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } /** * 订单配送区域校验 */ if (tradeDTO.getNotSupportFreight() != null && tradeDTO.getNotSupportFreight().size() > 0) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> { stringBuilder.append(sku.getGoodsSku().getGoodsName()); }); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint().longValue(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.update(new LambdaUpdateWrapper() .eq(KanjiaActivity::getId, kanjiaId) .set(KanjiaActivity::getStatus, KanJiaStatusEnum.END.name())); } } } \ No newline at end of file +package cn.lili.modules.order.order.serviceimpl; import cn.hutool.json.JSONUtil; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.member.entity.enums.PointTypeEnum; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; 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.vo.CartVO; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.enums.PayStatusEnum; import cn.lili.modules.order.order.mapper.TradeMapper; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.order.order.service.TradeService; import cn.lili.modules.promotion.entity.dos.KanjiaActivity; import cn.lili.modules.promotion.entity.enums.KanJiaStatusEnum; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.KanjiaActivityService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import cn.lili.rocketmq.tags.OrderTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; /** * 交易业务层实现 * * @author Chopper * @date 2020/11/17 7:39 下午 */ @Service @Transactional(rollbackFor = Exception.class) public class TradeServiceImpl extends ServiceImpl implements TradeService { /** * 缓存 */ @Autowired private Cache cache; /** * 订单 */ @Autowired private OrderService orderService; /** * 会员 */ @Autowired private MemberService memberService; /** * 优惠券 */ @Autowired private CouponService couponService; /** * 会员优惠券 */ @Autowired private MemberCouponService memberCouponService; /** * 砍价 */ @Autowired private KanjiaActivityService kanjiaActivityService; /** * RocketMQ */ @Autowired private RocketMQTemplate rocketMQTemplate; /** * RocketMQ 配置 */ @Autowired private RocketmqCustomProperties rocketmqCustomProperties; @Override @Transactional(rollbackFor = Exception.class) public Trade createTrade(TradeDTO tradeDTO) { //创建订单预校验 createTradeCheck(tradeDTO); Trade trade = new Trade(tradeDTO); String key = CachePrefix.TRADE.getPrefix() + trade.getSn(); //优惠券预处理 couponPretreatment(tradeDTO); //积分预处理 pointPretreatment(tradeDTO); //添加交易 this.save(trade); //添加订单 orderService.intoDB(tradeDTO); //砍价订单处理 kanjiaPretreatment(tradeDTO); //写入缓存,给消费者调用 cache.put(key, JSONUtil.toJsonStr(tradeDTO)); //构建订单创建消息 String destination = rocketmqCustomProperties.getOrderTopic() + ":" + OrderTagsEnum.ORDER_CREATE.name(); //发送订单创建消息 rocketMQTemplate.asyncSend(destination, key, RocketmqSendCallbackBuilder.commonCallback()); return trade; } /** * 创建订单最后一步校验 * * @param tradeDTO */ private void createTradeCheck(TradeDTO tradeDTO) { //创建订单如果没有收获地址, MemberAddress memberAddress = tradeDTO.getMemberAddress(); if (memberAddress == null) { throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } /** * 订单配送区域校验 */ if (tradeDTO.getNotSupportFreight() != null && tradeDTO.getNotSupportFreight().size() > 0) { StringBuilder stringBuilder = new StringBuilder("包含商品有-"); tradeDTO.getNotSupportFreight().forEach(sku -> { stringBuilder.append(sku.getGoodsSku().getGoodsName()); }); throw new ServiceException(ResultCode.ORDER_NOT_SUPPORT_DISTRIBUTION, stringBuilder.toString()); } } @Override public Trade getBySn(String sn) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Trade::getSn, sn); return this.getOne(queryWrapper); } @Override public void payTrade(String tradeSn, String paymentName, String receivableNo) { LambdaQueryWrapper orderQueryWrapper = new LambdaQueryWrapper<>(); orderQueryWrapper.eq(Order::getTradeSn, tradeSn); List orders = orderService.list(orderQueryWrapper); for (Order order : orders) { orderService.payOrder(order.getSn(), paymentName, receivableNo); } Trade trade = this.getBySn(tradeSn); trade.setPayStatus(PayStatusEnum.PAID.name()); this.saveOrUpdate(trade); } /** * 优惠券预处理 * 下单同时,扣除优惠券 * * @param tradeDTO */ private void couponPretreatment(TradeDTO tradeDTO) { List memberCouponDTOList = new ArrayList<>(); if (null != tradeDTO.getPlatformCoupon()) { memberCouponDTOList.add(tradeDTO.getPlatformCoupon()); } Collection storeCoupons = tradeDTO.getStoreCoupons().values(); if (!storeCoupons.isEmpty()) { memberCouponDTOList.addAll(storeCoupons); } List ids = memberCouponDTOList.stream().map(e -> e.getMemberCoupon().getId()).collect(Collectors.toList()); memberCouponService.used(ids); memberCouponDTOList.forEach(e -> couponService.usedCoupon(e.getMemberCoupon().getCouponId(), 1)); } /** * 创建交易,积分处理 * * @param tradeDTO */ private void pointPretreatment(TradeDTO tradeDTO) { //需要支付积分 if (tradeDTO.getPriceDetailDTO() != null && tradeDTO.getPriceDetailDTO().getPayPoint() != null && tradeDTO.getPriceDetailDTO().getPayPoint() > 0) { StringBuilder orderSns = new StringBuilder(); for (CartVO item : tradeDTO.getCartList()) { orderSns.append(item.getSn()); } boolean result = memberService.updateMemberPoint(tradeDTO.getPriceDetailDTO().getPayPoint().longValue(), PointTypeEnum.REDUCE.name(), tradeDTO.getMemberId(), "订单【" + orderSns + "】创建,积分扣减"); if (!result) { throw new ServiceException(ResultCode.PAY_POINT_ENOUGH); } } } /** * 创建交易、砍价处理 * * @param tradeDTO */ private void kanjiaPretreatment(TradeDTO tradeDTO) { if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.KANJIA)) { String kanjiaId = tradeDTO.getSkuList().get(0).getKanjiaId(); kanjiaActivityService.update(new LambdaUpdateWrapper() .eq(KanjiaActivity::getId, kanjiaId) .set(KanjiaActivity::getStatus, KanJiaStatusEnum.END.name())); } } } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/vos/CouponSearchParams.java b/framework/src/main/java/cn/lili/modules/promotion/entity/vos/CouponSearchParams.java index a57b6b85..279c73b0 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/entity/vos/CouponSearchParams.java +++ b/framework/src/main/java/cn/lili/modules/promotion/entity/vos/CouponSearchParams.java @@ -93,8 +93,8 @@ public class CouponSearchParams extends BasePromotionsSearchParams implements Se queryWrapper.nested(i -> i.gt(PromotionTools.START_TIME_COLUMN, new Date()).gt(PromotionTools.END_TIME_COLUMN, new Date())); break; case START: - queryWrapper.nested(i -> i.le(PromotionTools.START_TIME_COLUMN, new Date()).ge(PromotionTools.END_TIME_COLUMN, new Date())); -// .or(i -> i.gt("effective_days", 0).eq(RANGE_DAY_TYPE_COLUMN, CouponRangeDayEnum.DYNAMICTIME.name())); + queryWrapper.nested(i -> i.le(PromotionTools.START_TIME_COLUMN, new Date()).ge(PromotionTools.END_TIME_COLUMN, new Date())) + .or(i -> i.gt("effective_days", 0).eq(RANGE_DAY_TYPE_COLUMN, CouponRangeDayEnum.DYNAMICTIME.name())); break; case END: queryWrapper.nested(i -> i.lt(PromotionTools.START_TIME_COLUMN, new Date()).lt(PromotionTools.END_TIME_COLUMN, new Date())); diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionGoodsServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionGoodsServiceImpl.java index a827e99c..49e67a90 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionGoodsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/PromotionGoodsServiceImpl.java @@ -15,8 +15,6 @@ import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.entity.vos.PromotionGoodsSearchParams; import cn.lili.modules.promotion.entity.vos.SeckillSearchParams; import cn.lili.modules.promotion.mapper.PromotionGoodsMapper; -import cn.lili.modules.promotion.service.CouponService; -import cn.lili.modules.promotion.service.FullDiscountService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.promotion.service.SeckillApplyService; import cn.lili.modules.promotion.tools.PromotionTools; @@ -46,6 +44,8 @@ import java.util.List; @Transactional(rollbackFor = Exception.class) public class PromotionGoodsServiceImpl extends ServiceImpl implements PromotionGoodsService { + private static final String SKU_ID_COLUMN = "sku_id"; + /** * Redis */ @@ -62,12 +62,6 @@ public class PromotionGoodsServiceImpl extends ServiceImpl findSkuValidPromotion(String skuId, String storeIds) { @@ -77,7 +71,7 @@ public class PromotionGoodsServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); - queryWrapper.and(i -> i.or(j -> j.eq("sku_id", skuId)) + queryWrapper.and(i -> i.or(j -> j.eq(SKU_ID_COLUMN, skuId)) .or(n -> n.eq("scope_type", PromotionsScopeTypeEnum.ALL.name())) .or(n -> n.and(k -> k.eq("scope_type", PromotionsScopeTypeEnum.PORTION_GOODS_CATEGORY.name()) .and(l -> l.like("scope_id", sku.getCategoryPath()))))); @@ -123,7 +117,7 @@ public class PromotionGoodsServiceImpl extends ServiceImpl promotionTypes) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("sku_id", skuId); + queryWrapper.eq(SKU_ID_COLUMN, skuId); queryWrapper.in("promotion_type", promotionTypes); queryWrapper.and(PromotionTools.queryPromotionStatus(PromotionsStatusEnum.START)); return this.getOne(queryWrapper, false); @@ -139,7 +133,7 @@ public class PromotionGoodsServiceImpl extends ServiceImpl promotionTypes) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("sku_id", skuId); + queryWrapper.eq(SKU_ID_COLUMN, skuId); queryWrapper.in("promotion_type", promotionTypes); queryWrapper.and(PromotionTools.queryPromotionStatus(PromotionsStatusEnum.START)); return this.baseMapper.selectPromotionsGoodsPrice(queryWrapper); diff --git a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java index 9a4f4c7c..7c70fa0b 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsIndexService.java @@ -79,6 +79,13 @@ public interface EsGoodsIndexService { */ void deleteIndexById(String id); + /** + * 删除索引 + * + * @param ids 商品索引id集合 + */ + void deleteIndexByIds(List ids); + /** * 初始化商品索引 * diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java index ae7f5164..782b92a1 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java @@ -49,8 +49,11 @@ import org.elasticsearch.index.reindex.UpdateByQueryRequest; import org.elasticsearch.script.Script; import org.mybatis.spring.MyBatisSystemException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchPage; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @@ -100,6 +103,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Autowired private Cache cache; + @Autowired + @Qualifier("elasticsearchRestTemplate") + private ElasticsearchRestTemplate restTemplate; + @Override public void init() { //获取索引任务标识 @@ -286,6 +293,19 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements goodsIndexRepository.deleteById(id); } + /** + * 删除索引 + * + * @param ids 商品索引id集合 + */ + @Override + public void deleteIndexByIds(List ids) { + NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); + queryBuilder.withQuery(QueryBuilders.termsQuery("id", ids.toArray())); + this.restTemplate.delete(queryBuilder.build(), EsGoodsIndex.class); + + } + @Override public void initIndex(List goodsIndexList) { if (goodsIndexList == null || goodsIndexList.isEmpty()) { @@ -480,17 +500,13 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements //获取商品索引 if (promotionMap != null && !promotionMap.isEmpty()) { //促销不为空则进行清洗 - for (Map.Entry entry : promotionMap.entrySet()) { - BasePromotions promotion = (BasePromotions) entry.getValue(); - //判定条件为活动已结束 - if (promotion.getEndTime() != null && promotion.getEndTime().getTime() < DateUtil.date().getTime()) { - if (entry.getKey().contains(PromotionTypeEnum.SECKILL.name()) || entry.getKey().contains(PromotionTypeEnum.PINTUAN.name())) { - goodsIndex.setPromotionPrice(goodsIndex.getPrice()); - } - promotionMap.remove(entry.getKey()); + promotionMap.entrySet().removeIf(i -> { + BasePromotions promotion = (BasePromotions) i.getValue(); + if (i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())) { + goodsIndex.setPromotionPrice(goodsIndex.getPrice()); } - - } + return promotion.getEndTime() != null && promotion.getEndTime().getTime() < DateUtil.date().getTime(); + }); } } goodsIndexRepository.saveAll(all); diff --git a/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java b/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java index 682b4d15..673ec2d8 100644 --- a/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java +++ b/manager-api/src/test/java/cn/lili/test/elasticsearch/EsTest.java @@ -80,6 +80,12 @@ class EsTest { } + @Test + void cleanInvalidPromotion() { + this.esGoodsIndexService.cleanInvalidPromotion(); + Assertions.assertTrue(true); + } + @Test void searchGoods() { EsGoodsSearchDTO goodsSearchDTO = new EsGoodsSearchDTO();