Commit a3e8b42be66757b76bfe236cd61870b42720daa8

Authored by owen
1 parent 75874035

trade: 分销业务review代码修改

Showing 15 changed files with 183 additions and 201 deletions
sql/mysql/brokerage.sql
... ... @@ -2,41 +2,50 @@
2 2 create table trade_config
3 3 (
4 4 id bigint auto_increment comment '自增主键' primary key,
5   - brokerage_enabled bit default 1 not null comment '是å¦å¯ç”¨åˆ†ä½£',
6   - brokerage_enabled_condition tinyint default 0 not null comment '分佣模å¼ï¼š1-人人分销 2-指定分销',
7   - brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模å¼: 1-没有推广人,2-新用户, 3-扫ç è¦†ç›–',
8   - brokerage_post_urls varchar(2000) default '' null comment 'åˆ†é”€æµ·æŠ¥å›¾åœ°å€æ•°ç»„',
9   - brokerage_first_percent int default 0 not null comment '一级返佣比例',
10   - brokerage_second_percent int default 0 not null comment '二级返佣比例',
11   - brokerage_withdraw_min_price int default 0 not null comment '用户æçŽ°æœ€ä½Žé‡‘é¢',
12   - brokerage_bank_names varchar(200) default '' not null comment 'æçŽ°é“¶è¡Œï¼ˆå­—å…¸ç±»åž‹=brokerage_bank_name)',
13   - brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)',
14   - brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment 'æçŽ°æ–¹å¼ï¼š1-钱包;2-银行å¡ï¼›3-微信;4-支付å®',
15   - creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者',
16   - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
17   - updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者',
18   - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
19   - deleted bit default b'0' not null comment '是å¦åˆ é™¤',
20   - tenant_id bigint default 0 not null comment '租户编å·'
  5 + brokerage_enabled bit default 1 not null comment '是å¦å¯ç”¨åˆ†ä½£',
  6 + brokerage_enabled_condition tinyint default 0 not null comment '分佣模å¼ï¼š1-人人分销 2-指定分销',
  7 + brokerage_bind_mode tinyint default 0 not null comment '分销关系绑定模å¼: 1-没有推广人,2-新用户, 3-扫ç è¦†ç›–',
  8 + brokerage_post_urls varchar(2000) default '' null comment 'åˆ†é”€æµ·æŠ¥å›¾åœ°å€æ•°ç»„',
  9 + brokerage_first_percent int default 0 not null comment '一级返佣比例',
  10 + brokerage_second_percent int default 0 not null comment '二级返佣比例',
  11 + brokerage_withdraw_min_price int default 0 not null comment '用户æçŽ°æœ€ä½Žé‡‘é¢',
  12 + brokerage_bank_names varchar(200) default '' not null comment 'æçŽ°é“¶è¡Œï¼ˆå­—å…¸ç±»åž‹=brokerage_bank_name)',
  13 + brokerage_frozen_days int default 7 not null comment '佣金冻结时间(天)',
  14 + brokerage_withdraw_type varchar(32) default '1,2,3,4' not null comment 'æçŽ°æ–¹å¼ï¼š1-钱包;2-银行å¡ï¼›3-微信;4-支付å®',
  15 + creator varchar(64) default '' null comment '创建者',
  16 + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  17 + updater varchar(64) default '' null comment '更新者',
  18 + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
  19 + deleted bit default b'0' not null comment '是å¦åˆ é™¤',
  20 + tenant_id bigint default 0 not null comment '租户编å·'
21 21 ) comment '交易中心é…ç½®';
22 22  
  23 +# alter table trade_brokerage_user
  24 +# add level int not null default 1 comment '等级' after frozen_price;
  25 +# alter table trade_brokerage_user
  26 +# add path varchar(2000) null comment '路径' after level;
  27 +
  28 +
