Commit f97c7a0f6e14decc794b538d2611dd8a6a4f138f

Authored by owen
1 parent 6ef36d5c

trade: 分销业务绑定推广员

yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java
1 1 package cn.iocoder.yudao.module.trade.api.brokerage;
2 2  
3 3 import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO;
4   -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
5 4  
6 5 /**
7 6 * 分销 API 接口
... ... @@ -23,8 +22,8 @@ public interface BrokerageApi {
23 22 *
24 23 * @param userId 用户编号
25 24 * @param bindUserId 推广员编号
26   - * @param bindMode 绑定模式 {@link BrokerageBindModeEnum}
  25 + * @param isNewUser 是否为新用户
27 26 * @return 是否绑定
28 27 */
29   - boolean bindUser(Long userId, Long bindUserId, Integer bindMode);
  28 + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser);
30 29 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -78,5 +78,11 @@ public interface ErrorCodeConstants {
78 78 // ========== 分销用户 模块 1011007000 ==========
79 79 ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
80 80 ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足");
  81 + ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己");
  82 + ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格");
  83 + ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员");
  84 + ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定");
  85 + ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人");
  86 + ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级");
81 87  
82 88 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApiImpl.java
... ... @@ -25,9 +25,8 @@ public class BrokerageApiImpl implements BrokerageApi {
25 25 }
26 26  
27 27 @Override
28   - public boolean bindUser(Long userId, Long bindUserId, Integer bindMode) {
29   - // todo 待实现
30   - return false;
  28 + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) {
  29 + return brokerageUserService.bindUser(userId, bindUserId, isNewUser);
31 30 }
32 31  
33 32 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageUserController.java
... ... @@ -4,21 +4,22 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 6 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*;
  7 +import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
7 8 import io.swagger.v3.oas.annotations.Operation;
8 9 import io.swagger.v3.oas.annotations.Parameter;
9 10 import io.swagger.v3.oas.annotations.tags.Tag;
10 11 import lombok.extern.slf4j.Slf4j;
11 12 import org.springframework.format.annotation.DateTimeFormat;
12 13 import org.springframework.validation.annotation.Validated;
13   -import org.springframework.web.bind.annotation.GetMapping;
14   -import org.springframework.web.bind.annotation.RequestMapping;
15   -import org.springframework.web.bind.annotation.RequestParam;
16   -import org.springframework.web.bind.annotation.RestController;
  14 +import org.springframework.web.bind.annotation.*;
17 15  
  16 +import javax.annotation.Resource;
  17 +import javax.validation.Valid;
18 18 import java.time.LocalDateTime;
19 19  
20 20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 21 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  22 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
22 23 import static java.util.Arrays.asList;
23 24  
24 25 @Tag(name = "用户 APP - 分销用户")
... ... @@ -27,6 +28,8 @@ import static java.util.Arrays.asList;
27 28 @Validated
28 29 @Slf4j
29 30 public class AppBrokerageUserController {
  31 + @Resource
  32 + private BrokerageUserService brokerageUserService;
30 33  
31 34 // TODO 芋艿:临时 mock =>
32 35 @GetMapping("/get")
... ... @@ -120,4 +123,10 @@ public class AppBrokerageUserController {
120 123 return success(1);
121 124 }
122 125  
  126 + @PutMapping("/bind-user")
  127 + @Operation(summary = "绑定推广员")
  128 + public CommonResult<Boolean> getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) {
  129 + return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false));
  130 + }
  131 +
123 132 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Schema(description = "应用 App - 绑定推广员 Request VO")
  10 +@Data
  11 +public class AppBrokerageUserBindReqVO extends PageParam {
  12 +
  13 + @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  14 + @NotNull(message = "推广员编号不能为空")
  15 + private Long bindUserId;
  16 +
  17 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserService.java
... ... @@ -93,4 +93,14 @@ public interface BrokerageUserService {
93 93 * @return 推广用户数量
94 94 */
95 95 Long getCountByBindUserId(Long bindUserId);
  96 +
  97 + /**
  98 + * 【会员】绑定推广员
  99 + *
  100 + * @param userId 用户编号
  101 + * @param bindUserId 推广员编号
  102 + * @param isNewUser 是否为新用户
  103 + * @return 是否绑定
  104 + */
  105 + boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser);
96 106 }
... ...
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 3 import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.BooleanUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
6 7 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
  8 +import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
