增加了修改,查看抽佣比例的功能

This commit is contained in:
2025-07-13 11:37:46 +08:00
parent dbf924d9e9
commit d13bd60a84
17 changed files with 658 additions and 82 deletions

View File

@ -18,8 +18,13 @@ public class RedisConfig {
// 指定kv的序列化方式 // 指定kv的序列化方式
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // 普通 KV 用 JSON 序列化 value用字符串序列化 key
redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// Hash 类型hashKey 用字符串序列化hashValue 也用字符串
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
return redisTemplate; return redisTemplate;
} }

View File

@ -1,19 +1,29 @@
package com.greenorange.promotion.controller.userInfo; package com.greenorange.promotion.controller.userInfo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.hash.Hash;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.greenorange.promotion.annotation.RequiresPermission; import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.common.BaseResponse; import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.OrderStatusConstant; import com.greenorange.promotion.constant.OrderStatusConstant;
import com.greenorange.promotion.constant.SystemConstant;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.*; import com.greenorange.promotion.model.dto.userPerformanceSummary.*;
import com.greenorange.promotion.model.entity.CourseOrder; import com.greenorange.promotion.model.entity.*;
import com.greenorange.promotion.model.entity.UserInfo; import com.greenorange.promotion.model.enums.CommissionStatusEnum;
import com.greenorange.promotion.model.entity.UserPerformanceSummary; import com.greenorange.promotion.model.enums.UserRoleEnum;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderBaseInfoVO; import com.greenorange.promotion.model.vo.courseOrder.CourseOrderBaseInfoVO;
import com.greenorange.promotion.model.vo.userPerformanceSummary.SupervisorPerformanceSummaryVO;
import com.greenorange.promotion.model.vo.userPerformanceSummary.UserPerformanceSummaryDetailVO; import com.greenorange.promotion.model.vo.userPerformanceSummary.UserPerformanceSummaryDetailVO;
import com.greenorange.promotion.service.common.CommonService; import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CourseOrderService; import com.greenorange.promotion.service.course.CourseOrderService;
import com.greenorange.promotion.service.course.CoursePromotionCommissionPendingService;
import com.greenorange.promotion.service.userInfo.EmployeePromotionRecordsService;
import com.greenorange.promotion.service.userInfo.UserInfoService; import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserPerformanceSummaryService; import com.greenorange.promotion.service.userInfo.UserPerformanceSummaryService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -21,6 +31,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -28,9 +40,8 @@ import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap; import java.math.BigDecimal;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -46,16 +57,29 @@ public class UserPerformanceSummaryController {
@Resource @Resource
private UserPerformanceSummaryService userPerformanceSummaryService; private UserPerformanceSummaryService userPerformanceSummaryService;
@Resource @Resource
private CommonService commonService; private CommonService commonService;
@Resource @Resource
private UserInfoService userInfoService; private UserInfoService userInfoService;
@Resource @Resource
private CourseOrderService courseOrderService; private CourseOrderService courseOrderService;
@Resource
private EmployeePromotionRecordsService employeePromotionRecordsService;
@Resource
private CoursePromotionCommissionPendingService coursePromotionCommissionPendingService;
/** /**
* Web端管理员分页查询主管绩效汇总 * Web端管理员分页查询主管绩效汇总
@ -190,48 +214,148 @@ public class UserPerformanceSummaryController {
// /** /**
// * Web端管理员分页查询主管绩效排名 * Web端管理员分页查询主管绩效排名
// * @param userPerformanceSummaryQueryRequest 主管绩效汇总查询请求体 * @param userPerformanceSummaryRankQueryRequest 主管绩效排名查询请求体
// * @return 用户绩效汇总列表 * @return 用户绩效汇总列表
// */ */
// @PostMapping("user/page") @PostMapping("rank/user/page")
// @Operation(summary = "Web端管理员分页查询主管绩效排名", description = "参数:用户绩效汇总查询请求体权限管理员方法名listUserPerformanceSummaryByPage") @Operation(summary = "Web端管理员分页查询主管绩效排名", description = "参数:主管绩效排名查询请求体权限管理员方法名listUserPerformanceSummaryRankingsByPage")
// @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
// public BaseResponse<Page<CourseOrderBaseInfoVO>> listUserPerformanceSummaryByPage(@Valid @RequestBody UserCourseOrderQueryRequest userPerformanceSummaryQueryRequest) { public BaseResponse<Page<CourseOrderBaseInfoVO>> listUserPerformanceSummaryRankingsByPage(@Valid @RequestBody UserPerformanceSummaryRankQueryRequest userPerformanceSummaryRankQueryRequest) {
// long current = userPerformanceSummaryQueryRequest.getCurrent(); String startTimeStr = userPerformanceSummaryRankQueryRequest.getStartDate();
// long pageSize = userPerformanceSummaryQueryRequest.getPageSize(); String endTimeStr = userPerformanceSummaryRankQueryRequest.getEndDate();
// Long staffUserId = userPerformanceSummaryQueryRequest.getStaffUserId(); DateTime startDate = DateUtil.parse(startTimeStr, "yyyy-MM-dd HH:mm:ss");
// DateTime endDate = DateUtil.parse(endTimeStr, "yyyy-MM-dd HH:mm:ss");
// QueryWrapper<CourseOrder> courseOrderQueryWrapper = userPerformanceSummaryService.getCourseOrderQueryWrapper(userPerformanceSummaryQueryRequest);
// courseOrderQueryWrapper.in("orderStatus", OrderStatusConstant.SUCCESS, OrderStatusConstant.REFUNDED); QueryWrapper<EmployeePromotionRecords> empQueryWrapper = new QueryWrapper<>();
// empQueryWrapper.ge(StringUtils.isNotBlank(startTimeStr), "createTime", startDate);
// List<Long> ids = userInfoService.findAllSubUser(staffUserId); empQueryWrapper.le(StringUtils.isNotBlank(endTimeStr), "createTime", endDate);
// List<UserInfo> userInfoList = commonService.findByFieldInTargetField(ids, userInfoService, Function.identity(), UserInfo::getId); List<EmployeePromotionRecords> employeePromotionRecordsList = employeePromotionRecordsService.list(empQueryWrapper);
// courseOrderQueryWrapper.in("userId", ids); // 封装Map集合主管id, 值:推广数量)
// Map<Long, Integer> supervisorCntMap = new HashMap<>();
// Page<CourseOrder> page = courseOrderService.page(new Page<>(current, pageSize), courseOrderQueryWrapper); // 封装Map集合员工id, 值:推广数量)
// List<CourseOrder> courseOrderList = page.getRecords(); Map<Long, Integer> staffCntMap = new HashMap<>();
// List<CourseOrderBaseInfoVO> courseOrderBaseInfoVOS = commonService.convertList(courseOrderList, CourseOrderBaseInfoVO.class); for (EmployeePromotionRecords employeePromotionRecords : employeePromotionRecordsList) {
// Long firstUserId = employeePromotionRecords.getFirstUserId();
// // 封装Map集合键:用户id, 值:用户信息) Long secondUserId = employeePromotionRecords.getSecondUserId();
// Map<Long, UserInfo> userInfoMap = new HashMap<>(); supervisorCntMap.merge(firstUserId, 1, Integer::sum);
// for (UserInfo userInfo : userInfoList) userInfoMap.put(userInfo.getId(), userInfo); staffCntMap.merge(secondUserId, 1, Integer::sum);
// for (CourseOrderBaseInfoVO courseOrderBaseInfoVO : courseOrderBaseInfoVOS) { }
// UserInfo userInfo = userInfoMap.get(courseOrderBaseInfoVO.getUserId());
// courseOrderBaseInfoVO.setNickName(userInfo.getNickName()); // 封装Map集合主管id, 值:下单数量)
// courseOrderBaseInfoVO.setPhoneNumber(userInfo.getPhoneNumber()); Map<Long, Integer> supervisorOrderCntMap = new HashMap<>();
// } // 封装Map集合员工id, 值:下单数量)
// Map<Long, Integer> staffOrderCntMap = new HashMap<>();
// Page<CourseOrderBaseInfoVO> voPage = new Page<>(current, pageSize); // 主管id, 值:下单金额)
// voPage.setRecords(courseOrderBaseInfoVOS); Map<Long, BigDecimal> supervisorOrderAmountMap = new HashMap<>();
// voPage.setPages(page.getPages()); // 员工id, 值:下单金额)
// voPage.setTotal(page.getTotal()); Map<Long, BigDecimal> staffOrderAmountMap = new HashMap<>();
// return ResultUtils.success(voPage); // 主管id, 值:净成交金额)
// } Map<Long, BigDecimal> supervisorNetSalesAmountMap = new HashMap<>();
// 员工id, 值:净成交金额)
Map<Long, BigDecimal> staffNetSalesAmountMap = new HashMap<>();
QueryWrapper<CoursePromotionCommissionPending> coursePromotionQueryWrapper = new QueryWrapper<>();
coursePromotionQueryWrapper.ge(StringUtils.isNotBlank(startTimeStr), "createTime", startDate);
coursePromotionQueryWrapper.le(StringUtils.isNotBlank(endTimeStr), "createTime", endDate);
List<CoursePromotionCommissionPending> coursePromotionCommissionPendingList = coursePromotionCommissionPendingService.list(coursePromotionQueryWrapper);
for (CoursePromotionCommissionPending coursePromotionCommissionPending : coursePromotionCommissionPendingList) {
Long firstUserId = coursePromotionCommissionPending.getFirstUserId();
Long secondUserId = coursePromotionCommissionPending.getSecondUserId();
BigDecimal totalAmount = coursePromotionCommissionPending.getTotalAmount();
DateTime updateDate = DateUtil.date(coursePromotionCommissionPending.getUpdateTime());
String commissionStatus = coursePromotionCommissionPending.getCommissionStatus();
CommissionStatusEnum commissionStatusEnum = CommissionStatusEnum.getEnumByValue(commissionStatus);
supervisorOrderCntMap.merge(firstUserId, 1, Integer::sum);
staffOrderCntMap.merge(secondUserId, 1, Integer::sum);
supervisorOrderAmountMap.merge(firstUserId, totalAmount, BigDecimal::add);
staffOrderAmountMap.merge(secondUserId, totalAmount, BigDecimal::add);
if (!(CommissionStatusEnum.COMPLETED.equals(commissionStatusEnum) && updateDate.isAfterOrEquals(startDate) && updateDate.isBeforeOrEquals(endDate))) {
totalAmount = totalAmount.multiply(SystemConstant.FEE_RATE);
}
supervisorNetSalesAmountMap.merge(firstUserId, totalAmount, BigDecimal::add);
staffNetSalesAmountMap.merge(secondUserId, totalAmount, BigDecimal::add);
}
// 封装Map集合主管id, 值:员工数量)
Map<Long, Integer> supervisorStaffCntMap = new HashMap<>();
List<UserInfo> userInfoList = commonService.findByFieldEqTargetField(UserInfo::getUserRole, UserRoleEnum.SUPERVISOR, userInfoService);
List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(userInfoList, userPerformanceSummaryService, UserInfo::getId, UserPerformanceSummary::getUserId);
// 封装Map集合主管id, 用户信息)
Map<Long, UserInfo> userInfoMap = new HashMap<>();
for (UserInfo userInfo : userInfoList) {
userInfoMap.put(userInfo.getId(), userInfo);
}
// 封装主管绩效排名列表
List<SupervisorPerformanceSummaryVO> supervisorPerformanceSummaryVOS = new ArrayList<>();
for (UserPerformanceSummary userPerformanceSummary : userPerformanceSummaryList) {
Long userId = userPerformanceSummary.getUserId();
UserInfo userInfo = userInfoMap.get(userId);
SupervisorPerformanceSummaryVO supervisorPerformanceSummaryVO = SupervisorPerformanceSummaryVO.builder()
.nickName(userInfo.getNickName())
.phoneNumber(userInfo.getPhoneNumber())
.empCount(userPerformanceSummary.getEmpCount())
.orderCount(supervisorOrderCntMap.get(userId))
.totalAmount(supervisorOrderAmountMap.get(userId))
.netAmount(supervisorNetSalesAmountMap.get(userId))
.promoCount(supervisorCntMap.get(userId))
.build();
supervisorPerformanceSummaryVOS.add(supervisorPerformanceSummaryVO);
}
long current = userPerformanceSummaryRankQueryRequest.getCurrent();
long pageSize = userPerformanceSummaryRankQueryRequest.getPageSize();
String nickName = userPerformanceSummaryRankQueryRequest.getNickName();
String phoneNumber = userPerformanceSummaryRankQueryRequest.getPhoneNumber();
String sortField = userPerformanceSummaryRankQueryRequest.getSortField();
String sortOrder = userPerformanceSummaryRankQueryRequest.getSortOrder();
return null;
}
/**
* Web端管理员修改一、二级抽成比例
* @param rakeRewardsUpdateRequest 抽成比例更新请求体
* @return 是否更新成功
*/
@PostMapping("update/rate")
@Operation(summary = "Web端管理员修改一、二级抽成比例", description = "参数抽成比例更新请求体权限管理员方法名updateRakeRewardsRate")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> updateRakeRewardsRate(@Valid @RequestBody RakeRewardsUpdateRequest rakeRewardsUpdateRequest) {
userPerformanceSummaryService.updateRakeRewards(rakeRewardsUpdateRequest);
return ResultUtils.success(true);
}
/**
* Web端管理员查询一、二级抽成比例
* @return 抽成比例对象
*/
@PostMapping("query/rate")
@Operation(summary = "Web端管理员查询一、二级抽成比例", description = "参数权限管理员方法名queryRakeRewardsRate")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Map<String, BigDecimal>> queryRakeRewardsRate() {
Map<String, BigDecimal> rateMap = userPerformanceSummaryService.queryRakeRewardsRate();
return ResultUtils.success(rateMap);
}
/**
* Web端管理员根据级别查询抽佣比例
* @param rakeRewardsQueryRequest 级别
* @return 抽成比例
*/
@PostMapping("query/level/rate")
@Operation(summary = "Web端管理员根据级别查询抽佣比例", description = "参数权限管理员方法名queryRakeRewardsRateByLevel")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<BigDecimal> queryRakeRewardsRateByLevel(@Valid @RequestBody RakeRewardsQueryRequest rakeRewardsQueryRequest) {
BigDecimal rate = userPerformanceSummaryService.queryRakeRewardsRateByLevel(rakeRewardsQueryRequest);
return ResultUtils.success(rate);
}

