邀请码 列表和统计功能完善
This commit is contained in:
parent
88ef879b22
commit
815f42db27
@ -12,6 +12,8 @@ import com.red.circle.other.app.dto.cmd.activity.InviteUserActivityLimitCmd;
|
||||
import com.red.circle.other.app.service.activity.InviteUserActivityService;
|
||||
import com.red.circle.other.app.dto.cmd.activity.BindInviteCodeCmd;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteCodeCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteIncomeStatisticsCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.ValidInviteUserCO;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -173,4 +175,32 @@ public class InviteUserActivityRestController {
|
||||
inviteUserActivityService.bindInviteCode(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请收益统计.
|
||||
*
|
||||
* @eo.name 邀请收益统计
|
||||
* @eo.url /income/statistics
|
||||
* @eo.method get
|
||||
* @eo.request-type formdata
|
||||
*/
|
||||
@GetMapping("/income/statistics")
|
||||
public InviteIncomeStatisticsCO getIncomeStatistics(AppExtCommand cmd) {
|
||||
InviteIncomeStatisticsCO statistics = inviteUserActivityService.getIncomeStatistics(cmd);
|
||||
return statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* 有效邀请用户列表.
|
||||
*
|
||||
* @eo.name 有效邀请用户列表
|
||||
* @eo.url /valid/invite/users
|
||||
* @eo.method get
|
||||
* @eo.request-type formdata
|
||||
*/
|
||||
@GetMapping("/valid/invite/users")
|
||||
public List<ValidInviteUserCO> getValidInviteUsers(AppExtCommand cmd) {
|
||||
List<ValidInviteUserCO> users = inviteUserActivityService.getValidInviteUsers(cmd);
|
||||
return users;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.UserInviteUserService;
|
||||
import com.red.circle.other.infra.enums.user.InviteTypeEnum;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.sequence.IdWorkerUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -40,45 +41,81 @@ public class BindInviteCodeExe {
|
||||
public void execute(BindInviteCodeCmd cmd) {
|
||||
Long userId = cmd.getReqUserId();
|
||||
String inviteCode = cmd.getInviteCode();
|
||||
String inviteType = cmd.getInviteType();
|
||||
String sysOrigin = cmd.getReqSysOrigin().getOrigin();
|
||||
|
||||
log.info("开始绑定邀请码, userId={}, inviteCode={}", userId, inviteCode);
|
||||
log.info("开始绑定邀请码, userId={}, inviteCode={}, inviteType={}", userId, inviteCode, inviteType);
|
||||
|
||||
// 1. 校验用户是否存在
|
||||
// 1. 校验inviteType是否合法
|
||||
if (!InviteTypeEnum.LOTTERY.getCode().equals(inviteType) &&
|
||||
!InviteTypeEnum.REGISTER.getCode().equals(inviteType)) {
|
||||
throw new RuntimeException("Invalid invitation type, must be LOTTERY or REGISTER");
|
||||
}
|
||||
|
||||
// 3. 校验用户是否存在
|
||||
UserProfile userProfile = userProfileGateway.getByUserId(userId);
|
||||
if (userProfile == null) {
|
||||
throw new RuntimeException("The user does not exist.");
|
||||
}
|
||||
|
||||
// 2. 校验是否已绑定过邀请人
|
||||
List<UserInviteUser> existingInvite = userInviteUserService.query().eq(UserInviteUser::getUserId, userId).list();
|
||||
// 4. 校验是否已绑定过邀请人(userId=邀请人, inviteUserId=被邀请人)
|
||||
// 当前用户作为被邀请人,查询 inviteUserId=当前用户
|
||||
List<UserInviteUser> existingInvite = userInviteUserService.query()
|
||||
.eq(UserInviteUser::getInviteUserId, userId) // 当前用户作为被邀请人
|
||||
.list();
|
||||
if (existingInvite != null && !existingInvite.isEmpty()) {
|
||||
throw new RuntimeException("The inviter has been bound before and cannot be bound again");
|
||||
}
|
||||
|
||||
// 3. 根据邀请码查找邀请人
|
||||
// 5. 根据邀请码查找邀请人
|
||||
UserProfile inviterProfile = inviteCodeService.getUserProfileByInviteCode(inviteCode);
|
||||
if (inviterProfile == null) {
|
||||
throw new RuntimeException("The invitation code is invalid and the corresponding user was not found");
|
||||
}
|
||||
|
||||
// 4. 校验不能邀请自己
|
||||
// 6. 校验不能邀请自己
|
||||
if (Objects.equals(userId, inviterProfile.getId())) {
|
||||
throw new RuntimeException("You cannot bind your own invitation code");
|
||||
}
|
||||
|
||||
// 5. 保存邀请关系
|
||||
// 再次校验:如果当前用户已经绑定了其他邀请人,则不能再绑定
|
||||
// 这里是双重校验,确保数据一致性
|
||||
List<UserInviteUser> doubleCheck = userInviteUserService.query()
|
||||
.eq(UserInviteUser::getInviteUserId, userId)
|
||||
.list();
|
||||
if (doubleCheck != null && !doubleCheck.isEmpty()) {
|
||||
Long existingInviterId = doubleCheck.get(0).getUserId();
|
||||
log.warn("用户已绑定邀请人,不能重复绑定, userId={}, existingInviterId={}, newInviterId={}",
|
||||
userId, existingInviterId, inviterProfile.getId());
|
||||
throw new RuntimeException("You have already bound an inviter and cannot bind again");
|
||||
}
|
||||
|
||||
// 校验双向绑定:如果邀请人已经被当前用户邀请过,则不能再绑定
|
||||
// 即:如果 inviterProfile 已经是当前用户的被邀请人,则不能让 inviterProfile 成为当前用户的邀请人
|
||||
// 查询:userId=当前用户, inviteUserId=邀请人(检查当前用户是否已经邀请过这个邀请人)
|
||||
List<UserInviteUser> reverseInvite = userInviteUserService.query()
|
||||
.eq(UserInviteUser::getUserId, userId) // 当前用户作为邀请人
|
||||
.eq(UserInviteUser::getInviteUserId, inviterProfile.getId()) // 邀请人作为被邀请人
|
||||
.list();
|
||||
if (reverseInvite != null && !reverseInvite.isEmpty()) {
|
||||
log.warn("不能双向绑定,该用户已被当前用户邀请过, userId={}, inviterUserId={}",
|
||||
userId, inviterProfile.getId());
|
||||
throw new RuntimeException("Cannot bind bidirectionally, this user has already been invited by you");
|
||||
}
|
||||
|
||||
// 7. 保存邀请关系(userId=邀请人, inviteUserId=被邀请人)
|
||||
UserInviteUser inviteUser = new UserInviteUser();
|
||||
inviteUser.setId(IdWorkerUtils.getId());
|
||||
inviteUser.setSysOrigin(sysOrigin);
|
||||
inviteUser.setUserId(userId);
|
||||
inviteUser.setInviteUserId(inviterProfile.getId());
|
||||
inviteUser.setUserId(inviterProfile.getId()); // 邀请人
|
||||
inviteUser.setInviteUserId(userId); // 被邀请人(当前用户)
|
||||
inviteUser.setInviteType(inviteType); // 使用传入的inviteType
|
||||
inviteUser.setCreateTime(TimestampUtils.now());
|
||||
inviteUser.setUpdateTime(TimestampUtils.now());
|
||||
|
||||
userInviteUserService.save(inviteUser);
|
||||
|
||||
log.info("绑定邀请码成功, userId={}, inviterUserId={}, inviteCode={}",
|
||||
userId, inviterProfile.getId(), inviteCode);
|
||||
log.info("绑定邀请码成功, userId={}, inviterUserId={}, inviteCode={}, inviteType={}",
|
||||
userId, inviterProfile.getId(), inviteCode, inviteType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,163 @@
|
||||
package com.red.circle.other.app.command.activity;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteIncomeStatisticsCO;
|
||||
import com.red.circle.other.infra.database.rds.dao.user.user.InviteUserRechargeCommissionDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
|
||||
import com.red.circle.other.infra.enums.user.InviteTypeEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 获取邀请收益统计执行器
|
||||
*
|
||||
* 表结构说明:
|
||||
* user_invite_user: userId(邀请人), inviteUserId(被邀请人)
|
||||
* user_invite_user_recharge_commission: userId(被邀请人-充值人), inviteUserId(邀请人-获得佣金人)
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GetIncomeStatisticsExe {
|
||||
|
||||
private final UserInviteUserDAO userInviteUserDAO;
|
||||
private final InviteUserRechargeCommissionDAO inviteUserRechargeCommissionDAO;
|
||||
|
||||
/**
|
||||
* 执行获取邀请收益统计
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @return 收益统计
|
||||
*/
|
||||
public InviteIncomeStatisticsCO execute(AppExtCommand cmd) {
|
||||
Long userId = cmd.getReqUserId();
|
||||
|
||||
// 查询当前用户邀请的所有用户(userId=邀请人)
|
||||
List<UserInviteUser> allInvites = userInviteUserDAO.selectList(
|
||||
new LambdaQueryWrapper<UserInviteUser>()
|
||||
.eq(UserInviteUser::getUserId, userId) // userId是邀请人
|
||||
);
|
||||
|
||||
// 筛选有效邀请
|
||||
List<Long> validInvitedUserIds = getValidInvitedUserIds(allInvites);
|
||||
|
||||
// 计算总收益
|
||||
BigDecimal totalIncome = calculateTotalIncome(userId, validInvitedUserIds);
|
||||
|
||||
// 计算今日收益
|
||||
BigDecimal todayIncome = calculateTodayIncome(userId, validInvitedUserIds);
|
||||
|
||||
InviteIncomeStatisticsCO statistics = new InviteIncomeStatisticsCO();
|
||||
statistics.setTotalIncome(totalIncome);
|
||||
statistics.setTodayIncome(todayIncome);
|
||||
statistics.setValidInviteCount(validInvitedUserIds.size());
|
||||
|
||||
log.info("邀请收益统计, userId={}, totalIncome={}, todayIncome={}, validCount={}",
|
||||
userId, totalIncome, todayIncome, validInvitedUserIds.size());
|
||||
|
||||
return statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有效邀请用户ID列表
|
||||
*/
|
||||
private List<Long> getValidInvitedUserIds(List<UserInviteUser> allInvites) {
|
||||
return allInvites.stream()
|
||||
.filter(this::isValidInvite)
|
||||
.map(UserInviteUser::getInviteUserId) // inviteUserId是被邀请人
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为有效邀请
|
||||
*/
|
||||
private boolean isValidInvite(UserInviteUser invite) {
|
||||
String inviteType = invite.getInviteType();
|
||||
|
||||
// LOTTERY类型直接算有效
|
||||
if (InviteTypeEnum.LOTTERY.getCode().equals(inviteType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// REGISTER类型需要检查充值记录
|
||||
if (InviteTypeEnum.REGISTER.getCode().equals(inviteType)) {
|
||||
// userId=邀请人, inviteUserId=被邀请人
|
||||
return hasValidRecharge(invite.getInviteUserId(), invite.getUserId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有有效充值记录(commission > 0)
|
||||
* @param invitedUserId 被邀请人 ID(充值的人)
|
||||
* @param inviterUserId 邀请人 ID(获得佣金的人)
|
||||
*/
|
||||
private boolean hasValidRecharge(Long invitedUserId, Long inviterUserId) {
|
||||
Long count = inviteUserRechargeCommissionDAO.selectCount(
|
||||
new LambdaQueryWrapper<InviteUserRechargeCommission>()
|
||||
.eq(InviteUserRechargeCommission::getUserId, invitedUserId) // 被邀请人
|
||||
.eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId) // 邀请人
|
||||
.gt(InviteUserRechargeCommission::getCommission, BigDecimal.ZERO)
|
||||
);
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算总收益
|
||||
*/
|
||||
private BigDecimal calculateTotalIncome(Long inviterUserId, List<Long> validInvitedUserIds) {
|
||||
if (validInvitedUserIds.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
List<InviteUserRechargeCommission> commissions = inviteUserRechargeCommissionDAO.selectList(
|
||||
new LambdaQueryWrapper<InviteUserRechargeCommission>()
|
||||
.eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId)
|
||||
.in(InviteUserRechargeCommission::getUserId, validInvitedUserIds)
|
||||
);
|
||||
|
||||
return commissions.stream()
|
||||
.map(InviteUserRechargeCommission::getCommission)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算今日收益
|
||||
*/
|
||||
private BigDecimal calculateTodayIncome(Long inviterUserId, List<Long> validInvitedUserIds) {
|
||||
if (validInvitedUserIds.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
|
||||
LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
|
||||
|
||||
List<InviteUserRechargeCommission> todayCommissions = inviteUserRechargeCommissionDAO.selectList(
|
||||
new LambdaQueryWrapper<InviteUserRechargeCommission>()
|
||||
.eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId)
|
||||
.in(InviteUserRechargeCommission::getUserId, validInvitedUserIds)
|
||||
.ge(InviteUserRechargeCommission::getCreateTime, Timestamp.valueOf(todayStart))
|
||||
.le(InviteUserRechargeCommission::getCreateTime, Timestamp.valueOf(todayEnd))
|
||||
);
|
||||
|
||||
return todayCommissions.stream()
|
||||
.map(InviteUserRechargeCommission::getCommission)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,179 @@
|
||||
package com.red.circle.other.app.command.activity;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.ValidInviteUserCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.rds.dao.user.user.InviteUserRechargeCommissionDAO;
|
||||
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
|
||||
import com.red.circle.other.infra.enums.user.InviteTypeEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 获取有效邀请用户列表执行器
|
||||
*
|
||||
* 表结构说明:
|
||||
* user_invite_user: userId(邀请人), inviteUserId(被邀请人)
|
||||
* user_invite_user_recharge_commission: userId(被邀请人-充值人), inviteUserId(邀请人-获得佣金人)
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GetValidInviteUsersExe {
|
||||
|
||||
private final UserInviteUserDAO userInviteUserDAO;
|
||||
private final InviteUserRechargeCommissionDAO inviteUserRechargeCommissionDAO;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
|
||||
// 邀请关系有效期(天数)
|
||||
private static final int VALID_DAYS = 30;
|
||||
|
||||
/**
|
||||
* 执行获取有效邀请用户列表
|
||||
*
|
||||
* @param cmd 命令
|
||||
* @return 有效邀请用户列表
|
||||
*/
|
||||
public List<ValidInviteUserCO> execute(AppExtCommand cmd) {
|
||||
Long inviterUserId = cmd.getReqUserId(); // 邀请人ID
|
||||
|
||||
// 查询当前用户邀请的所有用户(userId=邀请人)
|
||||
List<UserInviteUser> allInvites = userInviteUserDAO.selectList(
|
||||
new LambdaQueryWrapper<UserInviteUser>()
|
||||
.eq(UserInviteUser::getUserId, inviterUserId) // userId是邀请人
|
||||
.orderByDesc(UserInviteUser::getCreateTime)
|
||||
);
|
||||
|
||||
if (allInvites.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 筛选有效邀请
|
||||
List<UserInviteUser> validInvites = allInvites.stream()
|
||||
.filter(this::isValidInvite)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (validInvites.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 获取被邀请用户ID列表(inviteUserId)
|
||||
List<Long> invitedUserIds = validInvites.stream()
|
||||
.map(UserInviteUser::getInviteUserId) // inviteUserId是被邀请人
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 批量查询用户信息
|
||||
Map<Long, UserProfile> userProfileMap = userProfileGateway.mapByUserIds(new HashSet<>(invitedUserIds));
|
||||
|
||||
// 批量查询佣金信息(inviteUserId=邀请人,userId=被邀请人)
|
||||
List<InviteUserRechargeCommission> commissions = inviteUserRechargeCommissionDAO.selectList(
|
||||
new LambdaQueryWrapper<InviteUserRechargeCommission>()
|
||||
.eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId) // 邀请人
|
||||
.in(InviteUserRechargeCommission::getUserId, invitedUserIds) // 被邀请人
|
||||
);
|
||||
|
||||
Map<Long, BigDecimal> commissionMap = commissions.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
InviteUserRechargeCommission::getUserId, // 被邀请人ID
|
||||
Collectors.reducing(BigDecimal.ZERO,
|
||||
InviteUserRechargeCommission::getCommission,
|
||||
BigDecimal::add)
|
||||
));
|
||||
|
||||
// 组装返回数据
|
||||
List<ValidInviteUserCO> result = new ArrayList<>();
|
||||
for (UserInviteUser invite : validInvites) {
|
||||
ValidInviteUserCO userCO = buildValidInviteUserCO(invite, userProfileMap, commissionMap);
|
||||
result.add(userCO);
|
||||
}
|
||||
|
||||
log.info("有效邀请用户列表, inviterUserId={}, validCount={}", inviterUserId, result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为有效邀请
|
||||
*/
|
||||
private boolean isValidInvite(UserInviteUser invite) {
|
||||
String inviteType = invite.getInviteType();
|
||||
|
||||
// LOTTERY类型直接算有效
|
||||
if (InviteTypeEnum.LOTTERY.getCode().equals(inviteType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// REGISTER类型需要检查充值记录
|
||||
if (InviteTypeEnum.REGISTER.getCode().equals(inviteType)) {
|
||||
// userId=邀请人, inviteUserId=被邀请人
|
||||
return hasValidRecharge(invite.getInviteUserId(), invite.getUserId());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有有效充值记录(commission > 0)
|
||||
* @param invitedUserId 被邀请人ID(充值的人)
|
||||
* @param inviterUserId 邀请人ID(获得佣金的人)
|
||||
*/
|
||||
private boolean hasValidRecharge(Long invitedUserId, Long inviterUserId) {
|
||||
long count = inviteUserRechargeCommissionDAO.selectCount(
|
||||
new LambdaQueryWrapper<InviteUserRechargeCommission>()
|
||||
.eq(InviteUserRechargeCommission::getUserId, invitedUserId) // 被邀请人
|
||||
.eq(InviteUserRechargeCommission::getInviteUserId, inviterUserId) // 邀请人
|
||||
.gt(InviteUserRechargeCommission::getCommission, BigDecimal.ZERO)
|
||||
);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建有效邀请用户CO
|
||||
*/
|
||||
private ValidInviteUserCO buildValidInviteUserCO(
|
||||
UserInviteUser invite,
|
||||
Map<Long, UserProfile> userProfileMap,
|
||||
Map<Long, BigDecimal> commissionMap) {
|
||||
|
||||
Long invitedUserId = invite.getInviteUserId(); // 被邀请人ID
|
||||
|
||||
ValidInviteUserCO userCO = new ValidInviteUserCO();
|
||||
userCO.setInvitedUserId(invitedUserId);
|
||||
userCO.setInviteType(invite.getInviteType());
|
||||
userCO.setInviteTime(invite.getCreateTime());
|
||||
|
||||
// 设置用户账号
|
||||
UserProfile userProfile = userProfileMap.get(invitedUserId);
|
||||
if (userProfile != null) {
|
||||
userCO.setInvitedUserAccount(userProfile.getAccount());
|
||||
}
|
||||
|
||||
// 计算剩余天数
|
||||
LocalDateTime inviteTime = invite.getCreateTime().toLocalDateTime();
|
||||
LocalDateTime expireTime = inviteTime.plusDays(VALID_DAYS);
|
||||
long remainingDays = ChronoUnit.DAYS.between(LocalDateTime.now(), expireTime);
|
||||
userCO.setRemainingDays(Math.max(0, (int) remainingDays));
|
||||
|
||||
// 设置提供的收益
|
||||
BigDecimal income = commissionMap.getOrDefault(invitedUserId, BigDecimal.ZERO);
|
||||
userCO.setProvideIncome(income);
|
||||
|
||||
return userCO;
|
||||
}
|
||||
}
|
||||
@ -18,8 +18,12 @@ import com.red.circle.other.app.dto.clientobject.activity.InviteUserCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteUserCommissionDetailsCO;
|
||||
import com.red.circle.other.app.command.activity.GetMyInviteCodeExe;
|
||||
import com.red.circle.other.app.command.activity.BindInviteCodeExe;
|
||||
import com.red.circle.other.app.command.activity.GetIncomeStatisticsExe;
|
||||
import com.red.circle.other.app.command.activity.GetValidInviteUsersExe;
|
||||
import com.red.circle.other.app.dto.cmd.activity.BindInviteCodeCmd;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteCodeCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteIncomeStatisticsCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.ValidInviteUserCO;
|
||||
import com.red.circle.other.app.dto.cmd.activity.InviteUserActivityLimitCmd;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -47,6 +51,8 @@ public class InviteUserActivityServiceImpl implements InviteUserActivityService
|
||||
private final InviteActivityExtractedListCmdExe inviteActivityExtractedListCmdExe;
|
||||
private final GetMyInviteCodeExe getMyInviteCodeExe;
|
||||
private final BindInviteCodeExe bindInviteCodeExe;
|
||||
private final GetIncomeStatisticsExe getIncomeStatisticsExe;
|
||||
private final GetValidInviteUsersExe getValidInviteUsersExe;
|
||||
|
||||
@Override
|
||||
public InviteUserActivitySummaryCO getSummary(AppExtCommand cmd) {
|
||||
@ -98,4 +104,14 @@ public class InviteUserActivityServiceImpl implements InviteUserActivityService
|
||||
public void bindInviteCode(BindInviteCodeCmd cmd) {
|
||||
bindInviteCodeExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InviteIncomeStatisticsCO getIncomeStatistics(AppExtCommand cmd) {
|
||||
return getIncomeStatisticsExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ValidInviteUserCO> getValidInviteUsers(AppExtCommand cmd) {
|
||||
return getValidInviteUsersExe.execute(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package com.red.circle.other.app.dto.clientobject.activity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 邀请收益统计CO
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class InviteIncomeStatisticsCO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 总收益
|
||||
*/
|
||||
private BigDecimal totalIncome;
|
||||
|
||||
/**
|
||||
* 今日收益
|
||||
*/
|
||||
private BigDecimal todayIncome;
|
||||
|
||||
/**
|
||||
* 有效邀请用户数量
|
||||
*/
|
||||
private Integer validInviteCount;
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.red.circle.other.app.dto.clientobject.activity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* 有效邀请用户CO
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ValidInviteUserCO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 被邀请用户ID
|
||||
*/
|
||||
private Long invitedUserId;
|
||||
|
||||
/**
|
||||
* 被邀请用户账号
|
||||
*/
|
||||
private String invitedUserAccount;
|
||||
|
||||
/**
|
||||
* 邀请类型:LOTTERY-抽奖, REGISTER-注册
|
||||
*/
|
||||
private String inviteType;
|
||||
|
||||
/**
|
||||
* 剩余天数
|
||||
*/
|
||||
private Integer remainingDays;
|
||||
|
||||
/**
|
||||
* 提供的收益
|
||||
*/
|
||||
private BigDecimal provideIncome;
|
||||
|
||||
/**
|
||||
* 邀请时间
|
||||
*/
|
||||
private Timestamp inviteTime;
|
||||
}
|
||||
@ -18,4 +18,10 @@ public class BindInviteCodeCmd extends AppExtCommand {
|
||||
|
||||
@NotBlank(message = "邀请码不能为空")
|
||||
private String inviteCode;
|
||||
|
||||
/**
|
||||
* 邀请类型:LOTTERY-抽奖类型, REGISTER-注册类型
|
||||
*/
|
||||
@NotBlank(message = "邀请类型不能为空")
|
||||
private String inviteType;
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@ import com.red.circle.other.app.dto.clientobject.activity.InviteUserCommissionDe
|
||||
import com.red.circle.other.app.dto.cmd.activity.InviteUserActivityLimitCmd;
|
||||
import com.red.circle.other.app.dto.cmd.activity.BindInviteCodeCmd;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteCodeCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.InviteIncomeStatisticsCO;
|
||||
import com.red.circle.other.app.dto.clientobject.activity.ValidInviteUserCO;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -70,4 +72,14 @@ public interface InviteUserActivityService {
|
||||
* 绑定邀请码.
|
||||
*/
|
||||
void bindInviteCode(BindInviteCodeCmd cmd);
|
||||
|
||||
/**
|
||||
* 邀请收益统计.
|
||||
*/
|
||||
InviteIncomeStatisticsCO getIncomeStatistics(AppExtCommand cmd);
|
||||
|
||||
/**
|
||||
* 有效邀请用户列表.
|
||||
*/
|
||||
List<ValidInviteUserCO> getValidInviteUsers(AppExtCommand cmd);
|
||||
}
|
||||
|
||||
@ -46,4 +46,10 @@ public class UserInviteUser extends TimestampBaseEntity {
|
||||
*/
|
||||
@TableField("invite_user_id")
|
||||
private Long inviteUserId;
|
||||
|
||||
/**
|
||||
* 邀请类型:LOTTERY-抽奖类型, REGISTER-注册类型
|
||||
*/
|
||||
@TableField("invite_type")
|
||||
private String inviteType;
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.red.circle.other.infra.enums.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 邀请类型枚举
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-22
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum InviteTypeEnum {
|
||||
|
||||
/**
|
||||
* 抽奖类型 - 直接算有效邀请
|
||||
*/
|
||||
LOTTERY("LOTTERY", "抽奖类型"),
|
||||
|
||||
/**
|
||||
* 注册类型 - 需要充值才算有效邀请
|
||||
*/
|
||||
REGISTER("REGISTER", "注册类型");
|
||||
|
||||
private final String code;
|
||||
private final String desc;
|
||||
|
||||
public static InviteTypeEnum fromCode(String code) {
|
||||
for (InviteTypeEnum type : values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user