code review:分销逻辑

This commit is contained in:
YunaiV 2023-09-12 09:20:42 +08:00
parent 18c9f22560
commit 82c6354e1d
13 changed files with 46 additions and 32 deletions

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.time.LocalDateTime; import java.time.LocalDateTime;
// TODO @疯狂是不是不需要这个啦
/** /**
* 分销 API 接口 * 分销 API 接口
* *
@ -31,6 +32,7 @@ public interface BrokerageApi {
*/ */
default boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull LocalDateTime registerTime) { default boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull LocalDateTime registerTime) {
// 注册时间在30秒内的都算新用户 // 注册时间在30秒内的都算新用户
// TODO @疯狂这个要不抽到 service 里哈
boolean isNewUser = LocalDateTimeUtils.afterNow(registerTime.minusSeconds(30)); boolean isNewUser = LocalDateTimeUtils.afterNow(registerTime.minusSeconds(30));
return bindUser(userId, bindUserId, isNewUser); return bindUser(userId, bindUserId, isNewUser);
} }
@ -43,5 +45,8 @@ public interface BrokerageApi {
* @param isNewUser 是否为新用户 * @param isNewUser 是否为新用户
* @return 是否绑定 * @return 是否绑定
*/ */
boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull Boolean isNewUser); boolean bindUser(@NotNull(message = "用户编号不能为空") Long userId,
@NotNull(message = "推广员编号不能为空") Long bindUserId,
@NotNull Boolean isNewUser);
} }

View File

@ -6,6 +6,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
// TODO @疯狂是不是搞成层级类似 level 这样因为本质上它是 1 2 3 级这样的关系哈
/** /**
* 分销用户类型枚举 * 分销用户类型枚举
* *

View File

@ -55,10 +55,11 @@ public class BrokerageRecordController {
public CommonResult<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) { public CommonResult<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) {
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO); PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO);
// 查询用户信息
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId); Set<Long> userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId);
userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId)); userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId));
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds); Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 拼接数据
return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap)); return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap));
} }

View File

@ -19,7 +19,7 @@ public class AppBrokerageUserMySummaryRespVO {
@Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
private Integer frozenPrice; private Integer frozenPrice;
@Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer firstBrokerageUserCount; private Integer firstBrokerageUserCount;
@Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")

View File

@ -52,15 +52,12 @@ public interface BrokerageRecordConvert {
default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) { default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
PageResult<BrokerageRecordRespVO> result = convertPage(pageResult); PageResult<BrokerageRecordRespVO> result = convertPage(pageResult);
for (BrokerageRecordRespVO respVO : result.getList()) { for (BrokerageRecordRespVO respVO : result.getList()) {
Optional.ofNullable(userMap.get(respVO.getUserId())).ifPresent(user -> Optional.ofNullable(userMap.get(respVO.getUserId())).ifPresent(user ->
respVO.setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar())); respVO.setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar()));
Optional.ofNullable(userMap.get(respVO.getSourceUserId())).ifPresent(user -> Optional.ofNullable(userMap.get(respVO.getSourceUserId())).ifPresent(user ->
respVO.setSourceUserNickname(user.getNickname()).setSourceUserAvatar(user.getAvatar())); respVO.setSourceUserNickname(user.getNickname()).setSourceUserAvatar(user.getAvatar()));
} }
return result; return result;
} }
} }

View File

@ -35,18 +35,18 @@ public interface BrokerageUserConvert {
Map<Long, Long> brokerageUserCountMap, Map<Long, Long> brokerageUserCountMap,
Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap) { Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap) {
PageResult<BrokerageUserRespVO> result = convertPage(pageResult); PageResult<BrokerageUserRespVO> result = convertPage(pageResult);
for (BrokerageUserRespVO vo : result.getList()) { for (BrokerageUserRespVO userVO : result.getList()) {
// 用户信息 // 用户信息
copyTo(userMap.get(vo.getId()), vo); copyTo(userMap.get(userVO.getId()), userVO);
// 推广用户数量 // 推广用户数量
vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); userVO.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, userVO.getId(), 0));
// 推广订单数量推广订单金额 // 推广订单数量推广订单金额
Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(userVO.getId()));
vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)) userVO.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0))
.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));
// todo 已提现次数已提现金额 // todo 已提现次数已提现金额
vo.setWithdrawCount(0).setWithdrawPrice(0); userVO.setWithdrawCount(0).setWithdrawPrice(0);
} }
return result; return result;
} }

View File

@ -279,11 +279,9 @@ public interface TradeOrderConvert {
TradeOrderDO convert(TradeOrderRemarkReqVO reqVO); TradeOrderDO convert(TradeOrderRemarkReqVO reqVO);
default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) {
return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
.setSourceUserId(item.getUserId())
.setBasePrice(item.getPayPrice() * item.getCount()) .setBasePrice(item.getPayPrice() * item.getCount())
.setFirstFixedPrice(sku.getSubCommissionFirstPrice()) .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle()) // TODO @疯狂标题类似木晴冰雪成功购买云时代的JVM原理与实战茫农成功购买深入拆解消息队列47讲
.setSecondFixedPrice(sku.getSubCommissionSecondPrice()) .setFirstFixedPrice(sku.getSubCommissionFirstPrice()).setSecondFixedPrice(sku.getSubCommissionSecondPrice());
.setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle());
} }
} }

View File

@ -85,13 +85,13 @@ public class BrokerageRecordDO extends BaseDO {
/** /**
* 来源用户类型 * 来源用户类型
* <p> * <p>
* 枚举 {@link BrokerageUserTypeEnum} * 枚举 {@link BrokerageUserTypeEnum}被推广用户和 {@link #userId} 的推广层级关系
*/ */
private Integer sourceUserType; private Integer sourceUserType;
/** /**
* 来源用户编号 * 来源用户编号
* <p> * <p>
* 关联 MemberUserDO.id * 关联 MemberUserDO.id 字段被推广用户的编号
*/ */
private Long sourceUserId; private Long sourceUserId;

