'优惠券领取改良完成'

This commit is contained in:
Chopper711
2023-01-05 18:02:40 +08:00
parent 5218702005
commit 613f397c33
13 changed files with 390 additions and 62 deletions

View File

@@ -240,6 +240,10 @@ public enum CachePrefix {
* 积分商品缓存key前缀
*/
STORE_ID_EXCHANGE,
/**
* 会员领取标记
*/
MEMBER_COUPON_SIGN,
//================交易=================

View File

@@ -185,7 +185,7 @@ public class RedisCache implements Cache {
public Long counter(Object key) {
HyperLogLogOperations<Object, Object> operations = redisTemplate.opsForHyperLogLog();
//add 方法对应 PFADD 命令
//add 方法对应 PFCOUNT 命令
return operations.size(key);
}

View File

@@ -26,15 +26,16 @@ public class DateUtil {
* @return 今天开始时间
*/
public static Long getDayOfStart() {
return DateUtil.getDateline()/(60*24*60);
return DateUtil.getDateline() / (60 * 24 * 60);
}
/**
* 指定日的开始时间
*
* @return 指定日时间
*/
public static Long getDayOfStart(Date date) {
return date.getTime()/(60*24*60);
return date.getTime() / (60 * 24 * 60);
}
/**
@@ -349,6 +350,22 @@ public class DateUtil {
return getDateline(mon, STANDARD_FORMAT);
}
/**
* 获取当前天的结束时间
*
* @return 当前天的开始时间
*/
public static Date getCurrentDayStartTime() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) - 1);
return cal.getTime();
}
/**
* 获取当前天的结束时间
*
@@ -366,6 +383,21 @@ public class DateUtil {
return cal.getTime();
}
/**
* 获取干净的时间
*
* @return 时间对象
*/
public static Calendar getCleanCalendar() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal;
}
/**
* 获取延时时间(秒)
*

View File

@@ -2,6 +2,7 @@ package cn.lili.modules.promotion.entity.dos;
import cn.lili.modules.promotion.entity.enums.CouponActivitySendTypeEnum;
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
import cn.lili.modules.promotion.entity.enums.CouponFrequencyEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -36,6 +37,12 @@ public class CouponActivity extends BasePromotions {
@NotNull(message = "请选择活动范围")
@ApiModelProperty(value = "活动范围", allowableValues = "ALL:全部会员,DESIGNATED指定会员")
private String activityScope;
/**
* @see CouponFrequencyEnum
*/
@NotNull(message = "领取周期")
@ApiModelProperty(value = "活动范围", allowableValues = " DAY:每天, WEEK:每周, MONTH:每月")
private String couponFrequencyEnum;
@ApiModelProperty(value = "活动范围详情,只有精准发券使用")
private String activityScopeInfo;

View File

@@ -0,0 +1,50 @@
package cn.lili.modules.promotion.entity.dos;
import cn.lili.mybatis.BaseIdEntity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 会员优惠券实体类
*
* @author Chopper
* @since 2020-03-19 10:44 上午
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("li_member_coupon_sign")
@ApiModel(value = "会员优惠券领取标记")
public class MemberCouponSign extends BaseIdEntity {
@ApiModelProperty(value = "优惠券活动ID")
private String couponActivityId;
@ApiModelProperty(value = "会员ID")
private String memberId;
@ApiModelProperty(value = "失效时间,到达失效时间后自动删除,用户可以再次领取")
private Date invalidTime;
@CreatedDate
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.INSERT)
@ApiModelProperty(value = "创建时间", hidden = true)
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy/MM/dd HH:mm:ss|| yyyy/MM/dd ||epoch_millis")
private Date createTime;
}

View File

