feat(memberCenter): 新增会员促销活动功能

- 新增积分奖励活动类型
- 实现活动期间内订阅或续订会员的积分加成
- 增加活动参与记录和状态管理
- 优化活动列表展示逻辑
- 修复活动开始时间不能大于结束时间的问题
feature/comment
yang 2025-01-05 18:35:08 +08:00
parent 40bc8128eb
commit 4fc9909191
10 changed files with 137 additions and 26 deletions

View File

@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
@ -43,10 +44,11 @@ public class MemberController {
* @return
*/
@PostMapping("createMember")
public AjaxResult createMemberCenter(@RequestBody UserMemberDto userMemberDto) {
public AjaxResult createMemberCenter(@RequestBody @Valid UserMemberDto userMemberDto) {
Long userId = userMemberDto.getUserId();
Long memberLevelId = userMemberDto.getMemberLevelId();
String paymentMethod = userMemberDto.getPaymentMethod();
Long promotionId = userMemberDto.getPromotionId();
SysUser sysUser = sysUserService.selectUserById(userId);
if (!Optional.ofNullable(sysUser).isPresent()) {
@ -58,7 +60,7 @@ public class MemberController {
return AjaxResult.warn("会员等级不存在");
}
Member member = memberService.createUserMember(userId, memberLevelId, paymentMethod);
Member member = memberService.createUserMember(userId, memberLevelId, paymentMethod, promotionId);
if (!Optional.ofNullable(member).isPresent()) {
return AjaxResult.warn("创建会员失败");
}
@ -69,6 +71,7 @@ public class MemberController {
/**
*
*
* @return
*/
@GetMapping("getPoints")
@ -99,7 +102,7 @@ public class MemberController {
*
*/
@PostMapping("rechargePoints")
public AjaxResult rechargePoints(@RequestBody RechargePointsDto rechargePointsDto) {
public AjaxResult rechargePoints(@RequestBody @Valid RechargePointsDto rechargePointsDto) {
Long userId = rechargePointsDto.getUserId();
Double amount = rechargePointsDto.getAmount();

View File

@ -4,12 +4,15 @@ package com.mcwl.web.controller.memberCenter;
import cn.hutool.core.bean.BeanUtil;
import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.memberCenter.domain.Member;
import com.mcwl.memberCenter.domain.MemberPromotion;
import com.mcwl.memberCenter.domain.Promotion;
import com.mcwl.memberCenter.domain.dto.JoinPromotionDto;
import com.mcwl.memberCenter.domain.dto.PromotionDto;
import com.mcwl.memberCenter.enums.MemberEnum;
import com.mcwl.memberCenter.enums.PromotionEnum;
import com.mcwl.memberCenter.service.MemberPromotionService;
import com.mcwl.memberCenter.service.MemberService;
import com.mcwl.memberCenter.service.PromotionService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@ -32,6 +35,8 @@ public class PromotionController {
private final MemberPromotionService memberPromotionService;
private final MemberService memberService;
/**
*
@ -39,6 +44,11 @@ public class PromotionController {
@PostMapping("createPromotion")
public AjaxResult createPromotion(@RequestBody @Valid PromotionDto promotionDto) {
Date startTime = promotionDto.getStartTime();
Date endTime = promotionDto.getEndTime();
if (startTime.after(endTime)) {
return AjaxResult.warn("活动开始时间不能大于结束时间");
}
Promotion promotion = new Promotion();
BeanUtil.copyProperties(promotionDto, promotion);
@ -55,7 +65,7 @@ public class PromotionController {
@GetMapping("promotionList")
public AjaxResult promotionList() {
List<Promotion> promotionList = promotionService.lambdaQuery()
.lt(Promotion::getEndTime, new Date())
.gt(Promotion::getEndTime, new Date())
.list();
return AjaxResult.success(promotionList);
}
@ -68,7 +78,7 @@ public class PromotionController {
// 获取当前用户
Long userId = SecurityUtils.getUserId();
List<MemberPromotion> memberPromotionList = memberPromotionService.lambdaQuery()
.eq(MemberPromotion::getMemberId, userId)
.eq(MemberPromotion::getUserId, userId)
.list();
return AjaxResult.success(memberPromotionList);
}
@ -98,20 +108,63 @@ public class PromotionController {
return AjaxResult.warn("活动已过期");
}
String memberLevelIds = promotion.getMemberLevelId();
if (!memberLevelIds.contains(userId.toString())) {
// 获取当前用户是否参与过该活动
if (isJoinPromotion(userId, promotionId)) {
return AjaxResult.warn("您已参与过该活动");
}
// 是否在活动期间内订阅或续订会员
// if (!isSubscribe(userId, promotion)) {
// return AjaxResult.warn("请在活动期间内订阅或续期会员后参加该活动");
// }
Member member = memberService.getUseUserMemberByUserId(userId);
String memberLevelIds = promotion.getMemberLevelIds();
if (!memberLevelIds.contains(member.getMemberLevelId().toString())) {
return AjaxResult.warn("无法参与该活动,请查看活动条件");
}
MemberPromotion memberPromotion = new MemberPromotion();
memberPromotion.setMemberId(userId);
memberPromotion.setPromotionId(promotionId);
memberPromotion.setStatus(PromotionEnum.EXPIRED);
memberPromotion.setParticipationTime(new Date());
MemberPromotion memberPromotion = getMemberPromotion(userId, promotionId);
memberPromotionService.save(memberPromotion);
return AjaxResult.success();
}
// private boolean isSubscribe(Long userId, Promotion promotion) {
// if (promotion.getActivityType() == PromotionEnum.SUBSCRIBE) {
// // 获取当前用户最新的订阅或续订
// Member member = memberService.latestSubscription(userId);
// if (!Optional.ofNullable(member).isPresent()) {
// return false;
// }
// Date createTime = member.getCreateTime();
// // 会员创建时间在活动开始时间之前,说明用户不符合“活动期间内订阅或续订会员”的条件
// return !createTime.before(promotion.getStartTime());
// }
// return true;
// }
private boolean isJoinPromotion(Long userId, Long promotionId) {
MemberPromotion memberPromotion = memberPromotionService.lambdaQuery()
.eq(MemberPromotion::getUserId, userId)
.eq(MemberPromotion::getPromotionId, promotionId)
.one();
return memberPromotion != null;
}
private static MemberPromotion getMemberPromotion(Long userId, Long promotionId) {
MemberPromotion memberPromotion = new MemberPromotion();
memberPromotion.setUserId(userId);
memberPromotion.setPromotionId(promotionId);
memberPromotion.setStatus(PromotionEnum.PARTICIPATE);
memberPromotion.setParticipationTime(new Date());
memberPromotion.setCreateBy(SecurityUtils.getUsername());
memberPromotion.setCreateTime(new Date());
memberPromotion.setUpdateBy(SecurityUtils.getUsername());
memberPromotion.setUpdateTime(new Date());
return memberPromotion;
}
}

View File

@ -38,7 +38,7 @@ public class MemberCenterTest {
private EmptyPointsRemindConsumer emptyPointsRemindConsumer;
@Test
public void createUserMember() {
System.out.println(memberService.createUserMember(1L, 1013L, "wechat"));
System.out.println(memberService.createUserMember(1L, 1013L, "wechat",1L));
}
@Test

View File

@ -20,9 +20,9 @@ public class MemberPromotion extends BaseEntity {
private Long id;
/**
* ID
* ID
*/
private Long memberId;
private Long userId;
/**
* ID

View File

@ -3,6 +3,7 @@ package com.mcwl.memberCenter.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mcwl.common.core.domain.BaseEntity;
import com.mcwl.memberCenter.enums.PromotionEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -35,9 +36,9 @@ public class Promotion extends BaseEntity {
private Date endTime;
/**
*
*
*/
private String activityType;
private PromotionEnum activityType;
/**
* / 0.88
@ -52,7 +53,7 @@ public class Promotion extends BaseEntity {
/**
* ID
*/
private String memberLevelId;
private String memberLevelIds;

View File

@ -3,8 +3,10 @@ package com.mcwl.memberCenter.domain.dto;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mcwl.common.core.domain.BaseEntity;
import com.mcwl.memberCenter.enums.PromotionEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
@ -30,19 +32,21 @@ public class PromotionDto {
*
*/
@NotNull(message = "活动开始时间不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
*
*/
@NotNull(message = "活动结束时间不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
*
*/
@NotBlank(message = "活动类型不能为空")
private String activityType;
@NotNull()
private PromotionEnum activityType;
/**
* / 0.88
@ -59,7 +63,7 @@ public class PromotionDto {
/**
* ID
*/
private String memberLevelId;
private String memberLevelIds;

View File

@ -23,4 +23,7 @@ public class UserMemberDto {
@NotBlank(message = "支付方式不能为空")
private String paymentMethod;
// 活动ID
private Long promotionId;
}

View File

@ -18,7 +18,20 @@ public enum PromotionEnum {
/**
*
*/
EXPIRED("expired", "过期");
EXPIRED("expired", "过期"),
// /**
// * 订阅/续订会员
// */
// SUBSCRIBE("subscribe", "订阅/续订会员"),
/**
*
*/
DISCOUNT("discount", "限时折扣"),
/**
*
*/
POINTS("points", "积分奖励");
private final String name;
@EnumValue

View File

@ -12,9 +12,11 @@ public interface MemberService extends IService<Member> {
*
* @param userId id
* @param memberLevelId id
* @param paymentMethod
* @param promotionId id
* @return
*/
Member createUserMember(Long userId, Long memberLevelId, String paymentMethod);
Member createUserMember(Long userId, Long memberLevelId, String paymentMethod, Long promotionId);
/**
*
@ -31,4 +33,6 @@ public interface MemberService extends IService<Member> {
Member rechargePoints(Long userId, Double points);
Member latestSubscription(Long userId);
}

View File

@ -7,13 +7,17 @@ import com.mcwl.common.exception.ServiceException;
import com.mcwl.memberCenter.domain.MemberBenefit;
import com.mcwl.memberCenter.domain.MemberLevel;
import com.mcwl.memberCenter.domain.Member;
import com.mcwl.memberCenter.domain.Promotion;
import com.mcwl.memberCenter.enums.MemberBenefitTypeEnum;
import com.mcwl.memberCenter.enums.MemberEnum;
import com.mcwl.memberCenter.enums.MemberPeriodicEnum;
import com.mcwl.memberCenter.enums.PromotionEnum;
import com.mcwl.memberCenter.mapper.MemberMapper;
import com.mcwl.memberCenter.mapper.PromotionMapper;
import com.mcwl.memberCenter.service.MemberBenefitService;
import com.mcwl.memberCenter.service.MemberLevelService;
import com.mcwl.memberCenter.service.MemberService;
import com.mcwl.memberCenter.service.PromotionService;
import com.mcwl.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -31,8 +35,10 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
private final MemberBenefitService memberBenefitService;
private final PromotionMapper promotionMapper;
@Override
public Member createUserMember(Long userId, Long memberLevelId, String paymentMethod) {
public Member createUserMember(Long userId, Long memberLevelId, String paymentMethod, Long promotionId) {
if (userId == null) {
return null;
}
@ -79,7 +85,15 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
.eq(MemberBenefit::getBenefitType, MemberBenefitTypeEnum.POINTS)
.one();
if (memberBenefit != null) {
member.setPoints(memberBenefit.getBenefitDiscount());
Double points = memberBenefit.getBenefitDiscount();
// 根据活动id查询活动类型如果为积分则积分加成
if (promotionId != null) {
Promotion promotion = promotionMapper.selectById(promotionId);
if (promotion.getActivityType() == PromotionEnum.POINTS) {
points = points + promotion.getActivityValue();
}
}
member.setPoints(points);
}
// 设置订阅状态
@ -143,6 +157,21 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
return null;
}
@Override
public Member latestSubscription(Long userId) {
// 根据userId 查询会员,按创建时间降序,获取最新的会员
LambdaQueryWrapper<Member> qw = new LambdaQueryWrapper<>();
qw.eq(Member::getUserId, userId)
.ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_EXPIRED)
.ne(Member::getSubscriptionStatus, MemberEnum.MEMBER_CENTER_PENDING)
.orderByDesc(Member::getCreateTime);
List<Member> memberList = baseMapper.selectList(qw);
if (memberList != null && !memberList.isEmpty()) {
return memberList.get(0);
}
return null;
}
private List<Member> getUseUserMember(Long userId) {
// startDate 小于等于当前时间、endDate 大于等于当前时间
// subscriptionStatus 不为 "过期" 或 "待支付"
@ -160,6 +189,7 @@ public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> impleme
/**
*
*
* @param subscriptionPeriod
* @param calendar
* @return