Commit 18c9f22560e0a83e7af3121ee1421c1a84539674

Authored by 芋道源码
Committed by Gitee
2 parents 314dee43 77daa008

!616 完善分销功能

Merge pull request !616 from 疯狂的世界/brokerate
Showing 25 changed files with 352 additions and 100 deletions
sql/mysql/brokerage.sql
@@ -44,24 +44,26 @@ create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是å @@ -44,24 +44,26 @@ create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是å
44 44
45 create table trade_brokerage_record 45 create table trade_brokerage_record
46 ( 46 (
47 - id int auto_increment comment 'ç¼–å·' 47 + id int auto_increment comment 'ç¼–å·'
48 primary key, 48 primary key,
49 - user_id bigint not null comment '用户编å·',  
50 - biz_id varchar(64) default '' not null comment '业务编å·',  
51 - biz_type tinyint default 0 not null comment '业务类型:0-订å•,1-æçް',  
52 - title varchar(64) default '' not null comment '标题',  
53 - price int default 0 not null comment '金é¢',  
54 - total_price int default 0 not null comment '当剿€»ä½£é‡‘',  
55 - description varchar(500) default '' not null comment '说明',  
56 - status tinyint default 0 not null comment '状æ€ï¼š0-待结算,1-已结算,2-已喿¶ˆ',  
57 - frozen_days int default 0 not null comment '冻结时间(天)',  
58 - unfreeze_time datetime null comment '解冻时间',  
59 - creator varchar(64) collate utf8mb4_general_ci default '' null comment '创建者',  
60 - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',  
61 - updater varchar(64) collate utf8mb4_general_ci default '' null comment '更新者',  
62 - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',  
63 - deleted bit default b'0' not null comment '是å¦åˆ é™¤',  
64 - tenant_id bigint default 0 not null comment '租户编å·' 49 + user_id bigint not null comment '用户编å·',
  50 + biz_id varchar(64) default '' not null comment '业务编å·',
  51 + biz_type tinyint default 0 not null comment '业务类型:1-订å•,2-æçް',
  52 + title varchar(64) default '' not null comment '标题',
  53 + price int default 0 not null comment '金é¢',
  54 + total_price int default 0 not null comment '当剿€»ä½£é‡‘',
  55 + description varchar(500) default '' not null comment '说明',
  56 + status tinyint default 0 not null comment '状æ€ï¼š0-待结算,1-已结算,2-已喿¶ˆ',
  57 + frozen_days int default 0 not null comment '冻结时间(天)',
  58 + unfreeze_time datetime null comment '解冻时间',
  59 + source_user_type tinyint not null comment 'æ¥æºç”¨æˆ·ç±»åž‹ï¼š1-一级推广用户,2-二级推广用户',
  60 + source_user_id bigint not null comment 'æ¥æºç”¨æˆ·ç¼–å·',
  61 + creator varchar(64) collate utf8mb4_general_ci default '' null comment '创建者',
  62 + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  63 + updater varchar(64) collate utf8mb4_general_ci default '' null comment '更新者',
  64 + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
  65 + deleted bit default b'0' not null comment '是å¦åˆ é™¤',
  66 + tenant_id bigint default 0 not null comment '租户编å·'
65 ) 67 )
66 comment '佣金记录'; 68 comment '佣金记录';
67 69
@@ -192,9 +194,9 @@ VALUES ('åˆ†é”€ç”¨æˆ·æŽ¨å¹¿è®¢å•æŸ¥è¯¢', 'trade:brokerage-user:order-query', 3, @@ -192,9 +194,9 @@ VALUES ('åˆ†é”€ç”¨æˆ·æŽ¨å¹¿è®¢å•æŸ¥è¯¢', 'trade:brokerage-user:order-query', 3,
192 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) 194 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
193 VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0); 195 VALUES ('分销用户修改推广资格', 'trade:brokerage-user:update-brokerage-enable', 3, 4, @parentId, '', '', '', 0);
194 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) 196 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
195 -VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-brokerage-user', 3, 5, @parentId, '', '', '', 0); 197 +VALUES ('分销用户修改推广员', 'trade:brokerage-user:update-bind-user', 3, 5, @parentId, '', '', '', 0);
196 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) 198 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
197 -VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-brokerage-user', 3, 6, @parentId, '', '', '', 0); 199 +VALUES ('分销用户清除推广员', 'trade:brokerage-user:clear-bind-user', 3, 6, @parentId, '', '', '', 0);
198 200
199 -- 增加èœå•:佣金记录 201 -- 增加èœå•:佣金记录
200 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) 202 INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name)
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm
@@ -15,6 +15,9 @@ import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName} @@ -15,6 +15,9 @@ import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}
15 import static ${ServiceExceptionUtilClassName}.exception; 15 import static ${ServiceExceptionUtilClassName}.exception;
16 import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; 16 import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*;
17 17
  18 +import cn.hutool.core.collection.CollUtil;
  19 +import cn.hutool.core.collection.ListUtil;
  20 +
