feat(新增): 根据skuId获取促销与优惠券信息

This commit is contained in:
bunny 2024-04-10 10:01:20 +08:00
parent ee1c005f44
commit f9fc1053df
23 changed files with 360 additions and 39 deletions

View File

@ -14,7 +14,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,6 +1,8 @@
package com.atguigu.ssyx.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -8,7 +10,12 @@ import java.util.List;
import java.util.Map;
@FeignClient(value = "service-activity", path = "/api/activity")
public interface ActivityFeignClient { // 根据skuId列表获取促销信息
public interface ActivityFeignClient {
// 根据skuId列表获取促销信息
@PostMapping("inner/findActivity")
Map<Long, List<String>> findActivity(@RequestBody List<Long> skuIdList);
// 根据skuId获取促销与优惠券信息
@GetMapping("inner/findActivityAndCoupon/{skuId}/{userId}")
Map<String, Object> findActivityAndCoupon(@PathVariable Long skuId, @PathVariable Long userId);
}

View File

@ -3,6 +3,7 @@ package com.atguigu.ssyx.client.product;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -40,4 +41,8 @@ public interface ProductFeignClient {
// 获取新人专享
@GetMapping("inner/findNewPersonSkuInfoList")
Result<List<SkuInfo>> findNewPersonSkuInfoList();
// 根据skuId获取sku信息
@GetMapping("inner/getSkuInfoVo/{skuId}")
SkuInfoVo getSkuInfoVo(@PathVariable Long skuId);
}

View File

@ -3,6 +3,7 @@ package com.atguigu.ssyx.client.search;
import com.atguigu.ssyx.model.search.SkuEs;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@ -11,4 +12,8 @@ public interface SearchFeignClient {
// 获取爆品商品
@GetMapping("inner/findHotSkuList")
List<SkuEs> findHotSkuList();
// 更新商品incrHotScore
@GetMapping("inner/incrHotScore/{skuId}")
Boolean incrHotScore(@PathVariable Long skuId);
}

View File

@ -5,10 +5,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@ -26,4 +23,10 @@ public class ActivityApiController {
public Map<Long, List<String>> findActivity(@RequestBody List<Long> skuIdList) {
return activityInfoService.findActivity(skuIdList);
}
@ApiOperation(value = "根据skuId获取促销与优惠券信息")
@GetMapping("inner/findActivityAndCoupon/{skuId}/{userId}")
public Map<String, Object> findActivityAndCoupon(@PathVariable Long skuId, @PathVariable Long userId) {
return activityInfoService.findActivityAndCoupon(skuId, userId);
}
}

View File

@ -4,6 +4,8 @@ import com.atguigu.ssyx.model.activity.CouponInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 优惠券信息 Mapper 接口
@ -14,5 +16,13 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface CouponInfoMapper extends BaseMapper<CouponInfo> {
/**
* * 根据skuId获取活动规则数据
*
* @param id 商品id
* @param categoryId 分类id
* @param userId 用户id
* @return 优惠卷信息列表
*/
List<CouponInfo> selectCouponInfoList(Long id, Long categoryId, Long userId);
}

View File

@ -50,4 +50,13 @@ public interface ActivityInfoService extends IService<ActivityInfo> {
* @return Map<Long, List < String>>
*/
Map<Long, List<String>> findActivity(List<Long> skuIdList);
/**
* * 根据skuId获取促销与优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 营销的活动
*/
Map<String, Object> findActivityAndCoupon(Long skuId, Long userId);
}

View File

@ -57,4 +57,13 @@ public interface CouponInfoService extends IService<CouponInfo> {
* @return 根据关键字获取sku列表活动使用
*/
List<CouponInfo> findCouponByKeyword(String keyword);
/**
* * 获取优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 优惠卷列表
*/
List<CouponInfo> findCouponInfo(Long skuId, Long userId);
}

View File

@ -4,11 +4,13 @@ import com.atguigu.ssyx.activity.mapper.ActivityInfoMapper;
import com.atguigu.ssyx.activity.mapper.ActivityRuleMapper;
import com.atguigu.ssyx.activity.mapper.ActivitySkuMapper;
import com.atguigu.ssyx.activity.service.ActivityInfoService;
import com.atguigu.ssyx.activity.service.CouponInfoService;
import com.atguigu.ssyx.activity.service.module.ActivityInfoServiceModule;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.enums.ActivityType;
import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.activity.ActivityRule;
import com.atguigu.ssyx.model.activity.ActivitySku;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.ActivityRuleVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -36,6 +38,10 @@ public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, Act
private ActivityRuleMapper activityRuleMapper;
@Autowired
private ActivitySkuMapper activitySkuMapper;
@Autowired
private CouponInfoService couponInfoService;
@Autowired
private ActivityInfoServiceModule module;
/**
* 获取分页列表
@ -58,22 +64,22 @@ public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, Act
/**
* 获取活动规则
*
* @param id 当前id
* @param activityId 当前id
* @return 返回集合
*/
@Override
public Map<String, Object> findActivityRuleList(Long id) {
public Map<String, Object> findActivityRuleList(Long activityId) {
Map<String, Object> result = new HashMap<>();
// 活动信息列表
List<ActivityRule> activityInfoList = activityRuleMapper.selectList(
Wrappers.<ActivityRule>lambdaQuery().eq(ActivityRule::getActivityId, id)
Wrappers.<ActivityRule>lambdaQuery().eq(ActivityRule::getActivityId, activityId)
);
result.put("activityRuleList", activityInfoList);
// 查询活动列表
List<ActivitySku> activitySkuList = activitySkuMapper.selectList(
Wrappers.<ActivitySku>lambdaQuery().eq(ActivitySku::getActivityId, id)
Wrappers.<ActivitySku>lambdaQuery().eq(ActivitySku::getActivityId, activityId)
);
List<Long> skuIdList = activitySkuList.stream().map(ActivitySku::getSkuId).collect(Collectors.toList());
@ -159,7 +165,7 @@ public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, Act
List<String> ruleList = new ArrayList<>();
// 把规则名称处理
for (ActivityRule activityRule : activityRuleList) {
ruleList.add(this.getRuleDesc(activityRule));
ruleList.add(module.getRuleDesc(activityRule));
}
result.put(skuId, ruleList);
}
@ -167,25 +173,22 @@ public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, Act
return result;
}
// 构造规则名称的方法
private String getRuleDesc(ActivityRule activityRule) {
ActivityType activityType = activityRule.getActivityType();
StringBuilder ruleDesc = new StringBuilder();
if (activityType == ActivityType.FULL_REDUCTION) {
ruleDesc
.append("")
.append(activityRule.getConditionAmount())
.append("元减")
.append(activityRule.getBenefitAmount())
.append("");
} else {
ruleDesc
.append("")
.append(activityRule.getConditionNum())
.append("元打")
.append(activityRule.getBenefitDiscount())
.append("");
}
return ruleDesc.toString();
/**
* * 根据skuId获取促销与优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 营销的活动
*/
@Override
public Map<String, Object> findActivityAndCoupon(Long skuId, Long userId) {
// 一个sku只能有一个促销活动一个活动有多个活动规则如满赠满100送10满500送50
List<ActivityRule> activityRuleList = module.findActivityRuleList(skuId);
// 获取优惠券信息
List<CouponInfo> couponInfoList = couponInfoService.findCouponInfo(skuId, userId);
Map<String, Object> map = new HashMap<>();
map.put("activityRuleList", activityRuleList);
map.put("couponInfoList", couponInfoList);
return map;
}
}

View File

@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -29,6 +30,8 @@ public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponI
@Autowired
private CouponRangeMapper couponRangeMapper;
@Autowired
private CouponInfoMapper couponInfoMapper;
@Autowired
private ProductFeignClient productFeignClient;
/**
@ -133,4 +136,19 @@ public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponI
couponInfoQueryWrapper.like("coupon_name", keyword);
return list(couponInfoQueryWrapper);
}
/**
* * 获取优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 优惠卷列表
*/
@Override
public List<CouponInfo> findCouponInfo(Long skuId, Long userId) {
SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId).getData();
if (null == skuInfo) return new ArrayList<>();
// 根据skuId获取活动规则数据
return couponInfoMapper.selectCouponInfoList(skuInfo.getId(), skuInfo.getCategoryId(), userId);
}
}