23 29 -- 增加分销用户扩展表
24 30 create table trade_brokerage_user
25 31 (
26 32 id bigint auto_increment comment '用户编å·' primary key,
27   - bind_user_id bigint null comment '推广员编å·',
28   - bind_user_time datetime null comment '推广员绑定时间',
29   - brokerage_enabled bit default 1 not null comment 'æ˜¯å¦æˆä¸ºæŽ¨å¹¿å‘˜',
30   - brokerage_time datetime null comment 'æˆä¸ºåˆ†é”€å‘˜æ—¶é—´',
31   - price int default 0 not null comment 'å¯ç”¨ä½£é‡‘',
32   - frozen_price int default 0 not null comment '冻结佣金',
33   - creator varchar(64) collate utf8mb4_unicode_ci default '' null comment '创建者',
34   - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
35   - updater varchar(64) collate utf8mb4_unicode_ci default '' null comment '更新者',
36   - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
37   - deleted bit default b'0' not null comment '是å¦åˆ é™¤',
38   - tenant_id bigint default 0 not null comment '租户编å·'
39   -) comment '分销用户';
  33 + bind_user_id bigint null comment '推广员编å·',
  34 + bind_user_time datetime null comment '推广员绑定时间',
  35 + brokerage_enabled bit default 1 not null comment 'æ˜¯å¦æˆä¸ºæŽ¨å¹¿å‘˜',
  36 + brokerage_time datetime null comment 'æˆä¸ºåˆ†é”€å‘˜æ—¶é—´',
  37 + price int default 0 not null comment 'å¯ç”¨ä½£é‡‘',
  38 + frozen_price int default 0 not null comment '冻结佣金',
  39 + level int default 1 not null comment '等级',
  40 + path varchar(2000) null comment '路径',
  41 + creator varchar(64) default '' null comment '创建者',
  42 + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  43 + updater varchar(64) default '' null comment '更新者',
  44 + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
  45 + deleted bit default b'0' not null comment '是å¦åˆ é™¤',
  46 + tenant_id bigint default 0 not null comment '租户编å·'
  47 +)
  48 + comment '分销用户';