18 /** 21 /**
19 * ${table.classComment} Service 实现类 22 * ${table.classComment} Service 实现类
20 * 23 *
@@ -61,6 +64,9 @@ public class ${table.className}ServiceImpl implements ${table.className}Service @@ -61,6 +64,9 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
61 64
62 @Override 65 @Override
63 public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) { 66 public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) {
  67 + if (CollUtil.isEmpty(ids)) {
  68 + return ListUtil.empty();
  69 + }
64 return ${classNameVar}Mapper.selectById(id); 70 return ${classNameVar}Mapper.selectById(id);
65 } 71 }
66 72
yudao-module-mall/yudao-module-trade-api/pom.xml
@@ -21,6 +21,13 @@ @@ -21,6 +21,13 @@
21 <groupId>cn.iocoder.boot</groupId> 21 <groupId>cn.iocoder.boot</groupId>
22 <artifactId>yudao-common</artifactId> 22 <artifactId>yudao-common</artifactId>
23 </dependency> 23 </dependency>
  24 +
  25 + <!-- 参数校验 -->
  26 + <dependency>
  27 + <groupId>org.springframework.boot</groupId>
  28 + <artifactId>spring-boot-starter-validation</artifactId>
  29 + <optional>true</optional>
  30 + </dependency>
24 </dependencies> 31 </dependencies>
25 32
26 </project> 33 </project>
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java
1 package cn.iocoder.yudao.module.trade.api.brokerage; 1 package cn.iocoder.yudao.module.trade.api.brokerage;
2 2
  3 +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
3 import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO; 4 import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO;
4 5
  6 +import javax.validation.constraints.NotNull;
  7 +import java.time.LocalDateTime;
  8 +
5 /** 9 /**
6 * 分销 API 接口 10 * 分销 API 接口
7 * 11 *
@@ -18,6 +22,20 @@ public interface BrokerageApi { @@ -18,6 +22,20 @@ public interface BrokerageApi {
18 BrokerageUserDTO getBrokerageUser(Long userId); 22 BrokerageUserDTO getBrokerageUser(Long userId);
19 23
20 /** 24 /**
  25 + * 【会员】绑定推广员
  26 + *
  27 + * @param userId 用户编号
  28 + * @param bindUserId 推广员编号
  29 + * @param registerTime 用户注册时间
  30 + * @return 是否绑定
  31 + */
  32 + default boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull LocalDateTime registerTime) {
  33 + // 注册时间在30秒内的,都算新用户
  34 + boolean isNewUser = LocalDateTimeUtils.afterNow(registerTime.minusSeconds(30));
  35 + return bindUser(userId, bindUserId, isNewUser);
  36 + }
  37 +
  38 + /**
21 * 绑定推广员 39 * 绑定推广员
22 * 40 *
23 * @param userId 用户编号 41 * @param userId 用户编号
@@ -25,5 +43,5 @@ public interface BrokerageApi { @@ -25,5 +43,5 @@ public interface BrokerageApi {
25 * @param isNewUser 是否为新用户 43 * @param isNewUser 是否为新用户
26 * @return 是否绑定 44 * @return 是否绑定
27 */ 45 */
28 - boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser); 46 + boolean bindUser(@NotNull Long userId, @NotNull Long bindUserId, @NotNull Boolean isNewUser);
29 } 47 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.enums.brokerage;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * 分销用户类型枚举
  11 + *
  12 + * @author owen
  13 + */
  14 +@AllArgsConstructor
  15 +@Getter
  16 +public enum BrokerageUserTypeEnum implements IntArrayValuable {
  17 +
  18 + ALL(0, "全部"),
  19 + FIRST(1, "一级推广人"),
  20 + SECOND(2, "二级推广人"),
  21 + ;
  22 +
  23 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageUserTypeEnum::getType).toArray();
  24 +
  25 + /**
  26 + * 类型
  27 + */
  28 + private final Integer type;
  29 + /**
  30 + * 名字
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public int[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/BrokerageRecordController.java
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record; @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
  6 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
5 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; 7 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO;
6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; 8 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO;
7 import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert; 9 import cn.iocoder.yudao.module.trade.convert.brokerage.record.BrokerageRecordConvert;
@@ -19,8 +21,12 @@ import org.springframework.web.bind.annotation.RestController; @@ -19,8 +21,12 @@ import org.springframework.web.bind.annotation.RestController;
19 21
20 import javax.annotation.Resource; 22 import javax.annotation.Resource;
21 import javax.validation.Valid; 23 import javax.validation.Valid;
  24 +import java.util.Map;
  25 +import java.util.Set;
22 26
23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 27 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  28 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
24 30
25 @Tag(name = "管理后台 - 佣金记录") 31 @Tag(name = "管理后台 - 佣金记录")
26 @RestController 32 @RestController
@@ -31,6 +37,9 @@ public class BrokerageRecordController { @@ -31,6 +37,9 @@ public class BrokerageRecordController {
31 @Resource 37 @Resource
32 private BrokerageRecordService brokerageRecordService; 38 private BrokerageRecordService brokerageRecordService;
33 39
  40 + @Resource
  41 + private MemberUserApi memberUserApi;
  42 +
34 @GetMapping("/get") 43 @GetMapping("/get")
35 @Operation(summary = "获得佣金记录") 44 @Operation(summary = "获得佣金记录")
36 @Parameter(name = "id", description = "编号", required = true, example = "1024") 45 @Parameter(name = "id", description = "编号", required = true, example = "1024")
@@ -45,7 +54,12 @@ public class BrokerageRecordController { @@ -45,7 +54,12 @@ public class BrokerageRecordController {
45 @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')") 54 @PreAuthorize("@ss.hasPermission('trade:brokerage-record:query')")
46 public CommonResult<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) { 55 public CommonResult<PageResult<BrokerageRecordRespVO>> getBrokerageRecordPage(@Valid BrokerageRecordPageReqVO pageVO) {
47 PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO); 56 PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(pageVO);
48 - return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult)); 57 +
  58 + Set<Long> userIds = convertSet(pageResult.getList(), BrokerageRecordDO::getUserId);
  59 + userIds.addAll(convertList(pageResult.getList(), BrokerageRecordDO::getSourceUserId));
  60 + Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
  61 +
  62 + return success(BrokerageRecordConvert.INSTANCE.convertPage(pageResult, userMap));
49 } 63 }
50 64
51 } 65 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java
@@ -57,4 +57,9 @@ public class BrokerageRecordBaseVO { @@ -57,4 +57,9 @@ public class BrokerageRecordBaseVO {
57 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 57 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
58 private LocalDateTime unfreezeTime; 58 private LocalDateTime unfreezeTime;
59 59
  60 + @Schema(description = "来源用户类型")
  61 + private Integer sourceUserType;
  62 +
  63 + @Schema(description = "来源用户编号")
  64 + private Long sourceUserId;
60 } 65 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java
1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo; 1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
4 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 7 import lombok.Data;
6 import lombok.EqualsAndHashCode; 8 import lombok.EqualsAndHashCode;
@@ -30,4 +32,8 @@ public class BrokerageRecordPageReqVO extends PageParam { @@ -30,4 +32,8 @@ public class BrokerageRecordPageReqVO extends PageParam {
30 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 32 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
31 private LocalDateTime[] createTime; 33 private LocalDateTime[] createTime;
32 34
  35 + @Schema(description = "用户类型")
  36 + @InEnum(value = BrokerageUserTypeEnum.class, message = "用户类型必须是 {value}")
  37 + private Integer sourceUserType;
  38 +
33 } 39 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordRespVO.java
@@ -19,4 +19,19 @@ public class BrokerageRecordRespVO extends BrokerageRecordBaseVO { @@ -19,4 +19,19 @@ public class BrokerageRecordRespVO extends BrokerageRecordBaseVO {
19 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 19 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
20 private LocalDateTime createTime; 20 private LocalDateTime createTime;
21 21
  22 +
  23 + // ========== 用户信息 ==========
  24 +
  25 + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
  26 + private String userAvatar;
  27 + @Schema(description = "用户昵称", example = "李四")
  28 + private String userNickname;
  29 +
  30 +
  31 + // ========== 来源用户信息 ==========
  32 +
  33 + @Schema(description = "来源用户头像", example = "https://www.iocoder.cn/xxx.png")
  34 + private String sourceUserAvatar;
  35 + @Schema(description = "来源用户昵称", example = "李四")
  36 + private String sourceUserNickname;
22 } 37 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java
@@ -9,8 +9,9 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert @@ -9,8 +9,9 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert
9 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; 9 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; 11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
12 -import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService; 12 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
13 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; 13 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
  14 +import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
14 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; 15 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
15 import io.swagger.v3.oas.annotations.Operation; 16 import io.swagger.v3.oas.annotations.Operation;
16 import io.swagger.v3.oas.annotations.Parameter; 17 import io.swagger.v3.oas.annotations.Parameter;
@@ -42,18 +43,18 @@ public class BrokerageUserController { @@ -42,18 +43,18 @@ public class BrokerageUserController {
42 @Resource 43 @Resource
43 private MemberUserApi memberUserApi; 44 private MemberUserApi memberUserApi;
44 45
45 - @PutMapping("/update-brokerage-user") 46 + @PutMapping("/update-bind-user")
46 @Operation(summary = "修改推广员") 47 @Operation(summary = "修改推广员")
47 - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-brokerage-user')")  
48 - public CommonResult<Boolean> updateBrokerageUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) { 48 + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:update-bind-user')")
  49 + public CommonResult<Boolean> updateBindUser(@Valid @RequestBody BrokerageUserUpdateBrokerageUserReqVO updateReqVO) {
49 brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId()); 50 brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), updateReqVO.getBindUserId());
50 return success(true); 51 return success(true);
51 } 52 }
52 53
53 - @PutMapping("/clear-brokerage-user") 54 + @PutMapping("/clear-bind-user")
54 @Operation(summary = "清除推广员") 55 @Operation(summary = "清除推广员")
55 - @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-brokerage-user')")  
56 - public CommonResult<Boolean> clearBrokerageUser(@Valid @RequestBody BrokerageUserClearBrokerageUserReqVO updateReqVO) { 56 + @PreAuthorize("@ss.hasPermission('trade:brokerage-user:clear-bind-user')")
  57 + public CommonResult<Boolean> clearBindUser(@Valid @RequestBody BrokerageUserClearBrokerageUserReqVO updateReqVO) {
57 brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null); 58 brokerageUserService.updateBrokerageUserId(updateReqVO.getId(), null);
58 return success(true); 59 return success(true);
59 } 60 }
@@ -72,7 +73,8 @@ public class BrokerageUserController { @@ -72,7 +73,8 @@ public class BrokerageUserController {
72 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')") 73 @PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')")
73 public CommonResult<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) { 74 public CommonResult<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) {
74 BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id); 75 BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id);
75 - return success(BrokerageUserConvert.INSTANCE.convert(brokerageUser)); 76 + BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser);
  77 + return success(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id), respVO));
76 } 78 }
77 79
78 @GetMapping("/page") 80 @GetMapping("/page")
@@ -94,7 +96,7 @@ public class BrokerageUserController { @@ -94,7 +96,7 @@ public class BrokerageUserController {
94 // 合计推广用户数量 96 // 合计推广用户数量
95 Map<Long, Long> brokerageUserCountMap = convertMap(userIds, 97 Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
96 userId -> userId, 98 userId -> userId,
97 - userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId)); 99 + userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, BrokerageUserTypeEnum.ALL));
98 100
99 // todo 合计提现 101 // todo 合计提现
100 102
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java
1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo; 1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
4 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 7 import lombok.Data;
6 import lombok.EqualsAndHashCode; 8 import lombok.EqualsAndHashCode;
@@ -27,4 +29,11 @@ public class BrokerageUserPageReqVO extends PageParam { @@ -27,4 +29,11 @@ public class BrokerageUserPageReqVO extends PageParam {
27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 29 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
28 private LocalDateTime[] createTime; 30 private LocalDateTime[] createTime;
29 31
  32 + @Schema(description = "用户类型")
  33 + @InEnum(value = BrokerageUserTypeEnum.class, message = "用户类型必须是 {value}")
  34 + private Integer userType;
  35 +
  36 + @Schema(description = "绑定时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + private LocalDateTime[] bindUserTime;
30 } 39 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserRespVO.java
@@ -28,7 +28,7 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO { @@ -28,7 +28,7 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
28 28
29 // ========== 推广信息 ========== 29 // ========== 推广信息 ==========
30 30
31 - @Schema(description = "推广用户数量(一级)", example = "20019") 31 + @Schema(description = "推广用户数量", example = "20019")
32 private Integer brokerageUserCount; 32 private Integer brokerageUserCount;
33 @Schema(description = "推广订单数量", example = "20019") 33 @Schema(description = "推广订单数量", example = "20019")
34 private Integer brokerageOrderCount; 34 private Integer brokerageOrderCount;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO; 6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; 7 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
8 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO; 8 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
  9 +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
9 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
10 import io.swagger.v3.oas.annotations.tags.Tag; 11 import io.swagger.v3.oas.annotations.tags.Tag;
11 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
@@ -15,10 +16,12 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -15,10 +16,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
15 import org.springframework.web.bind.annotation.RequestParam; 16 import org.springframework.web.bind.annotation.RequestParam;
16 import org.springframework.web.bind.annotation.RestController; 17 import org.springframework.web.bind.annotation.RestController;
17 18
  19 +import javax.annotation.Resource;
18 import javax.validation.Valid; 20 import javax.validation.Valid;
19 import java.time.LocalDateTime; 21 import java.time.LocalDateTime;
20 22
21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  24 +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
22 import static java.util.Arrays.asList; 25 import static java.util.Arrays.asList;
23 26
24 @Tag(name = "用户 APP - 分销用户") 27 @Tag(name = "用户 APP - 分销用户")
@@ -27,6 +30,8 @@ import static java.util.Arrays.asList; @@ -27,6 +30,8 @@ import static java.util.Arrays.asList;
27 @Validated 30 @Validated
28 @Slf4j 31 @Slf4j
29 public class AppBrokerageRecordController { 32 public class AppBrokerageRecordController {
  33 + @Resource
  34 + private BrokerageUserService brokerageUserService;
30 35
31 // TODO 芋艿:临时 mock => 36 // TODO 芋艿:临时 mock =>
32 @GetMapping("/page") 37 @GetMapping("/page")
@@ -46,7 +51,7 @@ public class AppBrokerageRecordController { @@ -46,7 +51,7 @@ public class AppBrokerageRecordController {
46 @Operation(summary = "获得商品的分销金额") 51 @Operation(summary = "获得商品的分销金额")
47 public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) { 52 public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
48 AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO(); 53 AppBrokerageProductPriceRespVO respVO = new AppBrokerageProductPriceRespVO();
49 - respVO.setEnabled(true); // TODO @疯狂:需要开启分销 + 人允许分销 54 + respVO.setEnabled(brokerageUserService.getUserBrokerageEnabled(getLoginUserId()));
50 respVO.setBrokerageMinPrice(1); 55 respVO.setBrokerageMinPrice(1);
51 respVO.setBrokerageMaxPrice(2); 56 respVO.setBrokerageMaxPrice(2);
52 return success(respVO); 57 return success(respVO);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserMySummaryRespVO.java
@@ -19,7 +19,7 @@ public class AppBrokerageUserMySummaryRespVO { @@ -19,7 +19,7 @@ public class AppBrokerageUserMySummaryRespVO {
19 @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234") 19 @Schema(description = "冻结的佣金,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "234")
20 private Integer frozenPrice; 20 private Integer frozenPrice;
21 21
22 - @Schema(description = "分销用户数量(一级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 22 + @Schema(description = "分销用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
23 private Integer firstBrokerageUserCount; 23 private Integer firstBrokerageUserCount;
24 24
25 @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 25 @Schema(description = "分销用户数量(二级)", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.convert.brokerage.record;
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO; 7 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordRespVO;
7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; 8 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO;
8 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; 9 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
@@ -13,6 +14,8 @@ import org.mapstruct.factory.Mappers; @@ -13,6 +14,8 @@ import org.mapstruct.factory.Mappers;
13 14
14 import java.time.LocalDateTime; 15 import java.time.LocalDateTime;
15 import java.util.List; 16 import java.util.List;
  17 +import java.util.Map;
  18 +import java.util.Optional;
16 19
17 /** 20 /**
18 * 佣金记录 Convert 21 * 佣金记录 Convert
@@ -30,10 +33,9 @@ public interface BrokerageRecordConvert { @@ -30,10 +33,9 @@ public interface BrokerageRecordConvert {
30 33
31 PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> page); 34 PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> page);
32 35
33 - // TODO @疯狂:可能 title 不是很固化,会存在类似:沐晴成功购买《XXX JVM 实战》  
34 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId, 36 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId,
35 Integer brokerageFrozenDays, int brokeragePrice, LocalDateTime unfreezeTime, 37 Integer brokerageFrozenDays, int brokeragePrice, LocalDateTime unfreezeTime,
36 - String title) { 38 + String title, Long sourceUserId, Integer sourceUserType) {
37 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0); 39 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0);
38 // 不冻结时,佣金直接就是结算状态 40 // 不冻结时,佣金直接就是结算状态
39 Integer status = brokerageFrozenDays > 0 41 Integer status = brokerageFrozenDays > 0
@@ -43,8 +45,22 @@ public interface BrokerageRecordConvert { @@ -43,8 +45,22 @@ public interface BrokerageRecordConvert {
43 .setBizType(bizType.getType()).setBizId(bizId) 45 .setBizType(bizType.getType()).setBizId(bizId)
44 .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice()) 46 .setPrice(brokeragePrice).setTotalPrice(user.getBrokeragePrice())
45 .setTitle(title) 47 .setTitle(title)
46 - .setDescription(StrUtil.format(bizType.getDescription(), String.valueOf(brokeragePrice / 100.0)))  
47 - .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime); 48 + .setDescription(StrUtil.format(bizType.getDescription(), String.format("¥%.2f", brokeragePrice / 100d)))
  49 + .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime)
  50 + .setSourceUserType(sourceUserType).setSourceUserId(sourceUserId);
48 } 51 }
49 52
  53 + default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
  54 + PageResult<BrokerageRecordRespVO> result = convertPage(pageResult);
  55 +
  56 + for (BrokerageRecordRespVO respVO : result.getList()) {
  57 + Optional.ofNullable(userMap.get(respVO.getUserId())).ifPresent(user ->
  58 + respVO.setUserNickname(user.getNickname()).setUserAvatar(user.getAvatar()));
  59 +
  60 + Optional.ofNullable(userMap.get(respVO.getSourceUserId())).ifPresent(user ->
  61 + respVO.setSourceUserNickname(user.getNickname()).setSourceUserAvatar(user.getAvatar()));
  62 + }
  63 +
  64 + return result;
  65 + }
50 } 66 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/user/BrokerageUserConvert.java
@@ -37,20 +37,25 @@ public interface BrokerageUserConvert { @@ -37,20 +37,25 @@ public interface BrokerageUserConvert {
37 PageResult<BrokerageUserRespVO> result = convertPage(pageResult); 37 PageResult<BrokerageUserRespVO> result = convertPage(pageResult);
38 for (BrokerageUserRespVO vo : result.getList()) { 38 for (BrokerageUserRespVO vo : result.getList()) {
39 // 用户信息 39 // 用户信息
40 - Optional.ofNullable(userMap.get(vo.getId())).ifPresent(  
41 - user -> vo.setNickname(user.getNickname()).setAvatar(user.getAvatar()));  
42 - // 推广用户数量(一级) 40 + copyTo(userMap.get(vo.getId()), vo);
  41 +
  42 + // 推广用户数量
43 vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0)); 43 vo.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, vo.getId(), 0));
44 // 推广订单数量、推广订单金额 44 // 推广订单数量、推广订单金额
45 Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId())); 45 Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(vo.getId()));
46 vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0)) 46 vo.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0))
47 .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0)); 47 .setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));
48 // todo 已提现次数、已提现金额 48 // todo 已提现次数、已提现金额
49 - vo.setWithdrawCount(0);  
50 - vo.setWithdrawPrice(0); 49 + vo.setWithdrawCount(0).setWithdrawPrice(0);
51 } 50 }
52 return result; 51 return result;
53 } 52 }
54 53
  54 + default BrokerageUserRespVO copyTo(MemberUserRespDTO source, BrokerageUserRespVO target) {
  55 + Optional.ofNullable(source).ifPresent(
  56 + user -> target.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
  57 + return target;
  58 + }
  59 +
55 BrokerageUserDTO convertDTO(BrokerageUserDO brokerageUser); 60 BrokerageUserDTO convertDTO(BrokerageUserDO brokerageUser);
56 } 61 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils; @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.util.string.StrUtils;
7 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; 7 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
8 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; 8 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
9 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 9 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
10 -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;  
11 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 10 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
12 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 11 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
13 import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; 12 import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
@@ -28,9 +27,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; @@ -28,9 +27,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
28 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; 27 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
29 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 28 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
30 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 29 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  30 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
31 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; 31 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
32 import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; 32 import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
33 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 33 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
  34 +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
34 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 35 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
35 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; 36 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
36 import org.mapstruct.Mapper; 37 import org.mapstruct.Mapper;
@@ -279,8 +280,10 @@ public interface TradeOrderConvert { @@ -279,8 +280,10 @@ public interface TradeOrderConvert {
279 280
280 default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) { 281 default BrokerageAddReqBO convert(TradeOrderItemDO item, ProductSkuRespDTO sku) {
281 return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())) 282 return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId()))
  283 + .setSourceUserId(item.getUserId())
282 .setBasePrice(item.getPayPrice() * item.getCount()) 284 .setBasePrice(item.getPayPrice() * item.getCount())
283 .setFirstFixedPrice(sku.getSubCommissionFirstPrice()) 285 .setFirstFixedPrice(sku.getSubCommissionFirstPrice())
284 - .setSecondFixedPrice(sku.getSubCommissionSecondPrice()); 286 + .setSecondFixedPrice(sku.getSubCommissionSecondPrice())
  287 + .setTitle(BrokerageRecordBizTypeEnum.ORDER.getTitle());
285 } 288 }
286 } 289 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 4 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
5 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; 5 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
  6 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
7 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
@@ -32,6 +33,8 @@ public class BrokerageRecordDO extends BaseDO { @@ -32,6 +33,8 @@ public class BrokerageRecordDO extends BaseDO {
32 private Integer id; 33 private Integer id;
33 /** 34 /**
34 * 用户编号 35 * 用户编号
  36 + * <p>
  37 + * 关联 MemberUserDO.id
35 */ 38 */
36 private Long userId; 39 private Long userId;
37 /** 40 /**
@@ -79,4 +82,17 @@ public class BrokerageRecordDO extends BaseDO { @@ -79,4 +82,17 @@ public class BrokerageRecordDO extends BaseDO {
79 */ 82 */
80 private LocalDateTime unfreezeTime; 83 private LocalDateTime unfreezeTime;
81 84
  85 + /**
  86 + * 来源用户类型
  87 + * <p>
  88 + * 枚举 {@link BrokerageUserTypeEnum}
  89 + */
  90 + private Integer sourceUserType;
  91 + /**
  92 + * 来源用户编号
  93 + * <p>
  94 + * 关联 MemberUserDO.id
  95 + */
  96 + private Long sourceUserId;
  97 +
