分销:调整推广人列表查询方式

This commit is contained in:
owen 2023-10-02 23:51:49 +08:00
parent 7fdd36d979
commit d0f0bc5888
5 changed files with 72 additions and 114 deletions

View File

@ -78,6 +78,13 @@ public class CollectionUtils {
return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toSet()); return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toSet());
} }
public static <T, K> Map<K, T> convertMapByFilter(Collection<T> from, Predicate<T> filter, Function<T, K> keyFunc) {
if (CollUtil.isEmpty(from)) {
return new HashMap<>();
}
return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v));
}
public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) { public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
if (CollUtil.isEmpty(from)) { if (CollUtil.isEmpty(from)) {
return new HashMap<>(); return new HashMap<>();

View File

@ -81,6 +81,7 @@ public interface ErrorCodeConstants {
ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1_011_007_005, "只有在注册时可以绑定"); ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1_011_007_005, "只有在注册时可以绑定");
ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人"); ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人");
ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级"); ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级");
ErrorCode BROKERAGE_USER_LEVEL_NOT_SUPPORT = new ErrorCode(1_011_007_008, "目前只支持 level 小于等于 2");
// ========== 分销提现 模块 1-011-008-000 ========== // ========== 分销提现 模块 1-011-008-000 ==========

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.trade.dal.mysql.brokerage; package cn.iocoder.yudao.module.trade.dal.mysql.brokerage;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.common.pojo.SortingField;
@ -17,6 +18,8 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -27,12 +30,12 @@ import java.util.List;
@Mapper @Mapper
public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO, List<Long> bindUserIds) { default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO, List<Long> ids) {
return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>() return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>()
.inIfPresent(BrokerageUserDO::getId, ids)
.eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled())
.betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime())
.betweenIfPresent(BrokerageUserDO::getBindUserTime, reqVO.getBindUserTime()) .betweenIfPresent(BrokerageUserDO::getBindUserTime, reqVO.getBindUserTime())
.inIfPresent(BrokerageUserDO::getBindUserId, bindUserIds)
.orderByDesc(BrokerageUserDO::getId)); .orderByDesc(BrokerageUserDO::getId));
} }
@ -124,11 +127,6 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
.set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null));
} }
default Long selectCountByBindUserIdIn(List<Long> bindUserIds) {
return selectCount(new LambdaQueryWrapperX<BrokerageUserDO>()
.inIfPresent(BrokerageUserDO::getBindUserId, bindUserIds));
}
@Select("SELECT bind_user_id AS id, COUNT(1) AS brokerageUserCount FROM trade_brokerage_user " + @Select("SELECT bind_user_id AS id, COUNT(1) AS brokerageUserCount FROM trade_brokerage_user " +
"WHERE bind_user_id IS NOT NULL AND deleted = FALSE " + "WHERE bind_user_id IS NOT NULL AND deleted = FALSE " +
"AND bind_user_time BETWEEN #{beginTime} AND #{endTime} " + "AND bind_user_time BETWEEN #{beginTime} AND #{endTime} " +
@ -143,32 +141,21 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
* *
* @param bizType 业务类型 * @param bizType 业务类型
* @param status 状态 * @param status 状态
* @param bindUserIds 绑定用户编号列表 * @param ids 用户编号列表
* @param sortingField 排序字段 * @param sortingField 排序字段
* @return 下级分销统计分页列表 * @return 下级分销统计分页列表
*/ */
IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page, IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page,
@Param("bizType") Integer bizType, @Param("bizType") Integer bizType,
@Param("status") Integer status, @Param("status") Integer status,
@Param("bindUserIds") List<Long> bindUserIds, @Param("ids") Collection<Long> ids,
@Param("sortingField") SortingField sortingField); @Param("sortingField") SortingField sortingField);
/** default List<Long> selectIdListByBindUserIdIn(Collection<Long> bindUserIds) {
* 下级分销统计不分页 return Convert.toList(Long.class,
* selectObjs(new LambdaQueryWrapperX<BrokerageUserDO>()
* @param bizType 业务类型 .select(Collections.singletonList(BrokerageUserDO::getId))
* @param status 状态 .in(BrokerageUserDO::getBindUserId, bindUserIds)));
* @param bindUserIds 绑定用户编号列表
* @param sortingField 排序字段
* @return 下级分销统计列表
*/
List<AppBrokerageUserChildSummaryRespVO> selectSummaryListByUserId(@Param("bizType") Integer bizType,
@Param("status") Integer status,
@Param("bindUserIds") List<Long> bindUserIds,
@Param("sortingField") SortingField sortingField);
default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) {
return selectList(BrokerageUserDO::getBindUserId, bindUserId);
} }
} }

