diff --git a/README.md b/README.md index 41d30105..a94031b2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ##### 体验 公众号/小程序/APP 体验,扫描二维码 -![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png) +![image-20210511171611793](https://static.pickmall.cn/images/h5-qrcode.png) [![star](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop/stargazers)   ![github](https://img.shields.io/github/stars/hongyehuicheng/lilishop.svg?style=social&logo=#181717) @@ -56,7 +56,7 @@ PS:手机验证码为 ‘111111’ **商城 小程序/公众号/APP**:扫描二维码 -![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png) +![image-20210511171611793](https://static.pickmall.cn/images/h5-qrcode.png) ### 快速本地部署 @@ -75,24 +75,24 @@ PS:手机验证码为 ‘111111’ #### 平台管理端功能 -![平台管理端功能](https://pickmall.cn/assets/imgs/other/managerList1.jpg) +![平台管理端功能](https://static.pickmall.cn/images/other/managerList1.jpg) #### 卖家功能 -![商家端功能](https://pickmall.cn/assets/imgs/other/storeList.jpg) +![商家端功能](https://static.pickmall.cn/images/other/storeList.jpg) ### 商城前端功能展示 #### 商城移动端 -移动端功能展示 +移动端功能展示 #### 平台管理端 -![管理端功能展示](https://pickmall.cn/assets/imgs/other/manager.gif) +![管理端功能展示](https://static.pickmall.cn/images/other/manager.gif) ### 技术选型 diff --git a/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java index fc5a5f0d..19caa3e0 100644 --- a/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/goods/GoodsBuyerController.java @@ -18,14 +18,13 @@ import cn.lili.modules.search.service.HotWordsService; import cn.lili.modules.statistics.aop.PageViewPoint; import cn.lili.modules.statistics.aop.enums.PageViewEnum; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.elasticsearch.core.SearchPage; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -104,10 +103,9 @@ public class GoodsBuyerController { @ApiOperation(value = "从ES中获取商品信息") @GetMapping("/es") - public ResultMessage> getGoodsByPageFromEs(EsGoodsSearchDTO goodsSearchParams, PageVO pageVO) { + public ResultMessage> getGoodsByPageFromEs(EsGoodsSearchDTO goodsSearchParams, PageVO pageVO) { pageVO.setNotConvert(true); - SearchPage esGoodsIndices = goodsSearchService.searchGoods(goodsSearchParams, pageVO); - return ResultUtil.data(esGoodsIndices); + return ResultUtil.data(goodsSearchService.searchGoodsByPage(goodsSearchParams, pageVO)); } @ApiOperation(value = "从ES中获取相关商品品牌名称,分类名称及属性") diff --git a/buyer-api/src/main/java/cn/lili/controller/member/MemberAddressBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/member/MemberAddressBuyerController.java index 16caae69..fdd8e297 100644 --- a/buyer-api/src/main/java/cn/lili/controller/member/MemberAddressBuyerController.java +++ b/buyer-api/src/main/java/cn/lili/controller/member/MemberAddressBuyerController.java @@ -68,6 +68,8 @@ public class MemberAddressBuyerController { @ApiOperation(value = "修改会员收件地址") @PutMapping public ResultMessage editShippingAddress(@Valid MemberAddress shippingAddress) { + OperationalJudgment.judgment(memberAddressService.getById(shippingAddress.getId())); + shippingAddress.setMemberId(Objects.requireNonNull(UserContext.getCurrentUser()).getId()); return ResultUtil.data(memberAddressService.updateMemberAddress(shippingAddress)); } diff --git a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java index 692e3ade..e8949915 100644 --- a/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java +++ b/consumer/src/main/java/cn/lili/listener/GoodsMessageListener.java @@ -343,6 +343,7 @@ public class GoodsMessageListener implements RocketMQListener { searchParams.setGoodsId(goods.getId()); searchParams.setPageNumber(i); searchParams.setPageSize(BATCH_SIZE); + searchParams.setGeQuantity(0); IPage goodsSkuByPage = this.goodsSkuService.getGoodsSkuByPage(searchParams); if (goodsSkuByPage == null || goodsSkuByPage.getRecords().isEmpty()) { break; diff --git a/framework/pom.xml b/framework/pom.xml index 8e631d65..bfcd88a3 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -460,6 +460,14 @@ system ${project.basedir}/src/main/resources/maven-repository/SF-CSIM-EXPRESS-SDK-V2.1.7.jar + + + io.netty + netty-resolver-dns-native-macos + 4.1.90.Final + runtime + osx-aarch_64 + diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index e2b702d2..c1040bb8 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -82,6 +82,7 @@ public enum ResultCode { HAVE_INVALID_SALES_MODEL(11023, "批发规则存在小于等于0的无效数据!"), MUST_HAVE_GOODS_SKU_VALUE(11024, "规格值不能为空!"), DO_NOT_MATCH_WHOLESALE(11025, "批发商品购买数量不能低于起拍量!"), + GOODS_NOT_ERROR(11026, "商品不存在"), GOODS_PARAMS_ERROR(11013, "商品参数错误,刷新后重试"), PHYSICAL_GOODS_NEED_TEMP(11014, "实物商品需选择配送模板"), diff --git a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java index 46c0c5b3..e7d5ba1c 100644 --- a/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/connect/serviceimpl/ConnectServiceImpl.java @@ -14,6 +14,7 @@ import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.security.token.Token; import cn.lili.common.utils.HttpUtils; +import cn.lili.common.utils.UuidUtils; import cn.lili.modules.connect.entity.Connect; import cn.lili.modules.connect.entity.dto.AuthToken; import cn.lili.modules.connect.entity.dto.ConnectAuthUser; @@ -179,16 +180,26 @@ public class ConnectServiceImpl extends ServiceImpl impl String iv = params.getIv(); JSONObject userInfo = this.getUserInfo(encryptedData, sessionKey, iv); log.info("联合登陆返回:{}", userInfo.toString()); - String phone = (String) userInfo.get("purePhoneNumber"); + ConnectAuthUser connectAuthUser = new ConnectAuthUser(); connectAuthUser.setUuid(openId); connectAuthUser.setNickname(params.getNickName()); connectAuthUser.setAvatar(params.getImage()); - connectAuthUser.setUsername("m" + phone); - connectAuthUser.setPhone(phone); - connectAuthUser.setSource(ConnectEnum.WECHAT.name()); - connectAuthUser.setType(ClientTypeEnum.WECHAT_MP.name()); + + if (userInfo.containsKey("purePhoneNumber")) { + String phone = (String) userInfo.get("purePhoneNumber"); + connectAuthUser.setUsername("m" + phone); + connectAuthUser.setPhone(phone); + connectAuthUser.setSource(ConnectEnum.WECHAT.name()); + connectAuthUser.setType(ClientTypeEnum.WECHAT_MP.name()); + + } else { + connectAuthUser.setUsername(UuidUtils.getUUID()); + connectAuthUser.setSource(ConnectEnum.WECHAT.name()); + connectAuthUser.setType(ClientTypeEnum.WECHAT_MP.name()); + } + AuthToken authToken = new AuthToken(); authToken.setUnionId(unionId); @@ -204,9 +215,12 @@ public class ConnectServiceImpl extends ServiceImpl impl public Connect queryConnect(ConnectQueryDTO connectQueryDTO) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUserId()), Connect::getUserId, connectQueryDTO.getUserId()) - .eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUnionType()), Connect::getUnionType, connectQueryDTO.getUnionType()) - .eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUnionId()), Connect::getUnionId, connectQueryDTO.getUnionId()); + queryWrapper.eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUserId()), Connect::getUserId, + connectQueryDTO.getUserId()) + .eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUnionType()), Connect::getUnionType, + connectQueryDTO.getUnionType()) + .eq(CharSequenceUtil.isNotEmpty(connectQueryDTO.getUnionId()), Connect::getUnionId, + connectQueryDTO.getUnionId()); return this.getOne(queryWrapper); } @@ -265,7 +279,8 @@ public class ConnectServiceImpl extends ServiceImpl impl .eq(Connect::getUnionType, authUser.getSource()); } else { //使用OpenID登录 - SourceEnum sourceEnum = SourceEnum.getSourceEnum(ConnectEnum.valueOf(authUser.getType()), ClientTypeEnum.valueOf(authUser.getSource())); + SourceEnum sourceEnum = SourceEnum.getSourceEnum(ConnectEnum.valueOf(authUser.getType()), + ClientTypeEnum.valueOf(authUser.getSource())); queryWrapper.eq(Connect::getUnionId, authUser.getToken().getUnionId()) .eq(Connect::getUnionType, sourceEnum.name()); } @@ -289,9 +304,11 @@ public class ConnectServiceImpl extends ServiceImpl impl MemberConnectLoginMessage memberConnectLoginMessage = new MemberConnectLoginMessage(); memberConnectLoginMessage.setMember(member); memberConnectLoginMessage.setConnectAuthUser(authUser); - String destination = rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_CONNECT_LOGIN.name(); + String destination = + rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_CONNECT_LOGIN.name(); //发送用户第三方登录消息 - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(memberConnectLoginMessage), RocketmqSendCallbackBuilder.commonCallback()); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(memberConnectLoginMessage), + RocketmqSendCallbackBuilder.commonCallback()); return memberTokenGenerate.createToken(member, longTerm); } catch (Exception e) { @@ -308,7 +325,8 @@ public class ConnectServiceImpl extends ServiceImpl impl private WechatConnectSettingItem getWechatMPSetting() { Setting setting = settingService.get(SettingEnum.WECHAT_CONNECT.name()); - WechatConnectSetting wechatConnectSetting = JSONUtil.toBean(setting.getSettingValue(), WechatConnectSetting.class); + WechatConnectSetting wechatConnectSetting = JSONUtil.toBean(setting.getSettingValue(), + WechatConnectSetting.class); if (wechatConnectSetting == null) { throw new ServiceException(ResultCode.WECHAT_CONNECT_NOT_EXIST); diff --git a/framework/src/main/java/cn/lili/modules/file/plugin/impl/TencentFilePlugin.java b/framework/src/main/java/cn/lili/modules/file/plugin/impl/TencentFilePlugin.java index 61dda55d..e4f69a1d 100644 --- a/framework/src/main/java/cn/lili/modules/file/plugin/impl/TencentFilePlugin.java +++ b/framework/src/main/java/cn/lili/modules/file/plugin/impl/TencentFilePlugin.java @@ -52,7 +52,7 @@ public class TencentFilePlugin implements FilePlugin { // 1 初始化用户身份信息(secretId, secretKey)。 COSCredentials cred = new BasicCOSCredentials(ossSetting.getTencentCOSSecretId(), ossSetting.getTencentCOSSecretKey()); // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224 - ClientConfig clientConfig = new ClientConfig(new Region("COS_REGION")); + ClientConfig clientConfig = new ClientConfig(new Region(ossSetting.getTencentCOSRegion())); // 这里建议设置使用 https 协议 clientConfig.setHttpProtocol(HttpProtocol.https); // 3 生成 cos 客户端。 @@ -66,7 +66,8 @@ public class TencentFilePlugin implements FilePlugin { * @return */ private String getUrlPrefix() { - return "https://" + ossSetting.getTencentCOSBucket() + "." + ossSetting.getTencentCOSEndPoint() + "/"; +// return "https://" + ossSetting.getTencentCOSBucket() + "." + ossSetting.getTencentCOSEndPoint() + "/"; + return "https://" + ossSetting.getTencentCOSBucket() + ".cos" + ossSetting.getTencentCOSEndPoint() + ".myqcloud.com/"; } @Override 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 c516b6c2..20962422 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 @@ -12,6 +12,7 @@ import cn.lili.common.enums.ResultCode; import cn.lili.common.event.TransactionCommitSendMQEvent; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.RocketmqCustomProperties; +import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.SnowFlake; import cn.lili.modules.goods.entity.dos.Goods; @@ -29,16 +30,22 @@ import cn.lili.modules.goods.entity.vos.GoodsSkuVO; import cn.lili.modules.goods.entity.vos.GoodsVO; import cn.lili.modules.goods.entity.vos.SpecValueVO; import cn.lili.modules.goods.mapper.GoodsSkuMapper; -import cn.lili.modules.goods.service.*; +import cn.lili.modules.goods.service.GoodsGalleryService; +import cn.lili.modules.goods.service.GoodsService; +import cn.lili.modules.goods.service.GoodsSkuService; +import cn.lili.modules.goods.service.WholesaleService; import cn.lili.modules.goods.sku.GoodsSkuBuilder; import cn.lili.modules.goods.sku.render.SalesModelRender; import cn.lili.modules.member.entity.dos.FootPrint; import cn.lili.modules.member.entity.dto.EvaluationQueryParams; import cn.lili.modules.member.entity.enums.EvaluationGradeEnum; import cn.lili.modules.member.service.MemberEvaluationService; +import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.dto.search.PromotionGoodsSearchParams; import cn.lili.modules.promotion.entity.enums.CouponGetEnum; +import cn.lili.modules.promotion.service.CouponService; +import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import cn.lili.modules.search.service.EsGoodsIndexService; @@ -80,7 +87,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl i * 分类 */ @Autowired - private CategoryService categoryService; + private MemberCouponService memberCouponService; /** * 商品相册 */ @@ -121,6 +128,9 @@ public class GoodsSkuServiceImpl extends ServiceImpl i @Autowired private WholesaleService wholesaleService; + @Autowired + private CouponService couponService; + @Autowired private List salesModelRenders; @@ -166,7 +176,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl i //发送mq消息 String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.SKU_DELETE.name(); - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(oldSkuIds), RocketmqSendCallbackBuilder.commonCallback()); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(oldSkuIds), + RocketmqSendCallbackBuilder.commonCallback()); } else { skuList = new ArrayList<>(); for (Map map : goodsOperationDTO.getSkuList()) { @@ -176,14 +187,15 @@ public class GoodsSkuServiceImpl extends ServiceImpl i //如果商品状态值不对,则es索引移除 if (goods.getAuthFlag().equals(GoodsAuthEnum.PASS.name()) && goods.getMarketEnable().equals(GoodsStatusEnum.UPPER.name())) { goodsIndexService.deleteIndexById(sku.getId()); - this.clearCache(sku.getId()); } + this.clearCache(sku.getId()); } } if (!skuList.isEmpty()) { LambdaQueryWrapper unnecessarySkuIdsQuery = new LambdaQueryWrapper<>(); unnecessarySkuIdsQuery.eq(GoodsSku::getGoodsId, goods.getId()); - unnecessarySkuIdsQuery.notIn(GoodsSku::getId, skuList.stream().map(BaseEntity::getId).collect(Collectors.toList())); + unnecessarySkuIdsQuery.notIn(GoodsSku::getId, + skuList.stream().map(BaseEntity::getId).collect(Collectors.toList())); this.remove(unnecessarySkuIdsQuery); this.saveOrUpdateBatch(skuList); this.updateStock(skuList); @@ -263,14 +275,16 @@ public class GoodsSkuServiceImpl extends ServiceImpl i if (goodsVO == null || goodsSku == null) { //发送mq消息 String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name(); - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback()); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), + RocketmqSendCallbackBuilder.commonCallback()); throw new ServiceException(ResultCode.GOODS_NOT_EXIST); } //商品下架||商品未审核通过||商品删除,则提示:商品已下架 if (GoodsStatusEnum.DOWN.name().equals(goodsVO.getMarketEnable()) || !GoodsAuthEnum.PASS.name().equals(goodsVO.getAuthFlag()) || Boolean.TRUE.equals(goodsVO.getDeleteFlag())) { String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GOODS_DELETE.name(); - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), RocketmqSendCallbackBuilder.commonCallback()); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(Collections.singletonList(goodsId)), + RocketmqSendCallbackBuilder.commonCallback()); throw new ServiceException(ResultCode.GOODS_NOT_EXIST); } @@ -284,15 +298,31 @@ public class GoodsSkuServiceImpl extends ServiceImpl i GoodsSkuVO goodsSkuDetail = this.getGoodsSkuVO(goodsSku); Map promotionMap = goodsIndex.getPromotionMap(); + AuthUser currentUser = UserContext.getCurrentUser(); //设置当前商品的促销价格 if (promotionMap != null && !promotionMap.isEmpty()) { promotionMap = promotionMap.entrySet().stream().parallel().filter(i -> { JSONObject jsonObject = JSONUtil.parseObj(i.getValue()); + if (i.getKey().contains(PromotionTypeEnum.COUPON.name()) && currentUser != null) { + Integer couponLimitNum = jsonObject.getInt("couponLimitNum"); + Coupon coupon = couponService.getById(jsonObject.getStr("id")); + if (coupon == null || (coupon.getPublishNum() != 0 && coupon.getReceivedNum() >= coupon.getPublishNum())) { + return false; + } + if (couponLimitNum > 0) { + Long count = memberCouponService.getMemberCouponNum(currentUser.getId(), jsonObject.getStr( + "id")); + if (count >= couponLimitNum) { + return false; + } + } + } // 过滤活动赠送优惠券和无效时间的活动 return (jsonObject.get("getType") == null || jsonObject.get("getType", String.class).equals(CouponGetEnum.FREE.name())) && (jsonObject.get("startTime") != null && jsonObject.get("startTime", Date.class).getTime() <= System.currentTimeMillis()) && (jsonObject.get("endTime") == null || jsonObject.get("endTime", Date.class).getTime() >= System.currentTimeMillis()); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - Optional> containsPromotion = promotionMap.entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); + Optional> containsPromotion = + promotionMap.entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.SECKILL.name()) || i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); if (containsPromotion.isPresent()) { JSONObject jsonObject = JSONUtil.parseObj(containsPromotion.get().getValue()); PromotionGoodsSearchParams searchParams = new PromotionGoodsSearchParams(); @@ -312,8 +342,10 @@ public class GoodsSkuServiceImpl extends ServiceImpl i map.put("data", goodsSkuDetail); //获取分类 - map.put("wholesaleList", GoodsSalesModeEnum.WHOLESALE.name().equals(goodsVO.getSalesModel()) ? wholesaleService.findByGoodsId(goodsSkuDetail.getGoodsId()) : Collections.emptyList()); - map.put("categoryName", CharSequenceUtil.isNotEmpty(goodsIndex.getCategoryNamePath()) ? goodsIndex.getCategoryNamePath().split(",") : null); + map.put("wholesaleList", GoodsSalesModeEnum.WHOLESALE.name().equals(goodsVO.getSalesModel()) ? + wholesaleService.findByGoodsId(goodsSkuDetail.getGoodsId()) : Collections.emptyList()); + map.put("categoryName", CharSequenceUtil.isNotEmpty(goodsIndex.getCategoryNamePath()) ? + goodsIndex.getCategoryNamePath().split(",") : null); //获取规格信息 map.put("specs", this.groupBySkuAndSpec(goodsVO.getSkuList())); @@ -325,8 +357,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl i } //记录用户足迹 - if (UserContext.getCurrentUser() != null) { - FootPrint footPrint = new FootPrint(UserContext.getCurrentUser().getId(), goodsIndex.getStoreId(), goodsId, skuId); + if (currentUser != null) { + FootPrint footPrint = new FootPrint(currentUser.getId(), goodsIndex.getStoreId(), goodsId, skuId); String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.VIEW_GOODS.name(); rocketMQTemplate.asyncSend(destination, footPrint, RocketmqSendCallbackBuilder.commonCallback()); } @@ -374,10 +406,13 @@ public class GoodsSkuServiceImpl extends ServiceImpl i boolean update = this.update(updateWrapper); if (Boolean.TRUE.equals(update)) { if (GoodsStatusEnum.UPPER.name().equals(marketEnable)) { - applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_STORE_GOODS_INDEX.name(), storeId)); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("生成店铺商品", + rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.GENERATOR_STORE_GOODS_INDEX.name(), + storeId)); } else if (GoodsStatusEnum.DOWN.name().equals(marketEnable)) { cache.vagueDel(CachePrefix.GOODS_SKU.getPrefix()); - applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除店铺商品", rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.STORE_GOODS_DELETE.name(), storeId)); + applicationEventPublisher.publishEvent(new TransactionCommitSendMQEvent("删除店铺商品", + rocketmqCustomProperties.getGoodsTopic(), GoodsTagsEnum.STORE_GOODS_DELETE.name(), storeId)); } } } @@ -443,9 +478,11 @@ public class GoodsSkuServiceImpl extends ServiceImpl i if ("images".equals(entry.getKey())) { specValueVO.setSpecName(entry.getKey()); if (entry.getValue().toString().contains("url")) { - List specImages = JSONUtil.toList(JSONUtil.parseArray(entry.getValue()), SpecValueVO.SpecImages.class); + List specImages = JSONUtil.toList(JSONUtil.parseArray(entry.getValue()), + SpecValueVO.SpecImages.class); specValueVO.setSpecImage(specImages); - goodsGalleryList = specImages.stream().map(SpecValueVO.SpecImages::getUrl).collect(Collectors.toList()); + goodsGalleryList = + specImages.stream().map(SpecValueVO.SpecImages::getUrl).collect(Collectors.toList()); } } else { specValueVO.setSpecName(entry.getKey()); @@ -496,7 +533,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl i goodsIndexService.deleteIndexById(goodsSku.getId()); } goodsSku.setQuantity(quantity); - boolean update = this.update(new LambdaUpdateWrapper().eq(GoodsSku::getId, skuId).set(GoodsSku::getQuantity, quantity)); + boolean update = + this.update(new LambdaUpdateWrapper().eq(GoodsSku::getId, skuId).set(GoodsSku::getQuantity, quantity)); if (update) { cache.remove(CachePrefix.GOODS.getPrefix() + goodsSku.getGoodsId()); } @@ -527,7 +565,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl i @Override @Transactional(rollbackFor = Exception.class) public void updateGoodsStuck(List goodsSkus) { - Map> groupByGoodsIds = goodsSkus.stream().collect(Collectors.groupingBy(GoodsSku::getGoodsId)); + Map> groupByGoodsIds = + goodsSkus.stream().collect(Collectors.groupingBy(GoodsSku::getGoodsId)); //获取相关的sku集合 LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.in(GoodsSku::getGoodsId, groupByGoodsIds.keySet()); @@ -572,9 +611,14 @@ public class GoodsSkuServiceImpl extends ServiceImpl i //修改规格索引,发送mq消息 - Map updateIndexFieldsMap = EsIndexUtil.getUpdateIndexFieldsMap(MapUtil.builder(new HashMap()).put("id", goodsSku.getId()).build(), MapUtil.builder(new HashMap()).put("commentNum", goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum).put("grade", grade).build()); - String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_FIELD.name(); - rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(updateIndexFieldsMap), RocketmqSendCallbackBuilder.commonCallback()); + Map updateIndexFieldsMap = + EsIndexUtil.getUpdateIndexFieldsMap(MapUtil.builder(new HashMap()).put("id", + goodsSku.getId()).build(), MapUtil.builder(new HashMap()).put("commentNum", + goodsSku.getCommentNum()).put("highPraiseNum", highPraiseNum).put("grade", grade).build()); + String destination = + rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.UPDATE_GOODS_INDEX_FIELD.name(); + rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(updateIndexFieldsMap), + RocketmqSendCallbackBuilder.commonCallback()); //修改商品的评价数量 goodsService.updateGoodsCommentNum(goodsSku.getGoodsId()); @@ -608,11 +652,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl i public Long countSkuNum(String storeId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper - .eq(GoodsSku::getStoreId, storeId) - .eq(GoodsSku::getDeleteFlag, Boolean.FALSE) - .eq(GoodsSku::getAuthFlag, GoodsAuthEnum.PASS.name()) - .eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); + queryWrapper.eq(GoodsSku::getStoreId, storeId).eq(GoodsSku::getDeleteFlag, Boolean.FALSE).eq(GoodsSku::getAuthFlag, GoodsAuthEnum.PASS.name()).eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); return this.count(queryWrapper); } diff --git a/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java b/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java index a2626156..3933ebb6 100644 --- a/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java +++ b/framework/src/main/java/cn/lili/modules/member/mapper/FootprintMapper.java @@ -27,7 +27,7 @@ public interface FootprintMapper extends BaseMapper { " FROM li_foot_print " + " WHERE member_id = ${memberId} " + " ORDER BY create_time DESC " + - " LIMIT 1 " + + " LIMIT 100 " + " ) AS keep " + ") AS latest_footprints " + "ON li_foot_print.id = latest_footprints.id " + diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java index f0c92f6c..b9239f6e 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/FootprintServiceImpl.java @@ -1,13 +1,13 @@ package cn.lili.modules.member.serviceimpl; import cn.lili.common.security.context.UserContext; -import cn.lili.common.vo.PageVO; +import cn.lili.modules.goods.entity.dos.GoodsSku; +import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.member.entity.dos.FootPrint; import cn.lili.modules.member.entity.dto.FootPrintQueryParams; import cn.lili.modules.member.mapper.FootprintMapper; import cn.lili.modules.member.service.FootprintService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; -import cn.lili.modules.search.service.EsGoodsSearchService; import cn.lili.mybatis.util.PageUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -21,7 +21,9 @@ import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * 会员浏览历史业务层实现 @@ -34,7 +36,7 @@ public class FootprintServiceImpl extends ServiceImpl footPrintPage(FootPrintQueryParams params) { - IPage footPrintPages = this.page(PageUtil.initPage(params), params.queryWrapper()); + params.setSort("createTime"); + Page footPrintPages = this.page(PageUtil.initPage(params), params.queryWrapper()); //定义结果 - IPage esGoodsIndexIPage = new Page<>(); - - if (footPrintPages.getRecords() == null || footPrintPages.getRecords().isEmpty()) { - return esGoodsIndexIPage; - } else { - List list = esGoodsSearchService.getEsGoodsBySkuIds( - footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()), params); + Page esGoodsIndexIPage = new Page<>(); + if (footPrintPages.getRecords() != null && !footPrintPages.getRecords().isEmpty()) { + List skuIds = footPrintPages.getRecords().stream().map(FootPrint::getSkuId).collect(Collectors.toList()); + List goodsSkuByIdFromCache = goodsSkuService.getGoodsSkuByIdFromCache(skuIds); + List collect = IntStream.range(0, goodsSkuByIdFromCache.size()) + .mapToObj(i -> { + if (goodsSkuByIdFromCache.get(i) == null) { + EsGoodsIndex esGoodsIndex = new EsGoodsIndex(); + esGoodsIndex.setReleaseTime(footPrintPages.getRecords().get(i).getCreateTime().getTime()); + return esGoodsIndex; + } + Optional first = footPrintPages.getRecords().stream().filter(j -> j.getSkuId().equals(goodsSkuByIdFromCache.get(i).getId())).findFirst(); + return first.map(footPrint -> new EsGoodsIndex(goodsSkuByIdFromCache.get(i), footPrint.getCreateTime())).orElseGet(() -> new EsGoodsIndex(goodsSkuByIdFromCache.get(i))); + }) + .collect(Collectors.toList()); esGoodsIndexIPage.setPages(footPrintPages.getPages()); - esGoodsIndexIPage.setRecords(list); + esGoodsIndexIPage.setRecords(collect); esGoodsIndexIPage.setTotal(footPrintPages.getTotal()); esGoodsIndexIPage.setSize(footPrintPages.getSize()); esGoodsIndexIPage.setCurrent(footPrintPages.getCurrent()); return esGoodsIndexIPage; } + return esGoodsIndexIPage; } @Override diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberAddressServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberAddressServiceImpl.java index a05ff296..5ccee96c 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberAddressServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberAddressServiceImpl.java @@ -69,9 +69,7 @@ public class MemberAddressServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(MemberSign::getMemberId, authUser.getId()); - List signSize = this.baseMapper.getTodayMemberSign(queryWrapper); - if (signSize.isEmpty()) { - throw new ServiceException(ResultCode.MEMBER_SIGN_REPEAT); - } //当前签到天数的前一天日期 List signs = this.baseMapper.getBeforeMemberSign(authUser.getId()); //构建参数 diff --git a/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java b/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java index 1cef92e1..938c9fb3 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/entity/vo/CartSkuVO.java @@ -102,6 +102,9 @@ public class CartSkuVO extends CartBase implements Serializable { */ public CartSkuVO(GoodsSku goodsSku) { this.goodsSku = goodsSku; + if (goodsSku.getUpdateTime() == null) { + this.goodsSku.setUpdateTime(goodsSku.getCreateTime()); + } this.checked = true; this.invalid = false; //默认时间为0,让系统为此商品更新缓存 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 a39e99ae..e5cd8981 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 @@ -120,6 +120,9 @@ public class CheckDataRender implements CartRenderStep { if (checkGoodsStatus || checkGoodsValid) { + if (checkGoodsValid) { + cartSkuVO.rebuildBySku(dataSku); + } if (checkGoodsStatus) { //设置购物车未选中 cartSkuVO.setChecked(false); @@ -127,10 +130,9 @@ public class CheckDataRender implements CartRenderStep { cartSkuVO.setInvalid(true); //设置失效消息 cartSkuVO.setErrorMessage("商品已下架"); + continue; } - if (checkGoodsValid) { - cartSkuVO.rebuildBySku(dataSku); - } + } //商品库存判定 diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/dto/search/CouponSearchParams.java b/framework/src/main/java/cn/lili/modules/promotion/entity/dto/search/CouponSearchParams.java index eddecde6..80227ee1 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/entity/dto/search/CouponSearchParams.java +++ b/framework/src/main/java/cn/lili/modules/promotion/entity/dto/search/CouponSearchParams.java @@ -103,7 +103,7 @@ public class CouponSearchParams extends BasePromotionsSearchParams implements Se } if (this.getStartTime() != null) { - queryWrapper.ge("start_time", new Date(this.getEndTime())); + queryWrapper.ge("start_time", new Date(this.getStartTime())); } if (this.getEndTime() != null) { queryWrapper.le("end_time", new Date(this.getEndTime())); diff --git a/framework/src/main/java/cn/lili/modules/promotion/service/AbstractPromotionsService.java b/framework/src/main/java/cn/lili/modules/promotion/service/AbstractPromotionsService.java index 241f7781..18a65b7f 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/service/AbstractPromotionsService.java +++ b/framework/src/main/java/cn/lili/modules/promotion/service/AbstractPromotionsService.java @@ -128,4 +128,11 @@ public interface AbstractPromotionsService extends ISe */ PromotionTypeEnum getPromotionType(); + /** + * 是否允许同一时间内存在相同的促销 + * + * @return 是否允许同一时间内存在相同的促销 + */ + boolean allowExistSame(); + } diff --git a/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java b/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java index 4bd4fa87..b807a080 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java +++ b/framework/src/main/java/cn/lili/modules/promotion/service/MemberCouponService.java @@ -165,4 +165,9 @@ public interface MemberCouponService extends IService { */ Page getMemberCouponsPage(Page page, MemberCouponSearchParams param); + /** + * 获取会员领取过的优惠券数量 + */ + long getMemberCouponNum(String memberId, String couponId); + } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java index fa75898c..3a16eb86 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/AbstractPromotionsServiceImpl.java @@ -112,6 +112,7 @@ public abstract class AbstractPromotionsServiceImpl, T e List promotionsList = this.list(new QueryWrapper().in("id", ids)); for (T t : promotionsList) { if (startTime != null && endTime != null) { + this.checkPromotions(t); t.setStartTime(new Date(startTime)); t.setEndTime(new Date(endTime)); } else { @@ -192,6 +193,9 @@ public abstract class AbstractPromotionsServiceImpl, T e @Override public void checkPromotions(T promotions) { PromotionTools.checkPromotionTime(promotions.getStartTime(), promotions.getEndTime()); + if (!this.allowExistSame()) { + this.checkSamePromotions(promotions); + } } /** @@ -264,4 +268,21 @@ public abstract class AbstractPromotionsServiceImpl, T e } } + @Override + public boolean allowExistSame() { + return false; + } + + public void checkSamePromotions(T promotions) { + if (promotions.getStartTime() == null || promotions.getEndTime() == null) { + return; + } + QueryWrapper queryWrapper = PromotionTools.checkActiveTime(promotions.getStartTime(), promotions.getEndTime(), this.getPromotionType(), promotions.getStoreId(), promotions.getId()); + long sameNum = this.count(queryWrapper); + //当前时间段是否存在同类活动 + if (sameNum > 0) { + throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST); + } + } + } diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java index 7592db71..88259b66 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/CouponServiceImpl.java @@ -310,11 +310,11 @@ public class CouponServiceImpl extends AbstractPromotionsServiceImpl promotionGoodsList = PromotionTools.promotionGoodsInit(fullDiscountVO.getPromotionGoodsList(), fullDiscountVO, PromotionTypeEnum.FULL_DISCOUNT); + List promotionGoodsList = + PromotionTools.promotionGoodsInit(fullDiscountVO.getPromotionGoodsList(), fullDiscountVO, + PromotionTypeEnum.FULL_DISCOUNT); this.promotionGoodsService.deletePromotionGoods(Collections.singletonList(promotions.getId())); //促销活动商品更新 result = this.promotionGoodsService.saveBatch(promotionGoodsList); @@ -166,8 +163,7 @@ public class FullDiscountServiceImpl extends AbstractPromotionsServiceImpl queryWrapper = PromotionTools.checkActiveTime(statTime, endTime, PromotionTypeEnum.FULL_DISCOUNT, storeId, id); - long sameNum = this.count(queryWrapper); - if (sameNum > 0) { - throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST); - } - } - /** * 检查优惠券信息 * diff --git a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/MemberCouponServiceImpl.java b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/MemberCouponServiceImpl.java index 467d4862..b4d643ae 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/MemberCouponServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/promotion/serviceimpl/MemberCouponServiceImpl.java @@ -327,6 +327,14 @@ public class MemberCouponServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(MemberCoupon::getMemberId, memberId); + queryWrapper.eq(MemberCoupon::getCouponId, couponId); + return this.count(queryWrapper); + } + /** * 清除无效的会员优惠券 * 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 51e60018..108931e9 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 @@ -31,12 +31,10 @@ import cn.lili.trigger.interfaces.TimeTrigger; import cn.lili.trigger.model.TimeExecuteConstant; import cn.lili.trigger.model.TimeTriggerMsg; import cn.lili.trigger.util.DelayQueueTools; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; /** @@ -156,48 +154,6 @@ public class PintuanServiceImpl extends AbstractPromotionsServiceImpl ids, Long startTime, Long endTime) { - if (startTime != null && endTime != null) { - for (String id : ids) { - Pintuan pintuan = this.getById(id); - QueryWrapper queryWrapper = PromotionTools.checkActiveTime(new Date(startTime), new Date(endTime), PromotionTypeEnum.PINTUAN, pintuan.getStoreId(), id); - long sameNum = this.count(queryWrapper); - //当前时间段是否存在同类活动 - if (sameNum > 0) { - throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST); - } - } - } - - return super.updateStatus(ids, startTime, endTime); - } - - /** - * 检查促销参数 - * - * @param promotions 促销实体 - */ - @Override - public void checkPromotions(Pintuan promotions) { - QueryWrapper queryWrapper = PromotionTools.checkActiveTime(promotions.getStartTime(), promotions.getEndTime(), PromotionTypeEnum.PINTUAN, promotions.getStoreId(), promotions.getId()); - long sameNum = this.count(queryWrapper); - //当前时间段是否存在同类活动 - if (sameNum > 0) { - throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST); - } - super.checkPromotions(promotions); - } - /** * 更新促销商品信息 * 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 2be950f4..f61c3e38 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 @@ -74,7 +74,8 @@ public class PointsGoodsServiceImpl extends AbstractPromotionsServiceImpl queryWrapper = PromotionTools.checkActiveTime(promotions.getStartTime(), promotions.getEndTime(), PromotionTypeEnum.SECKILL, null, promotions.getId()); - long sameNum = this.count(queryWrapper); - //当前时间段是否存在同类活动 - if (sameNum > 0) { - throw new ServiceException(ResultCode.PROMOTION_SAME_ACTIVE_EXIST); - } - } - - } /** diff --git a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java b/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java index 19b52cc0..6dc91f2f 100644 --- a/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java +++ b/framework/src/main/java/cn/lili/modules/promotion/tools/PromotionTools.java @@ -34,6 +34,10 @@ public class PromotionTools { public static final String PLATFORM_ID = "0"; public static final String PLATFORM_NAME = "platform"; + private PromotionTools() { + throw new IllegalStateException("Utility class"); + } + /** * 参数验证 * 1、活动起始时间必须大于当前时间 @@ -87,13 +91,43 @@ public class PromotionTools { } else { queryWrapper.ge(START_TIME_COLUMN, DateUtil.beginOfDay(startTime)).le(END_TIME_COLUMN, DateUtil.endOfDay(endTime)); } - queryWrapper.eq(CharSequenceUtil.isNotEmpty(storeId), "store_id", storeId); - queryWrapper.ne(CharSequenceUtil.isNotEmpty(activityId), "id", activityId); + if (storeId != null) { + queryWrapper.eq("store_id", storeId); + } + if (activityId != null) { + queryWrapper.ne("id", activityId); + } queryWrapper.and(i -> i.or(queryPromotionStatus(PromotionsStatusEnum.NEW)).or(queryPromotionStatus(PromotionsStatusEnum.START))); queryWrapper.eq("delete_flag", false); return queryWrapper; } + /** + * 检查商品是否重复参加同类型活动 + * + * @param exceptType 排除的促销活动类型(可同时参加的活动类型) + * @param skuIds 商品skuId + * @param activityId 当前活动id + * @return mybatis plus query wrapper对象 + */ + public static QueryWrapper checkSkuDuplicate(List exceptType, List skuIds, String activityId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (skuIds != null && !skuIds.isEmpty()) { + queryWrapper.in("sku_id", skuIds); + } + if (CharSequenceUtil.isNotEmpty(activityId)) { + queryWrapper.ne("id", activityId); + } + queryWrapper.and(i -> i.or(PromotionTools.queryPromotionStatus(PromotionsStatusEnum.START)).or(PromotionTools.queryPromotionStatus(PromotionsStatusEnum.NEW))); + + if (exceptType != null) { + queryWrapper.notIn(!exceptType.isEmpty(), "promotion_type", exceptType.stream().map(PromotionTypeEnum::name).collect(Collectors.toList())); + } + queryWrapper.eq("delete_flag", false); + + return queryWrapper; + } + public static Consumer> queryPromotionStatus(PromotionsStatusEnum promotionsStatusEnum) { switch (promotionsStatusEnum) { @@ -158,6 +192,12 @@ public class PromotionTools { return nextHour; } + /** + * 过滤无效促销活动 + * + * @param map 促销活动map + * @return 过滤后的促销活动map + */ public static Map filterInvalidPromotionsMap(Map map) { if (CollUtil.isEmpty(map)) { return new HashMap<>(); @@ -173,9 +213,22 @@ public class PromotionTools { return i.getValue() != null; }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue)); } catch (Exception e) { - log.error("过滤无效促销活动出现异常。异常促销信息:{},异常信息:{} ", map, e); + log.error("过滤无效促销活动出现异常。异常促销信息:{},异常信息 ", map, e); return new HashMap<>(); } } + /** + * 是否为需要检查的促销活动类型(用于判定部分类型的商品不能参与活动的条件) + * 内容为不需要检查的促销活动类型 + * + * @param key 促销key + * @return 当前促销key是否存在 + */ + public static boolean isPromotionsTypeNeedsToChecked(String key) { + return !CharSequenceUtil.containsAny(key, + PromotionTypeEnum.COUPON.name(), + PromotionTypeEnum.FULL_DISCOUNT.name()); + } + } diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java index 743b5dd5..493f594c 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dos/EsGoodsIndex.java @@ -350,6 +350,11 @@ public class EsGoodsIndex implements Serializable { } } + public EsGoodsIndex(GoodsSku sku, Date createDate) { + this(sku); + this.releaseTime = createDate.getTime(); + } + public void setGoodsSku(GoodsSku sku) { if (sku != null) { this.id = sku.getId(); diff --git a/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java b/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java index b0cf8c4b..1eeb7710 100644 --- a/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java +++ b/framework/src/main/java/cn/lili/modules/search/entity/dto/EsGoodsSearchDTO.java @@ -58,6 +58,24 @@ public class EsGoodsSearchDTO { @ApiModelProperty(value = "促销活动id") private String promotionsId; + /** + * @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum + */ + @ApiModelProperty(value = "商品类型") + private String goodsType; + + @ApiModelProperty("销售模式") + private String salesModel; + + /** + * @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum + */ + @ApiModelProperty(value = "除了当前商品类型之外") + private String neGoodsType; + + @ApiModelProperty("除了销售模式当前销售模式之外") + private String neSalesModel; + //过滤搜索关键字 public String getKeyword() { if (CharSequenceUtil.isNotEmpty(keyword)) { diff --git a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java index 22b46a27..61930be0 100644 --- a/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java +++ b/framework/src/main/java/cn/lili/modules/search/service/EsGoodsSearchService.java @@ -4,6 +4,7 @@ import cn.lili.common.vo.PageVO; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo; import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.springframework.data.elasticsearch.core.SearchPage; import java.util.List; @@ -25,6 +26,15 @@ public interface EsGoodsSearchService { */ SearchPage searchGoods(EsGoodsSearchDTO searchDTO, PageVO pageVo); + /** + * 商品搜索 + * + * @param searchDTO 搜索参数 + * @param pageVo 分页参数 + * @return 搜索结果 + */ + Page searchGoodsByPage(EsGoodsSearchDTO searchDTO, PageVO pageVo); + /** * 获取筛选器 * 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 3c12ceef..6a77c8e5 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 @@ -22,6 +22,7 @@ import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.dto.GoodsParamsDTO; import cn.lili.modules.goods.entity.dto.GoodsSkuDTO; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; +import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; import cn.lili.modules.goods.service.BrandService; import cn.lili.modules.goods.service.CategoryService; @@ -167,6 +168,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements skuQueryWrapper.eq("gs.auth_flag", GoodsAuthEnum.PASS.name()); skuQueryWrapper.eq("gs.market_enable", GoodsStatusEnum.UPPER.name()); skuQueryWrapper.eq("gs.delete_flag", false); + skuQueryWrapper.gt("gs.quantity", 0); Map resultMap = (Map) cache.get(CachePrefix.INIT_INDEX_PROCESS.getPrefix()); @@ -176,6 +178,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements skuCountQueryWrapper.eq("auth_flag", GoodsAuthEnum.PASS.name()); skuCountQueryWrapper.eq("market_enable", GoodsStatusEnum.UPPER.name()); skuCountQueryWrapper.eq("delete_flag", false); + skuCountQueryWrapper.ge("quantity", 0); resultMap = new HashMap<>(); resultMap.put(KEY_SUCCESS, 0L); resultMap.put(KEY_FAIL, 0L); @@ -540,6 +543,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements public UpdateRequest updateEsGoodsIndexPromotions(String id, BasePromotions promotion, String key) { EsGoodsIndex goodsIndex = findById(id); if (goodsIndex != null) { + // 批发商品不参与促销(除优惠券和满减) + if (PromotionTools.isPromotionsTypeNeedsToChecked(key) && GoodsSalesModeEnum.WHOLESALE.name().equals(goodsIndex.getSalesModel())) { + return null; + } //更新索引 return this.updateGoodsIndexPromotion(goodsIndex, key, promotion); } else { @@ -606,26 +613,25 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } private void executeUpdateEsGoodsIndexAll(BasePromotions promotion, String key) { - for (int i = 1; ; i++) { + for (int i = 0; ; i++) { List skuIds; + PageVO pageVO = new PageVO(); + pageVO.setPageNumber(i); + pageVO.setPageSize(1000); + EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO(); + if (PromotionTools.isPromotionsTypeNeedsToChecked(key)) { + searchDTO.setSalesModel(GoodsSalesModeEnum.RETAIL.name()); + } //如果storeId不为空,则表示是店铺活动 if (promotion.getStoreId() != null && !promotion.getStoreId().equals(PromotionTools.PLATFORM_ID)) { - PageVO pageVO = new PageVO(); - pageVO.setPageNumber(i); - pageVO.setPageSize(1000); - EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO(); searchDTO.setStoreId(promotion.getStoreId()); - //查询出店铺商品 - SearchPage esGoodsIndices = goodsSearchService.searchGoods(searchDTO, pageVO); - - skuIds = esGoodsIndices.isEmpty() ? new ArrayList<>() : esGoodsIndices.getContent().stream().map(SearchHit::getId).collect(Collectors.toList()); - } else { - //否则是平台活动 - org.springframework.data.domain.Page all = goodsIndexRepository.findAll(PageRequest.of(i, 1000)); - - //查询出全部商品 - skuIds = all.isEmpty() ? new ArrayList<>() : all.toList().stream().map(EsGoodsIndex::getId).collect(Collectors.toList()); } + + //查询出店铺商品 + SearchPage esGoodsIndices = goodsSearchService.searchGoods(searchDTO, pageVO); + + skuIds = esGoodsIndices.isEmpty() ? new ArrayList<>() : + esGoodsIndices.getContent().stream().map(SearchHit::getId).collect(Collectors.toList()); if (skuIds.isEmpty()) { break; } diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java index 669e6241..6078d77e 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsSearchServiceImpl.java @@ -17,6 +17,7 @@ import cn.lili.modules.search.entity.dto.SelectorOptions; import cn.lili.modules.search.service.EsGoodsSearchService; import cn.lili.modules.search.utils.SqlFilter; import com.alibaba.druid.util.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.apache.lucene.search.join.ScoreMode; import org.elasticsearch.common.lucene.search.function.FieldValueFactorFunction; @@ -37,15 +38,13 @@ import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.data.elasticsearch.core.ElasticsearchOperations; -import org.springframework.data.elasticsearch.core.SearchHitSupport; -import org.springframework.data.elasticsearch.core.SearchHits; -import org.springframework.data.elasticsearch.core.SearchPage; +import org.springframework.data.elasticsearch.core.*; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * ES商品搜索业务层实现 @@ -95,6 +94,20 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { return SearchHitSupport.searchPageFor(search, searchQuery.getPageable()); } + @Override + public Page searchGoodsByPage(EsGoodsSearchDTO searchDTO, PageVO pageVo) { + SearchPage esGoodsIndices = this.searchGoods(searchDTO, pageVo); + Page resultPage = new Page<>(); + if (esGoodsIndices != null && !esGoodsIndices.getContent().isEmpty()) { + List collect = esGoodsIndices.getSearchHits().getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()); + resultPage.setRecords(collect); + resultPage.setPages(esGoodsIndices.getTotalPages()); + resultPage.setCurrent(esGoodsIndices.getNumber() + 1L); + resultPage.setSize(esGoodsIndices.getSize()); + resultPage.setTotal(esGoodsIndices.getTotalElements()); + } + return resultPage; + } @Override public EsGoodsRelatedInfo getSelector(EsGoodsSearchDTO goodsSearch, PageVO pageVo) { @@ -453,6 +466,20 @@ public class EsGoodsSearchServiceImpl implements EsGoodsSearchService { if (searchDTO.getRecommend() != null) { filterBuilder.filter(QueryBuilders.termQuery("recommend", searchDTO.getRecommend())); } + // 商品类型判定 + if (CharSequenceUtil.isNotEmpty(searchDTO.getGoodsType())) { + filterBuilder.filter(QueryBuilders.termQuery("goodsType", searchDTO.getGoodsType())); + } + if (CharSequenceUtil.isNotEmpty(searchDTO.getNeGoodsType())) { + filterBuilder.mustNot(QueryBuilders.termQuery("goodsType", searchDTO.getNeGoodsType())); + } + // 销售类型判定 + if (CharSequenceUtil.isNotEmpty(searchDTO.getSalesModel())) { + filterBuilder.filter(QueryBuilders.termQuery("salesModel", searchDTO.getSalesModel())); + } + if (CharSequenceUtil.isNotEmpty(searchDTO.getNeSalesModel())) { + filterBuilder.mustNot(QueryBuilders.termQuery("salesModel", searchDTO.getNeSalesModel())); + } //规格项判定 if (searchDTO.getNameIds() != null && !searchDTO.getNameIds().isEmpty()) { filterBuilder.must(QueryBuilders.nestedQuery(ATTR_PATH, QueryBuilders.termsQuery("attrList.nameId", searchDTO.getNameIds()), ScoreMode.None)); 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 a45ef8a6..a145a47f 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 @@ -227,7 +227,7 @@ public class StoreServiceImpl extends ServiceImpl implements } else { store.setStoreDisable(StoreStatusEnum.REFUSED.value()); } - + cache.remove(CachePrefix.STORE.getPrefix()+store.getId()); return this.updateById(store); } diff --git a/im-api/src/main/java/cn/lili/controller/im/ImMessageController.java b/im-api/src/main/java/cn/lili/controller/im/ImMessageController.java index 6ef1180a..ab562631 100644 --- a/im-api/src/main/java/cn/lili/controller/im/ImMessageController.java +++ b/im-api/src/main/java/cn/lili/controller/im/ImMessageController.java @@ -75,7 +75,7 @@ public class ImMessageController { return ResultUtil.data(imMessageService.hasNewMessage(accessToken)); } - @GetMapping(value = "/unredMessage") + @GetMapping(value = "/unreadMessage") @ApiOperation(value = "获取所有未读消息") public ResultMessage getUnreadMessageCount() { return ResultUtil.data(imMessageService.unreadMessageCount()); 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 0262010e..5417c94f 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 @@ -63,6 +63,7 @@ public class StoreManagerController { @ApiImplicitParam(name = "storeId", value = "店铺ID", required = true, paramType = "path", dataType = "String") @GetMapping(value = "/get/detail/{storeId}") public ResultMessage detail(@PathVariable String storeId) { + // todo 对于刚提交审核的信息需要等待缓存失效后才能操作,否则缓存信息还在 return ResultUtil.data(storeDetailService.getStoreDetailVO(storeId)); } diff --git a/pom.xml b/pom.xml index 29fcaf50..84a36127 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ 2.2.2 0.11.2 4.0.0 - 1.2.8 + 1.2.16 1.0.3 4.7.2 4.7.2