82 } 98 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO; 6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO;
7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO; 7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO;
  8 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
8 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; 9 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
9 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 10 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
10 import org.apache.ibatis.annotations.Mapper; 11 import org.apache.ibatis.annotations.Mapper;
@@ -23,10 +24,14 @@ import java.util.List; @@ -23,10 +24,14 @@ import java.util.List;
23 public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { 24 public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> {
24 25
25 default PageResult<BrokerageRecordDO> selectPage(BrokerageRecordPageReqVO reqVO) { 26 default PageResult<BrokerageRecordDO> selectPage(BrokerageRecordPageReqVO reqVO) {
  27 + boolean sourceUserTypeCondition = reqVO.getSourceUserType() != null &&
  28 + !BrokerageUserTypeEnum.ALL.getType().equals(reqVO.getSourceUserType());
  29 +
26 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageRecordDO>() 30 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageRecordDO>()
27 .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId()) 31 .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId())
28 .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType()) 32 .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType())
29 .eqIfPresent(BrokerageRecordDO::getStatus, reqVO.getStatus()) 33 .eqIfPresent(BrokerageRecordDO::getStatus, reqVO.getStatus())
  34 + .eq(sourceUserTypeCondition, BrokerageRecordDO::getSourceUserType, reqVO.getSourceUserType())
