code review:分佣剩余部分的 review

This commit is contained in:
YunaiV 2023-09-28 22:22:38 +08:00
parent b1ce971a2f
commit f9bf41d773
13 changed files with 79 additions and 61 deletions

View File

@ -17,7 +17,7 @@ public enum BrokerageRecordBizTypeEnum implements IntArrayValuable {
ORDER(1, "获得推广佣金", "获得推广佣金 {}", true), ORDER(1, "获得推广佣金", "获得推广佣金 {}", true),
WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false), WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false),
WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回返还佣金 {}", true), WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回返还佣金 {}", true),
; ;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray();

View File

@ -6,6 +6,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
// TODO 芋艿提现的打通在纠结下
/** /**
* 佣金提现状态枚举 * 佣金提现状态枚举
* *

View File

@ -45,7 +45,7 @@ public class AppBrokerageRecordController {
@GetMapping("/get-product-brokerage-price") @GetMapping("/get-product-brokerage-price")
@Operation(summary = "获得商品的分销金额") @Operation(summary = "获得商品的分销金额")
public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) { public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
return success(brokerageRecordService.calculateProductBrokeragePrice(spuId, getLoginUserId())); return success(brokerageRecordService.calculateProductBrokeragePrice(getLoginUserId(), spuId));
} }
} }

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
@ -32,14 +31,10 @@ public class AppBrokerageWithdrawController {
@Resource @Resource
private BrokerageWithdrawService brokerageWithdrawService; private BrokerageWithdrawService brokerageWithdrawService;
@Resource
private DictDataApi dictDataApi;
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得分销提现分页") @Operation(summary = "获得分销提现分页")
@PreAuthenticated @PreAuthenticated
public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) { public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
// 分页查询
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage( PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId())); BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult)); return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
@ -49,7 +44,7 @@ public class AppBrokerageWithdrawController {
@Operation(summary = "创建分销提现") @Operation(summary = "创建分销提现")
@PreAuthenticated @PreAuthenticated
public CommonResult<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) { public CommonResult<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) {
return success(brokerageWithdrawService.createBrokerageWithdraw(createReqVO, getLoginUserId())); return success(brokerageWithdrawService.createBrokerageWithdraw(getLoginUserId(), createReqVO));
} }
} }

View File

@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.common.pojo.SortingField;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 下级分销统计分页 Request VO") @Schema(description = "用户 App - 下级分销统计分页 Request VO")
@Data @Data
@ -19,7 +22,9 @@ public class AppBrokerageUserChildSummaryPageReqVO extends PageParam {
@Schema(description = "排序字段", example = "userCount") @Schema(description = "排序字段", example = "userCount")
private SortingField sortingField; private SortingField sortingField;
@Schema(description = "下级的级别", example = "1") // 1 - 直接下级2 - 间接下级 @Schema(description = "下级的级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 1 - 直接下级2 - 间接下级
@NotNull(message = "下级的级别不能为空")
@Range(min = 1, max = 2, message = "下级的级别只能是 {min} 或者 {max}")
private Integer level; private Integer level;
} }

View File

@ -105,6 +105,8 @@ public class TradeOrderDO extends BaseDO {
*/ */
private Boolean commentStatus; private Boolean commentStatus;
// TODO @疯狂加一个推广人编号
// ========== 价格 + 支付基本信息 ========== // ========== 价格 + 支付基本信息 ==========
// 价格文档 - 淘宝https://open.taobao.com/docV3.htm?docId=108471&docType=1 // 价格文档 - 淘宝https://open.taobao.com/docV3.htm?docId=108471&docType=1

View File

@ -1,4 +0,0 @@
/**
* 占位文件无特殊用途
*/
package cn.iocoder.yudao.module.trade.job;

View File

@ -61,6 +61,19 @@ public interface BrokerageRecordService {
*/ */
void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId, Integer brokeragePrice, String title); void addBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId, Integer brokeragePrice, String title);
/**
* 减少佣金只针对自己
*
* @param userId 会员编号
* @param bizType 业务类型
* @param bizId 业务编号
* @param brokeragePrice 佣金
* @param title 标题
*/
default void reduceBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId, Integer brokeragePrice, String title) {
addBrokerage(userId, bizType, bizId, -brokeragePrice, title);
}
/** /**
* 取消佣金将佣金记录状态修改为已失效 * 取消佣金将佣金记录状态修改为已失效
* *
@ -134,10 +147,10 @@ public interface BrokerageRecordService {
/** /**
* 计算商品被购买后推广员可以得到的佣金 * 计算商品被购买后推广员可以得到的佣金
* *
* @param spuId 商品编号
* @param userId 用户编号 * @param userId 用户编号
* @param spuId 商品编号
* @return 用户佣金 * @return 用户佣金
*/ */
AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long spuId, Long userId); AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long userId, Long spuId);
} }