View File

@ -0,0 +1,47 @@
package com.atguigu.ssyx.activity.service.module;
import com.atguigu.ssyx.activity.mapper.ActivityInfoMapper;
import com.atguigu.ssyx.enums.ActivityType;
import com.atguigu.ssyx.model.activity.ActivityRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ActivityInfoServiceModule {
@Autowired
private ActivityInfoMapper activityInfoMapper;
// 根据skuId获取活动规则数据
public List<ActivityRule> findActivityRuleList(Long skuId) {
List<ActivityRule> activityRuleList = activityInfoMapper.findActivityRule(skuId);
activityRuleList.forEach(activityRule -> {
String ruleDesc = this.getRuleDesc(activityRule);
activityRule.setRuleDesc(ruleDesc);
});
return activityRuleList;
}
// 构造规则名称的方法
public String getRuleDesc(ActivityRule activityRule) {
ActivityType activityType = activityRule.getActivityType();
StringBuilder ruleDesc = new StringBuilder();
if (activityType == ActivityType.FULL_REDUCTION) {
ruleDesc
.append("")
.append(activityRule.getConditionAmount())
.append("元减")
.append(activityRule.getBenefitAmount())
.append("");
} else {
ruleDesc
.append("")
.append(activityRule.getConditionNum())
.append("元打")
.append(activityRule.getBenefitDiscount())
.append("");
}
return ruleDesc.toString();
}
}

