|
|
@@ -0,0 +1,579 @@
|
|
|
+package com.fs.distribution.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.fs.distribution.constant.DistributionConstants;
|
|
|
+import com.fs.distribution.domain.*;
|
|
|
+import com.fs.distribution.dto.*;
|
|
|
+import com.fs.distribution.mapper.*;
|
|
|
+import com.fs.distribution.service.DistributionService;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 分销核心业务实现
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class DistributionServiceImpl implements DistributionService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DistributionUserRelationMapper relationMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DistributionAccountMapper accountMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DistributionCommissionRecordMapper commissionRecordMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DistributionWithdrawRecordMapper withdrawRecordMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private DistributionConfigMapper configMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 注册成功后绑定分销关系
|
|
|
+ *
|
|
|
+ * 核心规则:
|
|
|
+ * 1. 只能绑定一次
|
|
|
+ * 2. 不能绑定自己
|
|
|
+ * 3. 邀请人必须存在
|
|
|
+ * 4. 当前用户绑定 parentUserId
|
|
|
+ * 5. 当前用户的 grandParentUserId = 邀请人的 parentUserId
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void bindRelation(BindRelationRequest request) {
|
|
|
+ if (request == null || request.getUserId() == null) {
|
|
|
+ throw new RuntimeException("用户ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ Long userId = request.getUserId();
|
|
|
+ Long inviteUserId = request.getInviteUserId();
|
|
|
+
|
|
|
+ // 先保证当前用户有分销账户
|
|
|
+ createAccountIfAbsent(userId);
|
|
|
+
|
|
|
+ // 如果没有邀请人,也创建一条空关系,方便后续查询
|
|
|
+ if (inviteUserId == null) {
|
|
|
+// createEmptyRelationIfAbsent(userId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 不能绑定自己
|
|
|
+ if (userId.equals(inviteUserId)) {
|
|
|
+ throw new RuntimeException("不能绑定自己为邀请人");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当前用户是否已经有关系
|
|
|
+ DistributionUserRelation currentRelation = relationMapper.selectByUserId(userId);
|
|
|
+ if (currentRelation != null && currentRelation.getParentUserId() != null && currentRelation.getParentUserId() > 0) {
|
|
|
+ // 已绑定过上级,不允许重复绑定
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询邀请人的关系
|
|
|
+ DistributionUserRelation inviterRelation = relationMapper.selectByUserId(inviteUserId);
|
|
|
+
|
|
|
+ // 邀请人必须有账户,没有则创建
|
|
|
+ createAccountIfAbsent(inviteUserId);
|
|
|
+
|
|
|
+ Long grandParentUserId = null;
|
|
|
+
|
|
|
+ if (inviterRelation != null && inviterRelation.getParentUserId() != null) {
|
|
|
+ grandParentUserId = inviterRelation.getParentUserId();
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionUserRelation relation = new DistributionUserRelation();
|
|
|
+ relation.setUserId(userId);
|
|
|
+ relation.setParentUserId(inviteUserId);
|
|
|
+ relation.setGrandParentUserId(grandParentUserId);
|
|
|
+ relation.setBindType(request.getBindType() == null
|
|
|
+ ? DistributionConstants.BIND_TYPE_REGISTER
|
|
|
+ : request.getBindType());
|
|
|
+ relation.setStatus(DistributionConstants.RELATION_NORMAL);
|
|
|
+
|
|
|
+ if (currentRelation == null) {
|
|
|
+ relationMapper.insertRelation(relation);
|
|
|
+ } else {
|
|
|
+ relationMapper.updateRelation(relation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单支付成功后生成佣金
|
|
|
+ *
|
|
|
+ * 注意:
|
|
|
+ * 1. 必须幂等,同一个订单不能重复生成佣金
|
|
|
+ * 2. 佣金先进入冻结状态
|
|
|
+ * 3. 增加分销员 frozenCommission 和 totalCommission
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void createCommissionAfterPay(CreateCommissionRequest request) {
|
|
|
+ if (request == null) {
|
|
|
+ throw new RuntimeException("分佣参数不能为空");
|
|
|
+ }
|
|
|
+ if (request.getOrderId() == null || request.getBuyerUserId() == null) {
|
|
|
+ throw new RuntimeException("订单ID或购买人ID不能为空");
|
|
|
+ }
|
|
|
+ if (request.getCommissionBaseAmount() == null || request.getCommissionBaseAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionConfig config = configMapper.selectConfig();
|
|
|
+ if (config == null || config.getEnableStatus() == null || config.getEnableStatus() != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 幂等判断:同一个订单如果已经生成过佣金,则不再重复生成
|
|
|
+ int existCount = commissionRecordMapper.countByOrderId(request.getOrderId());
|
|
|
+ if (existCount > 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionUserRelation buyerRelation = relationMapper.selectByUserId(request.getBuyerUserId());
|
|
|
+ if (buyerRelation == null || buyerRelation.getStatus() == null || buyerRelation.getStatus() != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal orderAmount = request.getCommissionBaseAmount();
|
|
|
+
|
|
|
+ // 一级分佣
|
|
|
+ if (buyerRelation.getParentUserId() != null && buyerRelation.getParentUserId() > 0) {
|
|
|
+ createSingleCommission(
|
|
|
+ request,
|
|
|
+ buyerRelation.getParentUserId(),
|
|
|
+ DistributionConstants.COMMISSION_LEVEL_ONE,
|
|
|
+ config.getLevelOneRate(),
|
|
|
+ orderAmount
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 二级分佣
|
|
|
+ if (buyerRelation.getGrandParentUserId() != null && buyerRelation.getGrandParentUserId() > 0) {
|
|
|
+ createSingleCommission(
|
|
|
+ request,
|
|
|
+ buyerRelation.getGrandParentUserId(),
|
|
|
+ DistributionConstants.COMMISSION_LEVEL_TWO,
|
|
|
+ config.getLevelTwoRate(),
|
|
|
+ orderAmount
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建单条佣金记录
|
|
|
+ */
|
|
|
+ private void createSingleCommission(CreateCommissionRequest request,
|
|
|
+ Long distributorUserId,
|
|
|
+ Integer commissionLevel,
|
|
|
+ BigDecimal rate,
|
|
|
+ BigDecimal orderAmount) {
|
|
|
+ if (distributorUserId == null || distributorUserId <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (rate == null || rate.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 防止自己给自己分佣
|
|
|
+ if (distributorUserId.equals(request.getBuyerUserId())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保分销账户存在
|
|
|
+ createAccountIfAbsent(distributorUserId);
|
|
|
+
|
|
|
+ DistributionAccount account = accountMapper.selectByUserId(distributorUserId);
|
|
|
+ if (account == null || account.getStatus() == null || account.getStatus() != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal commissionAmount = orderAmount
|
|
|
+ .multiply(rate)
|
|
|
+ .divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ if (commissionAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionCommissionRecord record = new DistributionCommissionRecord();
|
|
|
+ record.setOrderId(request.getOrderId());
|
|
|
+ record.setOrderNo(request.getOrderNo());
|
|
|
+ record.setBuyerUserId(request.getBuyerUserId());
|
|
|
+ record.setDistributorUserId(distributorUserId);
|
|
|
+ record.setCommissionLevel(commissionLevel);
|
|
|
+ record.setOrderAmount(orderAmount);
|
|
|
+ record.setCommissionRate(rate);
|
|
|
+ record.setCommissionAmount(commissionAmount);
|
|
|
+ record.setStatus(DistributionConstants.COMMISSION_FROZEN);
|
|
|
+
|
|
|
+ commissionRecordMapper.insertRecord(record);
|
|
|
+
|
|
|
+ // 账户金额增加:冻结佣金 + 累计佣金
|
|
|
+ int rows = accountMapper.addFrozenCommission(distributorUserId, commissionAmount);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("增加冻结佣金失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解冻佣金
|
|
|
+ *
|
|
|
+ * 一般用定时任务每天执行:
|
|
|
+ * 订单完成 + 超过售后期后,把冻结佣金转为可提现。
|
|
|
+ *
|
|
|
+ * 这里的简化版是:
|
|
|
+ * 按佣金记录 create_time + freezeDays 判断。
|
|
|
+ *
|
|
|
+ * 更严谨做法:
|
|
|
+ * 结合订单状态,只解冻已完成、未退款的订单佣金。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void unlockFrozenCommission() {
|
|
|
+ DistributionConfig config = configMapper.selectConfig();
|
|
|
+ if (config == null || config.getEnableStatus() == null || config.getEnableStatus() != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int freezeDays = config.getFreezeDays() == null ? 7 : config.getFreezeDays();
|
|
|
+
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.add(Calendar.DAY_OF_MONTH, -freezeDays);
|
|
|
+ Date beforeTime = calendar.getTime();
|
|
|
+
|
|
|
+ List<DistributionCommissionRecord> records = commissionRecordMapper.selectFrozenRecordsBefore(beforeTime);
|
|
|
+ if (records == null || records.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (DistributionCommissionRecord record : records) {
|
|
|
+ BigDecimal amount = record.getCommissionAmount();
|
|
|
+
|
|
|
+ int rows = accountMapper.frozenToAvailable(record.getDistributorUserId(), amount);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("佣金解冻失败,recordId=" + record.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ commissionRecordMapper.updateStatus(record.getId(), DistributionConstants.COMMISSION_AVAILABLE);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单退款时佣金失效
|
|
|
+ *
|
|
|
+ * 规则:
|
|
|
+ * 1. 冻结中:扣冻结和累计
|
|
|
+ * 2. 可提现:扣可提现和累计
|
|
|
+ * 3. 已提现:目前不直接扣
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void invalidCommissionByRefund(Long orderId) {
|
|
|
+ if (orderId == null) {
|
|
|
+ throw new RuntimeException("订单ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<DistributionCommissionRecord> records = commissionRecordMapper.selectByOrderId(orderId);
|
|
|
+ if (records == null || records.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (DistributionCommissionRecord record : records) {
|
|
|
+ if (DistributionConstants.COMMISSION_INVALID.equals(record.getStatus())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal amount = record.getCommissionAmount();
|
|
|
+
|
|
|
+ if (DistributionConstants.COMMISSION_FROZEN.equals(record.getStatus())) {
|
|
|
+ int rows = accountMapper.deductFrozenAndTotal(record.getDistributorUserId(), amount);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("扣减冻结佣金失败,recordId=" + record.getId());
|
|
|
+ }
|
|
|
+ } else if (DistributionConstants.COMMISSION_AVAILABLE.equals(record.getStatus())) {
|
|
|
+ int rows = accountMapper.deductAvailableAndTotal(record.getDistributorUserId(), amount);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("扣减可提现佣金失败,recordId=" + record.getId());
|
|
|
+ }
|
|
|
+ } else if (DistributionConstants.COMMISSION_WITHDRAWN.equals(record.getStatus())) {
|
|
|
+ // 已提现的佣金,后续做一条负佣金记录,从未来佣金里抵扣
|
|
|
+ }
|
|
|
+
|
|
|
+ commissionRecordMapper.updateStatus(record.getId(), DistributionConstants.COMMISSION_INVALID);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用户申请提现
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void applyWithdraw(WithdrawApplyRequest request) {
|
|
|
+ if (request == null || request.getUserId() == null) {
|
|
|
+ throw new RuntimeException("用户ID不能为空");
|
|
|
+ }
|
|
|
+ if (request.getWithdrawAmount() == null
|
|
|
+ || request.getWithdrawAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ throw new RuntimeException("提现金额必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionConfig config = configMapper.selectConfig();
|
|
|
+ if (config == null || config.getEnableStatus() == null || config.getEnableStatus() != 1) {
|
|
|
+ throw new RuntimeException("分销功能未开启");
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal minWithdrawAmount = config.getMinWithdrawAmount() == null
|
|
|
+ ? BigDecimal.ZERO
|
|
|
+ : config.getMinWithdrawAmount();
|
|
|
+
|
|
|
+ if (request.getWithdrawAmount().compareTo(minWithdrawAmount) < 0) {
|
|
|
+ throw new RuntimeException("提现金额不能低于最低提现金额:" + minWithdrawAmount);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加锁查询账户,防止并发提现
|
|
|
+ DistributionAccount account = accountMapper.selectByUserIdForUpdate(request.getUserId());
|
|
|
+ if (account == null) {
|
|
|
+ throw new RuntimeException("分销账户不存在");
|
|
|
+ }
|
|
|
+ if (account.getStatus() == null || account.getStatus() != 1) {
|
|
|
+ throw new RuntimeException("分销账户已禁用");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (account.getAvailableCommission().compareTo(request.getWithdrawAmount()) < 0) {
|
|
|
+ throw new RuntimeException("可提现余额不足");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 可提现转提现中
|
|
|
+ int rows = accountMapper.availableToWithdrawing(request.getUserId(), request.getWithdrawAmount());
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("申请提现失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionWithdrawRecord record = new DistributionWithdrawRecord();
|
|
|
+ record.setUserId(request.getUserId());
|
|
|
+ record.setWithdrawNo(generateWithdrawNo());
|
|
|
+ record.setWithdrawAmount(request.getWithdrawAmount());
|
|
|
+ record.setStatus(DistributionConstants.WITHDRAW_WAIT_AUDIT);
|
|
|
+ record.setRemark("用户申请提现");
|
|
|
+
|
|
|
+ withdrawRecordMapper.insertWithdrawRecord(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 后台审核提现
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void auditWithdraw(WithdrawAuditRequest request) {
|
|
|
+ if (request == null || request.getWithdrawId() == null) {
|
|
|
+ throw new RuntimeException("提现ID不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!DistributionConstants.WITHDRAW_PAID.equals(request.getStatus())
|
|
|
+ && !DistributionConstants.WITHDRAW_REJECT.equals(request.getStatus())) {
|
|
|
+ throw new RuntimeException("审核状态不正确");
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionWithdrawRecord record = withdrawRecordMapper.selectByIdForUpdate(request.getWithdrawId());
|
|
|
+ if (record == null) {
|
|
|
+ throw new RuntimeException("提现记录不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!DistributionConstants.WITHDRAW_WAIT_AUDIT.equals(record.getStatus())) {
|
|
|
+ throw new RuntimeException("该提现记录已审核,不能重复处理");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (DistributionConstants.WITHDRAW_PAID.equals(request.getStatus())) {
|
|
|
+ // 审核通过:提现中转已提现
|
|
|
+ int rows = accountMapper.withdrawingToWithdrawn(record.getUserId(), record.getWithdrawAmount());
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("提现审核通过处理失败");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 审核拒绝:提现中退回可提现
|
|
|
+ int rows = accountMapper.withdrawingBackToAvailable(record.getUserId(), record.getWithdrawAmount());
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("提现审核拒绝处理失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionWithdrawRecord update = new DistributionWithdrawRecord();
|
|
|
+ update.setId(record.getId());
|
|
|
+ update.setStatus(request.getStatus());
|
|
|
+ update.setRemark(request.getRemark());
|
|
|
+
|
|
|
+ withdrawRecordMapper.updateAuditStatus(update);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DistributionAccount getAccount(Long userId) {
|
|
|
+ if (userId == null) {
|
|
|
+ throw new RuntimeException("用户ID不能为空");
|
|
|
+ }
|
|
|
+ createAccountIfAbsent(userId);
|
|
|
+ return accountMapper.selectByUserId(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DistributionUserRelation getRelation(Long userId) {
|
|
|
+ if (userId == null) {
|
|
|
+ throw new RuntimeException("用户ID不能为空");
|
|
|
+ }
|
|
|
+ return relationMapper.selectByUserId(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<DistributionCommissionRecord> getCommissionList(Long userId) {
|
|
|
+ return commissionRecordMapper.selectByUserId(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<DistributionWithdrawRecord> getWithdrawList(Long userId) {
|
|
|
+ return withdrawRecordMapper.selectByUserId(userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 如果账户不存在,则创建账户
|
|
|
+ */
|
|
|
+ private void createAccountIfAbsent(Long userId) {
|
|
|
+ DistributionAccount exist = accountMapper.selectByUserId(userId);
|
|
|
+ if (exist != null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionAccount account = new DistributionAccount();
|
|
|
+ account.setUserId(userId);
|
|
|
+ account.setStatus(DistributionConstants.ACCOUNT_NORMAL);
|
|
|
+
|
|
|
+ try {
|
|
|
+ accountMapper.insertAccount(account);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 并发场景下,可能两个请求同时创建,唯一索引会挡住
|
|
|
+ // 这里再次查询,存在就忽略,不存在再抛异常
|
|
|
+ DistributionAccount after = accountMapper.selectByUserId(userId);
|
|
|
+ if (after == null) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 没有邀请人的用户,也创建一条空关系
|
|
|
+ */
|
|
|
+ private void createEmptyRelationIfAbsent(Long userId) {
|
|
|
+ DistributionUserRelation exist = relationMapper.selectByUserId(userId);
|
|
|
+ if (exist != null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionUserRelation relation = new DistributionUserRelation();
|
|
|
+ relation.setUserId(userId);
|
|
|
+ relation.setParentUserId(0L);
|
|
|
+ relation.setGrandParentUserId(0L);
|
|
|
+ relation.setBindType(DistributionConstants.BIND_TYPE_REGISTER);
|
|
|
+ relation.setStatus(DistributionConstants.RELATION_NORMAL);
|
|
|
+
|
|
|
+ try {
|
|
|
+ relationMapper.insertRelation(relation);
|
|
|
+ } catch (Exception e) {
|
|
|
+ DistributionUserRelation after = relationMapper.selectByUserId(userId);
|
|
|
+ if (after == null) {
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成提现单号
|
|
|
+ */
|
|
|
+ private String generateWithdrawNo() {
|
|
|
+ return "TX" + System.currentTimeMillis() + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DistributionConfig getConfig() {
|
|
|
+ DistributionConfig config = configMapper.selectConfig();
|
|
|
+
|
|
|
+ if (config == null) {
|
|
|
+ // 理论上初始化 SQL 已经插入了配置
|
|
|
+ // 这里兜底返回默认值
|
|
|
+ config = new DistributionConfig();
|
|
|
+ config.setEnableStatus(1);
|
|
|
+ config.setLevelOneRate(new BigDecimal("10.00"));
|
|
|
+ config.setLevelTwoRate(new BigDecimal("5.00"));
|
|
|
+ config.setFreezeDays(7);
|
|
|
+ config.setMinWithdrawAmount(new BigDecimal("10.00"));
|
|
|
+ }
|
|
|
+
|
|
|
+ return config;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void saveConfig(DistributionConfig config) {
|
|
|
+ if (config == null) {
|
|
|
+ throw new RuntimeException("配置不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getEnableStatus() == null) {
|
|
|
+ throw new RuntimeException("请选择分销开关");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getLevelOneRate() == null || config.getLevelOneRate().compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ throw new RuntimeException("一级佣金比例不能小于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getLevelTwoRate() == null || config.getLevelTwoRate().compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ throw new RuntimeException("二级佣金比例不能小于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getLevelOneRate().compareTo(new BigDecimal("100")) > 0
|
|
|
+ || config.getLevelTwoRate().compareTo(new BigDecimal("100")) > 0) {
|
|
|
+ throw new RuntimeException("佣金比例不能大于100%");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getFreezeDays() == null || config.getFreezeDays() < 0) {
|
|
|
+ throw new RuntimeException("冻结天数不能小于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.getMinWithdrawAmount() == null || config.getMinWithdrawAmount().compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ throw new RuntimeException("最低提现金额不能小于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ DistributionConfig exist = configMapper.selectConfig();
|
|
|
+
|
|
|
+ if (exist == null) {
|
|
|
+ // 如果你没有 insertConfig 方法,可以直接先用 SQL 初始化一条配置
|
|
|
+ throw new RuntimeException("分销配置不存在,请先初始化 distribution_config 表");
|
|
|
+ }
|
|
|
+
|
|
|
+ config.setId(exist.getId());
|
|
|
+
|
|
|
+ int rows = configMapper.updateConfig(config);
|
|
|
+ if (rows <= 0) {
|
|
|
+ throw new RuntimeException("保存分销配置失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public QueryDistributionAccountResponse getAccountList(QueryDistributionAccountRequest queryDistributionAccountRequest) {
|
|
|
+ QueryDistributionAccountResponse queryDistributionAccountResponse = new QueryDistributionAccountResponse();
|
|
|
+ List<DistributionAccount> distributionAccounts = accountMapper.selectList(new LambdaQueryWrapper<DistributionAccount>());
|
|
|
+ if (ObjectUtil.isNotEmpty(distributionAccounts)){
|
|
|
+ queryDistributionAccountResponse.setList(distributionAccounts);
|
|
|
+ }
|
|
|
+ return queryDistributionAccountResponse;
|
|
|
+ }
|
|
|
+}
|