Commit 11227f2b 11227f2b39a95167c8936030165f7643256d28e4 by xianghan@topdraw.cn

优化部分接口,积分消耗添加分布式锁

1 parent 509a2011
......@@ -59,6 +59,7 @@ public class PointsOperationController {
@PostMapping(value = "/grantPointsByManual")
@ApiOperation("新增PointsDetail")
public ResultInfo grantPointsByManual(@Validated @RequestBody TempPoints tempPoints) {
LOG.info("======>>>>> grantPointsByManual start");
Long memberId = tempPoints.getMemberId();
this.pointsOperationService.grantPointsByManual(memberId,tempPoints);
return ResultInfo.success();
......
......@@ -57,12 +57,15 @@ public class CouponOperationServiceImpl implements CouponOperationService {
/**
* 手动发放优惠券
* @param memberId 会员id
* @param userId 账户id
* @param tempCouponList
*/
@Override
public void grantCouponByManual(Long memberId,Long userId ,List<TempCoupon> tempCouponList) {
// 优惠券领取、使用历史记录表
for (TempCoupon tempCoupon : tempCouponList) {
tempCoupon.setMemberId(memberId);
tempCoupon.setUserId(userId);
this.refresh(tempCoupon);
}
}
......
......@@ -88,7 +88,7 @@ public class ExpOperationServiceImpl implements ExpOperationService {
Long memberId = tempExp.getMemberId();
RLock rLock = this.redissonClient.getLock("refresh" + memberId.toString());
RLock rLock = this.redissonClient.getLock("refreshMemberExpAndLevel" + memberId.toString());
try {
RedissonUtil.lock(rLock);
// 1.获取当前成长值
......
......@@ -82,26 +82,39 @@ public class PointsOperationServiceImpl implements PointsOperationService {
@Transactional(rollbackFor = Exception.class)
public boolean customPoints(TempPoints tempPoints) {
Long memberId = tempPoints.getMemberId();
RLock rLock = this.redissonClient.getLock("refresh" + memberId.toString());
try {
RedissonUtil.lock(rLock);
// 1.判断可用积分是否够用
boolean b = this.checkAvailablePoints(tempPoints);
if (b) {
// 当前可用总积分
long currentPoints = this.findAvailablePointsByMemberId(memberId);
// 1.可用积分表,按照过期时间进行升序排列
// TODO 删除过期的积分
List<PointsAvailableDTO> pointsAvailableDTOS = this.findByMemberIdOrderByExpireTime(tempPoints);
// 当前可用总积分
long currentPoints = this.findAvailablePointsByMemberId(memberId);
// 2.优先使用即将过期的积分,累加到超过需兑换积分时,需要进行拆分
Map<String, List<PointsAvailableDTO>> customAvailablePointsMap = this.customAvailablePoints(tempPoints, pointsAvailableDTOS);
// 3.添加积分明细
this.doInsertTrPointsDetailByAvailablePointsMap(tempPoints,customAvailablePointsMap,currentPoints);
this.doInsertTrPointsDetailByAvailablePointsMap(tempPoints, customAvailablePointsMap, currentPoints);
// 4.更新可用积分表,超过的删除,剩余的新增
long totalPoints = this.doFreshTrPointsAvailableByAvailablePointsMap(customAvailablePointsMap,currentPoints);
long totalPoints = this.doFreshTrPointsAvailableByAvailablePointsMap(customAvailablePointsMap, currentPoints);
// 4.获取即将过期的积分
long soonExpireTime = this.getSoonExpirePoints(memberId,tempPoints);
// TODO 不用在这里查询
long soonExpireTime = this.getSoonExpirePoints(memberId, tempPoints);
// 6.更新会员积分信息
this.freshMemberCurrentPoints(memberId,totalPoints,soonExpireTime);
this.freshMemberCurrentPoints(memberId, totalPoints, soonExpireTime);
return true;
}
}catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
RedissonUtil.unlock(rLock);
}
return false;
}
......@@ -140,7 +153,7 @@ public class PointsOperationServiceImpl implements PointsOperationService {
}
/**
* 优先使用即将过期的积分,累加到超过需兑换积分时,需要进行拆分
* 优先使用即将过期的积分,注意拆分
* @param customAvailablePointsMap
*/
private void doInsertTrPointsDetailByAvailablePointsMap(TempPoints tempPoints,
......@@ -159,7 +172,8 @@ public class PointsOperationServiceImpl implements PointsOperationService {
BeanUtils.copyProperties(pointsAvailableDTO,tempPoints1);
BeanUtils.copyProperties(tempPoints,tempPoints1);
tempPoints1.setPoints(-(Math.abs(points)));
this.doInsertTrPointsDetail(memberId,tempPoints1,currentPoints);
long totalPoints = this.calculateTotalPoints(tempPoints1, currentPoints);
this.doInsertTrPointsDetail(memberId,tempPoints1,currentPoints,totalPoints);
}
}
......@@ -330,9 +344,13 @@ public class PointsOperationServiceImpl implements PointsOperationService {
RedissonUtil.lock(rLock);
// 1.可用总积分
long currentPoints = this.findAvailablePointsByMemberId(memberId);
// 2.计算总积分
long totalPoints = this.calculateTotalPoints(tempPoints, currentPoints);
// 2.添加积分明细,并计算总积分
long totalPoints = this.doInsertTrPointsDetail(memberId, tempPoints, currentPoints);
// TODO 把计算总积分的过程单独提取出来,保存积分流水的时候可以异步
this.doInsertTrPointsDetail(memberId, tempPoints, currentPoints,totalPoints);
// 3.获取即将过期的积分
// TODO 不需要在这里查询过期积分,用的时候再去查看
long soonExpireTime = this.getSoonExpirePoints(memberId, tempPoints);
// 4.更新会员的总积分
this.freshMemberCurrentPoints(memberId, totalPoints, soonExpireTime);
......@@ -347,6 +365,20 @@ public class PointsOperationServiceImpl implements PointsOperationService {
}
/**
* 获取总积分
* @param tempPoints
* @param currentPoints
* @return
*/
private long calculateTotalPoints(TempPoints tempPoints, long currentPoints) {
// 获取的积分
long rewardPoints = tempPoints.getPoints();
// 总积分
long totalPoints = currentPoints + rewardPoints;
return totalPoints;
}
/**
* 获取即将过期的积分
* @param memberId
* @return
......@@ -436,22 +468,22 @@ public class PointsOperationServiceImpl implements PointsOperationService {
* @param tempPoints 积分
* @return Integer 总积分
*/
private long doInsertTrPointsDetail(Long memberId, TempPoints tempPoints,long currentPoints){
private void doInsertTrPointsDetail(Long memberId, TempPoints tempPoints,long totalPoints,long currentPoints){
PointsDetail pointsDetail = new PointsDetail();
BeanUtils.copyProperties(tempPoints,pointsDetail);
// 获取的积分
/* // 获取的积分
long rewardPoints = tempPoints.getPoints();
// 原始积分
long originalPoints = currentPoints;
// 总积分
long totalPoints = originalPoints + rewardPoints;
long totalPoints = originalPoints + rewardPoints;*/
pointsDetail.setMemberId(memberId);
pointsDetail.setCode(String.valueOf(IdWorker.generator()));
pointsDetail.setOriginalPoints(originalPoints);
pointsDetail.setOriginalPoints(currentPoints);
pointsDetail.setResultPoints(totalPoints);
String description = pointsDetail.getDescription();
if (StringUtils.isEmpty(description)) {
......@@ -461,8 +493,6 @@ public class PointsOperationServiceImpl implements PointsOperationService {
// 保存积分流水
this.doInsertPointsDetail(pointsDetail);
return totalPoints;
}
/**
......
......@@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
/**
......@@ -76,7 +77,6 @@ public class RightsOperationServiceImpl implements RightsOperationService {
this.doInsertTrRightHistory(rightsList);
}
/**
*
* @param tempRightsMap
......@@ -169,29 +169,68 @@ public class RightsOperationServiceImpl implements RightsOperationService {
// 优惠券
List<TempCoupon> tempCouponList = new ArrayList<>();
List<TempExp> tempExpList = new ArrayList<>();
List<TempPoints> tempPointsList = new ArrayList<>();
for (RightsHistory right : rightsList) {
Long rightId = right.getRightsId();
Long memberId = right.getMemberId();
Long userId = right.getUserId();
// 权益类型
RightsDTO rightsDTO = this.getRights(rightId);
Integer type = rightsDTO.getType();
// 权益的实体类型 1:积分;2成长值;3优惠券
String type = rightsDTO.getEntityType();
String code = rightsDTO.getCode();
Long expireTime = rightsDTO.getExpireTime();
Timestamp validTime = rightsDTO.getValidTime();
switch (type) {
// 优惠券
if (type == 1) {
case "3":
TempCoupon tempCoupon = new TempCoupon();
tempCoupon.setId(rightId);
tempCoupon.setMemberId(memberId);
tempCoupon.setUserId(userId);
tempCoupon.setRightsAmount(1);
tempCoupon.setRightsSendStrategy(0);
tempCoupon.setExpireTime(TimestampUtil.long2Timestamp(expireTime));
tempCouponList.add(tempCoupon);
break;
// 成长值
case "2":
TempExp tempExp = new TempExp();
tempExp.setId(rightId);
tempExp.setMemberId(memberId);
tempExp.setUserId(userId);
tempExp.setRightsAmount(1);
tempExp.setRightsSendStrategy(0);
tempExpList.add(tempExp);
break;
// 积分
case "1":
TempPoints tempPoints = new TempPoints();
tempPoints.setId(rightId);
tempPoints.setMemberId(memberId);
tempPoints.setUserId(userId);
tempPoints.setRightsAmount(1);
tempPoints.setRightsSendStrategy(0);
tempPointsList.add(tempPoints);
break;
}
}
// TODO 其他
// 优惠券
if (!CollectionUtils.isEmpty(tempCouponList))
map.put(RightType.COUPON,tempCouponList);
// 成长值
if (!CollectionUtils.isEmpty(tempExpList))
map.put(RightType.EXP,tempExpList);
// 积分
if (!CollectionUtils.isEmpty(tempPointsList))
map.put(RightType.POINTS,tempPointsList);
return map;
}
......
......@@ -23,6 +23,7 @@ import com.topdraw.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
......@@ -81,7 +82,7 @@ public class TaskOperationServiceImpl implements TaskOperationService {
DataSyncMsg.MsgData msgData = dataSyncMsg.getMsg();
Long memberId = msgData.getMemberId();
// 1.通过任务标识获取任务模板
// 1.通过任务标识获取任务模板,通过模板参数获取具体的模板
TaskTemplate taskTemplate = this.getTaskTemplate(eventType);
// 2.解析模板参数
Map<String,Object> paramMap = this.parseTaskTemplateParam(taskTemplate);
......@@ -92,12 +93,8 @@ public class TaskOperationServiceImpl implements TaskOperationService {
if (checkResult) {
// 5.权益区分(积分、权益、成长值)
Map<RightType,Object> tempRightsMap = this.distinguishRight(memberId,taskList,msgData);
// 6.永久权益
PermanentRightsDTO permanentRights = this.getPermanentRights(memberId);
// 7.永久权益计算之后的权益
Map<RightType, Object> rightTypeObjectMap = this.calculateRight(permanentRights, tempRightsMap, memberId);
// 8..权益发放
this.grantRight(rightTypeObjectMap);
// 6.权益发放
this.grantRight(tempRightsMap);
}
long r = System.currentTimeMillis();
......@@ -201,6 +198,7 @@ public class TaskOperationServiceImpl implements TaskOperationService {
* @param permanentRights
* @param map
*/
@Deprecated
private Map<RightType, Object> calculateRight(PermanentRightsDTO permanentRights, Map<RightType, Object> map,Long memberId) {
// 验证永久权益
......@@ -229,6 +227,7 @@ public class TaskOperationServiceImpl implements TaskOperationService {
* @param tempPointsList 积分
* @return BigDecimal 总积分
*/
@Deprecated
private BigDecimal calculateTotalPoints(PermanentRightsDTO permanentRights, List<TempPoints> tempPointsList) {
// 总积分
......@@ -337,7 +336,8 @@ public class TaskOperationServiceImpl implements TaskOperationService {
* @param task
* @return
*/
private Map<RightType,Object> getTempRight(Long memberId , Task task,Map<RightType,Object> map) {
private Map<RightType,Object> getTempRight(Long memberId , Task task , Map<RightType,Object> map) {
// 优惠券
List<TempCoupon> tempCouponList = new ArrayList<>();
// 权益列表,用以保存权益记录
......@@ -346,88 +346,67 @@ public class TaskOperationServiceImpl implements TaskOperationService {
// 权益1
Long rights1Id = task.getRightsId();
if (Objects.nonNull(rights1Id)) {
// 权益详情
RightsDTO rightsDTO = this.getRight(rights1Id);
// 领取的权益数量
Integer rights1Amount = task.getRightsAmount();
// TODO 权益1发放的策略
Integer rightsSendStrategy = task.getRightsSendStrategy();
if (Objects.nonNull(rightsDTO)){
// 用以保存权益历史
Long expireTime = rightsDTO.getExpireTime();
TempRights tempRights = this.tmpRightsBuild(memberId,rights1Id,rights1Amount,expireTime);
rightsList.add(tempRights);
// 权益类型
Integer type = rightsDTO.getType();
switch (type) {
case 1:
// 优惠券
TempCoupon tempCoupon = this.tempCouponBuild(memberId,rights1Id,rights1Amount,rightsSendStrategy);
tempCouponList.add(tempCoupon);
break;
default:
break;
}
}
// 权益分类
this.getTempRightType(memberId,rights1Id,rights1Amount,rightsSendStrategy,tempCouponList,rightsList);
}
// 权益2
Long rights2Id = task.getRights2Id();
if (Objects.nonNull(rights2Id)) {
// 权益详情
RightsDTO rightsDTO = this.getRight(rights2Id);
Integer rights2Amount = task.getRights2Amount();
// TODO 权益2发放的策略
Integer rightsSendStrategy = task.getRightsSendStrategy();
if (Objects.nonNull(rightsDTO)) {
// 用以保存权益历史
Long expireTime = rightsDTO.getExpireTime();
TempRights tempRights = this.tmpRightsBuild(memberId,rights2Id,rights2Amount,expireTime);
rightsList.add(tempRights);
// 权益类型
Integer type = rightsDTO.getType();
switch (type) {
case 1:
// 优惠券
TempCoupon tempCoupon = this.tempCouponBuild(memberId,rights2Id,rights2Amount,rightsSendStrategy);
tempCouponList.add(tempCoupon);
break;
default:
break;
}
}
// 权权益分类
this.getTempRightType(memberId,rights2Id,rights2Amount,rightsSendStrategy,tempCouponList,rightsList);
}
// 权益3
Long rights3Id = task.getRights3Id();
if (Objects.nonNull(rights3Id)) {
// 权益详情
RightsDTO rightsDTO = this.getRight(rights3Id);
Integer rights3Amount = task.getRights3Amount();
// TODO 权益3发放的策略
Integer rightsSendStrategy = task.getRightsSendStrategy();
// 权益分类
this.getTempRightType(memberId,rights3Id,rights3Amount,rightsSendStrategy,tempCouponList,rightsList);
}
// 优惠券
map.put(RightType.COUPON,tempCouponList);
map.put(RightType.RIGHTS,rightsList);
return map;
}
/**
* 权益分类
* @param memberId
* @param rightsId
* @param rightsAmount
* @param rightsSendStrategy
* @param tempCouponList
* @param rightsList
*/
private void getTempRightType(Long memberId , Long rightsId, Integer rightsAmount,Integer rightsSendStrategy,List<TempCoupon> tempCouponList,
List<TempRights> rightsList) {
// 权益详情
RightsDTO rightsDTO = this.getRight(rightsId);
if (Objects.nonNull(rightsDTO)){
// 用以保存权益历史
Long expireTime = rightsDTO.getExpireTime();
TempRights tempRights = this.tmpRightsBuild(memberId,rights3Id,rights3Amount,expireTime);
TempRights tempRights = this.tmpRightsBuild(memberId,rightsId,rightsAmount,expireTime);
rightsList.add(tempRights);
// 权益类型
Integer type = rightsDTO.getType();
String type = rightsDTO.getEntityType();
switch (type) {
case 1:
case "1":
// 优惠券
TempCoupon tempCoupon = this.tempCouponBuild(memberId,rights3Id,rights3Amount,rightsSendStrategy);
TempCoupon tempCoupon = this.tempCouponBuild(memberId,rightsId,rightsAmount,rightsSendStrategy);
tempCouponList.add(tempCoupon);
break;
default:
......@@ -435,11 +414,6 @@ public class TaskOperationServiceImpl implements TaskOperationService {
}
}
}
// 优惠券
map.put(RightType.COUPON,tempCouponList);
map.put(RightType.RIGHTS,rightsList);
return map;
}
/**
*
......@@ -522,9 +496,9 @@ public class TaskOperationServiceImpl implements TaskOperationService {
* 判断任务是否完成
* 完成的条件如下:->
* 1. status 当前任务的状态 0:失效;1:生效
* 1. task_repeat_type 任务重复类型,-1:不限次;1:单次;>1:多次
* 2. valid_time 任务生效时间
* 3. expire_time 任务失效时间
* 1. task_repeat_type 任务重复类型,-1:不限次;1:单次;>1:多次
* 5. member_level 会员等级门槛(0表示无门槛)
* 6. member_vip 会员vip门槛(0表示没有门槛)
* 7. groups 能够获取该任务的用户分组,为空则都能获取
......@@ -533,6 +507,7 @@ public class TaskOperationServiceImpl implements TaskOperationService {
* @param taskList 任务列表
* @return boolean true:success false:fail
*/
//<taskId,boolean>
private boolean checkTaskCompletion(Long memberId , List<Task> taskList) {
if (!CollectionUtils.isEmpty(taskList)) {
// 会员信息
......@@ -542,11 +517,11 @@ public class TaskOperationServiceImpl implements TaskOperationService {
List<Task> taskStream = taskList1.stream().filter(task1 ->
task1.getStatus() == 1 &&
(Objects.isNull(task1.getExpireTime()) || task1.getExpireTime().compareTo(TimestampUtil.now()) <= 0) &&
(Objects.isNull(task1.getExpireTime()) || task1.getExpireTime().compareTo(TimestampUtil.now()) >= 0) &&
(Objects.isNull(task1.getGroups()) || task1.getGroups().equalsIgnoreCase(memberDTO1.getGroups())) &&
(Objects.isNull(task1.getValidTime()) || task1.getValidTime().compareTo(TimestampUtil.now()) <= 0) &&
(Objects.isNull(task1.getMemberLevel()) || task1.getMemberLevel() == 0 || task1.getMemberLevel() <= memberDTO1.getLevel()) &&
(Objects.isNull(task1.getMemberVip()) || task1.getMemberVip() == 0 || task1.getMemberVip() == memberDTO1.getVip())
(Objects.isNull(task1.getMemberVip()) || task1.getMemberVip() == 0 || task1.getMemberVip() <= memberDTO1.getVip())
).collect(Collectors.toList());
if (CollectionUtils.isEmpty(taskStream)) {
......@@ -564,6 +539,9 @@ public class TaskOperationServiceImpl implements TaskOperationService {
/**
* 检查并更新当前任务的完成情况
*
* 1.每天都能做,但要求总次数达到行为量
*
* @param memberId
* @param taskStream
* @return boolean false:失败 true:成功
......
......@@ -22,9 +22,9 @@ import java.util.List;
/**
* 积分台账
*/
@Component
@Slf4j
@EnableScheduling
//@Component
//@Slf4j
//@EnableScheduling
public class ScheduledTask {
@Autowired
......@@ -35,9 +35,9 @@ public class ScheduledTask {
/**
* 清理已过期的积分
*/
@Scheduled(cron = "0 0/1 * * * ? ")
// @Scheduled(cron = "0 0/1 * * * ? ")
public void cleanValidAvailablePoints(){
this.pointsOperationService.cleanInvalidAvailablePoints();
// this.pointsOperationService.cleanInvalidAvailablePoints();
}
}
......