提交 7414ea44 编写于 作者: huawei_code1994's avatar huawei_code1994

feat:优惠券模板对外暴露接口开发

上级 58335966
package com.youlai.mall.sms.pojo.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.youlai.mall.sms.pojo.enums.CouponCategoryEnum;
import com.youlai.mall.sms.pojo.enums.DistributeTargetEnum;
import com.youlai.mall.sms.pojo.enums.ProductLineEnum;
import com.youlai.mall.sms.pojo.vo.TemplateRuleVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xinyi
* @desc: 优惠券模板实体类:基础属性 + 规则属性
* @date 2021/6/26
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SmsCouponTemplate {
/**
* 主键自增ID
*/
@TableId
private Long id;
/**
* 是否是可用状态
*/
private Integer available;
/**
* 是否过期
*/
private Integer expired;
/**
* 优惠券名称
*/
private String name;
/**
* 优惠券logo
*/
private String logo;
/**
* 优惠券描述
*/
private String description;
/**
* 优惠券分类
*/
private CouponCategoryEnum category;
/**
* 产品线
*/
private ProductLineEnum productLine;
/**
* 总数
*/
private Integer total;
/**
* 优惠券模板编码
*/
private String code;
/**
* 目标用户
*/
private DistributeTargetEnum target;
/**
* 优惠券规则
*/
private TemplateRuleVO rule;
private Date gmtCreate;
private String gmtCreatedBy;
private Date gmtModified;
private String gmtModifiedBy;
}
......@@ -41,15 +41,14 @@ public class SmsSeckillSession implements Serializable {
/**
* 创建时间
*/
private Date createTime;
private Date gmtCreate;
/**
* 修改时间
*/
private Date updateTime;
private Date gmtModified;
@TableField(exist = false)
private List<SmsSeckillSkuRelation> relations;
private static final long serialVersionUID = 1L;
}
package com.youlai.mall.sms.pojo.dto;
import com.youlai.mall.sms.pojo.vo.TemplateRuleVO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xinyi
* @desc:微服务之间调用的优惠券模板信息
* @date 2021/6/27
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CouponTemplateDTO {
/**
* 优惠券模板主键ID
*/
private Long id;
/**
* 优惠券模板名称
*/
private String name;
/**
* 描述
*/
private String desc;
/**
* 分类
*/
private String category;
/**
* 产品线
*/
private String productLine;
/**
* 优惠券模板编码
*/
private String code;
/**
* 目标用户
*/
private Integer target;
/**
* 优惠券规则
*/
private TemplateRuleVO rule;
}
package com.youlai.mall.sms.pojo.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @author xinyi
* @desc: 优惠券分类
* @date 2021/6/26
*/
@Getter
@AllArgsConstructor
public enum CouponCategoryEnum {
MANJIAN("满减券", "001"),
ZHEKOU("折扣券", "002"),
LIJIAN("立减券", "003"),
;
/**
* 优惠券描述(分类)
*/
@JsonValue
private String desc;
/**
* 优惠券分类编码
*/
@EnumValue
private String code;
public static CouponCategoryEnum of(String code) {
Objects.requireNonNull(code);
return Stream.of(values()).filter(bean -> bean.code.equals(code))
.findAny()
.orElseThrow(() -> new IllegalArgumentException(code + " code not exist"));
}
}
package com.youlai.mall.sms.pojo.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @author xinyi
* @desc:优惠券分发目标枚举
* @date 2021/6/26
*/
@Getter
@AllArgsConstructor
public enum DistributeTargetEnum {
SINGLE("单用户",1),
MULTI("多用户",2),
;
/**
* 分发目标描述
*/
@JsonValue
private String desc;
/**
* 分发目标编码
*/
@EnumValue
private Integer code;
public static DistributeTargetEnum of(Integer code) {
Objects.requireNonNull(code);
return Stream.of(values()).filter(bean -> bean.code.equals(code))
.findAny()
.orElseThrow(() -> new IllegalArgumentException(code + " code not exist"));
}
}
package com.youlai.mall.sms.pojo.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @author xinyi
* @desc:有效期类型枚举
* @date 2021/6/26
*/
@Getter
@AllArgsConstructor
public enum PeriodTypeEnum {
REGULAR("固定的(固定日期)",1),
SHIFT("变动的(以领取之日开始计算)",2),
;
/**
* 有效期描述
*/
@JsonValue
private String desc;
/**
* 有效期编码
*/
@EnumValue
private Integer code;
public static PeriodTypeEnum of(Integer code) {
Objects.requireNonNull(code);
return Stream.of(values()).filter(bean -> bean.code.equals(code))
.findAny()
.orElseThrow(() -> new IllegalArgumentException(code + " code not exist"));
}
}
package com.youlai.mall.sms.pojo.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.stream.Stream;
/**
* @author xinyi
* @desc: 产品线枚举
* @date 2021/6/26
*/
@Getter
@AllArgsConstructor
public enum ProductLineEnum {
YOULAI("有来", 1),
WUHUI("无回", 2),
;
/**
* 产品线描述
*/
@JsonValue
private String desc;
/**
* 产品线编码
*/
@EnumValue
private Integer code;
public static ProductLineEnum of(String code) {
Objects.requireNonNull(code);
return Stream.of(values()).filter(bean -> bean.code.equals(code))
.findAny()
.orElseThrow(() -> new IllegalArgumentException(code + " code not exist"));
}
}
package com.youlai.mall.sms.pojo.form;
import com.youlai.mall.sms.pojo.vo.TemplateRuleVO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author xinyi
* @desc: 优惠券模板创建请求对象
* @date 2021/6/26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CouponTemplateForm {
private Long id;
/**
* 优惠券模板名称
*/
@NotBlank(message = "请填写优惠券模板名称")
private String name;
/**
* 优惠券 logo
*/
private String logo;
/**
* 优惠券描述
*/
@NotBlank(message = "请填写优惠券描述")
private String desc;
/**
* 优惠券分类
*/
@NotBlank(message = "请选择优惠券分类")
private String category;
/**
* 优惠券产品线
*/
@NotBlank(message = "请选择优惠券产品线")
private Integer productLine;
/**
* 优惠券总数量
*/
@NotNull(message = "请输入优惠券总数量")
@Min(value = 1, message = "优惠券数量必须大于1")
@Max(value = Integer.MAX_VALUE, message = "优惠券数量不能大于 " + Integer.MAX_VALUE)
private Integer total;
/**
* 目标用户
*/
private Integer target;
/**
* 优惠券规则
*/
private TemplateRuleVO rule;
}
package com.youlai.mall.sms.pojo.vo;
import com.youlai.common.base.BaseVO;
import com.youlai.mall.sms.pojo.enums.CouponCategoryEnum;
import com.youlai.mall.sms.pojo.enums.DistributeTargetEnum;
import com.youlai.mall.sms.pojo.enums.ProductLineEnum;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xinyi
* @desc: 优惠券模板实体类
* @date 2021/7/3
*/
@ApiModel(value = "优惠券模板模型",description = "优惠券模板模型")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CouponTemplateVO extends BaseVO {
/**
* 主键自增ID
*/
private Long id;
/**
* 是否是可用状态
*/
private Integer available;
/**
* 是否过期
*/
private Integer expired;
/**
* 优惠券名称
*/
private String name;
/**
* 优惠券logo
*/
private String logo;
/**
* 优惠券描述
*/
private String intro;
/**
* 优惠券分类
*/
private CouponCategoryEnum category;
/**
* 产品线
*/
private ProductLineEnum productLine;
/**
* 总数
*/
private Integer total;
/**
* 优惠券模板编码
*/
private String code;
/**
* 目标用户
*/
private DistributeTargetEnum target;
/**
* 优惠券规则
*/
private TemplateRuleVO rule;
}
package com.youlai.mall.sms.pojo.vo;
import com.youlai.mall.sms.pojo.enums.PeriodTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
/**
* @author xinyi
* @desc: 优惠券规则对象定义
* @date 2021/6/26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TemplateRuleVO {
/**
* 优惠券过期规则
*/
private Expiration expiration;
/**
* 折扣
*/
private Discount discount;
/**
* 限领张数限制
*/
private Integer limitation;
/**
* 使用范围:地域 + 商品类型
*/
private Usage usage;
/**
* 权重(可以和哪些优惠券叠加使用,同一类的优惠券一定不能叠加)
*/
private String weight;
/**
* 有效期规则定义
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Expiration {
/**
* 有效期规则,对应 PeriodType 的 code 字段
*/
private Integer period;
/**
* 有效间隔:只对变动性有效期有效
*/
private Integer gap;
/**
* 优惠券模板的失效日期,两类规则都有效
*/
private Long deadline;
boolean validate() {
// 最简化校验
return null != PeriodTypeEnum.of(period) && gap > 0;
}
}
/**
* 折扣的规则
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Discount {
/**
* 额度:满减(20),折扣(85),立减(10)
*/
private Integer quota;
/**
* 基准:需要满多少才可用
*/
private Integer base;
boolean validate() {
// 最简化校验
return quota > 0 && base > 0;
}
}
/**
* 优惠券使用范围
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Usage {
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 商品类型,list[文娱,生鲜,家居,全品类]
*/
private String goodsType;
boolean validate() {
return StringUtils.isNotEmpty(province)
&& StringUtils.isNotEmpty(province)
&& StringUtils.isNotEmpty(province);
}
}
}
......@@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 优惠营销系统
......@@ -16,6 +17,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableScheduling
public class SmsApplication {
public static void main(String[] args) {
......
package com.youlai.mall.sms.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author xinyi
* @desc: 自定义异步线程池
* @date 2021/6/27
*/
@Slf4j
@EnableAsync
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(20);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("youlai_async_");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
@SuppressWarnings("all")
class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
// 1、打印异常堆栈
throwable.printStackTrace();
// 2、日志记录错误信息
log.error("AsyncError:{}, Method:{}, Param:{}", throwable.getMessage(), method.getName(), Arrays.asList(objects));
// 3、TODO 发生异常后通知管理人员(邮件,短信)进一步处理
}
}
}
package com.youlai.mall.sms.controller.admin;
import com.youlai.common.result.Result;
import com.youlai.mall.sms.pojo.form.CouponTemplateForm;
import com.youlai.mall.sms.pojo.vo.CouponTemplateVO;
import com.youlai.mall.sms.service.ISmsCouponTemplateService;
import com.youlai.mall.sms.service.ITemplateBaseService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author xinyi
* @desc:优惠券模板API接口
* @date 2021/6/26
*/
@Slf4j
@Api(tags = "优惠券模板API接口")
@RestController
@RequestMapping("/api/v1/coupon_template")
public class CouponTemplateController {
@Autowired
private ITemplateBaseService templateBaseService;
@Autowired
private ISmsCouponTemplateService couponTemplateService;
/**
* 创建优惠券模板
*
* @param form 提交表单
* @return result
*/
@PostMapping("/template")
public Result<Object> createTemplate(@RequestBody CouponTemplateForm form) {
log.info("Create Coupon Template , form:{}", form);
couponTemplateService.createTemplate(form);
return Result.success();
}
/**
* 修改优惠券模板
* @param form 提交表单
* @return result
*/
@PutMapping("/template")
public Result<Object> updateTemplate(@RequestBody CouponTemplateForm form){
log.info("Update Coupon Template,form:{}",form);
couponTemplateService.updateTemplate(form);
return Result.success();
}
/**
* 查询优惠券模板详情
* @param id 优惠券模板ID
* @return result
*/
@GetMapping("/template/info")
public Result<CouponTemplateVO> getTemplateInfo(@RequestParam("id") Long id){
log.info("Query Coupon Template Info , id:{}",id);
CouponTemplateVO templateVO = templateBaseService.queryTemplateInfo(id);
return Result.success(templateVO);
}
}
......@@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SmsCouponDao extends BaseMapper<SmsCoupon> {
public interface SmsCouponMapper extends BaseMapper<SmsCoupon> {
int deleteByPrimaryKey(Long id);
int insertSelective(SmsCoupon record);
......
......@@ -5,7 +5,7 @@ import com.youlai.mall.sms.pojo.domain.SmsCouponRecord;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmsCouponRecordDao extends BaseMapper<SmsCouponRecord> {
public interface SmsCouponRecordMapper extends BaseMapper<SmsCouponRecord> {
int deleteByPrimaryKey(Long id);
int insertSelective(SmsCouponRecord record);
......
package com.youlai.mall.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import org.apache.ibatis.annotations.Mapper;
/**
* @author xinyi
* @desc:优惠券模板Dao接口定义
* @date 2021/6/26
*/
@Mapper
public interface SmsCouponTemplateMapper extends BaseMapper<SmsCouponTemplate> {
}
package com.youlai.mall.sms.service;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
/**
* @author xinyi
* @desc:异步服务接口
* @date 2021/6/27
*/
public interface IAsyncService {
/**
* 通过优惠券模板异步的创建优惠券码
* @param template {@link SmsCouponTemplate} 优惠券模板实体
*/
void asyncConstructCouponByTemplate(SmsCouponTemplate template);
}
package com.youlai.mall.sms.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.pojo.form.CouponTemplateForm;
import java.util.List;
/**
* @author xinyi
* @desc: 优惠券模板业务接口
* @date 2021/6/26
*/
public interface ISmsCouponTemplateService extends IService<SmsCouponTemplate> {
/**
* 创建优惠券模板
*
* @param form {@link CouponTemplateForm} 模板信息请求对象
* @return {@link SmsCouponTemplate} 优惠券模板实体类
*/
SmsCouponTemplate createTemplate(CouponTemplateForm form);
/**
* 修改优惠券模板
* @param form {@link CouponTemplateForm} 模板信息请求对象
* @return {@link SmsCouponTemplate} 优惠券模板实体类
*/
SmsCouponTemplate updateTemplate(CouponTemplateForm form);
/**
* 查询所有可用优惠券模板列表
*
* @param available 是否可用
* @param expired 是否过期
* @return 优惠券模板
*/
List<SmsCouponTemplate> findAllUsableTemplate(boolean available, boolean expired);
/**
* 查询未过期的优惠券模板列表
*
* @param expired 是否过期
* @return 优惠券模板列表
*/
List<SmsCouponTemplate> findAllNotExpiredTemplate(Integer expired);
}
package com.youlai.mall.sms.service;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.pojo.vo.CouponTemplateVO;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author xinyi
* @desc: 优惠券模板基础业务接口
* @date 2021/7/3
*/
public interface ITemplateBaseService {
/**
* 根据优惠券模板id 获取优惠券模板信息
* @param id 优惠券模板ID
* @return {@link SmsCouponTemplate} 优惠券模板实体类
*/
CouponTemplateVO queryTemplateInfo(Long id);
/**
* 查询所有可用优惠券模板列表
* @return 优惠券模板列表
*/
List<SmsCouponTemplate> findAllUsableTemplate();
/**
* 根据优惠券模板ID集合查询可用模板列表
* @param ids 优惠券模板ID集合
* @return 优惠券模板列表
*/
Map<Long, SmsCouponTemplate> findAllTemplateByIds(Collection<Long> ids);
}
package com.youlai.mall.sms.service.impl;
import cn.hutool.core.date.format.FastDateFormat;
import com.google.common.base.Stopwatch;
import com.youlai.common.constant.RedisConstants;
import com.youlai.common.redis.utils.RedisUtils;
import com.youlai.mall.sms.mapper.SmsCouponTemplateMapper;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.service.IAsyncService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author xinyi
* @desc:异步服务接口实现
* @date 2021/6/27
*/
@Slf4j
@Service
@AllArgsConstructor
public class AsyncServiceImpl implements IAsyncService {
private final RedisUtils redisUtils;
private final SmsCouponTemplateMapper couponTemplateMapper;
@Async("getAsyncExecutor")
@Override
public void asyncConstructCouponByTemplate(SmsCouponTemplate template) {
Stopwatch watch = Stopwatch.createStarted();
Set<String> couponCodes = buildCouponCode(template);
String couponCodeKey = String.format("%s%s", RedisConstants.SMS_COUPON_TEMPLATE_CODE_KEY, String.valueOf(template.getId()));
redisUtils.lSet(couponCodeKey, couponCodes);
log.info("Push CouponCode To Redis, Coupon Template " +
"ID:{}, Name:{}, TOTAL:{}", template.getId(), template.getName(), template.getTotal());
template.setAvailable(1);
couponTemplateMapper.updateById(template);
watch.stop();
log.info("Construct CouponCode By Coupon Template Use:{}ms", watch.elapsed(TimeUnit.MILLISECONDS));
}
/**
* 构造优惠券码
* 优惠券码对应于每一张优惠券,一共18位
* 前四位:产品线+类型
* 中间六位:日期随机
* 后八位:0 ~ 9 随机数构成
*
* @param template {@link SmsCouponTemplate} 优惠券模板实体类
* @return Set<String> 与 template.total 总优惠券数量
*/
private Set<String> buildCouponCode(SmsCouponTemplate template) {
Stopwatch watch = Stopwatch.createStarted();
Set<String> result = new HashSet<>(template.getTotal());
String prefix4 = template.getProductLine().getCode() + template.getCategory().getCode();
String date = FastDateFormat.getInstance("yyMMdd").format(new Date());
for (Integer i = 0; i < template.getTotal(); i++) {
result.add(buildCouponCodeSuffix14(date));
}
while (result.size() < template.getTotal()) {
result.add(prefix4 + buildCouponCodeSuffix14(date));
}
// 断言
assert result.size() == template.getTotal();
watch.stop();
log.info("Build Coupon Code use:{}ms", watch.elapsed(TimeUnit.MILLISECONDS));
return result;
}
/**
* 构造优惠券码后十四位
*
* @param date
* @return
*/
private String buildCouponCodeSuffix14(String date) {
char[] bases = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9'};
// 中间六位
List<Character> chars = date.chars().mapToObj(obj -> (char) obj).collect(Collectors.toList());
Collections.shuffle(chars);
String mid6 = chars.stream().map(Objects::toString).collect(Collectors.joining());
// 后八位
String suffix8 = RandomStringUtils.random(1, bases) + RandomStringUtils.randomNumeric(7);
return mid6 + suffix8;
}
}
......@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.common.web.exception.BizException;
import com.youlai.common.web.util.JwtUtils;
import com.youlai.mall.sms.mapper.SmsCouponRecordDao;
import com.youlai.mall.sms.mapper.SmsCouponRecordMapper;
import com.youlai.mall.sms.pojo.domain.SmsCoupon;
import com.youlai.mall.sms.pojo.domain.SmsCouponRecord;
import com.youlai.mall.sms.pojo.enums.CouponStateEnum;
......@@ -30,7 +30,7 @@ import static com.youlai.mall.sms.pojo.constant.AppConstants.COUPON_LOCK;
*/
@Service
@Slf4j
public class CouponRecordServiceImpl extends ServiceImpl<SmsCouponRecordDao, SmsCouponRecord> implements ICouponRecordService {
public class CouponRecordServiceImpl extends ServiceImpl<SmsCouponRecordMapper, SmsCouponRecord> implements ICouponRecordService {
@Autowired
private ISmsCouponService couponService;
......
package com.youlai.mall.sms.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.mall.sms.mapper.SmsCouponRecordDao;
import com.youlai.mall.sms.mapper.SmsCouponRecordMapper;
import com.youlai.mall.sms.pojo.domain.SmsCouponRecord;
import com.youlai.mall.sms.service.ISmsCouponRecordService;
import lombok.extern.slf4j.Slf4j;
......@@ -15,5 +15,5 @@ import org.springframework.stereotype.Service;
*/
@Slf4j
@Service
public class SmsCouponRecordServiceImpl extends ServiceImpl<SmsCouponRecordDao, SmsCouponRecord> implements ISmsCouponRecordService {
public class SmsCouponRecordServiceImpl extends ServiceImpl<SmsCouponRecordMapper, SmsCouponRecord> implements ISmsCouponRecordService {
}
......@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.common.base.BasePageQuery;
import com.youlai.common.web.util.BeanMapperUtils;
import com.youlai.mall.sms.mapper.SmsCouponDao;
import com.youlai.mall.sms.mapper.SmsCouponMapper;
import com.youlai.mall.sms.pojo.domain.SmsCoupon;
import com.youlai.mall.sms.pojo.form.CouponForm;
import com.youlai.mall.sms.pojo.vo.SmsCouponVO;
......@@ -22,7 +22,7 @@ import org.springframework.stereotype.Service;
*/
@Service
@Slf4j
public class SmsCouponServiceImpl extends ServiceImpl<SmsCouponDao, SmsCoupon> implements ISmsCouponService {
public class SmsCouponServiceImpl extends ServiceImpl<SmsCouponMapper, SmsCoupon> implements ISmsCouponService {
@Override
public SmsCouponVO detail(String couponId) {
log.info("根据优惠券ID获取优惠券详情,couponId={}", couponId);
......
package com.youlai.mall.sms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.common.web.exception.BizException;
import com.youlai.mall.sms.mapper.SmsCouponTemplateMapper;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.pojo.enums.CouponCategoryEnum;
import com.youlai.mall.sms.pojo.enums.DistributeTargetEnum;
import com.youlai.mall.sms.pojo.form.CouponTemplateForm;
import com.youlai.mall.sms.service.IAsyncService;
import com.youlai.mall.sms.service.ISmsCouponTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author xinyi
* @desc: 优惠券模板业务实现类
* @date 2021/6/26
*/
@Slf4j
@Service
public class SmsCouponTemplateServiceImpl extends ServiceImpl<SmsCouponTemplateMapper, SmsCouponTemplate>
implements ISmsCouponTemplateService {
@Autowired
private IAsyncService asyncService;
@Override
public SmsCouponTemplate createTemplate(CouponTemplateForm form) {
// 1、form 表单参数校验
// 2、不允许出现同名的模板
if (null == findByCouponTemplateName(form.getName())) {
throw new BizException("Coupon Template Name Exist");
}
// 构造 CouponTemplate 并保存到数据库
SmsCouponTemplate template = formToTemplate(form);
this.save(template);
// 根据优惠券模板异步生成优惠券码
asyncService.asyncConstructCouponByTemplate(template);
return template;
}
@Override
public SmsCouponTemplate updateTemplate(CouponTemplateForm form) {
// TODO 开发中。。。
return null;
}
@Override
public List<SmsCouponTemplate> findAllUsableTemplate(boolean available, boolean expired) {
QueryWrapper<SmsCouponTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("available", available)
.eq("expired", expired);
return this.list(queryWrapper);
}
@Override
public List<SmsCouponTemplate> findAllNotExpiredTemplate(Integer expired) {
QueryWrapper<SmsCouponTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("expired", expired);
return this.list(queryWrapper);
}
/**
* 根据模板名称查询实体类
*
* @param name 模板名称
* @return 模板实体类
*/
private SmsCouponTemplate findByCouponTemplateName(String name) {
QueryWrapper<SmsCouponTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", name);
return getOne(queryWrapper);
}
private SmsCouponTemplate formToTemplate(CouponTemplateForm form) {
SmsCouponTemplate template = new SmsCouponTemplate();
template.setName(form.getName());
template.setLogo(form.getLogo());
template.setCategory(CouponCategoryEnum.of(form.getCategory()));
template.setTotal(form.getTotal());
template.setTarget(DistributeTargetEnum.of(form.getTarget()));
template.setRule(form.getRule());
template.setCode("");
return template;
}
}
package com.youlai.mall.sms.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.youlai.common.web.exception.BizException;
import com.youlai.common.web.util.BeanMapperUtils;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.pojo.vo.CouponTemplateVO;
import com.youlai.mall.sms.service.ISmsCouponTemplateService;
import com.youlai.mall.sms.service.ITemplateBaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author xinyi
* @desc:优惠券模板基础业务实现类
* @date 2021/7/3
*/
@Service
public class TemplateBaseServiceImpl implements ITemplateBaseService {
@Autowired
private ISmsCouponTemplateService couponTemplateService;
@Override
public CouponTemplateVO queryTemplateInfo(Long id) {
SmsCouponTemplate template = couponTemplateService.getById(id);
if (null == template) {
throw new BizException("Template Is Not Exist: " + id);
}
return BeanMapperUtils.map(template,CouponTemplateVO.class);
}
@Override
public List<SmsCouponTemplate> findAllUsableTemplate() {
return couponTemplateService.findAllUsableTemplate(true, false);
}
@Override
public Map<Long, SmsCouponTemplate> findAllTemplateByIds(Collection<Long> ids) {
List<SmsCouponTemplate> templates = couponTemplateService.listByIds(ids);
if (CollUtil.isEmpty(templates)) {
return MapUtil.empty();
}
return templates.stream()
.collect(Collectors.toMap(SmsCouponTemplate::getId, Function.identity()));
}
}
package com.youlai.mall.sms.shedule;
import cn.hutool.core.collection.CollUtil;
import com.youlai.mall.sms.pojo.domain.SmsCouponTemplate;
import com.youlai.mall.sms.pojo.vo.TemplateRuleVO;
import com.youlai.mall.sms.service.ISmsCouponTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author xinyi
* @desc:定时清理已过期的优惠券模板
* @date 2021/7/3
*/
@Slf4j
@Component
public class ScheduleTask {
@Autowired
private ISmsCouponTemplateService couponTemplateService;
/**
* 下线已过期的优惠券模板
*/
@Scheduled(fixedRate = 60 * 60 * 1000)
public void offlineCouponTemplate() {
log.info("Start To Expired CouponTemplate.");
// 查询未过期的优惠券模板
List<SmsCouponTemplate> templates = couponTemplateService.findAllNotExpiredTemplate(1);
if (CollUtil.isEmpty(templates)) {
log.info("Done To Expired CouponTemplate.");
return;
}
Date nowTime = new Date();
List<SmsCouponTemplate> expiredTemplates = new ArrayList<>(templates.size());
for (SmsCouponTemplate template : templates) {
TemplateRuleVO rule = template.getRule();
if (rule.getExpiration().getDeadline() < nowTime.getTime()) {
template.setExpired(0);
expiredTemplates.add(template);
}
}
couponTemplateService.updateBatchById(expiredTemplates);
log.info("Update Expired CouponTemplate Num:{}", expiredTemplates.size());
log.info("Done To Expired CouponTemplate.");
}
}
package com.youlai.mall.sms;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author xinyi
* @desc: 营销系统测试
* @date 2021/7/3
*/
@SpringBootTest
public class SmsApplicationTest {
@Test
public void contestLoad(){
}
}
package com.youlai.common.constant;
/**
* @author xinyi
* @desc: MQ消息常量
* @date 2021/6/27
*/
public interface MQConstants {
/**
* SMS服务优惠券消息Topic
*/
String SMS_COUPON_TOPIC = "sms_coupon_topic";
}
......@@ -4,4 +4,26 @@ public interface RedisConstants {
String BUSINESS_NO_PREFIX = "business_no:";
/**
* 优惠券码KEY前缀
*/
String SMS_COUPON_TEMPLATE_CODE_KEY = "sms_coupon_template_code_";
/**
* 用户当前所有可用优惠券key
*/
String SMS_USER_COUPON_USABLE_KEY = "sms_user_coupon_usable_";
/**
* 用户当前所有已使用优惠券key
*/
String SMS_USER_COUPON_USED_KEY = "sms_user_coupon_used_";
/**
* 用户当前所有已过期优惠券key
*/
String SMS_USER_COUPON_EXPIRED_KEY = "sms_user_coupon_expired_";
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册