40 49  
41 50 create index idx_invite_user_id on trade_brokerage_user (bind_user_id) comment '推广员编å·';
42 51 create index idx_agent on trade_brokerage_user (brokerage_enabled) comment 'æ˜¯å¦æˆä¸ºæŽ¨å¹¿å‘˜';
... ... @@ -44,26 +53,26 @@ create index idx_agent on trade_brokerage_user (brokerage_enabled) comment '是å
44 53  
45 54 create table trade_brokerage_record
46 55 (
47   - id int auto_increment comment 'ç¼–å·'
  56 + id int auto_increment comment 'ç¼–å·'
48 57 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 '业务类型: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 '租户编å·'
  58 + user_id bigint not null comment '用户编å·',
  59 + biz_id varchar(64) default '' not null comment '业务编å·',
  60 + biz_type tinyint default 0 not null comment '业务类型:1-订å•,2-æçް',
  61 + title varchar(64) default '' not null comment '标题',
  62 + price int default 0 not null comment '金é¢',
  63 + total_price int default 0 not null comment '当剿€»ä½£é‡‘',
  64 + description varchar(500) default '' not null comment '说明',
  65 + status tinyint default 0 not null comment '状æ€ï¼š0-待结算,1-已结算,2-已喿¶ˆ',
  66 + frozen_days int default 0 not null comment '冻结时间(天)',
  67 + unfreeze_time datetime null comment '解冻时间',
  68 + source_user_level int not null comment 'æ¥æºç”¨æˆ·ç­‰çº§',
  69 + source_user_id bigint not null comment 'æ¥æºç”¨æˆ·ç¼–å·',
  70 + creator varchar(64) default '' null comment '创建者',
  71 + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  72 + updater varchar(64) default '' null comment '更新者',
  73 + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
  74 + deleted bit default b'0' not null comment '是å¦åˆ é™¤',
  75 + tenant_id bigint default 0 not null comment '租户编å·'
67 76 )
68 77 comment '佣金记录';
69 78  
... ... @@ -76,26 +85,26 @@ create table trade_brokerage_withdraw
76 85 (
77 86 id int auto_increment comment 'ç¼–å·'
78 87 primary key,
79   - user_id bigint not null comment '用户编å·',
80   - price int default 0 not null comment 'æçް金é¢',
81   - fee_price int default 0 not null comment 'æçŽ°æ‰‹ç»­è´¹',
82   - total_price int default 0 not null comment '当剿€»ä½£é‡‘',
83   - type tinyint default 0 not null comment 'æçŽ°ç±»åž‹ï¼š1-钱包;2-银行å¡ï¼›3-微信;4-支付å®',
84   - name varchar(64) null comment '真实姓å',
85   - account_no varchar(64) null comment 'è´¦å·',
86   - bank_name varchar(100) null comment '银行åç§°',
87   - bank_address varchar(200) null comment '开户地å€',
88   - account_qr_code_url varchar(512) null comment '收款ç ',
89   - status tinyint(2) default 0 not null comment '状æ€ï¼š0-审核中,10-审核通过 20-审核ä¸é€šè¿‡ï¼›é¢„留:11 - æçްæˆåŠŸï¼›21-æçŽ°å¤±è´¥',
90   - audit_reason varchar(128) null comment '审核驳回原因',
91   - audit_time datetime null comment '审核时间',
92   - remark varchar(500) null comment '备注',
93   - creator varchar(64) collate utf8mb4_general_ci default '' null comment '创建者',
94   - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
95   - updater varchar(64) collate utf8mb4_general_ci default '' null comment '更新者',
96   - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
97   - deleted bit default b'0' not null comment '是å¦åˆ é™¤',
98   - tenant_id bigint default 0 not null comment '租户编å·'
  88 + user_id bigint not null comment '用户编å·',
  89 + price int default 0 not null comment 'æçް金é¢',
  90 + fee_price int default 0 not null comment 'æçŽ°æ‰‹ç»­è´¹',
  91 + total_price int default 0 not null comment '当剿€»ä½£é‡‘',
  92 + type tinyint default 0 not null comment 'æçŽ°ç±»åž‹ï¼š1-钱包;2-银行å¡ï¼›3-微信;4-支付å®',
  93 + name varchar(64) null comment '真实姓å',
  94 + account_no varchar(64) null comment 'è´¦å·',
  95 + bank_name varchar(100) null comment '银行åç§°',
  96 + bank_address varchar(200) null comment '开户地å€',
  97 + account_qr_code_url varchar(512) null comment '收款ç ',
  98 + status tinyint(2) default 0 not null comment '状æ€ï¼š0-审核中,10-审核通过 20-审核ä¸é€šè¿‡ï¼›é¢„留:11 - æçްæˆåŠŸï¼›21-æçŽ°å¤±è´¥',
  99 + audit_reason varchar(128) null comment '审核驳回原因',
  100 + audit_time datetime null comment '审核时间',
  101 + remark varchar(500) null comment '备注',
  102 + creator varchar(64) default '' null comment '创建者',
  103 + create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  104 + updater varchar(64) default '' null comment '更新者',
  105 + update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment 'æ›´æ–°æ—¶é—´',
  106 + deleted bit default b'0' not null comment '是å¦åˆ é™¤',
  107 + tenant_id bigint default 0 not null comment '租户编å·'
99 108 )
100 109 comment '佣金æçް';
101 110  
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java
... ... @@ -100,6 +100,13 @@ public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {
100 100 return betweenIfPresent(column, val1, val2);
101 101 }
102 102  
  103 + public LambdaQueryWrapperX<T> findInSetIfPresent(SFunction<T, ?> column, Object val) {
  104 + if (val != null) {
  105 + return (LambdaQueryWrapperX<T>) super.apply("FIND_IN_SET({0}, " + columnToString(column) + ")", val);
  106 + }
  107 + return this;
  108 + }
  109 +