View File

@ -0,0 +1,18 @@
package com.greenorange.promotion.mapper;
import com.greenorange.promotion.model.entity.EmployeePromotionRecords;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author 35880
* @description 针对表【employee_promotion_records(员工推广记录表)】的数据库操作Mapper
* @createDate 2025-07-12 22:27:51
* @Entity com.greenorange.promotion.model.entity.EmployeePromotionRecords
*/
public interface EmployeePromotionRecordsMapper extends BaseMapper<EmployeePromotionRecords> {
}

View File

@ -0,0 +1,30 @@
package com.greenorange.promotion.model.dto.userPerformanceSummary;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 抽成比例查询请求体
*/
@Data
@Schema(description = "抽成比例查询请求体", requiredProperties = {"level"})
public class RakeRewardsQueryRequest implements Serializable {
/**
* 级别
*/
@NotBlank(message = "级别不能为空")
@Pattern(regexp = "first|second", message = "级别只能是first或second")
@Schema(description = "级别", example = "first")
private String level;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,40 @@
package com.greenorange.promotion.model.dto.userPerformanceSummary;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 抽成比例更新请求体
*/
@Data
@Schema(description = "抽成比例更新请求体", requiredProperties = {"level", "rate"})
public class RakeRewardsUpdateRequest implements Serializable {
/**
* 级别
*/
@NotBlank(message = "级别不能为空")
@Pattern(regexp = "first|second", message = "级别只能是first或second")
@Schema(description = "级别", example = "first")
private String level;
/**
* 抽成比例
*/
@DecimalMin(value = "0.0", message = "抽成比例不能小于0.0")
@DecimalMax(value = "1.0", message = "抽成比例不能大于1.0")
@Schema(description = "抽成比例", example = "0.1")
private BigDecimal rate;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -69,6 +69,16 @@ public class CoursePromotionCommissionPending implements Serializable {
*/ */
private Long userId; private Long userId;
/**
* 一级抽佣比例
*/
private BigDecimal firstRate;
/**
* 二级抽佣比例
*/
private BigDecimal secondRate;
/** /**
* 订单价格 * 订单价格
*/ */
@ -84,6 +94,16 @@ public class CoursePromotionCommissionPending implements Serializable {
*/ */
private Date orderCreateTime; private Date orderCreateTime;
/**
* 一级抽成奖励
*/
private BigDecimal firstReward;
/**
* 二级抽成奖励
*/
private BigDecimal secondReward;
/** /**
* 是否删除 * 是否删除
*/ */

View File

@ -0,0 +1,64 @@
package com.greenorange.promotion.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 员工推广记录表
* @TableName employee_promotion_records
*/
@TableName(value ="employee_promotion_records")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EmployeePromotionRecords implements Serializable {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 主管ID
*/
private Long firstUserId;
/**
* 员工ID
*/
private Long secondUserId;
/**
* 客户ID
*/
private Long userId;
/**
* 是否删除
*/
private Integer isDelete;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -15,7 +15,8 @@ import java.util.stream.Collectors;
public enum CourseTypeEnum implements BaseEnum { public enum CourseTypeEnum implements BaseEnum {
KAOGONG("考公"), KAOGONG("考公"),
CAIJING("财经"); KAOBIAN("考编"),
KAOZHENG("考证");
private final String value; private final String value;

View File

@ -0,0 +1,56 @@
package com.greenorange.promotion.model.vo.userPerformanceSummary;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 员工绩效排名信息 视图对象
*/
@Data
@Schema(description = "员工绩效排名信息 视图对象")
public class StaffPerformanceSummaryVO implements Serializable {
/**
* 用户昵称
*/
@Schema(description = "用户昵称", example = "chenxinzhi")
private String nickName;
/**
* 手机号
*/
@Schema(description = "手机号", example = "15888610253")
private String phoneNumber;
/**
* 推广人数
*/
@Schema(description = "推广人数", example = "300")
private Integer promoCount;
/**
* 下单数量
*/
@Schema(description = "下单数量", example = "100")
private Integer orderCount;
/**
* 订单总金额
*/
@Schema(description = "订单总金额", example = "15.00")
private BigDecimal totalAmount;
/**
* 净成交
*/
@Schema(description = "净成交", example = "20.00")
private BigDecimal netAmount;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,68 @@
package com.greenorange.promotion.model.vo.userPerformanceSummary;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 主管绩效排名信息 视图对象
*/
@Data
@Schema(description = "主管绩效排名信息 视图对象")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SupervisorPerformanceSummaryVO implements Serializable {
/**
* 用户昵称
*/
@Schema(description = "用户昵称", example = "chenxinzhi")
private String nickName;
/**
* 手机号
*/
@Schema(description = "手机号", example = "15888610253")
private String phoneNumber;
/**
* 员工数量
*/
@Schema(description = "员工数量", example = "150")
private Integer empCount;
/**
* 推广人数
*/
@Schema(description = "推广人数", example = "300")
private Integer promoCount;
/**
* 下单数量
*/
@Schema(description = "下单数量", example = "100")
private Integer orderCount;
/**
* 订单总金额
*/
@Schema(description = "订单总金额", example = "15.00")
private BigDecimal totalAmount;
/**
* 净成交
*/
@Schema(description = "净成交", example = "20.00")
private BigDecimal netAmount;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,13 @@
package com.greenorange.promotion.service.userInfo;
import com.greenorange.promotion.model.entity.EmployeePromotionRecords;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author 35880
* @description 针对表【employee_promotion_records(员工推广记录表)】的数据库操作Service
* @createDate 2025-07-12 22:27:51
*/
public interface EmployeePromotionRecordsService extends IService<EmployeePromotionRecords> {
}

View File

@ -2,12 +2,18 @@ package com.greenorange.promotion.service.userInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.greenorange.promotion.common.PageRequest; import com.greenorange.promotion.common.PageRequest;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.MiniUserCourseOrderQueryRequest; import com.greenorange.promotion.model.dto.userPerformanceSummary.MiniUserCourseOrderQueryRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.RakeRewardsQueryRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.RakeRewardsUpdateRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.UserCourseOrderQueryRequest; import com.greenorange.promotion.model.dto.userPerformanceSummary.UserCourseOrderQueryRequest;
import com.greenorange.promotion.model.entity.CourseOrder; import com.greenorange.promotion.model.entity.CourseOrder;
import com.greenorange.promotion.model.entity.UserPerformanceSummary; import com.greenorange.promotion.model.entity.UserPerformanceSummary;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal;
import java.util.Map;
/** /**
* @author 35880 * @author 35880
* @description 针对表【user_performance_summary(用户绩效汇总表)】的数据库操作Service * @description 针对表【user_performance_summary(用户绩效汇总表)】的数据库操作Service
@ -25,4 +31,22 @@ public interface UserPerformanceSummaryService extends IService<UserPerformanceS
* 获取课程订单的查询条件 * 获取课程订单的查询条件
*/ */
QueryWrapper<CourseOrder> getCourseOrderQueryWrapper(UserCourseOrderQueryRequest userCourseOrderQueryRequest); QueryWrapper<CourseOrder> getCourseOrderQueryWrapper(UserCourseOrderQueryRequest userCourseOrderQueryRequest);
/**
* Web端管理员修改一、二级抽成比例
*/
void updateRakeRewards(RakeRewardsUpdateRequest rakeRewardsUpdateRequest);
/**
* Web端管理员查询一、二级抽成比例
*/
Map<String, BigDecimal> queryRakeRewardsRate();
/**
* Web端管理员根据级别查询抽佣比例
*/
BigDecimal queryRakeRewardsRateByLevel(RakeRewardsQueryRequest rakeRewardsQueryRequest);
} }

View File

@ -0,0 +1,22 @@
package com.greenorange.promotion.service.userInfo.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.model.entity.EmployeePromotionRecords;
import com.greenorange.promotion.service.userInfo.EmployeePromotionRecordsService;
import com.greenorange.promotion.mapper.EmployeePromotionRecordsMapper;
import org.springframework.stereotype.Service;
/**
* @author 35880
* @description 针对表【employee_promotion_records(员工推广记录表)】的数据库操作Service实现
* @createDate 2025-07-12 22:27:51
*/
@Service
public class EmployeePromotionRecordsServiceImpl extends ServiceImpl<EmployeePromotionRecordsMapper, EmployeePromotionRecords>
implements EmployeePromotionRecordsService{
}

View File

@ -23,10 +23,7 @@ import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.project.ProjectCommissionService; import com.greenorange.promotion.service.project.ProjectCommissionService;
import com.greenorange.promotion.service.project.ProjectDetailService; import com.greenorange.promotion.service.project.ProjectDetailService;
import com.greenorange.promotion.service.project.SubUserProjectCommissionService; import com.greenorange.promotion.service.project.SubUserProjectCommissionService;
import com.greenorange.promotion.service.userInfo.AdvancementApplyService; import com.greenorange.promotion.service.userInfo.*;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserMainInfoService;
import com.greenorange.promotion.service.userInfo.UserPerformanceSummaryService;
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService; import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
import com.greenorange.promotion.utils.JWTUtils; import com.greenorange.promotion.utils.JWTUtils;
import com.greenorange.promotion.utils.RegexUtils; import com.greenorange.promotion.utils.RegexUtils;
@ -100,6 +97,10 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
private UserPerformanceSummaryService userPerformanceSummaryService; private UserPerformanceSummaryService userPerformanceSummaryService;
@Resource
private EmployeePromotionRecordsService employeePromotionRecordsService;
@ -176,9 +177,9 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
myUserInfo.setUserAvatar(UserConstant.USER_DEFAULT_AVATAR); myUserInfo.setUserAvatar(UserConstant.USER_DEFAULT_AVATAR);
this.save(myUserInfo); this.save(myUserInfo);
// 添加用户绩效记录 // // 添加用户绩效记录
UserPerformanceSummary userPerformanceSummary = UserPerformanceSummary.builder().userId(myUserInfo.getId()).build(); // UserPerformanceSummary userPerformanceSummary = UserPerformanceSummary.builder().userId(myUserInfo.getId()).build();
userPerformanceSummaryService.save(userPerformanceSummary); // userPerformanceSummaryService.save(userPerformanceSummary);
// 更新上级用户的数量 // 更新上级用户的数量
updateParentUserInfoEmpCount(myUserInfo.getId(), userRoleEnum); updateParentUserInfoEmpCount(myUserInfo.getId(), userRoleEnum);
@ -416,6 +417,16 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
} }
} }
userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList); userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);
// 如果是普通用户,就添加一条员工推广记录
if (userRoleEnum.equals(UserRoleEnum.USER)) {
EmployeePromotionRecords employeePromotionRecords = EmployeePromotionRecords.builder()
.firstUserId(pathToRoot.get(0))
.secondUserId(pathToRoot.get(1))
.userId(userId)
.build();
employeePromotionRecordsService.save(employeePromotionRecords);
}
} }