30 .betweenIfPresent(BrokerageRecordDO::getCreateTime, reqVO.getCreateTime()) 35 .betweenIfPresent(BrokerageRecordDO::getCreateTime, reqVO.getCreateTime())
31 .orderByDesc(BrokerageRecordDO::getId)); 36 .orderByDesc(BrokerageRecordDO::getId));
32 } 37 }
@@ -43,13 +48,13 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; { @@ -43,13 +48,13 @@ public interface BrokerageRecordMapper extends BaseMapperX&lt;BrokerageRecordDO&gt; {
43 .eq(BrokerageRecordDO::getStatus, status)); 48 .eq(BrokerageRecordDO::getStatus, status));
44 } 49 }
45 50
46 - default BrokerageRecordDO selectByBizTypeAndBizId(Integer bizType, String bizId) { 51 + default BrokerageRecordDO selectByBizTypeAndBizIdAndUserId(Integer bizType, String bizId, Long userId) {
47 return selectOne(BrokerageRecordDO::getBizType, bizType, 52 return selectOne(BrokerageRecordDO::getBizType, bizType,
48 - BrokerageRecordDO::getBizId, bizId); 53 + BrokerageRecordDO::getBizId, bizId,
  54 + BrokerageRecordDO::getUserId, userId);
49 } 55 }
50 56
51 - // TODO @疯狂:mysql 关键字,大写哈;这样看起来清晰点;例如说 SELECT COUNT(1)  
52 - @Select("select count(1), sum(price) from trade_brokerage_record where user_id = #{userId} and biz_type = #{bizType} and status = #{status}") 57 + @Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status}")
53 UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId, 58 UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId,
54 @Param("bizType") Integer bizType, 59 @Param("bizType") Integer bizType,
55 @Param("status") Integer status); 60 @Param("status") Integer status);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java
1 package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user; 1 package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; 8 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
8 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; 9 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  10 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
  11 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 12 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
