阅读前提:本文需要你至少了解过分销系统,在此不讨论系统如何设计,只从开发角度探讨功能的实现和扩展的一些思考,代码仅表达思路,不具有实际意义
分销的基本结构
分销系统从本质上来讲是树状的结构,每个节点代表一个分销员
用户可以有多个下级,但只能有一个或者没有上级
分销员拥有自己的角色和等级:角色体现了发展的级数,等级体现了佣金比例的不同,
在完成一定的规则或者业绩之后,分销员的角色可以升级
// 分销员
type Distributor struct {
Id int64 //用户ID
UserId int64 // 用户ID
Role int8 //角色
Level int8 //等级
Status bool //状态
}
分销关系
从数据结构看,分销关系是一维,A => B, B => C
为了维持关系的流动,分销关系一般都是有有效期和保护期的概念
保护期内,分销关系不会发生变更
有效期内,分销员可以收到下级产生的佣金
// 分销关系
type Relation struct {
UserId int //用户ID
Pid int //用户上级ID
IsValid bool //是否还在有效期
IsProtect bool //是否还在保护期
Distrbutor *Distributor //当前分销员信息
HeadRelation *Relation //上级关系
}
绑定的流程
分销员将分销链接,发给用户,用户点击后触发绑定流程
包含三个检测
// 分销员检测
type DistributorChecker struct {
IsDistributor //是否是分销员
IsValid bool //是否可以分销
}
// 用户检测
type UserChecker struct {
IsDistributor //用户是不是分销员
IsCanBeBinded //用户能不能被绑定 低级分销员不能把高级分销员设为下级
}
// 两者关系检测
type RelationChecker struct {
IsBinded bool //是否已经绑定过了
BindedRelation *Relation //发现已经绑定过了,判断是否有效期,如果有效,判断是否在
}
// 用户绑定的关系是否有效
func(r *RelationChecker) BindedRelationIsValid() bool {
return r.BindedRelation.IsValid
}
// 用户绑定的关系是否在保护期
func(r *RelationChecker) BindedRelationIsProtect() bool {
return r.BindedRelation.IsProtect
}
在没有关系、绑定过的关系失效或者过了保护期的情况下,可以发起绑定
// 查询角色配置的有效期和保护期
type RoleSetting struct {
RoleId int
BindValidTime *time.Time
BindProtectTime *time.Time
}
// 保存数据
佣金规则
佣金的规则主要与配置有关,根据用户的等级和角色产生佣金
// 佣金计算流程
// 检查分销员关系表,获取上一级分销员角色
var r = new(Relation)
role := r.HeadRelation.Distributor.Role
// 判断分销员是否可以得到佣金
...规则过滤
// 用户下单,上级分销员获取商品匹配到的佣金规则
type DistributionRule struct {
Role *Role //角色信息
Level *Level // 等级信息
CommissionType int8 // 规则类型,比例、固定金额
CommissionValue int // 规则值
}
// 获取分销员下的分销佣金
func (d *DistributionRule) GetCommission(distributor *Distributor, amount int) (int, error) {
//根据角色和等级匹配规则进行计算
return
}
// 佣金记录基本结构
type CommissionRecord struct {
OrderId int // 关联订单ID
OrderItemId int // 关联订单商品表ID
UserId int // 用户ID
NId int // 分销关系节点Id (不是一级循环的情况下,对应基础节点ID
Pid int // 上级ID
Amount int // 用户佣金
}
// 插入数据,返回上级ID
return Pid
以上是最基本的计算并记录一级佣金的方法,但实际业务中,会有二级三级甚至五级佣金的情况,该怎么写呢? 我们知道佣金的计算是按照找到用户上级,再根据上级的角色进行匹配,来计算佣金,如果三级佣金的话,就需要A => B(一级佣金) => C(二级佣金) => D(三级佣金) 同样的逻辑调用三次即可
var num = 3
var userId = 12345
var pid = userId
for i := 0; i < num; i++ {
//第一次循环时候,pid就是用户ID
//从第二次开始,pid就是返回的上个循环传进去的pid
if pid == 0 { //
break
}
pid = GetCommissionById(pid, amount)
}