分销分钱具体逻辑

This commit is contained in:
张松
2025-10-27 16:00:58 +08:00
parent 39984116d0
commit bf083f698e
14 changed files with 387 additions and 14 deletions

View File

@@ -52,7 +52,7 @@ public class DistributionController {
@SaAdminCheckPermission(value = "distribution:edit", name = "分销修改")
@SaCheckMainShop
@PutMapping
public CzgResult<Boolean> edit(@Validated({UpdateGroup.class, Default.class}) @RequestBody MkDistributionConfigDTO dto) {
public CzgResult<Boolean> edit( @RequestBody MkDistributionConfigDTO dto) {
return CzgResult.success(configService.edit(StpKit.USER.getShopId(), dto));
}

View File

@@ -0,0 +1,103 @@
package com.czg.market.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.experimental.Accessors;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 分销记录表 实体类。
*
* @author ww
* @since 2025-10-27
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class MkDistributionFlowDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
/**
* 店铺用户id
*/
private Long shopUserId;
/**
* 用户id
*/
private Long userId;
/**
* 店铺id
*/
private Long shopId;
/**
* 分销员id
*/
private Long distributionUserId;
/**
* 等级id
*/
private Long levelId;
/**
* 等级名称
*/
private String levelName;
/**
* 用户名称
*/
private String nickname;
/**
* 订单编号
*/
private String orderNo;
/**
* 订单总金额
*/
private BigDecimal amount;
/**
* 奖励金额
*/
private BigDecimal rewardAmount;
/**
* order订单 recharge充值
*/
private String type;
/**
* pending待入账 success已入账
*/
private String status;
/**
* 创建时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
/**
* 修改时间
*/
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,114 @@
package com.czg.market.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 分销记录表 实体类。
*
* @author ww
* @since 2025-10-27
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_distribution_flow")
@Accessors(chain = true)
public class MkDistributionFlow implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id(keyType = KeyType.Auto)
private Long id;
/**
* 店铺用户id
*/
private Long shopUserId;
/**
* 店铺id
*/
private Long shopId;
/**
* 分销员id
*/
private Long distributionUserId;
/**
* 等级id
*/
private Long levelId;
/**
* 等级
*/
private Integer level;
/**
* 用户名称
*/
private String nickname;
private String sourceNickName;
/**
* 订单编号
*/
private String orderNo;
private Long sourceId;
/**
* 订单总金额
*/
private BigDecimal amount;
/**
* 奖励金额
*/
private BigDecimal rewardAmount;
/**
* order订单 recharge充值
*/
private String type;
/**
* pending待入账 success已入账
*/
private String status;
/**
* 创建时间
*/
@Column(onInsertValue = "now()")
private LocalDateTime createTime;
/**
* 修改时间
*/
@Column(onInsertValue = "now()", onUpdateValue = "now()")
private LocalDateTime updateTime;
/**
* 来源用户id
*/
private Long sourceShopUserId;
}

View File

@@ -16,7 +16,7 @@ import java.util.Map;
* @since 2025-10-25
*/
public interface MkDistributionConfigService extends IService<MkDistributionConfig> {
MkDistributionConfigVO detail(Long mainShopId);
MkDistributionConfigVO detail(Long shopId);
Boolean edit(Long shopId, MkDistributionConfigDTO dto);
}

View File

@@ -0,0 +1,14 @@
package com.czg.market.service;
import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkDistributionFlow;
/**
* 分销记录表 服务层。
*
* @author ww
* @since 2025-10-27
*/
public interface MkDistributionFlowService extends IService<MkDistributionFlow> {
}

View File

@@ -54,6 +54,19 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
*/
void open(Long userId, BigDecimal amount, Long shopId, Long sourceId);
/**
* 分销商户运营余额充值回调
*/
void rechargeCallBack(Long userId, Long shopId, BigDecimal amount, Long paymentId);
/**
* 发放分销奖励
* @param orderId 订单id
* @param orderNo 订单编号
* @param amount 金额
* @param userId 用户id
* @param shopId 店铺id
*/
void distribute(Long orderId, String orderNo, BigDecimal amount, Long userId, Long shopId, String type);
}