7 9 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper;
  10 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
  11 +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
  12 +import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
8 13 import org.springframework.stereotype.Service;
9 14 import org.springframework.validation.annotation.Validated;
10 15  
11 16 import javax.annotation.Resource;
  17 +import java.time.LocalDateTime;
12 18 import java.util.Collection;
13 19 import java.util.List;
  20 +import java.util.Objects;
14 21 import java.util.Optional;
15 22  
16 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
17   -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH;
18   -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS;
  24 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
19 25  
20 26 /**
21 27 * 分销用户 Service 实现类
... ... @@ -29,6 +35,9 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
29 35 @Resource
30 36 private BrokerageUserMapper brokerageUserMapper;
31 37  
  38 + @Resource
  39 + private TradeConfigService tradeConfigService;
  40 +
32 41 @Override
33 42 public BrokerageUserDO getBrokerageUser(Long id) {
34 43 return brokerageUserMapper.selectById(id);
... ... @@ -105,4 +114,83 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
105 114 return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId);
106 115 }
107 116  
  117 + @Override
  118 + public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) {
  119 + if (userId == null) {
  120 + throw exception(0);
  121 + }
  122 +
  123 + boolean isInsert = false;
  124 + BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId);
  125 + // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开
  126 + if (brokerageUser == null) {
  127 + isInsert = true;
  128 + brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0);
  129 + }
  130 +
  131 + // 校验能否绑定
  132 + boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser);
  133 + if (!validated) {
  134 + return false;
  135 + }
  136 +
  137 + if (isInsert) {
  138 + Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition();
  139 + if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) {
  140 + // 人人分销:用户默认就有分销资格
  141 + brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now());
  142 + }
  143 + brokerageUserMapper.insert(brokerageUser);
  144 + } else {
  145 + brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId)
  146 + .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
  147 + }
  148 + return true;
  149 + }
  150 +
  151 + private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) {
  152 + if (bindUserId == null) {
  153 + return false;
  154 + }
  155 +
  156 + // 校验分销功能是否启用
  157 + TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
  158 + if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
  159 + return false;
  160 + }
  161 +
  162 + // 校验绑定自己
  163 + if (Objects.equals(user.getId(), bindUserId)) {
  164 + throw exception(BROKERAGE_BIND_SELF);
  165 + }
  166 +
  167 + // 校验要绑定的用户有无推广资格
  168 + BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId);
  169 + if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) {
  170 + throw exception(BROKERAGE_BIND_USER_NOT_ENABLED);
  171 + }
  172 +
  173 + // 校验分佣模式:仅可后台手动设置推广员
  174 + if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) {
  175 + throw exception(BROKERAGE_BIND_CONDITION_ADMIN);
  176 + }
  177 +
  178 + // 校验分销关系绑定模式
  179 + if (BrokerageBindModeEnum.REGISTER.getMode().equals(tradeConfig.getBrokerageBindMode())) {
  180 + if (!BooleanUtil.isTrue(isNewUser)) {
  181 + throw exception(BROKERAGE_BIND_MODE_REGISTER); // 只有在注册时可以绑定
  182 + }
  183 + } else if (BrokerageBindModeEnum.ANYTIME.getMode().equals(tradeConfig.getBrokerageBindMode())) {
  184 + if (user.getBindUserId() != null) {
  185 + throw exception(BROKERAGE_BIND_OVERRIDE); // 已绑定了推广人
  186 + }
  187 + }
  188 +
  189 + // A->B->A:下级不能绑定自己的上级, A->B->C->A可以!!
  190 + if (Objects.equals(user.getId(), bindUser.getBindUserId())) {
  191 + throw exception(BROKERAGE_BIND_LOOP);
  192 + }
  193 + return true;
  194 + }
  195 +
108 196 }
... ...