View File

@ -2,4 +2,36 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.CouponInfoMapper">
<!-- 根据skuId获取活动规则数据 -->
<select id="selectCouponInfoList" resultType="com.atguigu.ssyx.model.activity.CouponInfo">
select info.id
, info.coupon_type
, info.coupon_name
, info.amount
, info.condition_amount
, info.start_time
, info.end_time
, info.range_type
, info.range_desc
, info.publish_count
, info.per_limit
, info.use_count
, info.receive_count
, info.expire_time
, info.publish_status
, info.create_time
, info.update_time
, info.is_deleted
, cuse.coupon_status
from coupon_info info
left join coupon_range crange on crange.coupon_id = info.id
left join coupon_use cuse on cuse.coupon_id = info.id and cuse.user_id = #{userId}
where (
info.range_type = 1
or (crange.range_type = 2 and crange.range_id = #{skuId})
or (crange.range_type = 3 and crange.range_id = #{categoryId})
)
and now() between info.start_time and info.end_time
order by info.amount desc
</select>
</mapper>

View File

@ -23,6 +23,11 @@
<artifactId>service-user-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-activity-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-product-client</artifactId>

View File

@ -0,0 +1,19 @@
package com.atguigu.ssyx.home.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor() {
return new ThreadPoolExecutor(2, 5, 2,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}

View File

@ -0,0 +1,31 @@
package com.atguigu.ssyx.home.controller;
import com.atguigu.ssyx.common.context.BaseContext;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.home.service.ItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Api(tags = "商品详情")
@RestController
@RequestMapping("api/home")
public class ItemApiController {
@Autowired
private ItemService itemService;
@ApiOperation(value = "获取sku详细信息")
@GetMapping("item/{id}")
public Result<Map<String, Object>> index(@PathVariable Long id, HttpServletRequest request) {
Long userId = BaseContext.getUserId();
Map<String, Object> item = itemService.getItem(id, userId);
return Result.success(item);
}
}

View File

@ -0,0 +1,13 @@
package com.atguigu.ssyx.home.service;
import java.util.Map;
public interface ItemService {
/**
* * 获取sku详细信息
*
* @param userId 用户id
* @return sku详细信息
*/
Map<String, Object> getItem(Long skuId, Long userId);
}

View File

@ -0,0 +1,59 @@
package com.atguigu.ssyx.home.service.impl;
import com.atguigu.ssyx.client.ActivityFeignClient;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.client.search.SearchFeignClient;
import com.atguigu.ssyx.home.service.ItemService;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
private ProductFeignClient productFeignClient;
@Autowired
private ActivityFeignClient activityFeignClient;
@Autowired
private SearchFeignClient searchFeignClient;
/**
* * 获取sku详细信息
*
* @param userId 用户id
* @return sku详细信息
*/
@Override
public Map<String, Object> getItem(Long skuId, Long userId) {
HashMap<String, Object> result = new HashMap<>();
CompletableFuture<SkuInfoVo> skuInfoVoFuture = CompletableFuture.supplyAsync(() -> {
// 远程调用实现
SkuInfoVo skuInfoVo = productFeignClient.getSkuInfoVo(skuId);
result.put("skuInfoVo", skuInfoVo);
return skuInfoVo;
}, threadPoolExecutor);
// 获取优惠卷信息
CompletableFuture<Void> activityFuture = CompletableFuture.runAsync(() -> {
Map<String, Object> activityMap = activityFeignClient.findActivityAndCoupon(skuId, userId);
result.putAll(activityMap);
}, threadPoolExecutor);
// 更新商品热度
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
searchFeignClient.incrHotScore(skuId);
}, threadPoolExecutor);
// 任务组合
CompletableFuture.allOf(skuInfoVoFuture, activityFuture, voidCompletableFuture).join();
return result;
}
}