10 import org.apache.ibatis.annotations.Mapper; 13 import org.apache.ibatis.annotations.Mapper;
  14 +import org.apache.ibatis.annotations.Select;
11 15
12 /** 16 /**
13 * 分销用户 Mapper 17 * 分销用户 Mapper
@@ -19,12 +23,32 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; { @@ -19,12 +23,32 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
19 23
20 default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO) { 24 default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO) {
21 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>() 25 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>()
22 - .eqIfPresent(BrokerageUserDO::getBindUserId, reqVO.getBindUserId())  
23 .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) 26 .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled())
24 .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) 27 .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime())
  28 + .betweenIfPresent(BrokerageUserDO::getBindUserTime, reqVO.getBindUserTime())
  29 + .and(reqVO.getBindUserId() != null, w -> buildBindUserCondition(reqVO, w))
25 .orderByDesc(BrokerageUserDO::getId)); 30 .orderByDesc(BrokerageUserDO::getId));
26 } 31 }
27 32
  33 + static void buildBindUserCondition(BrokerageUserPageReqVO reqVO, LambdaQueryWrapper<BrokerageUserDO> wrapper) {
  34 + if (BrokerageUserTypeEnum.FIRST.getType().equals(reqVO.getUserType())) {
  35 + buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper);
  36 + } else if (BrokerageUserTypeEnum.SECOND.getType().equals(reqVO.getUserType())) {
  37 + buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper);
  38 + } else {
  39 + buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper);
  40 + buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or());
  41 + }
  42 + }
  43 +
  44 + static void buildFirstBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> wrapper) {
  45 + wrapper.eq(BrokerageUserDO::getBindUserId, bindUserId);
  46 + }
  47 +
  48 + static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> w) {
  49 + w.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId));
  50 + }
  51 +
28 /** 52 /**
29 * 更新用户可用佣金(增加) 53 * 更新用户可用佣金(增加)
30 * 54 *
@@ -112,4 +136,10 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; { @@ -112,4 +136,10 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
112 .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); 136 .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null));
113 } 137 }
114 138
  139 + default Long selectCountByBindUserId(Long bindUserId) {
  140 + return selectCount(BrokerageUserDO::getBindUserId, bindUserId);
  141 + }
  142 +
  143 + @Select("SELECT COUNT(1) from trade_brokerage_user WHERE bind_user_id IN (SELECT id FROM trade_brokerage_user WHERE bind_user_id = #{bindUserId})")
  144 + Long selectCountByBindUserIdInBindUserId(Long bindUserId);
115 } 145 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/bo/BrokerageAddReqBO.java
@@ -36,4 +36,13 @@ public class BrokerageAddReqBO { @@ -36,4 +36,13 @@ public class BrokerageAddReqBO {
36 */ 36 */
37 private Integer secondFixedPrice; 37 private Integer secondFixedPrice;
38 38
  39 + /**
  40 + * 来源用户编号
  41 + */
  42 + private Long sourceUserId;
  43 +
  44 + /**
  45 + * 佣金记录标题
  46 + */
  47 + private String title;