View File

@ -231,6 +231,30 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
return count; return count;
} }
/**
* 激动单条佣金记录
*
* @param record 佣金记录
* @return 解冻是否成功
*/
@Transactional(rollbackFor = Exception.class)
public boolean unfreezeRecord(BrokerageRecordDO record) {
// 更新记录状态
BrokerageRecordDO updateObj = new BrokerageRecordDO()
.setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus())
.setUnfreezeTime(LocalDateTime.now());
int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
if (updateRows == 0) {
log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId());
return false;
}
// 更新用户冻结佣金
brokerageUserService.updateFrozenPriceDecrAndPriceIncr(record.getUserId(), -record.getPrice());
log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId());
return true;
}
@Override @Override
public List<UserBrokerageSummaryRespBO> getUserBrokerageSummaryListByUserId(Collection<Long> userIds, public List<UserBrokerageSummaryRespBO> getUserBrokerageSummaryListByUserId(Collection<Long> userIds,
Integer bizType, Integer status) { Integer bizType, Integer status) {
@ -255,6 +279,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
} }
// TODO @疯狂这个要不我们先做精准的先查询自己的推广金额然后查询比该金额多的有多少人
@Override @Override
public Integer getUserRankByPrice(Long userId, LocalDateTime[] times) { public Integer getUserRankByPrice(Long userId, LocalDateTime[] times) {
AppBrokerageUserRankPageReqVO pageParam = new AppBrokerageUserRankPageReqVO().setTimes(times); AppBrokerageUserRankPageReqVO pageParam = new AppBrokerageUserRankPageReqVO().setTimes(times);
@ -291,26 +316,8 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
brokerageRecordMapper.insert(record); brokerageRecordMapper.insert(record);
} }
@Transactional(rollbackFor = Exception.class)
public boolean unfreezeRecord(BrokerageRecordDO record) {
// 更新记录状态
BrokerageRecordDO updateObj = new BrokerageRecordDO()
.setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus())
.setUnfreezeTime(LocalDateTime.now());
int updateRows = brokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
if (updateRows == 0) {
log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId());
return false;
}
// 更新用户冻结佣金
brokerageUserService.updateFrozenPriceDecrAndPriceIncr(record.getUserId(), -record.getPrice());
log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId());
return true;
}
@Override @Override
public AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long spuId, Long userId) { public AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long userId, Long spuId) {
// 1. 构建默认的返回值 // 1. 构建默认的返回值
AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO().setEnabled(false) AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO().setEnabled(false)
.setBrokerageMinPrice(0).setBrokerageMaxPrice(0); .setBrokerageMinPrice(0).setBrokerageMaxPrice(0);

View File

@ -49,11 +49,11 @@ public interface BrokerageWithdrawService {
/** /**
* 会员创建佣金提现 * 会员创建佣金提现
* *
* @param createReqVO 创建信息
* @param userId 会员用户编号 * @param userId 会员用户编号
* @param createReqVO 创建信息
* @return 佣金提现编号 * @return 佣金提现编号
*/ */
Long createBrokerageWithdraw(AppBrokerageWithdrawCreateReqVO createReqVO, Long userId); Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO);
/** /**
* 按照 userId汇总每个用户的提现 * 按照 userId汇总每个用户的提现
@ -62,7 +62,8 @@ public interface BrokerageWithdrawService {
* @param status 提现状态 * @param status 提现状态
* @return 用户提现汇总 List * @return 用户提现汇总 List
*/ */
List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds, BrokerageWithdrawStatusEnum status); List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
BrokerageWithdrawStatusEnum status);
/** /**
* 按照 userId汇总每个用户的提现 * 按照 userId汇总每个用户的提现

View File

@ -69,29 +69,27 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
} }
// 2. 更新 // 2. 更新
BrokerageWithdrawDO updateObj = new BrokerageWithdrawDO() int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
.setStatus(status.getStatus()) new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
.setAuditReason(auditReason)
.setAuditTime(LocalDateTime.now());
int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(), updateObj);
if (rows == 0) { if (rows == 0) {
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING); throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
} }
String templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_APPROVE; String templateCode;
if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) { if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) {
templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_APPROVE;
// 3.1 通过时佣金转余额 // 3.1 通过时佣金转余额
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) { if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
// todo // todo 疯狂
} }
// TODO 疯狂调用转账接口
} else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) { } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_REJECT; templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_REJECT;
// 3.2 驳回时需要退还用户佣金 // 3.2 驳回时需要退还用户佣金
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT, brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle()); String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
} else { } else {
throw new IllegalArgumentException("不支持的提现状态"); throw new IllegalArgumentException("不支持的提现状态" + status);
} }
// 4. 通知用户 // 4. 通知用户
@ -100,10 +98,8 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
.put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice())) .put("price", MoneyUtils.fenToYuanStr(withdraw.getPrice()))
.put("reason", withdraw.getAuditReason()) .put("reason", withdraw.getAuditReason())
.build(); .build();
NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO() notifyMessageSendApi.sendSingleMessageToMember(new NotifySendSingleToUserReqDTO()
.setUserId(withdraw.getUserId()) .setUserId(withdraw.getUserId()).setTemplateCode(templateCode).setTemplateParams(templateParams));
.setTemplateCode(templateCode).setTemplateParams(templateParams);
notifyMessageSendApi.sendSingleMessageToMember(reqDTO);
} }
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) { private BrokerageWithdrawDO validateBrokerageWithdrawExists(Integer id) {
@ -126,22 +122,22 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createBrokerageWithdraw(AppBrokerageWithdrawCreateReqVO createReqVO, Long userId) { public Long createBrokerageWithdraw(Long userId, AppBrokerageWithdrawCreateReqVO createReqVO) {
// 校验提现金额 // 1.1 校验提现金额
TradeConfigDO tradeConfig = validateWithdrawPrice(createReqVO.getPrice()); TradeConfigDO tradeConfig = validateWithdrawPrice(createReqVO.getPrice());
// 校验提现参数 // 1.2 校验提现参数
createReqVO.validate(validator); createReqVO.validate(validator);
// 计算手续费 // 2.1 计算手续费
Integer feePrice = calculateFeePrice(createReqVO.getPrice(), tradeConfig.getBrokerageWithdrawFeePercent()); Integer feePrice = calculateFeePrice(createReqVO.getPrice(), tradeConfig.getBrokerageWithdrawFeePercent());
// 创建佣金提现记录 // 2.2 创建佣金提现记录
BrokerageWithdrawDO withdraw = BrokerageWithdrawConvert.INSTANCE.convert(createReqVO, userId, feePrice); BrokerageWithdrawDO withdraw = BrokerageWithdrawConvert.INSTANCE.convert(createReqVO, userId, feePrice);
brokerageWithdrawMapper.insert(withdraw); brokerageWithdrawMapper.insert(withdraw);
// 创建用户佣金记录 // 3. 创建用户佣金记录
brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.WITHDRAW, String.valueOf(withdraw.getId()), // 注意佣金是否充足reduceBrokerage 已经进行校验
-createReqVO.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW.getTitle()); brokerageRecordService.reduceBrokerage(userId, BrokerageRecordBizTypeEnum.WITHDRAW, String.valueOf(withdraw.getId()),
createReqVO.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW.getTitle());
return withdraw.getId(); return withdraw.getId();
} }

View File

@ -5,6 +5,7 @@
<select id="selectSummaryPageByUserId" <select id="selectSummaryPageByUserId"
resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
SELECT bu.id, bu.bind_user_time AS brokerageTime, u.nickname, u.avatar, SELECT bu.id, bu.bind_user_time AS brokerageTime, u.nickname, u.avatar,
<!-- TODO @疯狂biz_type、status 可以通过参数传入哇? -->
(SELECT SUM(price) FROM trade_brokerage_record r (SELECT SUM(price) FROM trade_brokerage_record r
WHERE r.user_id = u.id AND biz_type = 1 AND r.status = 1 AND r.deleted = FALSE) AS brokeragePrice, WHERE r.user_id = u.id AND biz_type = 1 AND r.status = 1 AND r.deleted = FALSE) AS brokeragePrice,
(SELECT COUNT(1) FROM trade_brokerage_record r (SELECT COUNT(1) FROM trade_brokerage_record r
@ -13,6 +14,7 @@
WHERE c.bind_user_id = u.id AND c.deleted = FALSE) AS brokerageUserCount WHERE c.bind_user_id = u.id AND c.deleted = FALSE) AS brokerageUserCount
FROM member_user AS u FROM member_user AS u
JOIN trade_brokerage_user AS bu ON bu.id = u.id JOIN trade_brokerage_user AS bu ON bu.id = u.id
<!-- TODO @疯狂1bind_user_id 是不是可以先改成内存查询出 userId 的集合,然后去 in 哈2nickname 是不是可以基于查询出来的 userId 对应的 nickname 在内存里过滤,主要是避免和 member_user 链表 -->
<where> <where>
<if test="param.nickname != null and param.nickname != ''"> <if test="param.nickname != null and param.nickname != ''">
AND u.nickname LIKE concat('', #{param.nickname}, '') AND u.nickname LIKE concat('', #{param.nickname}, '')

View File

@ -9,7 +9,7 @@ spring:
exclude: exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置
- org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 # - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
- de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置