View File

@ -26,7 +26,7 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> {
default PageResult<BrokerageRecordDO> selectPage(BrokerageRecordPageReqVO reqVO) { default PageResult<BrokerageRecordDO> selectPage(BrokerageRecordPageReqVO reqVO) {
boolean sourceUserTypeCondition = reqVO.getSourceUserType() != null && boolean sourceUserTypeCondition = reqVO.getSourceUserType() != null &&
!BrokerageUserTypeEnum.ALL.getType().equals(reqVO.getSourceUserType()); !BrokerageUserTypeEnum.ALL.getType().equals(reqVO.getSourceUserType());
// 分页查询
return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageRecordDO>() return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageRecordDO>()
.eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId()) .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId())
.eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType()) .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType())
@ -54,7 +54,8 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> {
BrokerageRecordDO::getUserId, userId); BrokerageRecordDO::getUserId, userId);
} }
@Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status}") @Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record " +
"WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status}")
UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId,
@Param("bizType") Integer bizType, @Param("bizType") Integer bizType,
@Param("status") Integer status); @Param("status") Integer status);

View File

@ -36,8 +36,9 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
} else if (BrokerageUserTypeEnum.SECOND.getType().equals(reqVO.getUserType())) { } else if (BrokerageUserTypeEnum.SECOND.getType().equals(reqVO.getUserType())) {
buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper); buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper);
} else { } else {
// TODO @疯狂要不要把这个逻辑挪到 Service 算出子用户有哪些然后 IN
buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper); buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper);
buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or()); buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or()); // 通过 or 实现多个条件
} }
} }
@ -45,8 +46,8 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
wrapper.eq(BrokerageUserDO::getBindUserId, bindUserId); wrapper.eq(BrokerageUserDO::getBindUserId, bindUserId);
} }
static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> w) { static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> wrapper) {
w.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId)); wrapper.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId));
} }
/** /**
@ -142,4 +143,5 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
@Select("SELECT COUNT(1) from trade_brokerage_user WHERE bind_user_id IN (SELECT id FROM trade_brokerage_user WHERE bind_user_id = #{bindUserId})") @Select("SELECT COUNT(1) from trade_brokerage_user WHERE bind_user_id IN (SELECT id FROM trade_brokerage_user WHERE bind_user_id = #{bindUserId})")
Long selectCountByBindUserIdInBindUserId(Long bindUserId); Long selectCountByBindUserIdInBindUserId(Long bindUserId);
} }

View File

@ -5,6 +5,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/** /**
@ -30,6 +31,7 @@ public class BrokerageAddReqBO {
/** /**
* 一级佣金固定 * 一级佣金固定
*/ */
@NotNull(message = "一级佣金(固定)不能为空")
private Integer firstFixedPrice; private Integer firstFixedPrice;
/** /**
* 二级佣金固定 * 二级佣金固定
@ -39,10 +41,13 @@ public class BrokerageAddReqBO {
/** /**
* 来源用户编号 * 来源用户编号
*/ */
@NotNull(message = "来源用户编号不能为空")
private Long sourceUserId; private Long sourceUserId;
/** /**
* 佣金记录标题 * 佣金记录标题
*/ */
@NotEmpty(message = "佣金记录标题不能为空")
private String title; private String title;
} }

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage.record;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
@ -154,21 +155,24 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
int totalBrokerage = 0; int totalBrokerage = 0;
List<BrokerageRecordDO> records = new ArrayList<>(); List<BrokerageRecordDO> records = new ArrayList<>();
for (BrokerageAddReqBO item : list) { for (BrokerageAddReqBO item : list) {
Integer fixedPrice = 0; // 计算金额
Integer fixedPrice;
if (BrokerageUserTypeEnum.FIRST.equals(sourceUserType)) { if (BrokerageUserTypeEnum.FIRST.equals(sourceUserType)) {
fixedPrice = item.getFirstFixedPrice(); fixedPrice = item.getFirstFixedPrice();
} else if (BrokerageUserTypeEnum.SECOND.equals(sourceUserType)) { } else if (BrokerageUserTypeEnum.SECOND.equals(sourceUserType)) {
fixedPrice = item.getSecondFixedPrice(); fixedPrice = item.getSecondFixedPrice();
} else {
throw new IllegalArgumentException(StrUtil.format("来源用户({}) 不合法", sourceUserType));
} }
int brokeragePrice = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice);
int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice); if (brokeragePrice <= 0) {
if (brokeragePerItem <= 0) {
continue; continue;
} }
totalBrokerage += brokeragePrice;
// 创建记录实体
records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(),
brokerageFrozenDays, brokeragePerItem, unfreezeTime, item.getTitle(), brokerageFrozenDays, brokeragePrice, unfreezeTime, item.getTitle(),
item.getSourceUserId(), sourceUserType.getType())); item.getSourceUserId(), sourceUserType.getType()));
totalBrokerage += brokeragePerItem;
} }
if (CollUtil.isEmpty(records)) { if (CollUtil.isEmpty(records)) {
return; return;

View File

@ -134,7 +134,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
@Override @Override
public Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType) { public Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType) {
switch (userType) { switch (userType) {
case ALL: case ALL: // TODO @疯狂ALL 是不是不用搞个枚举默认为空就是不过滤哈~
Long firstCount = brokerageUserMapper.selectCountByBindUserId(bindUserId); Long firstCount = brokerageUserMapper.selectCountByBindUserId(bindUserId);
Long secondCount = brokerageUserMapper.selectCountByBindUserIdInBindUserId(bindUserId); Long secondCount = brokerageUserMapper.selectCountByBindUserIdInBindUserId(bindUserId);
return firstCount + secondCount; return firstCount + secondCount;
@ -183,7 +183,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
public Boolean getUserBrokerageEnabled(Long userId) { public Boolean getUserBrokerageEnabled(Long userId) {
// 全局分销功能是否开启 // 全局分销功能是否开启
TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) { if (tradeConfig == null || BooleanUtil.isFalse(tradeConfig.getBrokerageEnabled())) {
return false; return false;
} }