View File

@@ -58,6 +58,23 @@ public interface TableValueConstant {
}
}
}
interface DistributionFlow {
@Getter
enum Status {
PENDING("pending", "待入账"),
SUCCESS("sub", "已入账"),
SELF_RECHARGE("self_recharge", "自助充值");
private final String code;
private final String msg;
Status(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
}
interface EnableConfig {
@Getter

View File

@@ -5,7 +5,9 @@ import com.czg.account.dto.shopinfo.ShopInfoSubVO;
import com.czg.account.entity.ShopInfo;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -17,4 +19,7 @@ import java.util.List;
public interface ShopInfoMapper extends BaseMapper<ShopInfo> {
List<ShopInfoSubVO> getSubList(@Param("lng") String lng, @Param("lat") String lat, @Param("distance") float distance);
@Update("update tb_shop_info set amount = amount + #{amount} where id = #{id} and amount + #{amount} >= 0")
boolean updateAmount(@Param("id") Long id, @Param("amount") BigDecimal amount);
}

View File

@@ -453,9 +453,11 @@ public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> i
if (shopInfo.getAmount() == null) {
shopInfo.setAmount(BigDecimal.ZERO);
}
shopInfo.setAmount(shopInfo.getAmount().add(amount));
updateById(shopInfo);
return shopInfo.getAmount();
boolean flag = mapper.updateAmount(id, amount);
if (!flag) {
throw new CzgException("更新失败");
}
return shopInfo.getAmount().add(amount);
}

View File

@@ -34,7 +34,7 @@ public class Main {
// String packageName = "product";
String packageName = "market";
// tableName 指定需要生成的表
String tableName = "mk_distribution_amount_flow";
String tableName = "mk_distribution_flow";
String author = "ww";
//是否生成DTO实体 默认生成
boolean isGenerateDto = true;

View File

@@ -0,0 +1,14 @@
package com.czg.service.market.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.market.entity.MkDistributionFlow;
/**
* 分销记录表 映射层。
*
* @author ww
* @since 2025-10-27
*/
public interface MkDistributionFlowMapper extends BaseMapper<MkDistributionFlow> {
}

View File

@@ -0,0 +1,18 @@
package com.czg.service.market.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkDistributionFlow;
import com.czg.market.service.MkDistributionFlowService;
import com.czg.service.market.mapper.MkDistributionFlowMapper;
import org.springframework.stereotype.Service;
/**
* 分销记录表 服务层实现。
*
* @author ww
* @since 2025-10-27
*/
@Service
public class MkDistributionFlowServiceImpl extends ServiceImpl<MkDistributionFlowMapper, MkDistributionFlow> implements MkDistributionFlowService{
}

View File

@@ -10,14 +10,8 @@ import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkDistributionUserDTO;
import com.czg.market.entity.MkDistributionAmountFlow;
import com.czg.market.entity.MkDistributionConfig;
import com.czg.market.entity.MkDistributionLevelConfig;
import com.czg.market.entity.MkDistributionUser;
import com.czg.market.service.MkDistributionAmountFlowService;
import com.czg.market.service.MkDistributionConfigService;
import com.czg.market.service.MkDistributionLevelConfigService;
import com.czg.market.service.MkDistributionUserService;
import com.czg.market.entity.*;
import com.czg.market.service.*;
import com.czg.market.vo.MkDistributionConfigVO;
import com.czg.order.dto.MkDistributionPayDTO;
import com.czg.order.entity.OrderPayment;
@@ -26,14 +20,17 @@ import com.czg.sa.StpKit;
import com.czg.service.market.mapper.MkDistributionUserMapper;
import com.czg.system.service.WxService;
import com.czg.utils.AssertUtil;
import com.czg.utils.FunUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -46,6 +43,7 @@ import java.util.stream.Collectors;
* @author ww
* @since 2025-10-27
*/
@Slf4j
@Service
public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUserMapper, MkDistributionUser> implements MkDistributionUserService {
@@ -55,6 +53,9 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
private MkDistributionLevelConfigService levelConfigService;
@Resource
private MkDistributionAmountFlowService distributionAmountFlowService;
@Resource
private MkDistributionFlowService distributionFlowService;
@DubboReference
private ShopUserService shopUserService;
@DubboReference
@@ -188,4 +189,69 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
.setMainShopId(mainShopId).setShopId(shopId).setAmount(finalAmount).setChangeAmount(amount).setSourceId(paymentId)
.setRemark("自助充值").setOpAccount(StpKit.USER.getAccount()));
}
@Override
public void distribute(Long sourceId, String orderNo, BigDecimal amount, Long sourceUserId, Long shopId, String type) {
FunUtils.safeRunVoid(() -> {
AssertUtil.isTrue(amount.compareTo(BigDecimal.ZERO) == 0, "分销金额不能为0");
MkDistributionConfigVO config = mkDistributionConfigService.detail(shopId);
AssertUtil.isTrue(config.getIsEnable() != 1, "分销未开启");
// 当前用户上级分销员
ShopUser sourceShopUserInfo = shopUserService.getShopUserInfo(shopId, sourceUserId);
if (sourceShopUserInfo.getDistributionUserId() == null) {
return;
}
MkDistributionUser distributionUser = getOne(new QueryWrapper().eq(MkDistributionUser::getId, sourceShopUserInfo));
AssertUtil.isNull(distributionUser, "分销员不存在");
AssertUtil.isTrue(distributionUser.getStatus() != 1, "分销员未开启");
// 上上级分销员
if (distributionUser.getParentId() != null) {
}
MkDistributionLevelConfig level = levelConfigService.getById(distributionUser.getDistributionLevelId());
AssertUtil.isNull(level, "分销等级不存在");
if (config.getRewardCount() != null && config.getRewardCount() > 0) {
long count = distributionFlowService.count(new QueryWrapper().eq(MkDistributionFlow::getSourceShopUserId, sourceUserId)
.eq(MkDistributionFlow::getShopUserId, distributionUser.getShopUserId()));
if (count >= config.getRewardCount()) {
log.info("分销员{}已达到奖励次数上限, 次数: {}", distributionUser.getShopUserId(), config.getRewardCount());
return;
}
}
// 店铺信息
ShopInfo shopInfo = shopInfoService.getById(shopId);
BigDecimal oneAmount = amount.multiply(level.getLevelOneCommission().divide(BigDecimal.valueOf(100), RoundingMode.DOWN));
boolean flag = true;
BigDecimal finalAmount = BigDecimal.ZERO;
try {
shopInfoService.updateAmount(shopId, oneAmount.negate());
}catch (Exception e) {
flag = false;
}
MkDistributionFlow mkDistributionFlow = new MkDistributionFlow().setShopUserId(distributionUser.getShopUserId()).setShopId(distributionUser.getShopId()).setDistributionUserId(distributionUser.getId())
.setLevelId(distributionUser.getDistributionLevelId()).setLevel(level.getLevel()).setSourceNickName(sourceShopUserInfo.getNickName()).setOrderNo(orderNo)
.setSourceId(sourceId).setAmount(amount).setType(type).setStatus(flag ? TableValueConstant.DistributionFlow.Status.SUCCESS.getCode() :
TableValueConstant.DistributionFlow.Status.PENDING.getCode())
.setRewardAmount(oneAmount);
distributionFlowService.save(mkDistributionFlow);
if (flag) {
distributionAmountFlowService.save(new MkDistributionAmountFlow()
.setType(TableValueConstant.DistributionAmountFlow.Type.SELF_RECHARGE.getCode())
.setShopId(shopId).setAmount(finalAmount).setChangeAmount(amount).setSourceId(mkDistributionFlow.getId())
.setRemark("自助充值").setOpAccount(StpKit.USER.getAccount()));
}
}, "分销方法执行失败");
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.market.mapper.MkDistributionFlowMapper">
</mapper>