后台开发过程中经常遇到多级分销的问题,要求邀请的下线消费进行返佣,本文介绍一下我用nosql实现的方案,欢迎大家提出宝贵意见
首先,我们来探讨一下分销系统常见的需求
常见的功能如下:
- 等级
所有参与者都可以成为代理商,即系统满足无限级分销;
分销商只能获取三级分销所得的佣金,超过三级的部分不能获得佣金。 - 权限
上级代理可以查看下级代理,以及下级代理的所有下级代理的订单;
下级代理不能查看上级代理的订单;
同级不能查看对方以及他的下线订单 - 返佣
A->B->C->D->E->F->客户小明
如上分销体系中,客户小明从分销商F那里购买了商品,那么F获得一级佣金,E获得二级佣金,D获得三级佣金,D前面的分销商C,B,A就与此没有关系,也无法获得佣金。
一级佣金比例是5%,二级是3%,三级的是2%
题外话
分销一般分为三级,分销商超过三级是犯法的。
2010年5月7日,《最高人民检察院、公安部关于公安机关管辖的刑事案件立案追诉标准的规定(二)》发布,其在第七十八条中规定 “涉嫌组织、领导的传销活动人员在三十人以上且层级在三级以上的,对组织者、领导者,应予立案追诉”。
数据库存储设计
使用nosql数据库;以redis为例,实际开发过程中,可以同样使用支持hash表结构和k-v结构存储的nosql数据引擎,如ssdb,mongodb等。
- 下级的存储,使用hash表存储第一级经销商;
h_down_agency_${代理商ID} {
下线1_ID: 成为下线时间,
下线2_ID: 成为下线时间,
......
}
- 上级代理商的存储,使用k-v保存所有上级代理商;
k_up_agency 代理商ID 上级代理商ID
功能实现
加入分销
- B输入A的邀请码,B成为A的下级
- 同时A成为B的上级
代码实现:
async function joinAgency(clientId, agencyId){
await redis.HSETAsync('h_down_agency_'+agencyId, clientId, Date.now())
await redis.SETAsync('k_up_agency', clientId, agencyId)
}
获取下级
使用遍历的方式获取多级下层代理商
代码实现:
agency.getThreeFloorDownAgency = async function (id) {
async function getOneFloorDownAgency(ids) {
let result = []
if (typeof ids === 'string') {
ids = [ids]
}
if (ids.length == 0) {
return result
} else if (ids.length == 1) {
let results = await redisClient.HGETALLAsync('h_down_agency_' + ids[0])
for (let id in results) {
result.push(id)
}
return result
} else {
for (let id of ids) {
let results = await redisClient.HGETALLAsync('h_down_agency_' + id)
for (let id in results) {
result.push(id)
}
}
return result
}
}
let oneFloorAgencies = await getOneFloorDownAgency(id)
let twoFloorAgencies = await getOneFloorDownAgency(oneFloorAgencies)
let threeFloorAgencies = await getOneFloorDownAgency(twoFloorAgencies)
return [oneFloorAgencies, twoFloorAgencies, threeFloorAgencies]
}
获取上级
遍历获取多级上层代理商
代码实现:
agency.getThreeFloorUpAgency = async function (id) {
async function getOneFloorUpAgency(id) {
return await redisClient.GETAsync('k_up_agency_' + id)
}
let result = []
while (result.length < 3) {
let item = await getOneFloorUpAgency(id)
if (!item) {
break
}
result.push(item)
id = item
}
return result
}
具体实现参见代码地址
网友评论