diff --git a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java index ab36fce2..845967f0 100644 --- a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java @@ -2,6 +2,7 @@ package cn.lili.listener; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.lili.event.GoodsCommentCompleteEvent; import cn.lili.modules.distribution.entity.dos.DistributionGoods; @@ -42,6 +43,7 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; /** * 商品消息 @@ -137,16 +139,25 @@ public class GoodsMessageListener implements RocketMQListener { case UPDATE_GOODS_INDEX: try { String goodsIdsJsonStr = new String(messageExt.getBody()); - List goodsList = new ArrayList<>(); - for (String goodsId : JSONUtil.toList(goodsIdsJsonStr, String.class)) { - Goods goods = goodsService.getById(goodsId); - goodsList.add(goods); - } + List goodsList = goodsService.list(new LambdaQueryWrapper().in(Goods::getId, JSONUtil.toList(goodsIdsJsonStr, String.class))); this.updateGoodsIndex(goodsList); } catch (Exception e) { log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody())); } break; + case UPDATE_GOODS_INDEX_FIELD: + try { + String updateIndexFieldsJsonStr = new String(messageExt.getBody()); + JSONObject updateIndexFields = JSONUtil.parseObj(updateIndexFieldsJsonStr); + @SuppressWarnings("unchecked") + Map queryFields = updateIndexFields.get("queryFields", Map.class); + @SuppressWarnings("unchecked") + Map updateFields = updateIndexFields.get("updateFields", Map.class); + goodsIndexService.updateIndex(queryFields, updateFields); + } catch (Exception e) { + log.error("更新商品索引事件执行异常,商品信息 {}", new String(messageExt.getBody())); + } + break; case RESET_GOODS_INDEX: try { String goodsIdsJsonStr = new String(messageExt.getBody()); diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java index 8e1d9e4d..cbb9f9f6 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java @@ -1,5 +1,6 @@ package cn.lili.modules.order.cart.render.impl; +import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.utils.CurrencyUtil; import cn.lili.common.utils.StringUtils; @@ -18,6 +19,8 @@ import cn.lili.modules.promotion.service.MemberCouponService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -31,22 +34,21 @@ import java.util.stream.Collectors; @Service public class CouponRender implements CartRenderStep { + @Autowired + private PromotionPriceUtil promotionPriceUtil; + @Autowired + private MemberCouponService memberCouponService; + @Override public RenderStepEnums step() { return RenderStepEnums.COUPON; } - @Autowired - private PromotionPriceUtil promotionPriceUtil; - - @Autowired - private MemberCouponService memberCouponService; - @Override public void render(TradeDTO tradeDTO) { //优惠券列表 - renderCouponRule(tradeDTO); + this.renderCouponRule(tradeDTO); //主要渲染各个优惠的价格 this.renderCoupon(tradeDTO); } @@ -54,27 +56,55 @@ public class CouponRender implements CartRenderStep { /** * 渲染优惠券规则 + * + * @param tradeDTO 交易dto */ private void renderCouponRule(TradeDTO tradeDTO) { List memberCouponList = memberCouponService.getMemberCoupons(); - memberCouponList.forEach(memberCoupon -> { - available(tradeDTO, memberCoupon); - }); + if (!memberCouponList.isEmpty()) { + this.checkMemberExistCoupon(tradeDTO, memberCouponList); + } else { + tradeDTO.setPlatformCoupon(null); + tradeDTO.setStoreCoupons(new HashMap<>()); + } + memberCouponList.forEach(memberCoupon -> available(tradeDTO, memberCoupon)); + } + + /** + * 检查使用中的优惠券是否存在与用户的优惠券中 + * + * @param tradeDTO 交易dto + * @param memberCouponList 会员优惠券列表 + */ + private void checkMemberExistCoupon(TradeDTO tradeDTO, List memberCouponList) { + if (tradeDTO.getPlatformCoupon() != null && tradeDTO.getPlatformCoupon().getMemberCoupon() != null) { + boolean b = memberCouponList.parallelStream().anyMatch(i -> i.getId().equals(tradeDTO.getPlatformCoupon().getMemberCoupon().getId())); + if (!b) { + tradeDTO.setPlatformCoupon(null); + } + } + if (!tradeDTO.getStoreCoupons().isEmpty()) { + for (Map.Entry entry : tradeDTO.getStoreCoupons().entrySet()) { + if (entry.getValue().getMemberCoupon() != null && memberCouponList.parallelStream().noneMatch(i -> i.getId().equals(entry.getValue().getMemberCoupon().getId()))) { + tradeDTO.getStoreCoupons().remove(entry.getKey()); + } + } + } } /** * 判定优惠券是否可用 * - * @param tradeDTO - * @param memberCoupon + * @param tradeDTO 交易dto + * @param memberCoupon 会员优惠券 */ private void available(TradeDTO tradeDTO, MemberCoupon memberCoupon) { if (memberCoupon == null) { return; } List filterSku = filterSkuVo(tradeDTO.getSkuList(), memberCoupon); - if (filterSku == null || filterSku.size() == 0) { + if (filterSku == null || filterSku.isEmpty()) { tradeDTO.getCantUseCoupons().add(new MemberCouponVO(memberCoupon, "购物车中没有满足优惠券使用范围的优惠券")); return; @@ -100,23 +130,21 @@ public class CouponRender implements CartRenderStep { /** * 过滤购物车商品信息,按照优惠券的适用范围过滤 * - * @param cartSkuVOS - * @param memberCoupon - * @return + * @param cartSkuVOS 购物车中的产品列表 + * @param memberCoupon 会员优惠券 + * @return 按照优惠券的适用范围过滤的购物车商品信息 */ private List filterSkuVo(List cartSkuVOS, MemberCoupon memberCoupon) { List filterSku; //平台店铺过滤 - if (memberCoupon.getIsPlatform()) { + if (Boolean.TRUE.equals(memberCoupon.getIsPlatform())) { filterSku = cartSkuVOS; } else { - filterSku = cartSkuVOS.stream().filter(cartSkuVO -> { - return cartSkuVO.getStoreId().equals(memberCoupon.getStoreId()); - }).collect(Collectors.toList()); + filterSku = cartSkuVOS.stream().filter(cartSkuVO -> cartSkuVO.getStoreId().equals(memberCoupon.getStoreId())).collect(Collectors.toList()); } - if (filterSku == null || filterSku.size() == 0) { - return null; + if (filterSku == null || filterSku.isEmpty()) { + return Collections.emptyList(); } //优惠券类型判定 switch (CouponScopeTypeEnum.valueOf(memberCoupon.getScopeType())) { @@ -124,28 +152,12 @@ public class CouponRender implements CartRenderStep { return filterSku; case PORTION_GOODS: //按照商品过滤 - filterSku = filterSku.stream().filter(cartSkuVO -> { - return memberCoupon.getScopeId().indexOf(cartSkuVO.getGoodsSku().getId()) > 0; - }).collect(Collectors.toList()); + filterSku = filterSku.stream().filter(cartSkuVO -> memberCoupon.getScopeId().contains(cartSkuVO.getGoodsSku().getId())).collect(Collectors.toList()); break; case PORTION_SHOP_CATEGORY: //按照店铺分类过滤 - filterSku = filterSku.stream().filter(cartSkuVO -> { - if (StringUtils.isNotEmpty(cartSkuVO.getGoodsSku().getStoreCategoryPath())) { - //获取店铺分类 - String[] storeCategoryPath = cartSkuVO.getGoodsSku().getStoreCategoryPath().split(","); - for (String category : storeCategoryPath) { - //店铺分类只要有一项吻合,即可返回true - if (memberCoupon.getScopeId().indexOf(category) > 0) { - return true; - } - } - return false; - } else { - return false; - } - }).collect(Collectors.toList()); + filterSku = this.filterPromotionShopCategory(filterSku, memberCoupon); break; case PORTION_GOODS_CATEGORY: @@ -156,18 +168,37 @@ public class CouponRender implements CartRenderStep { String[] categoryPath = cartSkuVO.getGoodsSku().getCategoryPath().split(","); //平台三级分类 String categoryId = categoryPath[categoryPath.length - 1]; - if (memberCoupon.getScopeId().indexOf(categoryId) > 0) { - return true; - } - return false; + return memberCoupon.getScopeId().contains(categoryId); }).collect(Collectors.toList()); break; default: - return null; + return Collections.emptyList(); } return filterSku; } + /** + * 优惠券按照店铺分类过滤 + * + * @param filterSku 过滤的购物车商品信息 + * @param memberCoupon 会员优惠 + * @return 优惠券按照店铺分类过滤的购物车商品信息 + */ + private List filterPromotionShopCategory(List filterSku, MemberCoupon memberCoupon) { + return filterSku.stream().filter(cartSkuVO -> { + if (CharSequenceUtil.isNotEmpty(cartSkuVO.getGoodsSku().getStoreCategoryPath())) { + //获取店铺分类 + String[] storeCategoryPath = cartSkuVO.getGoodsSku().getStoreCategoryPath().split(","); + for (String category : storeCategoryPath) { + //店铺分类只要有一项吻合,即可返回true + if (memberCoupon.getScopeId().contains(category)) { + return true; + } + } + } + return false; + }).collect(Collectors.toList()); + } /** * 渲染优惠券 @@ -212,55 +243,78 @@ public class CouponRender implements CartRenderStep { coupon.setPrice(countPrice); } - //减免现金,则按照商品价格计算 需要通过工具类进行优惠金额的分发,分发给每个商品 if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name())) { - //分发优惠券 - promotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), - coupon.getIsPlatform() ? - PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON); - //如果是平台券 则需要计算商家承担比例 - if (coupon.getIsPlatform() && coupon.getStoreCommission() > 0) { - - //循环所有优惠券 - for (String skuId : couponMap.keySet()) { - - for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { - //写入平台优惠券承担比例 - if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { - //写入店铺承担比例 - cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission()); - } - } - } - } + //减免现金,则按照商品价格计算 需要通过工具类进行优惠金额的分发,分发给每个商品 + this.renderCouponPrice(couponMap, tradeDTO, coupon, memberCouponDTO); + } else { + //打折券 直接计算 + this.renderCouponDiscount(couponMap, tradeDTO, coupon); } - //打折券 直接计算 - else { + } + + /** + * 减免现金,则按照商品价格计算 需要通过工具类进行优惠金额的分发,分发给每个商品 + * + * @param couponMap 优惠券结算信息 + * @param tradeDTO 交易dto + * @param coupon 优惠券信息 + * @param memberCouponDTO 用于计算优惠券结算详情 + */ + private void renderCouponPrice(Map couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) { + //分发优惠券 + promotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(), + Boolean.TRUE.equals(coupon.getIsPlatform()) ? + PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON); + //如果是平台券 则需要计算商家承担比例 + if (Boolean.TRUE.equals(coupon.getIsPlatform()) && coupon.getStoreCommission() > 0) { + //循环所有优惠券 for (String skuId : couponMap.keySet()) { - // 循环购物车商品 - for (CartSkuVO item : tradeDTO.getSkuList()) { - //如果id相等,则渲染商品价格信息 - if (item.getGoodsSku().getId().equals(skuId)) { - - PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO(); - - // 打折金额=商品金额*折扣/10 - Double discountCouponPrice = CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), - CurrencyUtil.sub(1, CurrencyUtil.div(coupon.getDiscount(), 10, 3))); - - //平台券则写入店铺承担优惠券比例 - if (coupon.getIsPlatform()) { - priceDetailDTO.setSiteCouponPrice(discountCouponPrice); - priceDetailDTO.setSiteCouponPoint(coupon.getStoreCommission()); - } - priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice)); - + for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { + //写入平台优惠券承担比例 + if (cartSkuVO.getGoodsSku().getId().equals(skuId)) { + //写入店铺承担比例 + cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission()); } } } } - } + + + /** + * 打折券计算 + * + * @param couponMap 优惠券结算信息 + * @param tradeDTO 交易dto + * @param coupon 优惠券信息 + */ + private void renderCouponDiscount(Map couponMap, TradeDTO tradeDTO, MemberCoupon coupon) { + //循环所有优惠券 + for (String skuId : couponMap.keySet()) { + + // 循环购物车商品 + for (CartSkuVO item : tradeDTO.getSkuList()) { + //如果id相等,则渲染商品价格信息 + if (item.getGoodsSku().getId().equals(skuId)) { + + PriceDetailDTO priceDetailDTO = item.getPriceDetailDTO(); + + // 打折金额=商品金额*折扣/10 + Double discountCouponPrice = CurrencyUtil.mul(priceDetailDTO.getGoodsPrice(), + CurrencyUtil.sub(1, CurrencyUtil.div(coupon.getDiscount(), 10, 3))); + + //平台券则写入店铺承担优惠券比例 + if (Boolean.TRUE.equals(coupon.getIsPlatform())) { + priceDetailDTO.setSiteCouponPrice(discountCouponPrice); + priceDetailDTO.setSiteCouponPoint(coupon.getStoreCommission()); + } + priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice)); + + } + } + } + } + } diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponActivityServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponActivityServiceImpl.java index 99d71f0b..c46c60f9 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponActivityServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponActivityServiceImpl.java @@ -68,7 +68,7 @@ public class CouponActivityServiceImpl extends ServiceImpl 10) { throw new ServiceException(ResultCode.COUPON_ACTIVITY_ITEM_MUST_NUM_ERROR); 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 5172d66b..a33c8928 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 @@ -35,11 +35,19 @@ public interface EsGoodsIndexService { /** * 更新商品索引的的部分属性(只填写更新的字段,不需要更新的字段不要填写) * - * @param id 商品索引id + * @param id 商品索引id * @param goods 更新后的购买数量 */ void updateIndex(String id, EsGoodsIndex goods); + /** + * 更新商品索引的的部分属性 + * + * @param queryFields 查询字段 + * @param updateFields 更新字段 + */ + void updateIndex(Map queryFields, Map updateFields); + /** * 批量商品索引的的属性(ID 必填, 其他字段只填写更新的字段,不需要更新的字段不要填写。) * @@ -105,10 +113,12 @@ public interface EsGoodsIndexService { /** * 删除索引中指定的促销活动id的促销活动 - * @param skuId 商品skuId + * + * @param skuId 商品skuId * @param promotionId 促销活动Id */ void deleteEsGoodsPromotionByPromotionId(String skuId, String promotionId); + /** * 清除所以商品索引的无效促销活动 */ @@ -142,7 +152,7 @@ public interface EsGoodsIndexService { /** * 重置当前商品索引 * - * @param goodsSku 商品sku信息 + * @param goodsSku 商品sku信息 * @param goodsParamDTOS 商品参数 * @return 商品索引 */ 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 32b9c45c..af57ba99 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 @@ -30,11 +30,18 @@ import cn.lili.modules.search.service.EsGoodsSearchService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.assertj.core.util.IterableUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.indices.AnalyzeRequest; import org.elasticsearch.client.indices.AnalyzeResponse; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.index.reindex.BulkByScrollResponse; +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.data.elasticsearch.core.SearchHit; @@ -76,11 +83,9 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void addIndex(EsGoodsIndex goods) { - //索引名称拼接 - String indexName = elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; try { //分词器分词 - AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(indexName, "ik_max_word", goods.getGoodsName()); + AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(getIndexName(), "ik_max_word", goods.getGoodsName()); AnalyzeResponse analyze = client.indices().analyze(analyzeRequest, RequestOptions.DEFAULT); List tokens = analyze.getTokens(); @@ -126,6 +131,29 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements goodsIndexRepository.save(goods); } + /** + * 更新商品索引的的部分属性(只填写更新的字段,不需要更新的字段不要填写) + * + * @param queryFields 查询字段 + * @param updateFields 更新字段 + */ + @Override + public void updateIndex(Map queryFields, Map updateFields) { + UpdateByQueryRequest update = new UpdateByQueryRequest(getIndexName()); + BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); + for (Map.Entry entry : queryFields.entrySet()) { + TermQueryBuilder termQueryBuilder = new TermQueryBuilder(entry.getKey(), entry.getValue()); + queryBuilder.filter(termQueryBuilder); + } + update.setQuery(queryBuilder); + StringBuilder script = new StringBuilder(); + for (Map.Entry entry : updateFields.entrySet()) { + script.append("ctx._source.").append(entry.getKey()).append("=").append("'").append(entry.getValue()).append("'").append(";"); + } + update.setScript(new Script(script.toString())); + client.updateByQueryAsync(update, RequestOptions.DEFAULT, this.actionListener()); + } + /** * 批量商品索引的的属性(ID 必填, 其他字段只填写更新的字段,不需要更新的字段不要填写。) * @@ -135,7 +163,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements public void updateBulkIndex(List goodsIndices) { try { //索引名称拼接 - String indexName = elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; + String indexName = getIndexName(); BulkRequest request = new BulkRequest(); @@ -178,7 +206,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements return; } //索引名称拼接 - String indexName = elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; + String indexName = this.getIndexName(); //索引初始化,因为mapping结构问题: //但是如果索引已经自动生成过,这里就不会创建索引,设置mapping,所以这里决定在初始化索引的同时,将已有索引删除,重新创建 @@ -383,7 +411,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } return promotionMap; } - return null; + return new HashMap<>(); } /** @@ -519,4 +547,22 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } + private String getIndexName() { + //索引名称拼接 + return elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; + } + + private ActionListener actionListener() { + return new ActionListener() { + @Override + public void onResponse(BulkByScrollResponse bulkByScrollResponse) { + log.debug("UpdateByQueryResponse: {}", bulkByScrollResponse); + } + + @Override + public void onFailure(Exception e) { + log.error("UpdateByQueryRequestFailure: ", e); + } + }; + } } diff --git a/framework/src/main/java/cn/lili/modules/search/utils/EsIndexUtil.java b/framework/src/main/java/cn/lili/modules/search/utils/EsIndexUtil.java new file mode 100644 index 00000000..e514f011 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/search/utils/EsIndexUtil.java @@ -0,0 +1,45 @@ +package cn.lili.modules.search.utils; + +import cn.hutool.core.util.ReflectUtil; +import cn.lili.modules.search.entity.dos.EsGoodsIndex; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * @author paulG + * @since 2021/10/11 + **/ +public class EsIndexUtil { + + private static final String IGNORE_FIELD = "serialVersionUID,promotionMap,id,goodsId"; + + public static Map getUpdateIndexFieldsMap(EsGoodsIndex queryGoodsIndex, EsGoodsIndex updateGoodsIndex) { + Map queryFieldsMap = new HashMap<>(); + Map updateFieldsMap = new HashMap<>(); + + for (Map.Entry entry : ReflectUtil.getFieldMap(EsGoodsIndex.class).entrySet()) { + Object queryFieldValue = ReflectUtil.getFieldValue(queryGoodsIndex, entry.getValue()); + Object updateFieldValue = ReflectUtil.getFieldValue(updateGoodsIndex, entry.getValue()); + if (queryFieldValue != null && !IGNORE_FIELD.contains(entry.getKey())) { + ReflectUtil.setFieldValue(queryFieldsMap, entry.getValue(), queryFieldValue); + } + if (updateFieldValue != null && !IGNORE_FIELD.contains(entry.getKey())) { + ReflectUtil.setFieldValue(updateFieldsMap, entry.getValue(), updateFieldValue); + } + } + + return getUpdateIndexFieldsMap(queryFieldsMap, updateFieldsMap); + } + + public static Map getUpdateIndexFieldsMap(Map queryFieldsMap, Map updateFieldsMap) { + Map updateIndexMap = new HashMap<>(); + + updateIndexMap.put("queryFields", queryFieldsMap); + updateIndexMap.put("updateFields", updateFieldsMap); + return updateIndexMap; + } + + +} diff --git a/framework/src/main/java/cn/lili/modules/store/service/StoreDetailService.java b/framework/src/main/java/cn/lili/modules/store/service/StoreDetailService.java index cf7c311c..8232dd2f 100644 --- a/framework/src/main/java/cn/lili/modules/store/service/StoreDetailService.java +++ b/framework/src/main/java/cn/lili/modules/store/service/StoreDetailService.java @@ -1,10 +1,12 @@ package cn.lili.modules.store.service; +import cn.lili.modules.store.entity.dos.Store; import cn.lili.modules.store.entity.dos.StoreDetail; import cn.lili.modules.store.entity.dto.StoreAfterSaleAddressDTO; import cn.lili.modules.store.entity.dto.StoreSettingDTO; import cn.lili.modules.store.entity.vos.StoreBasicInfoVO; import cn.lili.modules.store.entity.vos.StoreDetailVO; +import cn.lili.modules.store.entity.vos.StoreManagementCategoryVO; import cn.lili.modules.store.entity.vos.StoreOtherVO; import com.baomidou.mybatisplus.extension.service.IService; @@ -95,7 +97,7 @@ public interface StoreDetailService extends IService { * @param storeId 店铺ID * @return 店铺经营范围 */ - List goodsManagementCategory(String storeId); + List goodsManagementCategory(String storeId); /** * 获取店铺其他信息 @@ -104,4 +106,11 @@ public interface StoreDetailService extends IService { * @return 店铺其他信息 */ StoreOtherVO getStoreOtherVO(String storeId); + + /** + * 更新店铺内所有商品信息 + * + * @param store 店铺信息 + */ + void updateStoreGoodsInfo(Store store); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java index b0c8a2ad..956a8bb9 100644 --- a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreDetailServiceImpl.java @@ -1,10 +1,18 @@ package cn.lili.modules.store.serviceimpl; +import cn.hutool.core.map.MapUtil; +import cn.hutool.json.JSONUtil; +import cn.lili.common.properties.RocketmqCustomProperties; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.BeanUtil; import cn.lili.modules.goods.entity.dos.Category; +import cn.lili.modules.goods.entity.dos.Goods; +import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.service.CategoryService; +import cn.lili.modules.goods.service.GoodsService; +import cn.lili.modules.goods.service.GoodsSkuService; +import cn.lili.modules.search.utils.EsIndexUtil; import cn.lili.modules.store.entity.dos.Store; import cn.lili.modules.store.entity.dos.StoreDetail; import cn.lili.modules.store.entity.dto.StoreAfterSaleAddressDTO; @@ -16,16 +24,20 @@ import cn.lili.modules.store.entity.vos.StoreOtherVO; import cn.lili.modules.store.mapper.StoreDetailMapper; import cn.lili.modules.store.service.StoreDetailService; import cn.lili.modules.store.service.StoreService; +import cn.lili.rocketmq.RocketmqSendCallbackBuilder; +import cn.lili.rocketmq.tags.GoodsTagsEnum; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; 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.List; +import java.util.Map; import java.util.Objects; /** @@ -49,6 +61,18 @@ public class StoreDetailServiceImpl extends ServiceImpl() + .eq(Goods::getStoreId, store.getId()) + .set(Goods::getStoreName, store.getStoreName()) + .set(Goods::getSelfOperated, store.getSelfOperated())); + goodsSkuService.update(new LambdaUpdateWrapper() + .eq(GoodsSku::getStoreId, store.getId()) + .set(GoodsSku::getStoreName, store.getStoreName()) + .set(GoodsSku::getSelfOperated, store.getSelfOperated())); + + Map updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap( + MapUtil.builder().put("storeId", store.getId()).build(), + MapUtil.builder().put("storeName", store.getStoreName()).put("selfOperated", store.getSelfOperated()).build()); + String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_FIELD.name(); + //发送mq消息 + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(updateIndexFieldsMap), RocketmqSendCallbackBuilder.commonCallback()); } @Override @@ -118,7 +165,7 @@ public class StoreDetailServiceImpl extends ServiceImpl goodsManagementCategory(String storeId) { //获取顶部分类列表 List categoryList = categoryService.firstCategory(); diff --git a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java index a12892d7..df337b0f 100644 --- a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java @@ -2,12 +2,12 @@ package cn.lili.modules.store.serviceimpl; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.text.CharSequenceUtil; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.BeanUtil; -import cn.lili.common.utils.StringUtils; import cn.lili.common.vo.PageVO; import cn.lili.modules.goods.entity.dos.Goods; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; @@ -39,6 +39,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Objects; import java.util.Optional; /** @@ -89,7 +90,7 @@ public class StoreServiceImpl extends ServiceImpl implements @Override public StoreVO getStoreDetail() { - AuthUser currentUser = UserContext.getCurrentUser(); + AuthUser currentUser = Objects.requireNonNull(UserContext.getCurrentUser()); StoreVO storeVO = this.baseMapper.getStoreDetail(currentUser.getStoreId()); storeVO.setNickName(currentUser.getNickName()); return storeVO; @@ -99,7 +100,7 @@ public class StoreServiceImpl extends ServiceImpl implements public Store add(AdminStoreApplyDTO adminStoreApplyDTO) { //判断店铺名称是否存在 - QueryWrapper queryWrapper = Wrappers.query(); + QueryWrapper queryWrapper = Wrappers.query(); queryWrapper.eq("store_name", adminStoreApplyDTO.getStoreName()); if (this.getOne(queryWrapper) != null) { throw new ServiceException(ResultCode.STORE_NAME_EXIST_ERROR); @@ -111,7 +112,7 @@ public class StoreServiceImpl extends ServiceImpl implements throw new ServiceException(ResultCode.USER_NOT_EXIST); } //判断是否拥有店铺 - if (member.getHaveStore()) { + if (Boolean.TRUE.equals(member.getHaveStore())) { throw new ServiceException(ResultCode.STORE_APPLY_DOUBLE_ERROR); } @@ -138,7 +139,7 @@ public class StoreServiceImpl extends ServiceImpl implements if (storeEditDTO != null) { //判断店铺名是否唯一 Store storeTmp = getOne(new QueryWrapper().eq("store_name", storeEditDTO.getStoreName())); - if (storeTmp != null && !StringUtils.equals(storeTmp.getId(), storeEditDTO.getStoreId())) { + if (storeTmp != null && !CharSequenceUtil.equals(storeTmp.getId(), storeEditDTO.getStoreId())) { throw new ServiceException(ResultCode.STORE_NAME_EXIST_ERROR); } //修改店铺详细信息 @@ -160,7 +161,10 @@ public class StoreServiceImpl extends ServiceImpl implements if (store != null) { BeanUtil.copyProperties(storeEditDTO, store); store.setId(storeEditDTO.getStoreId()); - this.updateById(store); + boolean result = this.updateById(store); + if (result) { + storeDetailService.updateStoreGoodsInfo(store); + } } return store; } @@ -232,7 +236,8 @@ public class StoreServiceImpl extends ServiceImpl implements Store store = getStoreByMember(); //如果没有申请过店铺,新增店铺 if (!Optional.ofNullable(store).isPresent()) { - Member member = memberService.getById(UserContext.getCurrentUser().getId()); + AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser()); + Member member = memberService.getById(authUser.getId()); store = new Store(member); BeanUtil.copyProperties(storeCompanyDTO, store); this.save(store); @@ -336,11 +341,12 @@ public class StoreServiceImpl extends ServiceImpl implements /** * 获取当前登录操作的店铺 * - * @return + * @return 店铺信息 */ private Store getStoreByMember() { + AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser()); LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); - lambdaQueryWrapper.eq(Store::getMemberId, UserContext.getCurrentUser().getId()); + lambdaQueryWrapper.eq(Store::getMemberId, authUser.getId()); return this.getOne(lambdaQueryWrapper); } diff --git a/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java b/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java index dedf7052..73e3b7d6 100644 --- a/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java +++ b/framework/src/main/java/cn/lili/rocketmq/tags/GoodsTagsEnum.java @@ -14,6 +14,11 @@ public enum GoodsTagsEnum { * "更新商品索引" */ UPDATE_GOODS_INDEX("更新商品索引"), + + /** + * "更新商品索引部分字段" + */ + UPDATE_GOODS_INDEX_FIELD("更新商品索引部分字段"), /** * "重置商品索引" */ diff --git a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java index 31ce2559..4770c933 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java @@ -90,45 +90,50 @@ public class ElasticsearchController { cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), true); ThreadUtil.execAsync(() -> { - //查询商品信息 - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name()); - queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); + try { + //查询商品信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name()); + queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); - List list = goodsSkuService.list(queryWrapper); - List esGoodsIndices = new ArrayList<>(); - //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 - for (GoodsSku goodsSku : list) { - Goods goods = goodsService.getById(goodsSku.getGoodsId()); - EsGoodsIndex index = new EsGoodsIndex(goodsSku); - if (goods.getParams() != null && !goods.getParams().isEmpty()) { - List goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class); - index = new EsGoodsIndex(goodsSku, goodsParamDTOS); - } - if (goods.getCategoryPath() != null) { - List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(","))); - if (!categories.isEmpty()) { - index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ",")); + List list = goodsSkuService.list(queryWrapper); + List esGoodsIndices = new ArrayList<>(); + //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 + for (GoodsSku goodsSku : list) { + Goods goods = goodsService.getById(goodsSku.getGoodsId()); + EsGoodsIndex index = new EsGoodsIndex(goodsSku); + if (goods.getParams() != null && !goods.getParams().isEmpty()) { + List goodsParamDTOS = JSONUtil.toList(goods.getParams(), GoodsParamsDTO.class); + index = new EsGoodsIndex(goodsSku, goodsParamDTOS); } - } - Brand brand = brandService.getById(goods.getBrandId()); - if (brand != null) { - index.setBrandName(brand.getName()); - index.setBrandUrl(brand.getLogo()); - } - if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) { - List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(","))); - if (!storeGoodsLabels.isEmpty()) { - index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ",")); + if (goods.getCategoryPath() != null) { + List categories = categoryService.listByIdsOrderByLevel(Arrays.asList(goods.getCategoryPath().split(","))); + if (!categories.isEmpty()) { + index.setCategoryNamePath(ArrayUtil.join(categories.stream().map(Category::getName).toArray(), ",")); + } } + Brand brand = brandService.getById(goods.getBrandId()); + if (brand != null) { + index.setBrandName(brand.getName()); + index.setBrandUrl(brand.getLogo()); + } + if (goods.getStoreCategoryPath() != null && CharSequenceUtil.isNotEmpty(goods.getStoreCategoryPath())) { + List storeGoodsLabels = storeGoodsLabelService.listByStoreIds(Arrays.asList(goods.getStoreCategoryPath().split(","))); + if (!storeGoodsLabels.isEmpty()) { + index.setStoreCategoryNamePath(ArrayUtil.join(storeGoodsLabels.stream().map(StoreGoodsLabel::getLabelName).toArray(), ",")); + } + } + Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); + index.setPromotionMap(goodsCurrentPromotionMap); + esGoodsIndices.add(index); + stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString()); } - Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); - index.setPromotionMap(goodsCurrentPromotionMap); - esGoodsIndices.add(index); - stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString()); + //初始化商品索引 + esGoodsIndexService.initIndex(esGoodsIndices); + } catch (Exception e) { + cache.put(CachePrefix.INIT_INDEX_PROCESS.getPrefix(), null); + cache.put(CachePrefix.INIT_INDEX_FLAG.getPrefix(), false); } - //初始化商品索引 - esGoodsIndexService.initIndex(esGoodsIndices); }); return ResultUtil.success(); } diff --git a/manager-api/src/main/java/cn/lili/controller/store/StoreManagerController.java b/manager-api/src/main/java/cn/lili/controller/store/StoreManagerController.java index 841d0464..e73b4fd9 100644 --- a/manager-api/src/main/java/cn/lili/controller/store/StoreManagerController.java +++ b/manager-api/src/main/java/cn/lili/controller/store/StoreManagerController.java @@ -3,11 +3,11 @@ package cn.lili.controller.store; import cn.lili.common.enums.ResultUtil; import cn.lili.common.vo.PageVO; import cn.lili.common.vo.ResultMessage; -import cn.lili.modules.goods.entity.vos.CategoryVO; import cn.lili.modules.store.entity.dos.Store; import cn.lili.modules.store.entity.dto.AdminStoreApplyDTO; import cn.lili.modules.store.entity.dto.StoreEditDTO; import cn.lili.modules.store.entity.vos.StoreDetailVO; +import cn.lili.modules.store.entity.vos.StoreManagementCategoryVO; import cn.lili.modules.store.entity.vos.StoreSearchParams; import cn.lili.modules.store.entity.vos.StoreVO; import cn.lili.modules.store.service.StoreDetailService; @@ -112,7 +112,7 @@ public class StoreManagerController { @ApiOperation(value = "查询一级分类列表") @ApiImplicitParam(name = "storeId", value = "店铺id", required = true, dataType = "String", paramType = "path") @GetMapping(value = "/managementCategory/{storeId}") - public ResultMessage> firstCategory(@PathVariable String storeId) { + public ResultMessage> firstCategory(@PathVariable String storeId) { return ResultUtil.data(this.storeDetailService.goodsManagementCategory(storeId)); }