Commit fc432ba073485be7a292557dd8fe1bd492bfae90

Authored by owen
1 parent 497ea2ee

优惠券:新人券使用 MQ 发放

yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
@@ -12,6 +12,7 @@ import org.apache.ibatis.annotations.Mapper; @@ -12,6 +12,7 @@ import org.apache.ibatis.annotations.Mapper;
12 import org.apache.ibatis.annotations.Param; 12 import org.apache.ibatis.annotations.Param;
13 13
14 import java.time.LocalDateTime; 14 import java.time.LocalDateTime;
  15 +import java.util.List;
15 import java.util.function.Consumer; 16 import java.util.function.Consumer;
16 17
17 /** 18 /**
@@ -48,4 +49,7 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> { @@ -48,4 +49,7 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
48 49
49 void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount); 50 void updateTakeCount(@Param("id") Long id, @Param("incrCount") Integer incrCount);
50 51
  52 + default List<CouponTemplateDO> selectListByTakeType(Integer takeType) {
  53 + return selectList(CouponTemplateDO::getTakeType, takeType);
  54 + }
51 } 55 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/RegisterCouponSendConsumer.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.mq.consumer.coupon;
  2 +
  3 +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
  4 +import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage;
  5 +import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +/**
  12 + * 针对 {@link RegisterCouponSendMessage} 的消费者
  13 + *
  14 + * @author owen
  15 + */
  16 +@Component
  17 +@Slf4j
  18 +public class RegisterCouponSendConsumer extends AbstractStreamMessageListener<RegisterCouponSendMessage> {
  19 +
  20 + @Resource
  21 + private CouponService couponService;
  22 +
  23 + @Override
  24 + public void onMessage(RegisterCouponSendMessage message) {
  25 + log.info("[onMessage][消息内容({})]", message);
  26 + couponService.takeCouponByRegister(message.getUserId());
  27 + }
  28 +
  29 +}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
@@ -119,12 +119,9 @@ public interface CouponService { @@ -119,12 +119,9 @@ public interface CouponService {
119 /** 119 /**
120 * 【系统】给用户发送新人券 120 * 【系统】给用户发送新人券
121 * 121 *
122 - * @param templateId 优惠券模板编号  
123 - * @param userId 用户编号列表 122 + * @param userId 用户编号
124 */ 123 */
125 - default void takeCouponByRegister(Long templateId, Long userId) {  
126 - takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);  
127 - } 124 + void takeCouponByRegister(Long userId);
128 125
129 /** 126 /**
130 * 获取会员领取指定优惠券的数量 127 * 获取会员领取指定优惠券的数量
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -40,7 +40,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -40,7 +40,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
40 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 40 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
41 import static java.util.Arrays.asList; 41 import static java.util.Arrays.asList;
42 42
43 -// TODO @疯狂:注册时,赠送用户优惠劵;为了解耦,可以考虑注册时发个 MQ 消息;然后营销这里监听后消费;  
44 /** 43 /**
45 * 优惠劵 Service 实现类 44 * 优惠劵 Service 实现类
46 * 45 *
@@ -184,6 +183,14 @@ public class CouponServiceImpl implements CouponService { @@ -184,6 +183,14 @@ public class CouponServiceImpl implements CouponService {
184 } 183 }
185 184
186 @Override 185 @Override
  186 + public void takeCouponByRegister(Long userId) {
  187 + List<CouponTemplateDO> templates = couponTemplateService.getCouponTemplateByTakeType(CouponTakeTypeEnum.REGISTER);
  188 + for (CouponTemplateDO template : templates) {
  189 + takeCoupon(template.getId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
  190 + }
  191 + }
  192 +
  193 + @Override
187 public List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId) { 194 public List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId) {
188 if (CollUtil.isEmpty(templateIds)) { 195 if (CollUtil.isEmpty(templateIds)) {
189 return ListUtil.empty(); 196 return ListUtil.empty();
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
@@ -5,8 +5,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou @@ -5,8 +5,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou
5 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO; 5 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
6 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO; 6 import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO;
7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; 7 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
  8 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
8 9
9 import javax.validation.Valid; 10 import javax.validation.Valid;
  11 +import java.util.List;
10 12
11 /** 13 /**
12 * 优惠劵模板 Service 接口 14 * 优惠劵模板 Service 接口
@@ -69,4 +71,11 @@ public interface CouponTemplateService { @@ -69,4 +71,11 @@ public interface CouponTemplateService {
69 */ 71 */
70 void updateCouponTemplateTakeCount(Long id, int incrCount); 72 void updateCouponTemplateTakeCount(Long id, int incrCount);
71 73
  74 + /**
  75 + * 获得指定领取方式的优惠券模板
  76 + *
  77 + * @param takeType 领取方式
  78 + * @return 优惠券模板列表
  79 + */
  80 + List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType);