View File

@ -6,7 +6,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.common.PageRequest; import com.greenorange.promotion.common.PageRequest;
import com.greenorange.promotion.constant.CommonConstant; import com.greenorange.promotion.constant.CommonConstant;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.MiniUserCourseOrderQueryRequest; import com.greenorange.promotion.model.dto.userPerformanceSummary.MiniUserCourseOrderQueryRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.RakeRewardsQueryRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.RakeRewardsUpdateRequest;
import com.greenorange.promotion.model.dto.userPerformanceSummary.UserCourseOrderQueryRequest; import com.greenorange.promotion.model.dto.userPerformanceSummary.UserCourseOrderQueryRequest;
import com.greenorange.promotion.model.entity.CourseOrder; import com.greenorange.promotion.model.entity.CourseOrder;
import com.greenorange.promotion.model.entity.UserPerformanceSummary; import com.greenorange.promotion.model.entity.UserPerformanceSummary;
@ -16,8 +19,15 @@ import com.greenorange.promotion.mapper.UserPerformanceSummaryMapper;
import com.greenorange.promotion.utils.SqlUtils; import com.greenorange.promotion.utils.SqlUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.security.Key;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* @author 35880 * @author 35880
* @description 针对表【user_performance_summary(用户绩效汇总表)】的数据库操作Service实现 * @description 针对表【user_performance_summary(用户绩效汇总表)】的数据库操作Service实现
@ -27,6 +37,10 @@ import org.springframework.stereotype.Service;
public class UserPerformanceSummaryServiceImpl extends ServiceImpl<UserPerformanceSummaryMapper, UserPerformanceSummary> public class UserPerformanceSummaryServiceImpl extends ServiceImpl<UserPerformanceSummaryMapper, UserPerformanceSummary>
implements UserPerformanceSummaryService{ implements UserPerformanceSummaryService{
private static final String KEY = "rakeRate";
@Resource
private RedisTemplate<String, String> redisTemplate;
/** /**
* 获取查询条件 * 获取查询条件
@ -57,6 +71,43 @@ public class UserPerformanceSummaryServiceImpl extends ServiceImpl<UserPerforman
queryWrapper.le(StringUtils.isNotBlank(endTimeStr), "createTime", endDate); queryWrapper.le(StringUtils.isNotBlank(endTimeStr), "createTime", endDate);
return queryWrapper; return queryWrapper;
} }
/**
* Web端管理员修改一、二级抽成比例
*/
@Override
public void updateRakeRewards(RakeRewardsUpdateRequest rakeRewardsUpdateRequest) {
String level = rakeRewardsUpdateRequest.getLevel();
BigDecimal rate = rakeRewardsUpdateRequest.getRate();
redisTemplate.opsForHash().put(KEY, level, rate.toPlainString());
}
/**
* Web端管理员查询一、二级抽成比例
*/
@Override
public Map<String, BigDecimal> queryRakeRewardsRate() {
// 直接从 redisTemplate 获取 HashOperations
HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
Map<String, String> entries = hashOps.entries(KEY);
return entries.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> new BigDecimal(e.getValue())
));
}
/**
* Web端管理员根据级别查询抽佣比例
*/
@Override
public BigDecimal queryRakeRewardsRateByLevel(RakeRewardsQueryRequest rakeRewardsQueryRequest) {
String level = rakeRewardsQueryRequest.getLevel();
return new BigDecimal(redisTemplate.opsForHash().get(KEY, level).toString());
}
} }

