關於DRP分銷系統的那些事
一、背景
1、在現實生活中我們經常遇到由推薦人註冊,比如一個購物平臺,使用者A推薦使用者B註冊,那當B購買商品成功時,使用者A就會拿到相應的提成。
只要是使用者A推薦的使用者購買商品成功後,A使用者都會拿到提成。
當用戶B推薦了使用者C,那當用戶C購買商品成功時,使用者B和使用者A都可以拿到相對應的提成。
如果使用者C推薦了使用者D,那當用戶C購買商品成功時,使用者C,使用者B和使用者A都可以拿到相對應的提成。
以此類推。這就是我們所說的分銷。
2、什麼是二級分銷?
二級分銷其實是一種讓使用者分裂通過邀請的形式來獲得更多的使用者。如有ABC三個人,A推薦B購買一件商品,B推薦C購買一件商品。
假定通過直接推薦購買該商品可獲得10%利潤,通過間接推薦購買可獲得5%的利潤。
設這件商品定價為1000元,結算下來A可以獲得100+50=150元的利潤,B可以獲得100元的利潤,這就是二級分銷。
二、需求
常見的功能如下:
1、等級
所有參與者都可以成為代理商,即系統滿足無限級分銷;
分銷商只能獲取三級分銷所得的佣金,超過三級的部分不能獲得佣金。
2、許可權
上級代理可以檢視下級代理,以及下級代理的所有下級代理的訂單;
下級代理不能檢視上級代理的訂單;
同級不能檢視對方以及他的下線訂單。
3、返傭
A->B->C->D->E->F->客戶小明。
如上分銷體系中,客戶小明從分銷商F那裡購買了商品,那麼F獲得一級佣金,E獲得二級佣金,D獲得三級佣金,D前面的分銷商C,B,A就與此沒有關係,也無法獲得佣金。
一級佣金比例是5%,二級是3%,三級的是2%
4、題外話
分銷一般分為三級,分銷商超過三級是犯法的。
2010年5月7日,《最高人民檢察院、公安部關於公安機關管轄的刑事案件立案追訴標準的規定(二)》釋出,
其在第七十八條中規定 “涉嫌組織、領導的傳銷活動人員在三十人以上且層級在三級以上的,對組織者、領導者,應予立案追訴”。
三、方案
1、首先是使用者註冊資訊表UserInfo需要增加一個ParentId欄位。
根據上圖,userid=1的這個會員Pid為0的說明會員是頂級的,沒有任何人推廣。
userid=2的這個會員pid為1,說明他是userid為1的會員推廣而來。然後看userid=7的這個會員,他的pid=2,說明他是userid=2的這個會員推廣來。說白了推廣關係就是:
userid(1)->userid(2)->userid(7)
userid(1)->userid(3)
userid(1)->userid(4)
userid(1)->userid(5)
userid(1)->userid(6)
那麼我們要查詢一個會員(假設他的id為1)所有的推廣一級會員,對應的sql就是:select * from t_user where Pid=1,這裡沒有什麼問題,到是不難。
那繼續來,要查詢他的二級或是三級分銷會員的話,就麻煩了,需要使用子迴圈了。對應的程式碼如下:
public String gets(int pid){
StringBuffer sb=new StringBuffer(sb);
ArrayList list=(ArrayList)DaoFactory.getUserDAO().exe("select id,Pid from t_user where Pid="+pid);
for (Iterator iter = list.iterator(); iter.hasNext(); ) {
DataField df=(DataField)iter.next();
sb.append("<li>"+df.getInt("id")+"</li>");
//遞迴呼叫
sb.append(gets(df.getInt("id")));
}
}
上面看到了,主要解決辦法就是遞迴呼叫。
雖然功能也能實現,但在數量比較大的情況下,很容易產生效能問題(這裡只是查詢會員,如果在統計每個級別下會員的消費,收入統計時,需要和消費表關係查詢,那效能不知卡到什麼時候)。
下面重點來了,我們重新設計一下表,這裡我們主要是通過資料庫設計來解決,
我們知道資料庫儲存數量量不怕多,於是可以這樣,每當使用者推廣一個會員的時候,我們向一個表(暫且叫作使用者關係表)寫入他的級別關係不就行了嗎。
比如 a推廣了b,然後b推廣了c,c推廣了d,這樣我我們就向資料庫中寫一個記錄b以上三級的關係。
然後,新建一張層級關係表TeamLevel,表結構如下:
CREATE TABLE `teamlevel` (
`Id` bigint(20) NOT NULL,
`UserId` varchar(50) DEFAULT NULL COMMENT '使用者Id',
`ParentId` varchar(50) DEFAULT NULL COMMENT '推薦人Id',
`Level` int(10) DEFAULT NULL COMMENT '層級',
PRIMARY KEY (`Id`)
)
比如:
例子:
在做交易所的時候,需要統計邀請註冊人數,比如 A邀請B, B邀請C, C邀請D。那麼A的邀請人數就是3個,B的邀請人數就是2個,C的邀請人數就是1個。
除此之外,還要能統計出A直接邀請人數,A下一級邀請人數,A下二級邀請的人數,以此類推。
2、在註冊的時候需要往這張表插入資料,比如D推薦E來註冊,就需要往庫裡插入如下記錄:
有了這些記錄之後,查詢統計就方便多了,使用者的層級關係也一目瞭然。
再比如:
這裡看到,ChildId=2的這個會員,他是id為1(Pid=1)的一級分銷使用者(FxLevel=1)
ChildId=7的這個會員,資料庫中有兩條記錄,一個是:他是id為2(Pid=2)的一級分銷使用者(FxLevel=1),
再就是他是id為1(Pid=1)的二級分銷使用者(FxLevel=2),所以不難理解,如果一個會員上面有三級的話,這裡應該有三條記錄。
簡單理解就是,當用戶新增加時,將此使用者上面所有級別對應的使用者資訊記錄到使用者關係表中。
這樣,當我們要查詢一個會員所有一級會員時,
可以使用sql:select * from t_user_relations where Pid=1 and FxLevel=1
所有二級會員sql:select * from t_user_relations where Pid=1 and FxLevel=2
所有三級會員sql:select * from t_user_relations where Pid=1 and FxLevel=3
當我們需要統計三級會員的消費總額的時候,
可以很方便使用sql:select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel=3
同理查詢二級會員的消費:select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel=2
那要查詢所有子會員的消費怎麼辦?總不能寫三個sql吧,當然不會了。使用條件FxLevel>0不就可以了嗎:)
select sum(t_pay.Money) from t_user_relations,t_pay where t_user_relations.ChildId=t_pay.Userid and t_user_relations.Pid=1 and t_user_relations.FxLevel>0
這樣一個sql就解決了。如果使用一開始使用的遞迴方法,隨著資料量的增長,速度會非常非常的糟糕。
上面你還可能 還會問一個問題,那如果知道某個會員他是誰的一級,誰的二級呢,.....?這需要用到第一個方法設計的表了,看到了,上面的表設計我們還是要用到:)
select Pid from t_user where id=2
if(Pid!=0)說明還不是頂級,繼續查。這裡可以 使用遞迴查詢或做三次查詢(通過 pid是否為0,這樣有的可能只是一級或兩次查詢,最多就是3次),放心,這樣的不會太影響效能的,可以忽略不計。
或者把id,pid資料放到快取裡,redis是個不錯的選擇。