103 110 // ========== 重写父类方法,方便链式调用 ==========
104 111  
105 112 @Override
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageUserTypeEnum.java deleted
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   -// TODO @疯狂:是不是搞成层级,类似 level 这样?因为本质上,它是 1 级、2 级、3 级这样的关系哈
10   -/**
11   - * 分销用户类型枚举
12   - *
13   - * @author owen
14   - */
15   -@AllArgsConstructor
16   -@Getter
17   -public enum BrokerageUserTypeEnum implements IntArrayValuable {
18   -
19   - ALL(0, "全部"),
20   - FIRST(1, "一级推广人"),
21   - SECOND(2, "二级推广人"),
22   - ;
23   -
24   - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageUserTypeEnum::getType).toArray();
25   -
26   - /**
27   - * 类型
28   - */
29   - private final Integer type;
30   - /**
31   - * 名字
32   - */
33   - private final String name;
34   -
35   - @Override
36   - public int[] array() {
37   - return ARRAYS;
38   - }
39   -
40   -}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordBaseVO.java
... ... @@ -57,8 +57,8 @@ public class BrokerageRecordBaseVO {
57 57 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
58 58 private LocalDateTime unfreezeTime;
59 59  
60   - @Schema(description = "来源用户类型")
61   - private Integer sourceUserType;
  60 + @Schema(description = "来源用户等级")
  61 + private Integer sourceUserLevel;
62 62  
63 63 @Schema(description = "来源用户编号")
64 64 private Long sourceUserId;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/record/vo/BrokerageRecordPageReqVO.java
1 1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo;
2 2  
3 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;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
8 6 import lombok.EqualsAndHashCode;
... ... @@ -33,7 +31,6 @@ public class BrokerageRecordPageReqVO extends PageParam {
33 31 private LocalDateTime[] createTime;
34 32  
35 33 @Schema(description = "用户类型")
36   - @InEnum(value = BrokerageUserTypeEnum.class, message = "用户类型必须是 {value}")
37   - private Integer sourceUserType;
  34 + private Integer sourceUserLevel;
38 35  
39 36 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/BrokerageUserController.java
... ... @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.convert.brokerage.user.BrokerageUserConvert
9 9 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
10 10 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
11 11 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
12   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
13 12 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
14 13 import cn.iocoder.yudao.module.trade.service.brokerage.record.BrokerageRecordService;
15 14 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
... ... @@ -96,7 +95,7 @@ public class BrokerageUserController {
96 95 // 合计推广用户数量
97 96 Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
98 97 userId -> userId,
99   - userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, BrokerageUserTypeEnum.ALL));
  98 + userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
100 99  
101 100 // todo 合计提现
102 101  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/user/vo/BrokerageUserPageReqVO.java
1 1 package cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo;
2 2  
3 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;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
8 6 import lombok.EqualsAndHashCode;
... ... @@ -29,9 +27,8 @@ public class BrokerageUserPageReqVO extends PageParam {
29 27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
30 28 private LocalDateTime[] createTime;
31 29  
32   - @Schema(description = "用户类型")
33   - @InEnum(value = BrokerageUserTypeEnum.class, message = "用户类型必须是 {value}")
34   - private Integer userType;
  30 + @Schema(description = "用户等级")
  31 + private Integer level;
35 32  
36 33 @Schema(description = "绑定时间")
37 34 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/record/BrokerageRecordConvert.java
... ... @@ -35,7 +35,7 @@ public interface BrokerageRecordConvert {
35 35  
36 36 default BrokerageRecordDO convert(BrokerageUserDO user, BrokerageRecordBizTypeEnum bizType, String bizId,
37 37 Integer brokerageFrozenDays, int brokeragePrice, LocalDateTime unfreezeTime,
38   - String title, Long sourceUserId, Integer sourceUserType) {
  38 + String title, Long sourceUserId, Integer sourceUserLevel) {
39 39 brokerageFrozenDays = ObjectUtil.defaultIfNull(brokerageFrozenDays, 0);
40 40 // 不冻结时,佣金直接就是结算状态
41 41 Integer status = brokerageFrozenDays > 0
... ... @@ -47,7 +47,7 @@ public interface BrokerageRecordConvert {
47 47 .setTitle(title)
48 48 .setDescription(StrUtil.format(bizType.getDescription(), String.format("¥%.2f", brokeragePrice / 100d)))
49 49 .setStatus(status).setFrozenDays(brokerageFrozenDays).setUnfreezeTime(unfreezeTime)
50   - .setSourceUserType(sourceUserType).setSourceUserId(sourceUserId);
  50 + .setSourceUserLevel(sourceUserLevel).setSourceUserId(sourceUserId);
51 51 }
52 52  
53 53 default PageResult<BrokerageRecordRespVO> convertPage(PageResult<BrokerageRecordDO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/record/BrokerageRecordDO.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record;
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
5 5 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
6   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
7 6 import com.baomidou.mybatisplus.annotation.KeySequence;
8 7 import com.baomidou.mybatisplus.annotation.TableId;
9 8 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -83,11 +82,11 @@ public class BrokerageRecordDO extends BaseDO {
83 82 private LocalDateTime unfreezeTime;
84 83  
85 84 /**
86   - * 来源用户类型
  85 + * 来源用户等级
87 86 * <p>
88   - * 枚举 {@link BrokerageUserTypeEnum},被推广用户和 {@link #userId} 的推广层级关系
  87 + * 被推广用户和 {@link #userId} 的推广层级关系
89 88 */
90   - private Integer sourceUserType;
  89 + private Integer sourceUserLevel;
91 90 /**
92 91 * 来源用户编号
93 92 * <p>
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/user/BrokerageUserDO.java
... ... @@ -60,4 +60,12 @@ public class BrokerageUserDO extends BaseDO {
60 60 */
61 61 private Integer frozenPrice;
62 62  
  63 + /**
  64 + * 等级
  65 + */
  66 + private Integer level;
  67 + /**
  68 + * 路径
  69 + */
  70 + private String path;
63 71 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/record/BrokerageRecordMapper.java
... ... @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.record.vo.BrokerageRecordPageReqVO;
7 7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.record.BrokerageRecordDO;
8   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
9 8 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
10 9 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
11 10 import org.apache.ibatis.annotations.Mapper;
... ... @@ -24,14 +23,12 @@ import java.util.List;
24 23 public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> {
25 24  
26 25 default PageResult<BrokerageRecordDO> selectPage(BrokerageRecordPageReqVO reqVO) {
27   - boolean sourceUserTypeCondition = reqVO.getSourceUserType() != null &&
28   - !BrokerageUserTypeEnum.ALL.getType().equals(reqVO.getSourceUserType());
29 26 // 分页查询
30 27 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageRecordDO>()
31 28 .eqIfPresent(BrokerageRecordDO::getUserId, reqVO.getUserId())
32 29 .eqIfPresent(BrokerageRecordDO::getBizType, reqVO.getBizType())
33 30 .eqIfPresent(BrokerageRecordDO::getStatus, reqVO.getStatus())
34   - .eq(sourceUserTypeCondition, BrokerageRecordDO::getSourceUserType, reqVO.getSourceUserType())
  31 + .eqIfPresent(BrokerageRecordDO::getSourceUserLevel, reqVO.getSourceUserLevel())
35 32 .betweenIfPresent(BrokerageRecordDO::getCreateTime, reqVO.getCreateTime())
36 33 .orderByDesc(BrokerageRecordDO::getId));
37 34 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/user/BrokerageUserMapper.java
1 1 package cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user;
2 2  
3 3 import cn.hutool.core.lang.Assert;
4   -import cn.hutool.core.util.StrUtil;
5 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
7 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
8 7 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
9 8 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;
12 9 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
13 10 import org.apache.ibatis.annotations.Mapper;
14   -import org.apache.ibatis.annotations.Select;
  11 +
  12 +import java.util.List;
15 13  
16 14 /**
17 15 * 分销用户 Mapper
... ... @@ -21,35 +19,16 @@ import org.apache.ibatis.annotations.Select;
21 19 @Mapper
22 20 public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
23 21  
24   - default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO) {
  22 + default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO, List<Integer> levels) {
25 23 return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>()
26 24 .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled())
27 25 .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime())
28 26 .betweenIfPresent(BrokerageUserDO::getBindUserTime, reqVO.getBindUserTime())
29   - .and(reqVO.getBindUserId() != null, w -> buildBindUserCondition(reqVO, w))
  27 + .findInSetIfPresent(BrokerageUserDO::getPath, reqVO.getBindUserId())
  28 + .inIfPresent(BrokerageUserDO::getLevel, levels)
30 29 .orderByDesc(BrokerageUserDO::getId));
31 30 }
32 31  
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   - // TODO @疯狂:要不要把这个逻辑,挪到 Service 里,算出子用户有哪些,然后 IN?
40   - buildFirstBindUserCondition(reqVO.getBindUserId(), wrapper);
41   - buildSecondBindUserCondition(reqVO.getBindUserId(), wrapper.or()); // 通过 or 实现多个条件
42   - }
43   - }
44   -
45   - static void buildFirstBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> wrapper) {
46   - wrapper.eq(BrokerageUserDO::getBindUserId, bindUserId);
47   - }
48   -
49   - static void buildSecondBindUserCondition(Long bindUserId, LambdaQueryWrapper<BrokerageUserDO> wrapper) {
50   - wrapper.inSql(BrokerageUserDO::getBindUserId, StrUtil.format("SELECT id FROM trade_brokerage_user WHERE bind_user_id = {}", bindUserId));
51   - }
52   -
53 32 /**
54 33 * 更新用户可用佣金(增加)
55 34 *
... ... @@ -128,7 +107,8 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
128 107 default void updateBindUserIdAndBindUserTimeToNull(Long id) {
129 108 update(null, new LambdaUpdateWrapper<BrokerageUserDO>()
130 109 .eq(BrokerageUserDO::getId, id)
131   - .set(BrokerageUserDO::getBindUserId, null).set(BrokerageUserDO::getBindUserTime, null));
  110 + .set(BrokerageUserDO::getBindUserId, null).set(BrokerageUserDO::getBindUserTime, null)
  111 + .set(BrokerageUserDO::getLevel, 1).set(BrokerageUserDO::getPath, ""));
132 112 }
133 113  
134 114 default void updateEnabledFalseAndBrokerageTimeToNull(Long id) {
... ... @@ -137,11 +117,10 @@ public interface BrokerageUserMapper extends BaseMapperX&lt;BrokerageUserDO&gt; {
137 117 .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null));
138 118 }
139 119  
140   - default Long selectCountByBindUserId(Long bindUserId) {
141   - return selectCount(BrokerageUserDO::getBindUserId, bindUserId);
  120 + default Long selectCountByBindUserIdAndLevelIn(Long bindUserId, List<Integer> levels) {
  121 + return selectCount(new LambdaQueryWrapperX<BrokerageUserDO>()
  122 + .findInSetIfPresent(BrokerageUserDO::getPath, bindUserId)
  123 + .inIfPresent(BrokerageUserDO::getLevel, levels));
142 124 }
143 125  
144   - @Select("SELECT COUNT(1) from trade_brokerage_user WHERE bind_user_id IN (SELECT id FROM trade_brokerage_user WHERE bind_user_id = #{bindUserId})")
145   - Long selectCountByBindUserIdInBindUserId(Long bindUserId);
146   -
147 126 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/record/BrokerageRecordServiceImpl.java
... ... @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
15 15 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.record.BrokerageRecordMapper;
16 16 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
17 17 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
18   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
19 18 import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
20 19 import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
21 20 import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
... ... @@ -29,6 +28,7 @@ import javax.annotation.Resource;
29 28 import java.time.LocalDateTime;
30 29 import java.util.ArrayList;
31 30 import java.util.List;
  31 +import java.util.Objects;
32 32  
33 33 /**
34 34 * 佣金记录 Service 实现类
... ... @@ -74,7 +74,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
74 74 }
75 75 // 1.2 计算一级分佣
76 76 addBrokerage(firstUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageFirstPercent(),
77   - bizType, BrokerageUserTypeEnum.FIRST);
  77 + bizType, 1);
78 78  
79 79 // 2.1 获得二级推广员
80 80 if (firstUser.getBindUserId() == null) {
... ... @@ -86,7 +86,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
86 86 }
87 87 // 2.2 计算二级分佣
88 88 addBrokerage(secondUser, list, memberConfig.getBrokerageFrozenDays(), memberConfig.getBrokerageSecondPercent(),
89   - bizType, BrokerageUserTypeEnum.SECOND);
  89 + bizType, 2);
90 90 }
91 91  
92 92 @Override
... ... @@ -142,10 +142,10 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
142 142 * @param brokerageFrozenDays 冻结天数
143 143 * @param brokeragePercent 佣金比例
144 144 * @param bizType 业务类型
145   - * @param sourceUserType 来源用户类型
  145 + * @param sourceUserLevel 来源用户等级
146 146 */
147 147 private void addBrokerage(BrokerageUserDO user, List<BrokerageAddReqBO> list, Integer brokerageFrozenDays,
148   - Integer brokeragePercent, BrokerageRecordBizTypeEnum bizType, BrokerageUserTypeEnum sourceUserType) {
  148 + Integer brokeragePercent, BrokerageRecordBizTypeEnum bizType, Integer sourceUserLevel) {
149 149 // 1.1 处理冻结时间
150 150 LocalDateTime unfreezeTime = null;
151 151 if (brokerageFrozenDays != null && brokerageFrozenDays > 0) {
... ... @@ -157,12 +157,12 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
157 157 for (BrokerageAddReqBO item : list) {
158 158 // 计算金额
159 159 Integer fixedPrice;
160   - if (BrokerageUserTypeEnum.FIRST.equals(sourceUserType)) {
  160 + if (Objects.equals(sourceUserLevel, 1)) {
161 161 fixedPrice = item.getFirstFixedPrice();
162   - } else if (BrokerageUserTypeEnum.SECOND.equals(sourceUserType)) {
  162 + } else if (Objects.equals(sourceUserLevel, 2)) {
163 163 fixedPrice = item.getSecondFixedPrice();
164 164 } else {
165   - throw new IllegalArgumentException(StrUtil.format("来源用户({}) 不合法", sourceUserType));
  165 + throw new IllegalArgumentException(StrUtil.format("用户等级({}) 不合法", sourceUserLevel));
166 166 }
167 167 int brokeragePrice = calculatePrice(item.getBasePrice(), brokeragePercent, fixedPrice);
168 168 if (brokeragePrice <= 0) {
... ... @@ -172,7 +172,7 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService {
172 172 // 创建记录实体
173 173 records.add(BrokerageRecordConvert.INSTANCE.convert(user, bizType, item.getBizId(),
174 174 brokerageFrozenDays, brokeragePrice, unfreezeTime, item.getTitle(),
175   - item.getSourceUserId(), sourceUserType.getType()));
  175 + item.getSourceUserId(), sourceUserLevel));
176 176 }
177 177 if (CollUtil.isEmpty(records)) {
178 178 return;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.brokerage.user;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
5 5 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
6   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
7 6  
8 7 import java.util.Collection;
9 8 import java.util.List;
... ... @@ -91,10 +90,10 @@ public interface BrokerageUserService {
91 90 * 获得推广用户数量
92 91 *
93 92 * @param bindUserId 绑定的推广员编号
94   - * @param userType 用户类型
  93 + * @param level 推广用户等级
95 94 * @return 推广用户数量
96 95 */
97   - Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType);
  96 + Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level);
98 97  
99 98 /**
100 99 * 【会员】绑定推广员
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java
1 1 package cn.iocoder.yudao.module.trade.service.brokerage.user;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.lang.Assert;
4 5 import cn.hutool.core.util.BooleanUtil;
  6 +import cn.hutool.core.util.ObjectUtil;
  7 +import cn.hutool.core.util.StrUtil;
5 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 9 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
7 10 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
... ... @@ -9,17 +12,13 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
9 12 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper;
10 13 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
11 14 import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
12   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageUserTypeEnum;
13 15 import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
14 16 import org.springframework.stereotype.Service;
15 17 import org.springframework.validation.annotation.Validated;
16 18  
17 19 import javax.annotation.Resource;
18 20 import java.time.LocalDateTime;
19   -import java.util.Collection;
20   -import java.util.List;
21   -import java.util.Objects;
22   -import java.util.Optional;
  21 +import java.util.*;
23 22  
24 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 24 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
... ... @@ -51,7 +50,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
51 50  
52 51 @Override
53 52 public PageResult<BrokerageUserDO> getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) {
54   - return brokerageUserMapper.selectPage(pageReqVO);
  53 + List<Integer> levels = buildUserQueryLevels(pageReqVO.getBindUserId(), pageReqVO.getLevel());
  54 + return brokerageUserMapper.selectPage(pageReqVO, levels);
55 55 }
56 56  
57 57 @Override
... ... @@ -66,10 +66,14 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
66 66 return;
67 67 }
68 68  
  69 + // 绑定关系未发生变化
  70 + if (Objects.equals(brokerageUser.getBindUserId(), bindUserId)) {
  71 + return;
  72 + }
  73 +
69 74 // 情况二:修改推广员
70 75 validateCanBindUser(brokerageUser, bindUserId);
71   - brokerageUserMapper.updateById(new BrokerageUserDO().setId(id)
72   - .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
  76 + brokerageUserMapper.updateById(fillBindUserData(bindUserId, new BrokerageUserDO().setId(id)));
73 77 }
74 78  
75 79 @Override
... ... @@ -132,19 +136,12 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
132 136 }
133 137  
134 138 @Override
135   - public Long getBrokerageUserCountByBindUserId(Long bindUserId, BrokerageUserTypeEnum userType) {
136   - switch (userType) {
137   - case ALL: // TODO @疯狂: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;
  139 + public Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level) {
  140 + List<Integer> levels = buildUserQueryLevels(bindUserId, level);
  141 + if (CollUtil.isEmpty(levels)) {
  142 + return 0L;
147 143 }
  144 + return brokerageUserMapper.selectCountByBindUserIdAndLevelIn(bindUserId, levels);
148 145 }
149 146  
150 147 @Override
... ... @@ -171,14 +168,30 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
171 168 brokerageUser.setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now());
172 169 }
173 170 brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now());
174   - brokerageUserMapper.insert(brokerageUser);
  171 + brokerageUserMapper.insert(fillBindUserData(bindUserId, brokerageUser));
175 172 } else {
176   - brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId)
177   - .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
  173 + brokerageUserMapper.updateById(fillBindUserData(bindUserId, new BrokerageUserDO().setId(userId)));
178 174 }
179 175 return true;
180 176 }
181 177  
  178 + private BrokerageUserDO fillBindUserData(Long bindUserId, BrokerageUserDO brokerageUser) {
  179 + BrokerageUserDO bindUser = getBrokerageUser(bindUserId);
  180 +
  181 + Integer bindUserLevel = 0;
  182 + String bindUserPath = "";
  183 + if (bindUser != null) {
  184 + bindUserLevel = ObjectUtil.defaultIfNull(bindUser.getLevel(), 0);
  185 + bindUserPath = bindUser.getPath();
  186 + }
  187 +
  188 + String path = StrUtil.isEmpty(bindUserPath)
  189 + ? String.valueOf(bindUserId)
  190 + : String.format("%s,%s", bindUserPath, bindUserId);
  191 + return brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now())
  192 + .setLevel(bindUserLevel + 1).setPath(path);
  193 + }
  194 +
182 195 @Override
183 196 public Boolean getUserBrokerageEnabled(Long userId) {
184 197 // 全局分销功能是否开启
... ... @@ -231,11 +244,29 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
231 244 throw exception(BROKERAGE_BIND_SELF);
232 245 }
233 246  
234   - // TODO @疯狂:这块是不是一直查询到根节点,中间不允许出现自己;就是不能形成环。虽然目前是 2 级,但是未来可能会改多级; = = 环的话,就会存在问题哈
235   - // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!!
236   - if (Objects.equals(user.getId(), bindUser.getBindUserId())) {
  247 + // 下级不能绑定自己的上级
  248 + if (StrUtil.split(bindUser.getPath(), ",").contains(String.valueOf(user.getId()))) {
237 249 throw exception(BROKERAGE_BIND_LOOP);
238 250 }
239 251 }
240 252  
  253 + private List<Integer> buildUserQueryLevels(Long bindUserId, Integer level) {
  254 + List<Integer> levels = new ArrayList<>(2);
  255 +
  256 + BrokerageUserDO bindUser = getBrokerageUser(bindUserId);
  257 + if (bindUser == null) {
  258 + return levels;
  259 + }
  260 +
  261 + if (level == null) {
  262 + // 默认查两层
  263 + levels.add(bindUser.getLevel() + 1);
  264 + levels.add(bindUser.getLevel() + 2);
  265 + } else {
  266 + levels.add(bindUser.getLevel() + level);
  267 + }
  268 + return levels;
  269 +
  270 + }
  271 +
241 272 }
... ...