Browse Source

trade: 分销业务绑定推广员

owen 1 year ago
parent
commit
f97c7a0f6e

+ 2 - 3
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/BrokerageApi.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.trade.api.brokerage;
 
 import cn.iocoder.yudao.module.trade.api.brokerage.dto.BrokerageUserDTO;
-import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
 
 /**
  * 分销 API 接口
@@ -23,8 +22,8 @@ public interface BrokerageApi {
      *
      * @param userId     用户编号
      * @param bindUserId 推广员编号
-     * @param bindMode   绑定模式 {@link BrokerageBindModeEnum}
+     * @param isNewUser  是否为新用户
      * @return 是否绑定
      */
-    boolean bindUser(Long userId, Long bindUserId, Integer bindMode);
+    boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser);
 }

+ 6 - 0
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 {
     // ========== 分销用户 模块 1011007000 ==========
     ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
     ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足");
+    ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己");
+    ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格");
+    ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员");
+    ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定");
+    ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人");
+    ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级");
 
 }

+ 2 - 3
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 {
     }
 
     @Override
-    public boolean bindUser(Long userId, Long bindUserId, Integer bindMode) {
-        // todo 待实现
-        return false;
+    public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) {
+        return brokerageUserService.bindUser(userId, bindUserId, isNewUser);
     }
 
 }

+ 13 - 4
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;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.*;
+import cn.iocoder.yudao.module.trade.service.brokerage.user.BrokerageUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
+import javax.annotation.Resource;
+import javax.validation.Valid;
 import java.time.LocalDateTime;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static java.util.Arrays.asList;
 
 @Tag(name = "用户 APP - 分销用户")
@@ -27,6 +28,8 @@ import static java.util.Arrays.asList;
 @Validated
 @Slf4j
 public class AppBrokerageUserController {
+    @Resource
+    private BrokerageUserService brokerageUserService;
 
     // TODO 芋艿:临时 mock =>
     @GetMapping("/get")
@@ -120,4 +123,10 @@ public class AppBrokerageUserController {
         return success(1);
     }
 
+    @PutMapping("/bind-user")
+    @Operation(summary = "绑定推广员")
+    public CommonResult<Boolean> getBrokerageUserRankByPrice(@Valid AppBrokerageUserBindReqVO reqVO) {
+        return success(brokerageUserService.bindUser(getLoginUserId(), reqVO.getBindUserId(), false));
+    }
+
 }

+ 17 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/user/AppBrokerageUserBindReqVO.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "应用 App - 绑定推广员 Request VO")
+@Data
+public class AppBrokerageUserBindReqVO extends PageParam {
+
+    @Schema(description = "推广员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotNull(message = "推广员编号不能为空")
+    private Long bindUserId;
+
+}

+ 10 - 0
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 {
      * @return 推广用户数量
      */
     Long getCountByBindUserId(Long bindUserId);
+
+    /**
+     * 【会员】绑定推广员
+     *
+     * @param userId     用户编号
+     * @param bindUserId 推广员编号
+     * @param isNewUser  是否为新用户
+     * @return 是否绑定
+     */
+    boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser);
 }

+ 90 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/user/BrokerageUserServiceImpl.java

@@ -1,21 +1,27 @@
 package cn.iocoder.yudao.module.trade.service.brokerage.user;
 
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.BooleanUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.trade.controller.admin.brokerage.user.vo.BrokerageUserPageReqVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.user.BrokerageUserDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
 import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.user.BrokerageUserMapper;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageBindModeEnum;
+import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageEnabledConditionEnum;
+import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
 
 /**
  * 分销用户 Service 实现类
@@ -29,6 +35,9 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
     @Resource
     private BrokerageUserMapper brokerageUserMapper;
 
+    @Resource
+    private TradeConfigService tradeConfigService;
+
     @Override
     public BrokerageUserDO getBrokerageUser(Long id) {
         return brokerageUserMapper.selectById(id);
@@ -105,4 +114,83 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
         return brokerageUserMapper.selectCount(BrokerageUserDO::getBindUserId, bindUserId);
     }
 
+    @Override
+    public boolean bindUser(Long userId, Long bindUserId, Boolean isNewUser) {
+        if (userId == null) {
+            throw exception(0);
+        }
+
+        boolean isInsert = false;
+        BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(userId);
+        // 分销用户不存在的情况:1.新注册 2.旧数据 3.分销功能关闭后又打开
+        if (brokerageUser == null) {
+            isInsert = true;
+            brokerageUser = new BrokerageUserDO().setId(userId).setBrokerageEnabled(false).setPrice(0).setFrozenPrice(0);
+        }
+
+        // 校验能否绑定
+        boolean validated = validateCanBindUser(brokerageUser, bindUserId, isNewUser);
+        if (!validated) {
+            return false;
+        }
+
+        if (isInsert) {
+            Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition();
+            if (BrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) {
+                // 人人分销:用户默认就有分销资格
+                brokerageUser.setBrokerageEnabled(true).setBindUserTime(LocalDateTime.now());
+            }
+            brokerageUserMapper.insert(brokerageUser);
+        } else {
+            brokerageUserMapper.updateById(new BrokerageUserDO().setId(userId)
+                    .setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now()));
+        }
+        return true;
+    }
+
+    private boolean validateCanBindUser(BrokerageUserDO user, Long bindUserId, Boolean isNewUser) {
+        if (bindUserId == null) {
+            return false;
+        }
+
+        // 校验分销功能是否启用
+        TradeConfigDO tradeConfig = tradeConfigService.getTradeConfig();
+        if (tradeConfig == null || !BooleanUtil.isTrue(tradeConfig.getBrokerageEnabled())) {
+            return false;
+        }
+
+        // 校验绑定自己
+        if (Objects.equals(user.getId(), bindUserId)) {
+            throw exception(BROKERAGE_BIND_SELF);
+        }
+
+        // 校验要绑定的用户有无推广资格
+        BrokerageUserDO bindUser = brokerageUserMapper.selectById(bindUserId);
+        if (bindUser == null || !BooleanUtil.isTrue(bindUser.getBrokerageEnabled())) {
+            throw exception(BROKERAGE_BIND_USER_NOT_ENABLED);
+        }
+
+        // 校验分佣模式:仅可后台手动设置推广员
+        if (BrokerageEnabledConditionEnum.ADMIN.getCondition().equals(tradeConfig.getBrokerageEnabledCondition())) {
+            throw exception(BROKERAGE_BIND_CONDITION_ADMIN);
+        }
+
+        // 校验分销关系绑定模式
+        if (BrokerageBindModeEnum.REGISTER.getMode().equals(tradeConfig.getBrokerageBindMode())) {
+            if (!BooleanUtil.isTrue(isNewUser)) {
+                throw exception(BROKERAGE_BIND_MODE_REGISTER); // 只有在注册时可以绑定
+            }
+        } else if (BrokerageBindModeEnum.ANYTIME.getMode().equals(tradeConfig.getBrokerageBindMode())) {
+            if (user.getBindUserId() != null) {
+                throw exception(BROKERAGE_BIND_OVERRIDE); // 已绑定了推广人
+            }
+        }
+
+        // A->B->A:下级不能绑定自己的上级,   A->B->C->A可以!!
+        if (Objects.equals(user.getId(), bindUser.getBindUserId())) {
+            throw exception(BROKERAGE_BIND_LOOP);
+        }
+        return true;
+    }
+
 }