39 } 48 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java
@@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
14 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper; 14 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper;
15 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; 15 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
16 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; 16 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
  17 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
17 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; 18 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
18 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO; 19 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
19 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService; 20 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
@@ -27,7 +28,6 @@ import javax.annotation.Resource; @@ -27,7 +28,6 @@ import javax.annotation.Resource;
27 import java.time.LocalDateTime; 28 import java.time.LocalDateTime;
28 import java.util.ArrayList; 29 import java.util.ArrayList;
29 import java.util.List; 30 import java.util.List;
30 -import java.util.function.Function;  
31 31
32 /** 32 /**
33 * 佣金记录 Service 实现类 33 * 佣金记录 Service 实现类
@@ -72,7 +72,8 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -72,7 +72,8 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
72 return; 72 return;
73 } 73 }
74 // 1.2 计算一级分佣 74 // 1.2 计算一级分佣
75 - addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(), BrokerageAddReqBO::getFirstFixedPrice, bizType); 75 + addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(),
  76 + bizType, BrokerageUserTypeEnum.FIRST);
76 77
77 // 2.1 获得二级推广员 78 // 2.1 获得二级推广员
78 if (firstUser.getBindUserId() == null) { 79 if (firstUser.getBindUserId() == null) {
@@ -83,15 +84,15 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -83,15 +84,15 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
83 return; 84 return;
84 } 85 }
85 // 2.2 计算二级分佣 86 // 2.2 计算二级分佣
86 - addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(), BrokerageAddReqBO::getSecondFixedPrice, bizType); 87 + addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(),
  88 + bizType, BrokerageUserTypeEnum.SECOND);
87 } 89 }
88 90
89 @Override 91 @Override
90 @Transactional(rollbackFor = Exception.class) 92 @Transactional(rollbackFor = Exception.class)
91 public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) { 93 public void cancelBrokerage(Long userId, BrokerageRecordBizTypeEnum bizType, String bizId) {
92 - // TODO @疯狂:userId 加进去查询,会不会更好一点?万一穿错参数;  
93 - BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizId(bizType.getType(), bizId);  
94 - if (record == null || ObjectUtil.notEqual(record.getUserId(), userId)) { 94 + BrokerageRecordDO record = brokerageRecordMapper.selectByBizTypeAndBizIdAndUserId(bizType.getType(), bizId, userId);
  95 + if (record == null) {
95 log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId); 96 log.error("[cancelBrokerage][userId({})][bizId({}) 更新为已失效失败:记录不存在]", userId, bizId);
96 return; 97 return;
97 } 98 }
@@ -139,12 +140,11 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -139,12 +140,11 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
139 * @param list 佣金增加参数列表 140 * @param list 佣金增加参数列表
140 * @param brokerageFrozenDays 冻结天数 141 * @param brokerageFrozenDays 冻结天数
141 * @param brokeragePercent 佣金比例 142 * @param brokeragePercent 佣金比例
142 - * @param fixedPriceFun 固定佣金 // TODO 疯狂:这里是不是可以直接传递 fixedPrice 呀?  
143 * @param bizType 业务类型 143 * @param bizType 业务类型
  144 + * @param sourceUserType 来源用户类型
144 */ 145 */
145 private void addBrokerage(BrokerageUserDO user, List<BrokerageAddReqBO> list, Integer brokerageFrozenDays, 146 private void addBrokerage(BrokerageUserDO user, List<BrokerageAddReqBO> list, Integer brokerageFrozenDays,
146 - Integer brokeragePercent, Function<BrokerageAddReqBO, Integer> fixedPriceFun,  
147 - BrokerageRecordBizTypeEnum bizType) { 147 + Integer brokeragePercent, BrokerageRecordBizTypeEnum bizType, BrokerageUserTypeEnum sourceUserType) {
148 // 1.1 处理冻结时间 148 // 1.1 处理冻结时间
149 LocalDateTime unfreezeTime = null; 149 LocalDateTime unfreezeTime = null;
150 if (brokerageFrozenDays != null && brokerageFrozenDays > 0) { 150 if (brokerageFrozenDays != null && brokerageFrozenDays > 0) {
@@ -154,12 +154,20 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { @@ -154,12 +154,20 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
154 int totalBrokerage = 0; 154 int totalBrokerage = 0;
155 List<BrokerageRecordDO> records = new ArrayList<>(); 155 List<BrokerageRecordDO> records = new ArrayList<>();
156 for (BrokerageAddReqBO item : list) { 156 for (BrokerageAddReqBO item : list) {
157 - int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPriceFun.apply(item)); 157 + Integer fixedPrice = 0;
  158 + if (BrokerageUserTypeEnum.FIRST.equals(sourceUserType)) {
  159 + fixedPrice = item.getFirstFixedPrice();
  160 + } else if (BrokerageUserTypeEnum.SECOND.equals(sourceUserType)) {
  161 + fixedPrice = item.getSecondFixedPrice();
  162 + }
  163 +
  164 + int brokeragePerItem = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice);
158 if (brokeragePerItem <= 0) { 165 if (brokeragePerItem <= 0) {
159 continue; 166 continue;
160 } 167 }
161 records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(), 168 records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(),
162 - brokerageFrozenDays, brokeragePerItem, unfreezeTime, bizType.getTitle())); 169 + brokerageFrozenDays, brokeragePerItem, unfreezeTime, item.getTitle(),
  170 + item.getSourceUserId(), sourceUserType.getType()));
163 totalBrokerage += brokeragePerItem; 171 totalBrokerage += brokeragePerItem;
164 } 172 }
165 if (CollUtil.isEmpty(records)) { 173 if (CollUtil.isEmpty(records)) {
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO; 4 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
5 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO; 5 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  6 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
6 7
7 import java.util.Collection; 8 import java.util.Collection;
8 import java.util.List; 9 import java.util.List;
@@ -86,14 +87,14 @@ public interface BrokerageUserService { @@ -86,14 +87,14 @@ public interface BrokerageUserService {
86 */ 87 */
87 void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice); 88 void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice);
88 89
89 - // TODO @疯狂:这个后面可能要支持下,二级  
90 /** 90 /**
91 - * 获得推广用户数量(一级) 91 + * 获得推广用户数量
92 * 92 *
93 * @param bindUserId 绑定的推广员编号 93 * @param bindUserId 绑定的推广员编号
  94 + * @param userType 用户类型
94 * @return 推广用户数量 95 * @return 推广用户数量
95 */ 96 */
96 - Long getBrokerageUserCountByBindUserId(Long bindUserId); 97 + Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType);
97 98
98 /** 99 /**
99 * 【会员】绑定推广员 100 * 【会员】绑定推广员
@@ -105,4 +106,11 @@ public interface BrokerageUserService { @@ -105,4 +106,11 @@ public interface BrokerageUserService {
105 */ 106 */
106 boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser); 107 boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser);
107 108
  109 + /**
  110 + * 获取用户是否有分销资格
  111 + *
  112 + * @param userId 用户编号
  113 + * @return 是否有分销资格
  114 + */
  115 + Boolean getUserBrokerageEnabled(Long userId);