72 } 81 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
@@ -8,11 +8,14 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou @@ -8,11 +8,14 @@ import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.Cou
8 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert; 8 import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert;
9 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; 9 import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
10 import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper; 10 import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper;
  11 +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
11 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
12 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
13 14
14 import javax.annotation.Resource; 15 import javax.annotation.Resource;
15 16
  17 +import java.util.List;
  18 +
16 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
17 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; 20 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS;
18 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL; 21 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL;
@@ -93,4 +96,9 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { @@ -93,4 +96,9 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
93 couponTemplateMapper.updateTakeCount(id, incrCount); 96 couponTemplateMapper.updateTakeCount(id, incrCount);
94 } 97 }
95 98
  99 + @Override
  100 + public List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType) {
  101 + return couponTemplateMapper.selectListByTakeType(takeType.getValue());
  102 + }
  103 +
96 } 104 }
yudao-module-member/yudao-module-member-api/pom.xml
@@ -22,6 +22,11 @@ @@ -22,6 +22,11 @@
22 <artifactId>yudao-common</artifactId> 22 <artifactId>yudao-common</artifactId>
23 </dependency> 23 </dependency>
24 24
  25 + <dependency>
  26 + <groupId>cn.iocoder.boot</groupId>
  27 + <artifactId>yudao-spring-boot-starter-mq</artifactId>
  28 + <scope>compile</scope>
  29 + </dependency>
25 <!-- 参数校验 --> 30 <!-- 参数校验 -->
26 <dependency> 31 <dependency>
27 <groupId>org.springframework.boot</groupId> 32 <groupId>org.springframework.boot</groupId>
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/RegisterCouponSendMessage.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.mq.message.user;
  2 +
  3 +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +/**
  10 + * 新人券发放消息
  11 + *
  12 + * @author owen
  13 + */
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +public class RegisterCouponSendMessage extends AbstractStreamMessage {
  17 +
  18 + /**
  19 + * 用户编号
  20 + */
  21 + @NotNull(message = "用户编号不能为空")
  22 + private Long userId;
  23 +
  24 + @Override
  25 + public String getStreamKey() {
  26 + return "member.register-coupon.send";
  27 + }
  28 +
  29 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/RegisterCouponProducer.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.mq.producer.user;
  2 +
  3 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
  4 +import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.stereotype.Component;
  7 +
  8 +import javax.annotation.Resource;
  9 +
  10 +/**
  11 + * 新人券发放 Producer
  12 + *
  13 + * @author owen
  14 + */
  15 +@Slf4j
  16 +@Component
  17 +public class RegisterCouponProducer {
  18 +
  19 + @Resource
  20 + private RedisMQTemplate redisMQTemplate;
  21 +
  22 + /**
  23 + * 发送 {@link RegisterCouponSendMessage} 消息
  24 + *
  25 + * @param userId 用户编号
  26 + */
  27 + public void sendMailSendMessage(Long userId) {
  28 + redisMQTemplate.send(new RegisterCouponSendMessage().setUserId(userId));
  29 + }
  30 +
  31 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
@@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
18 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; 18 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
19 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; 19 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
20 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; 20 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
  21 +import cn.iocoder.yudao.module.member.mq.producer.user.RegisterCouponProducer;
21 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 22 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
22 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; 23 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
23 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; 24 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
@@ -58,6 +59,9 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -58,6 +59,9 @@ public class MemberUserServiceImpl implements MemberUserService {
58 @Resource 59 @Resource
59 private PasswordEncoder passwordEncoder; 60 private PasswordEncoder passwordEncoder;
60 61
  62 + @Resource
  63 + private RegisterCouponProducer registerCouponProducer;
  64 +
61 @Override 65 @Override
62 public MemberUserDO getUserByMobile(String mobile) { 66 public MemberUserDO getUserByMobile(String mobile) {
63 return memberUserMapper.selectByMobile(mobile); 67 return memberUserMapper.selectByMobile(mobile);
@@ -89,6 +93,9 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -89,6 +93,9 @@ public class MemberUserServiceImpl implements MemberUserService {
89 user.setPassword(encodePassword(password)); // 加密密码 93 user.setPassword(encodePassword(password)); // 加密密码
90 user.setRegisterIp(registerIp); 94 user.setRegisterIp(registerIp);
91 memberUserMapper.insert(user); 95 memberUserMapper.insert(user);
  96 +
  97 + // 发送 MQ 消息,发放新人券
  98 + registerCouponProducer.sendMailSendMessage(user.getId());
92 return user; 99 return user;
93 } 100 }
94 101