View File

@ -5,6 +5,7 @@ import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.product.service.CategoryService;
import com.atguigu.ssyx.product.service.SkuInfoService;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@ -68,4 +69,10 @@ public class ProductInnerController {
List<SkuInfo> newPersonList = skuInfoService.findNewPersonList();
return Result.success(newPersonList);
}
@ApiOperation(value = "根据skuId获取sku信息")
@GetMapping("inner/getSkuInfoVo/{skuId}")
public SkuInfoVo getSkuInfoVo(@PathVariable Long skuId) {
return skuInfoService.getSkuInfoVo(skuId);
}
}

View File

@ -3,8 +3,8 @@ server:
bunny:
rabbitmq:
host: 192.168.1.4
# host: 192.168.3.98
# host: 192.168.1.4
host: 192.168.3.98
port: 5672
username: bunny
password: "02120212"

View File

@ -50,4 +50,11 @@ public class SkuApiController {
public List<SkuEs> findHotSkuList() {
return skuService.findHotSkuList();
}
@ApiOperation(value = "更新商品incrHotScore")
@GetMapping("inner/incrHotScore/{skuId}")
public Boolean incrHotScore(@PathVariable Long skuId) {
skuService.incrHotScore(skuId);
return true;
}
}

View File

@ -37,4 +37,11 @@ public interface SkuService {
* @return 分页结果
*/
Page<SkuEs> search(Pageable pageRequest, SkuEsQueryVo searchParamVo);
/**
* * 更新商品incrHotScore
*
* @param skuId 商品id
*/
void incrHotScore(Long skuId);
}

View File

@ -15,12 +15,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@ -31,6 +33,8 @@ public class SkuServiceImpl implements SkuService {
private ProductFeignClient productFeignClient;
@Autowired
private ActivityFeignClient activityFeignClient;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 上架商品
@ -122,4 +126,25 @@ public class SkuServiceImpl implements SkuService {
}
return pageModel;
}
/**
* * 更新商品incrHotScore
*
* @param skuId 商品id
*/
@Override
public void incrHotScore(Long skuId) {
// 定义key
String hotKey = "hotScore";
// 更新热度当到达一直值时再去更新ES中内容
Double hotScore = redisTemplate.opsForZSet().incrementScore(hotKey, "skuId:" + skuId, 1);
// 规则
if (hotScore % 10 == 0) {
Optional<SkuEs> optional = skuRepository.findById(skuId);
SkuEs skuEs = optional.get();
skuEs.setHotScore(Math.round(hotScore));
// 如果有id值是更新没有id值是添加
skuRepository.save(skuEs);
}
}
}

View File

@ -3,15 +3,15 @@ server:
bunny:
rabbitmq:
host: 192.168.1.4
# host: 192.168.3.98
# host: 192.168.1.4
host: 192.168.3.98
port: 5672
username: bunny
password: "02120212"
elasticsearch:
uris: http://192.168.1.4:9200
# uris: http://192.168.3.98:9200
# uris: http://192.168.1.4:9200
uris: http://192.168.3.98:9200
nacos:
server-addr: z-bunny.cn:8848