@@ -0,0 +1,35 @@
package cn.lili.modules.promotion.entity.enums;
/**
* 优惠券活动发送类型枚举
*
* @author Bulbasaur
* @since 2021/5/20 5:47 下午
*/
public enum CouponFrequencyEnum {
/**
* 领取周期
*/
DAY("每天"), WEEK("每周"), MONTH("每月");
private final String description;
CouponFrequencyEnum(String str) {
this.description = str;
}
public String description() {
return description;
}
public static boolean exist(String name) {
try {
CouponFrequencyEnum.valueOf(name);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,17 @@
package cn.lili.modules.promotion.mapper;
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 会员优惠券领取标记
*
* @author liushuai(liushuai711 @ gmail.com)
* @version v4.0
* @Description:
* @since 2023/1/3 18:11
*/
public interface MemberCouponSignMapper extends BaseMapper<MemberCouponSign> {
}

View File

@@ -0,0 +1,33 @@
package cn.lili.modules.promotion.service;
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 优惠券领取标记业务层
*
* @author liushuai(liushuai711 @ gmail.com)
* @version v4.0
* @Description:
* @since 2023/1/3 18:12
*/
public interface MemberCouponSignService extends IService<MemberCouponSign> {
/**
* 清除缓存
* 清除失效标记
*/
void clean();
/**
* 清除缓存
* 清除失效标记
*/
List<CouponActivityVO> receiveCoupon(List<CouponActivityVO> couponActivity);
}

View File

@@ -8,7 +8,6 @@ import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.promotion.entity.dos.Coupon;
import cn.lili.modules.promotion.entity.dos.CouponActivity;
@@ -20,10 +19,7 @@ import cn.lili.modules.promotion.entity.enums.*;
import cn.lili.modules.promotion.entity.vos.CouponActivityItemVO;
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
import cn.lili.modules.promotion.mapper.CouponActivityMapper;
import cn.lili.modules.promotion.service.CouponActivityItemService;
import cn.lili.modules.promotion.service.CouponActivityService;
import cn.lili.modules.promotion.service.CouponService;
import cn.lili.modules.promotion.service.MemberCouponService;
import cn.lili.modules.promotion.service.*;
import cn.lili.modules.promotion.tools.PromotionTools;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import groovy.util.logging.Slf4j;
@@ -31,7 +27,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -50,6 +49,11 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
private MemberCouponService memberCouponService;
@Autowired
private CouponActivityItemService couponActivityItemService;
@Autowired
private MemberCouponSignService memberCouponSignService;
@Autowired
private MemberService memberService;
@@ -90,6 +94,7 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
}
}
/**
* 初始化促销字段
*
@@ -181,6 +186,14 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
//获取当前正在进行的优惠券活动
List<CouponActivityVO> couponActivities = currentCouponActivity(couponActivityTrigger.getCouponActivityTypeEnum().name());
/**
* 自动发送优惠券则需要补足日志
*/
if (couponActivityTrigger.getCouponActivityTypeEnum().equals(CouponActivityTypeEnum.AUTO_COUPON)) {
couponActivities = memberCouponSignService.receiveCoupon(couponActivities);
}
//优惠券发放列表
List<CouponActivityItemVO> couponActivityItemVOS = new ArrayList<>();
@@ -191,6 +204,7 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
authUser.setId(couponActivityTrigger.getUserId());
authUser.setNickName(couponActivityTrigger.getNickName());
return this.sendCoupon(authUser, couponActivityItemVOS);
}
@@ -307,16 +321,20 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
* @param couponActivityItems 优惠券列表
*/
private List<MemberCoupon> sendCoupon(AuthUser authUser, List<? extends CouponActivityItem> couponActivityItems) {
//最终优惠券列表
List<MemberCoupon> finalCoupons = new ArrayList<>();
//循环优惠券赠送列表
for (CouponActivityItem couponActivityItem : couponActivityItems) {
//获取优惠券
Coupon coupon = couponService.getById(couponActivityItem.getCouponId());
//判断优惠券是否存在
if (coupon != null) {
List<MemberCoupon> memberCouponList = new LinkedList<>();
//循环优惠券的领取数量
int activitySendNum = couponActivityItem.getNum();
List<MemberCoupon> memberCouponList = new ArrayList<>();
for (int i = 1; i <= activitySendNum; i++) {
MemberCoupon memberCoupon = new MemberCoupon(coupon);
memberCoupon.setMemberId(authUser.getId());
@@ -325,6 +343,8 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
memberCoupon.setPlatformFlag(PromotionTools.PLATFORM_ID.equals(coupon.getStoreId()));
memberCouponList.add(memberCoupon);
}
finalCoupons.addAll(memberCouponList);
//批量添加优惠券
memberCouponService.saveBatch(memberCouponList);
//添加优惠券已领取数量
@@ -333,7 +353,10 @@ public class CouponActivityServiceImpl extends AbstractPromotionsServiceImpl<Cou
log.error("赠送优惠券失败,当前优惠券不存在:" + couponActivityItem.getCouponId());
}
}
return new ArrayList<>();
if (finalCoupons.isEmpty()) {
return new ArrayList<>();
}
return finalCoupons;
}