108 } 116 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
9 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper; 9 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper;
10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum; 10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum; 11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
  12 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
12 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; 13 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
13 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
14 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
@@ -56,7 +57,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -56,7 +57,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
56 @Override 57 @Override
57 public void updateBrokerageUserId(Long id, Long bindUserId) { 58 public void updateBrokerageUserId(Long id, Long bindUserId) {
58 // 校验存在 59 // 校验存在
59 - validateBrokerageUserExists(id); 60 + BrokerageUserDO brokerageUser = validateBrokerageUserExists(id);
60 61
61 // 情况一:清除推广员 62 // 情况一:清除推广员
62 if (bindUserId == null) { 63 if (bindUserId == null) {
@@ -66,7 +67,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -66,7 +67,7 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
66 } 67 }
67 68
68 // 情况二:修改推广员 69 // 情况二:修改推广员
69 - // TODO @疯狂:要复用一些 validateCanBindUser 的校验哈; 70 + validateCanBindUser(brokerageUser, bindUserId);
70 brokerageUserMapper.updateById(new BrokerageUserDO().setId(id) 71 brokerageUserMapper.updateById(new BrokerageUserDO().setId(id)
71 .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())); 72 .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
72 } 73 }
@@ -85,10 +86,13 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -85,10 +86,13 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
85 } 86 }
86 } 87 }
87 88
88 - private void validateBrokerageUserExists(Long id) {  
89 - if (brokerageUserMapper.selectById(id) == null) { 89 + private BrokerageUserDO validateBrokerageUserExists(Long id) {
  90 + BrokerageUserDO brokerageUserDO = brokerageUserMapper.selectById(id);
  91 + if (brokerageUserDO == null) {
90 throw exception(BROKERAGE_USER_NOT_EXISTS); 92 throw exception(BROKERAGE_USER_NOT_EXISTS);
91 } 93 }
  94 +
  95 + return brokerageUserDO;
92 } 96 }
93 97
94 @Override 98 @Override
@@ -128,19 +132,23 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -128,19 +132,23 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
128 } 132 }
129 133
130 @Override 134 @Override
131 - public Long getBrokerageUserCountByBindUserId(Long bindUserId) {  
132 - // TODO @疯狂:mapper 封装下哈;不直接在 service 调用这种基础 mapper 的基础方法  
133 - return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId); 135 + public Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType) {
  136 + switch (userType) {
  137 + case ALL:
  138 + Long firstCount = brokerageUserMapper.selectCountByBindUserId(bindUserId);
  139 + Long secondCount = brokerageUserMapper.selectCountByBindUserIdInBindUserId(bindUserId);
  140 + return firstCount + secondCount;
  141 + case FIRST:
  142 + return brokerageUserMapper.selectCountByBindUserId(bindUserId);
  143 + case SECOND:
  144 + return brokerageUserMapper.selectCountByBindUserIdInBindUserId(bindUserId);
  145 + default:
  146 + return 0L;
  147 + }
134 } 148 }
135 149
136 - // TODO @疯狂:因为现在 user 会存在使用验证码直接注册,所以 isNewUser 不太好传递;我们是不是可以约定绑定的时间,createTime 在 30 秒内,就认为新用户;  
137 @Override 150 @Override
138 public boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser) { 151 public boolean bindBrokerageUser(Long userId, Long bindUserId, Boolean isNewUser) {
139 - // TODO @疯狂:userId 为空,搞到参数校验里哇;  
140 - if (userId == null) {  
141 - throw exception(0);  
142 - }  
143 -  
144 // 1. 获得分销用户 152 // 1. 获得分销用户
145 boolean isNewBrokerageUser = false; 153 boolean isNewBrokerageUser = false;
146 BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId); 154 BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId);
@@ -149,20 +157,20 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -149,20 +157,20 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
149 brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0); 157 brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0);
150 } 158 }
151 159
152 - // 2.1 校验能否绑定  
153 - boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser); 160 + // 2.1 校验是否能绑定用户
  161 + boolean validated = isUserCanBind(brokerageUser, isNewUser);