View File

@ -31,10 +31,9 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMapByFilter;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
/** /**
@ -67,8 +66,12 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
@Override @Override
public PageResult<BrokerageUserDO> getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) { public PageResult<BrokerageUserDO> getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) {
List<Long> bindUserIds = buildBindUserIdsByLevel(pageReqVO.getBindUserId(), pageReqVO.getLevel()); List<Long> childIds = getChildUserIdsByLevel(pageReqVO.getBindUserId(), pageReqVO.getLevel());
return brokerageUserMapper.selectPage(pageReqVO, bindUserIds); // 绑定用户编号查询条件时没有查到下级会员直接返回空
if (pageReqVO.getBindUserId() != null && CollUtil.isEmpty(childIds)) {
return PageResult.empty();
}
return brokerageUserMapper.selectPage(pageReqVO, childIds);
} }
@Override @Override
@ -154,11 +157,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
@Override @Override
public Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level) { public Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level) {
List<Long> bindUserIds = buildBindUserIdsByLevel(bindUserId, level); List<Long> childIds = getChildUserIdsByLevel(bindUserId, level);
if (CollUtil.isEmpty(bindUserIds)) { return (long) CollUtil.size(childIds);
return 0L;
}
return brokerageUserMapper.selectCountByBindUserIdIn(bindUserIds);
} }
@Override @Override
@ -226,70 +226,29 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
@Override @Override
public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) { public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) {
// 生成推广员编号列表 // 1.1 查询下级用户编号列表
List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel()); List<Long> childIds = getChildUserIdsByLevel(userId, pageReqVO.getLevel());
if (CollUtil.isEmpty(childIds)) {
// TODO @疯狂情况一和情况二可以合并哈
// 如果有 nickname 的时候相当于提前查询 users然后 nickname 过滤掉 bindUserIds
// 之后继续使用 selectSummaryPageByUserId 里面 in bindUserIds 查询
// 情况一没有昵称过滤条件时直接使用数据库的分页查询
if (StrUtil.isBlank(pageReqVO.getNickname())) {
// 1.1 分页查询
IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId(
MyBatisUtils.buildPage(pageReqVO), BrokerageRecordBizTypeEnum.ORDER.getType(),
BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), bindUserIds, pageReqVO.getSortingField()
);
// 1.2 拼接数据并返回
List<Long> userIds = convertList(pageResult.getRecords(), AppBrokerageUserChildSummaryRespVO::getId);
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
BrokerageUserConvert.INSTANCE.copyTo(pageResult.getRecords(), userMap);
return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
}
// 情况二有昵称过滤条件时需要跨模块Member过滤
// 2.1 查询所有匹配的分销用户
List<AppBrokerageUserChildSummaryRespVO> list = brokerageUserMapper.selectSummaryListByUserId(
BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(),
bindUserIds, pageReqVO.getSortingField()
);
if (CollUtil.isEmpty(list)) {
return PageResult.empty(); return PageResult.empty();
} }
// 2.2 查出对应的用户信息 // 1.2 根据昵称过滤下级用户
List<MemberUserRespDTO> users = memberUserApi.getUserList(convertList(list, AppBrokerageUserChildSummaryRespVO::getId)); Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(memberUserApi.getUserList(childIds),
if (CollUtil.isEmpty(users)) { user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()),
return PageResult.empty(); MemberUserRespDTO::getId);
}
// 2.3 根据昵称过滤出用户编号
Map<Long, MemberUserRespDTO> userMap = users.stream()
.filter(user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()))
.collect(Collectors.toMap(MemberUserRespDTO::getId, dto -> dto));
if (CollUtil.isEmpty(userMap)) { if (CollUtil.isEmpty(userMap)) {
return PageResult.empty(); return PageResult.empty();
} }
// 2.4 根据用户编号过滤结果 // 2 分页查询
list.removeIf(vo -> !userMap.containsKey(vo.getId())); IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId(
if (CollUtil.isEmpty(list)) { MyBatisUtils.buildPage(pageReqVO), BrokerageRecordBizTypeEnum.ORDER.getType(),
return PageResult.empty(); BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), userMap.keySet(), pageReqVO.getSortingField()
} );
// 2.5 处理分页 // 3 拼接数据并返回
List<AppBrokerageUserChildSummaryRespVO> result = list.stream() BrokerageUserConvert.INSTANCE.copyTo(pageResult.getRecords(), userMap);
.skip((long) (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize()) return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
.limit(pageReqVO.getPageSize())
.collect(Collectors.toList());
if (CollUtil.isEmpty(result)) {
return PageResult.empty();
}
// 2.6 拼接数据并返回
BrokerageUserConvert.INSTANCE.copyTo(result, userMap);
return new PageResult<>(result, (long) list.size());
} }
private boolean isUserCanBind(BrokerageUserDO user) { private boolean isUserCanBind(BrokerageUserDO user) {
@ -360,24 +319,35 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
} }
/** /**
* 根据绑定用户编号获得绑定用户编号列表 * 根据绑定用户编号获得下级用户编号列表
* *
* @param bindUserId 绑定用户编号 * @param bindUserId 绑定用户编号
* @param level 绑定用户的层级 * @param level 下级用户的层级
* 如果 level 为空则查询 1+2 两个层级 * 如果 level 为空则查询 1+2 两个层级
* @return 绑定用户编号列表 * @return 下级用户编号列表
*/ */
private List<Long> buildBindUserIdsByLevel(Long bindUserId, Integer level) { private List<Long> getChildUserIdsByLevel(Long bindUserId, Integer level) {
if (bindUserId == null) { if (bindUserId == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
Assert.isTrue(level == null || level <= 2, "目前只支持 level 小于等于 2");
List<Long> bindUserIds = CollUtil.newArrayList(); // 先查第 1
if (level == null || level == 1) { List<Long> bindUserIds = brokerageUserMapper.selectIdListByBindUserIdIn(Collections.singleton(bindUserId));
bindUserIds.add(bindUserId); if (CollUtil.isEmpty(bindUserIds)) {
return Collections.emptyList();
} }
if (level == null || level == 2) {
bindUserIds.addAll(convertList(brokerageUserMapper.selectListByBindUserId(bindUserId), BrokerageUserDO::getId)); if (level == null) {
// level 为空再查第 2 并合并结果
bindUserIds.addAll(brokerageUserMapper.selectIdListByBindUserIdIn(bindUserIds));
} else if (level == 2) {
// 只查第 2
bindUserIds = brokerageUserMapper.selectIdListByBindUserIdIn(bindUserIds);
} else if (level == 1) {
// 只查第 1
return bindUserIds;
} else {
throw exception(BROKERAGE_USER_LEVEL_NOT_SUPPORT);
} }
return bindUserIds; return bindUserIds;
} }

View File

@ -2,7 +2,9 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper"> <mapper namespace="cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper">
<sql id="selectSummaryListByUserId"> <select id="selectSummaryPageByUserId"
resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
SELECT bu.id, bu.bind_user_time AS brokerageTime, SELECT bu.id, bu.bind_user_time AS brokerageTime,
(SELECT SUM(price) FROM trade_brokerage_record r (SELECT SUM(price) FROM trade_brokerage_record r
WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice, WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice,
@ -13,10 +15,10 @@
FROM trade_brokerage_user AS bu FROM trade_brokerage_user AS bu
<where> <where>
bu.deleted = false bu.deleted = false
<if test="bindUserIds != null and bindUserIds.size() > 0"> <if test="ids != null and ids.size() > 0">
and bu.bind_user_id in and bu.id in
<foreach collection="bindUserIds" open="(" item="bindUserId" separator="," close=")"> <foreach collection="ids" open="(" item="id" separator="," close=")">
#{bindUserId} #{id}
</foreach> </foreach>
</if> </if>
</where> </where>
@ -34,15 +36,6 @@
ORDER BY bu.bind_user_time DESC ORDER BY bu.bind_user_time DESC
</otherwise> </otherwise>
</choose> </choose>
</sql>
<select id="selectSummaryPageByUserId"
resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
<include refid="selectSummaryListByUserId" />
</select>
<select id="selectSummaryListByUserId"
resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
<include refid="selectSummaryListByUserId" />
</select> </select>
</mapper> </mapper>