View File

@@ -0,0 +1,124 @@
package cn.lili.modules.promotion.serviceimpl;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.DateUtil;
import cn.lili.modules.promotion.entity.dos.CouponActivity;
import cn.lili.modules.promotion.entity.dos.MemberCouponSign;
import cn.lili.modules.promotion.entity.enums.CouponFrequencyEnum;
import cn.lili.modules.promotion.entity.vos.CouponActivityVO;
import cn.lili.modules.promotion.mapper.MemberCouponSignMapper;
import cn.lili.modules.promotion.service.MemberCouponSignService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.Calendar;
import java.util.Date;
import java.util.List;
/**
* 会员优惠券领取标记
*
* @author liushuai(liushuai711 @ gmail.com)
* @version v4.0
* @Description:
* @since 2023/1/3 18:13
*/
@Service
public class MemberCouponSignServiceImpl extends ServiceImpl<MemberCouponSignMapper, MemberCouponSign> implements MemberCouponSignService {
@Autowired
private Cache cache;
@Override
public void clean() {
LambdaQueryWrapper<MemberCouponSign> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.lt(MemberCouponSign::getInvalidTime, DateUtil.getCurrentDayStartTime());
this.baseMapper.delete(queryWrapper);
cache.remove(CachePrefix.MEMBER_COUPON_SIGN.getPrefix());
}
@Override
public List<CouponActivityVO> receiveCoupon(List<CouponActivityVO> couponActivity) {
List<MemberCouponSign> memberCouponSigns = new ArrayList<>();
//查询当前用户领取标记
LambdaQueryWrapper<MemberCouponSign> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MemberCouponSign::getMemberId, UserContext.getCurrentUser().getId());
List<MemberCouponSign> oldMemberCouponSigns = this.list(queryWrapper);
//定义生效的活动
List<CouponActivityVO> assertCouponActivity = new ArrayList<>();
//生成标记对象
couponActivityFor:
for (CouponActivityVO activity : couponActivity) {
//如果旧的标记中包含记号,则略过
for (MemberCouponSign oldMemberCouponSign : oldMemberCouponSigns) {
if (oldMemberCouponSign.getCouponActivityId().equals(activity.getId())) {
continue couponActivityFor;
}
}
assertCouponActivity.add(activity);
MemberCouponSign memberCouponSign = new MemberCouponSign();
memberCouponSign.setMemberId(UserContext.getCurrentUser().getId());
memberCouponSign.setCouponActivityId(activity.getId());
memberCouponSign.setInvalidTime(getInvalidTime(activity));
memberCouponSigns.add(memberCouponSign);
}
this.saveBatch(memberCouponSigns);
return assertCouponActivity;
}
/**
* 根据活动优惠券获取标记失效时间
*
* @param activity
* @return
*/
private Date getInvalidTime(CouponActivity activity) {
//领取周期符合预设
if (CouponFrequencyEnum.exist(activity.getCouponFrequencyEnum())) {
Calendar cal = DateUtil.getCleanCalendar();
switch (CouponFrequencyEnum.valueOf(activity.getCouponFrequencyEnum())) {
case DAY:
return DateUtil.getCurrentDayEndTime();
case WEEK:
//周一
cal.set(Calendar.DAY_OF_WEEK, 2);
//去往下周
cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) + 1);
//减1毫秒上个星期最后一刻
cal.set(Calendar.MILLISECOND, -1);
return cal.getTime();
case MONTH:
//日期 1日
cal.set(Calendar.DAY_OF_MONTH, 1);
//下个月
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
//减少一毫秒去上个月最后一刻
cal.set(Calendar.MILLISECOND, -1);
return cal.getTime();
default:
throw new ServiceException();
}
} else {
throw new ServiceException();
}
}
}