154 if (!validated) { 162 if (!validated) {
155 return false; 163 return false;
156 } 164 }
157 -  
158 - // 2.2 绑定用户 165 + // 2.3 校验能否绑定
  166 + validateCanBindUser(brokerageUser, bindUserId);
  167 + // 2.3 绑定用户
159 if (isNewBrokerageUser) { 168 if (isNewBrokerageUser) {
160 Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition(); 169 Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition();
161 if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销:用户默认就有分销资格 170 if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销:用户默认就有分销资格
162 - // TODO @疯狂:应该设置下 brokerageTime,而不是 bindUserTime  
163 - brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now()); 171 + brokerageUser.setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now());
164 } 172 }
165 - // TODO @疯狂:这里是不是要设置 bindUserId、bindUserTime 字段哈; 173 + brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now());
166 brokerageUserMapper.insert(brokerageUser); 174 brokerageUserMapper.insert(brokerageUser);
167 } else { 175 } else {
168 brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId) 176 brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId)
@@ -171,30 +179,27 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -171,30 +179,27 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
171 return true; 179 return true;
172 } 180 }
173 181
174 - // TODO @疯狂:validate 方法,一般不返回 true false,而是抛出异常;如果要返回 true false 这种,方法名字可以改成 isUserCanBind  
175 - private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) {  
176 - // TODO @疯狂:bindUserId 为空,搞到参数校验里哇;  
177 - if (bindUserId == null) { 182 + @Override
  183 + public Boolean getUserBrokerageEnabled(Long userId) {
  184 + // 全局分销功能是否开启
  185 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
  186 + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
178 return false; 187 return false;
179 } 188 }
180 189
  190 + // 用户是否有分销资格
  191 + return Optional.ofNullable(getBrokerageUser(userId))
  192 + .map(BrokerageUserDO::getBrokerageEnabled)
  193 + .orElse(false);
  194 + }
  195 +
  196 + private boolean isUserCanBind(BrokerageUserDO user, Boolean isNewUser) {
181 // 校验分销功能是否启用 197 // 校验分销功能是否启用
182 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig(); 198 TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
183 - if (tradeConfig == null || BooleanUtil.isFalse(tradeConfig.getBrokerageEnabled())) { 199 + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
184 return false; 200 return false;
185 } 201 }
186 202
187 - // 校验绑定自己  
188 - if (Objects.equals(user.getId(), bindUserId)) {  
189 - throw exception(BROKERAGE_BIND_SELF);  
190 - }  
191 -  
192 - // 校验要绑定的用户有无推广资格  
193 - BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId);  
194 - if (bindUser == null || BooleanUtil.isFalse(bindUser.getBrokerageEnabled())) {  
195 - throw exception(BROKERAGE_BIND_USER_NOT_ENABLED);  
196 - }  
197 -  
198 // 校验分佣模式:仅可后台手动设置推广员 203 // 校验分佣模式:仅可后台手动设置推广员
199 if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) { 204 if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) {
200 throw exception(BROKERAGE_BIND_CONDITION_ADMIN); 205 throw exception(BROKERAGE_BIND_CONDITION_ADMIN);
@@ -211,12 +216,26 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { @@ -211,12 +216,26 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
211 } 216 }
212 } 217 }
213 218
  219 + return true;
  220 + }
  221 +
  222 + private void validateCanBindUser(BrokerageUserDO user, Long bindUserId) {
  223 + // 校验要绑定的用户有无推广资格
  224 + BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId);
  225 + if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) {
  226 + throw exception(BROKERAGE_BIND_USER_NOT_ENABLED);
  227 + }
  228 +
  229 + // 校验绑定自己
  230 + if (Objects.equals(user.getId(), bindUserId)) {
  231 + throw exception(BROKERAGE_BIND_SELF);
  232 + }
  233 +
214 // TODO @疯狂:这块是不是一直查询到根节点,中间不允许出现自己;就是不能形成环。虽然目前是 2 级,但是未来可能会改多级; = = 环的话,就会存在问题哈 234 // TODO @疯狂:这块是不是一直查询到根节点,中间不允许出现自己;就是不能形成环。虽然目前是 2 级,但是未来可能会改多级; = = 环的话,就会存在问题哈
215 // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!! 235 // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!!
216 if (Objects.equals(user.getId(), bindUser.getBindUserId())) { 236 if (Objects.equals(user.getId(), bindUser.getBindUserId())) {
217 throw exception(BROKERAGE_BIND_LOOP); 237 throw exception(BROKERAGE_BIND_LOOP);
218 } 238 }
219 - return true;  
220 } 239 }
221 240
222 } 241 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
1 package cn.iocoder.yudao.module.member.service.user; 1 package cn.iocoder.yudao.module.member.service.user;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
3 import cn.hutool.core.util.IdUtil; 5 import cn.hutool.core.util.IdUtil;
4 import cn.hutool.core.util.ObjectUtil; 6 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
@@ -103,6 +105,9 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -103,6 +105,9 @@ public class MemberUserServiceImpl implements MemberUserService {
103 105
104 @Override 106 @Override
105 public List<MemberUserDO> getUserList(Collection<Long> ids) { 107 public List<MemberUserDO> getUserList(Collection<Long> ids) {
  108 + if (CollUtil.isEmpty(ids)) {
  109 + return ListUtil.empty();
  110 + }
106 return memberUserMapper.selectBatchIds(ids); 111 return memberUserMapper.selectBatchIds(ids);
107 } 112 }
108 113