View File

@ -40,6 +40,7 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -153,9 +154,10 @@ public class WechatPayServiceImpl implements WechatPayService {
List<Long> superUserIdList = pathToRoot.subList(1, 3); List<Long> superUserIdList = pathToRoot.subList(1, 3);
List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(superUserIdList, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId); List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(superUserIdList, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId);
BigDecimal rate; BigDecimal rate;
Map<String, BigDecimal> rateMap = userPerformanceSummaryService.queryRakeRewardsRate();
for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) { for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) {
if (i == 0) rate = SystemConstant.FIRST_LEVEL_COMMISSION_RATE; if (i == 0) rate = rateMap.get("first");
else rate = SystemConstant.SECOND_LEVEL_COMMISSION_RATE; else rate = rateMap.get("second");
// 计算理论上获得的最大提成奖励 // 计算理论上获得的最大提成奖励
BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate); BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate);
UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i); UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i);
@ -169,25 +171,27 @@ public class WechatPayServiceImpl implements WechatPayService {
userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList); userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);
// // 添加课程推广待提成记录 // 添加课程推广待提成记录
// Long userId = courseOrder.getUserId(); Long firstUserId = pathToRoot.get(0);
// List<Long> pathToRoot = userInfoService.findPathToRoot(userId); Long secondUserId = pathToRoot.get(1);
// Long firstUserId = pathToRoot.get(0); CoursePromotionCommissionPending coursePromotionCommissionPending = CoursePromotionCommissionPending.builder()
// Long secondUserId = pathToRoot.get(1); .firstUserId(firstUserId)
// CoursePromotionCommissionPending coursePromotionCommissionPending = CoursePromotionCommissionPending.builder() .secondUserId(secondUserId)
// .firstUserId(firstUserId) .courseId(courseId)
// .secondUserId(secondUserId) .name(courseOrder.getName())
// .courseId(courseId) .type(courseOrder.getType())
// .name(courseOrder.getName()) .image(courseOrder.getImage())
// .type(courseOrder.getType()) .orderId(courseOrder.getId())
// .image(courseOrder.getImage()) .userId(userId)
// .orderId(courseOrder.getId()) .firstRate(rateMap.get("first"))
// .userId(userId) .secondRate(rateMap.get("second"))
// .totalAmount(courseOrder.getTotalAmount()) .firstReward(courseOrder.getTotalAmount().multiply(rateMap.get("first")))
// .commissionStatus(CommissionStatusEnum.PENDING.getValue()) .secondReward(courseOrder.getTotalAmount().multiply(rateMap.get("second")))
// .orderCreateTime(courseOrder.getCreateTime()) .totalAmount(courseOrder.getTotalAmount())
// .build(); .commissionStatus(CommissionStatusEnum.PENDING.getValue())
// coursePromotionCommissionPendingService.save(coursePromotionCommissionPending); .orderCreateTime(courseOrder.getCreateTime())
.build();
coursePromotionCommissionPendingService.save(coursePromotionCommissionPending);
System.out.println("---------------------------微信支付回调(结束)-------------------------------"); System.out.println("---------------------------微信支付回调(结束)-------------------------------");
@ -278,9 +282,12 @@ public class WechatPayServiceImpl implements WechatPayService {
List<Long> superUserIdList = pathToRoot.subList(1, 3); List<Long> superUserIdList = pathToRoot.subList(1, 3);
List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(superUserIdList, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId); List<UserPerformanceSummary> userPerformanceSummaryList = commonService.findByFieldInTargetField(superUserIdList, userPerformanceSummaryService, Function.identity(), UserPerformanceSummary::getUserId);
BigDecimal rate; BigDecimal rate;
LambdaQueryWrapper<CoursePromotionCommissionPending> coursePromotionQueryWrapper = new LambdaQueryWrapper<>();
coursePromotionQueryWrapper.eq(CoursePromotionCommissionPending::getOrderId, courseOrder.getId());
CoursePromotionCommissionPending coursePromotionCommissionPending = coursePromotionCommissionPendingService.getOne(coursePromotionQueryWrapper);
for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) { for (int i = 0; i < userPerformanceSummaryList.size(); i ++ ) {
if (i == 0) rate = SystemConstant.FIRST_LEVEL_COMMISSION_RATE; if (i == 0) rate = coursePromotionCommissionPending.getFirstRate();
else rate = SystemConstant.SECOND_LEVEL_COMMISSION_RATE; else rate = coursePromotionCommissionPending.getSecondRate();
// 计算理论上获得的最大提成奖励 // 计算理论上获得的最大提成奖励
BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate); BigDecimal rakeRewards = courseOrder.getTotalAmount().multiply(rate);
UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i); UserPerformanceSummary userPerformanceSummary = userPerformanceSummaryList.get(i);
@ -293,11 +300,11 @@ public class WechatPayServiceImpl implements WechatPayService {
} }
userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList); userPerformanceSummaryService.updateBatchById(userPerformanceSummaryList);
// // 修改课程推广待提成状态为"已失效" // 修改课程推广待提成状态为"已失效"
// LambdaUpdateWrapper<CoursePromotionCommissionPending> coursePromotionUpdateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<CoursePromotionCommissionPending> coursePromotionUpdateWrapper = new LambdaUpdateWrapper<>();
// coursePromotionUpdateWrapper.eq(CoursePromotionCommissionPending::getOrderId, courseOrder.getId()) coursePromotionUpdateWrapper.eq(CoursePromotionCommissionPending::getOrderId, courseOrder.getId())
// .set(CoursePromotionCommissionPending::getCommissionStatus, CommissionStatusEnum.EXPIRED.getValue()); .set(CoursePromotionCommissionPending::getCommissionStatus, CommissionStatusEnum.EXPIRED.getValue());
// coursePromotionCommissionPendingService.update(coursePromotionUpdateWrapper); coursePromotionCommissionPendingService.update(coursePromotionUpdateWrapper);
System.out.println("---------------------------微信退款回调(结束)-------------------------------"); System.out.println("---------------------------微信退款回调(结束)-------------------------------");
return true; return true;

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.greenorange.promotion.mapper.EmployeePromotionRecordsMapper">
<resultMap id="BaseResultMap" type="com.greenorange.promotion.model.entity.EmployeePromotionRecords">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="firstUserId" column="firstUserId" jdbcType="BIGINT"/>
<result property="secondUserId" column="secondUserId" jdbcType="BIGINT"/>
<result property="userId" column="userId" jdbcType="BIGINT"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,firstUserId,secondUserId,
userId,isDelete,createTime,
updateTime
</sql>
</mapper>