通过“三级分销”的形式,形成拿手端的裂变,提高拿手注册转化的积极性!
一、业务模式
拿手端的“三级分销”,其基础业务模式参考商家端,通过邀请注册的形式,形成3级关系,
在关系网内的用户产生返利行为时,可以按照进行获得返利的业务模式。
平台角色设定:
平台设定四个角色:“大师傅”、“师傅”、“徒弟”以及“徒孙”;
只有徒弟的人数累计满30人(即该用户的子集)才可获得“大师傅”资格;返利类型
返利的类型分为两种,一种是注册返利,一种是完成活动返利;触发返利的条件:
通过邀请链接注册成功即可触发注册返利;
由于拿手在平台上不产生消费行为,且可能存在中途放弃任务的行为,因此完成活动返利条件设定为商家通过该拿手的买家秀,向其返款时;返利行为:
徒弟和徒孙都会向其上一级邀请人以及大师傅进行返利,比如徒孙会向徒弟返利,同时也会向大师傅返利;
徒弟在返利时,由于其上一级就是大师傅,因此徒弟会向大师傅返利2次;
徒孙是支持多层级的,如下图所示,徒孙B2可能存在徒孙2.1甚至徒孙n这样的多层级关系,因此徒孙在计算返利时,按照徒孙n-1(即该徒孙的上一次邀请人)以及大师傅进行返利;
在未成为大师傅之前,只能获得上一级的返利,大师傅返利无法获得;
用户成为大师傅后,其自身的活动行为不会对任何人产生返利行为;
返利来源与计算
拿手的返利来源建议全部由平台支出,商家端因为会员等级的不同,推广费、增值费等平台营收费用的收取规则也不一样,很难做到统一,因此拿手的返利来源建议统一由平台进行支出;
返利的金额按照固定金额的进行操作,同时该金额需要支持可配置,可以参考下方表格:返利行为 对象与金额 注册返利 上一级(0.5)/大师傅(0.2) 活动返利 上一级(1)/大师傅(0.5) 关系脱离
当某个徒弟或者徒孙的下一级人数满30人时,该徒弟或徒孙则自动升级为大师傅,并自动从原有的体系中脱离(包括该用户下的所有子集),后续产生的返利行为也从原体系中脱离;
- 账单与交易记录
每个用户通过该体系收到的返利金额,沿用之前推广大师傅的设定,全部统一先到用户的推广金额里,然后统一提取到该用户的账户余额里;
提取账户余额的限制和之前保持一致,同样是5元起提;
系统账单同样沿用之前的设定,只有当用户将该金额提取到账户余额中时,才生成对应的账单记录;
用户获得的每一笔返利,系统都需要进行记录,包括返利的时间、金额、类型、返利的对象等;
二、界面部分改动
拿手端只增加手机端,PC端暂不操作,主要调整页面为推广大师傅主界面和查看详情页,设计稿待调整,原型如下。
三、系统设计:
- 实体类设计:
1、邀请关系表
package com.zhibi.xiuba.user.spi.model;
import com.zhibi.xiuba.domain.BaseDomain;
import com.zhibi.xiuba.model.BaseEnum;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.HashMap;
import java.util.Map;
/**
* Created by qinhe_admin on 2017/9/25.
*/
@Entity
@Table(name = "xb_us_showker_invitation", indexes = {@Index(name = "father_distance", columnList = "father_id,distance", unique = true)})
public class ShowkerInvitation extends BaseDomain {
private static final long serialVersionUID = 7228910123994809290L;
@Id
@GeneratedValue(generator = "id_generator")
@GenericGenerator(name = "id_generator", strategy = "redis_id")
private Long id;
/**
* 被邀请人ID
*/
@Column(unique = true)
private Long userId;
/**
* 邀请人ID
*/
@Column(name = "father_id")
private Long fatherId;
/**
* 祖先(子孙满30个的祖先)
*/
private Long forefatherId;
/**
* 与祖先差了多少个层级,最小是1
*/
@Column(name = "distance")
private Integer distance;
}
get、set方法省略
2、业务逻辑设计:
关系的建立:注册
奖励的触发:注册和拿手完成活动
奖励的触发涉及到对账户和金额的操作,需要做到必达性,所以需要做在消息队列里面,我用的是rocketmq做消息队列,mq有一个好处,就是他自身就支持消息回查,并且会自动重试,如果金额处理有问题,返回一个ConsumeConcurrentlyStatus.RECONSUME_LATER;mq会间隔一段时间重复去处理这个业务,如果处理金额成功,则直接返回一个CONSUME_SUCCESS就可以了
3、邀请关系的建立
这里有一个很麻烦的业务处理,需要在注册的时候就建立关系,和主要的注册方法是异步处理,保证注册成功并迅速完成。注册的时候会从页面上带上一个邀请商家id的请求头,在后端获取到这个请求头,并找到邀请人的用户信息,然后建立关系。如果只有一层关系就这样就可以了,但是我们三级分销是要有多层关系的,返款的时候不但需要找到邀请人,还要找到大师傅(所有父集里面邀请满足30人的用户),有人可能觉得直接循环去遍历父集就好了,但是这样对性能影响特别大,而且这种操作钱的操作都是重要的业务逻辑,不能这么耗性能。所以需要在每个人注册的时候不但要存储邀请人和和自己的邀请关系,同时要查看邀请人是否满足了大师傅的条件,如果满足,则对这个大师傅的所有子集都打上这个大师傅的标签。主要业务逻辑代码如下:
①主要注册代码:
private User signUp(User user, UserAccount userAccount, Long inviterId, String wechatPlatformType, String wechatOpenId, Long boostTaskApplyId) throws Exception {
User signUp = userService.signUp(user, userAccount, inviterId, wechatPlatformType, wechatOpenId, boostTaskApplyId);
if (signUp != null) {
String channelSource = signUp.getChannelSource();
//处理大师傅邀请
if (inviterId != null) {
User inviter = userService.get(inviterId);
if (UserService.CHANNEL_SOURCE_DSF.equalsIgnoreCase(channelSource)) {
//处理邀请逻辑
if (inviter != null && UserRoleEnum.SELLER.getCode().equals(inviter.getRole()) && UserRoleEnum.SELLER.getCode().equals(signUp.getRole())) {
//处理商家邀请逻辑
Long userId = signUp.getId();
Long fatherId = inviterId;
userService.handleSellerInvitation(userId, fatherId);
}
if (inviter != null && UserRoleEnum.SHOWKER.getCode().equals(inviter.getRole()) && UserRoleEnum.SHOWKER.getCode().equals(signUp.getRole())) {
//处理拿手邀请奖励
Long userId = signUp.getId();
Long fatherId = inviterId;
userService.handleShowkerInvitation(userId, fatherId);
}
}
}
userService.evictUserCache(signUp.getId());
userService.evictUserCache(inviterId);
}
return signUp;
}
②、邀请逻辑:
/**
* 处理拿手邀请逻辑
*/
@Override
@Async
public void handleShowkerInvitation(Long userId, Long fatherId) {
try {
User user = get(userId);
String channelSource = user.getChannelSource();
//大师傅
if (CHANNEL_SOURCE_DSF.equals(channelSource)) {
//事务分离
//邀请关系的创建
showkerInvitationService.createShowkerInvitationRelation(userId, fatherId);
//处理大师傅的子孙
showkerInvitationService.handleAllSon(fatherId);
//大师傅的注册奖励
ShowkerExtension showkerExtension = showkerExtensionRepository.findByUserId(userId);
if (showkerExtension == null || !ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode().equals(showkerExtension.getRole())) {
String k = rocketMQTransactionWrapper.createKey(userId + "");
JSONObject json = new JSONObject();
json.put("userId", userId);
json.put("fatherId", fatherId);
MessageExt messageExt = rocketMQTransactionWrapper.createMessageExt(MQTagEnum.SHOWKER_SIGNUP_REWARD, k, json);
rocketMQTransactionWrapper.sendSync(messageExt);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
③、邀请关系的创建
/**
* 创建邀请关系
*/
@Override
public Long createShowkerInvitationRelation(Long userId, Long fatherId) throws Exception {
if (userId != null && fatherId != null) {
ShowkerInvitation temp = showkerInvitationRepository.findByUserId(userId);
if (temp != null) {
throw new CommonException("已经有一条邀请记录了!");
} else {
AcquiredLockWrapper<Long> acquiredLockWrapper = () -> {
ShowkerExtension fatherExtension = createShowkerExtension(fatherId);
Integer fatherRole = fatherExtension.getRole();
ShowkerInvitation fatherInvitation = showkerInvitationRepository.findByUserId(fatherId);
ShowkerInvitation userInvitation = new ShowkerInvitation();
userInvitation.setCreateTime(new Date());
userInvitation.setUserId(userId);
userInvitation.setFatherId(fatherId);
userInvitation.setUserIsDivorced(false);
if (fatherInvitation != null) {
Integer ancestor = fatherInvitation.getAncestor() == null ? 0 : fatherInvitation.getAncestor();
userInvitation.setAncestor(ancestor + 1);
} else {
userInvitation.setAncestor(1);
}
if (ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode().equals(fatherRole)) {
userInvitation.setDistance(1);
userInvitation.setForefatherId(fatherId);
userInvitation.setEternityForefatherId(fatherId);
} else {
if (fatherInvitation != null && fatherInvitation.getForefatherId() != null) {
Integer distance = fatherInvitation.getDistance() == null ? 0 : fatherInvitation.getDistance();
userInvitation.setDistance(distance + 1);
userInvitation.setForefatherId(fatherInvitation.getForefatherId());
userInvitation.setEternityForefatherId(fatherInvitation.getForefatherId());
} else {
userInvitation.setDistance(null);
userInvitation.setForefatherId(null);
userInvitation.setEternityForefatherId(null);
}
showkerExtensionRepository.updateRoleById(fatherExtension.getId(), ShowkerExtension.RoleEnum.ROLE_FATHER.getCode());
}
showkerInvitationRepository.save(userInvitation);
return userInvitation.getForefatherId();
};
ShowkerInvitation fatherInvitation = showkerInvitationRepository.findByUserId(fatherId);
if (fatherInvitation != null) {
return distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(fatherInvitation.getFatherId() + ""), acquiredLockWrapper);
} else {
return acquiredLockWrapper.invokeAfterLockAcquire();
}
}
}
return null;
}
④、处理子孙的数据
/**
* 处理子孙的数据
*/
@Override
// @Transactional(rollbackFor = Exception.class)
public void handleAllSon(Long forefatherId) {
Long showkerInvitationLimit = 9999999999L;
SysConfig validSysConfig = sysConfigService.getValidSysConfig(UserConfigParam.SHOWKER_INVITATION_LIMIT);
if (validSysConfig != null) {
showkerInvitationLimit = Long.parseLong(validSysConfig.getConfigValue());
}
//确定父亲是不是祖先(查有多少个儿子)
ShowkerExtension fatherExtension = createShowkerExtension(forefatherId);
Long sonCount = showkerInvitationRepository.countByFatherId(forefatherId);
sonCount = sonCount == null ? 0L : sonCount;
if ((ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode().equals(fatherExtension.getRole()) && sonCount >= showkerInvitationLimit && sonCount <= showkerInvitationLimit + 4) ||
((!ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode().equals(fatherExtension.getRole())) && sonCount >= showkerInvitationLimit)) {
//如果是祖先则处理他的子孙
ShowkerInvitation byUserId = showkerInvitationRepository.findByUserId(forefatherId);
if (byUserId != null) {
byUserId.setForefatherId(null);
byUserId.setDistance(0);
byUserId.setUserIsDivorced(true);
showkerInvitationRepository.save(byUserId);
}
Integer distance = 1;
try {
handleSon(forefatherId, forefatherId, distance);
} catch (Exception e) {
e.printStackTrace();
}
try {
if (!ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode().equals(fatherExtension.getRole())) {
User forefather = userRepository.findOne(forefatherId);
momentQueue.push(Moment.TypeEnum.SHOWKER_BE_DSF, null, forefather.getPortraitPic(), forefather, null, null);
}
} catch (Exception e) {
e.printStackTrace();
}
showkerExtensionRepository.updateRoleById(fatherExtension.getId(), ShowkerExtension.RoleEnum.ROLE_FOREFATHER.getCode());
}
}
⑤、大师傅的注册奖励(mq消息的消费)
package com.zhibi.xiuba.handler;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.zhibi.xiuba.annotation.IMQConsumeHandler;
import com.zhibi.xiuba.annotation.MQConsumeTag;
import com.zhibi.xiuba.exception.CommonException;
import com.zhibi.xiuba.lock.service.DistributedLock;
import com.zhibi.xiuba.mq.MQTagEnum;
import com.zhibi.xiuba.service.*;
import com.zhibi.xiuba.service.impl.UserService;
import com.zhibi.xiuba.user.spi.enums.LockKeyUtils;
import com.zhibi.xiuba.user.spi.model.ShowkerInvitation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* 有关金额交易都放到mq消息队列中去
*/
@MQConsumeTag({
MQTagEnum.SHOWKER_SIGNUP_REWARD,
MQTagEnum.SHOWKER_BINDING_WANGWANG_REWARD,
MQTagEnum.SHOWKER_FINSH_SHOWKERTASK_REWARD,
MQTagEnum.SELLER_INVITATION_REWARD_FATHER,
MQTagEnum.SELLER_INVITATION_REWARD_FOREFATHER})
@Service
public class MoneyConsumeHandler implements IMQConsumeHandler {
private final ITradingRecordService tradingRecordService;
private final DistributedLock distributedLock;
private final IShowkerInvitationService showkerInvitationService;
private final ISellerInvitationService sellerInvitationService;
private final IRecommendRewardService recommendRewardService;
private final IUserService userService;
private Logger logger = LoggerFactory.getLogger(this.getClass());
public MoneyConsumeHandler(ITradingRecordService tradingRecordService,
DistributedLock distributedLock,
IShowkerInvitationService showkerInvitationService,
ISellerInvitationService sellerInvitationService,
IRecommendRewardService recommendRewardService,
UserService userService) {
this.tradingRecordService = tradingRecordService;
this.distributedLock = distributedLock;
this.showkerInvitationService = showkerInvitationService;
this.sellerInvitationService = sellerInvitationService;
this.recommendRewardService = recommendRewardService;
this.userService = userService;
}
@Override
public ConsumeConcurrentlyStatus consumeMessage(MessageExt messageExt, ConsumeConcurrentlyContext context) {
JSONObject paramObject = JSONObject.parseObject(new String(messageExt.getBody()));
logger.info("receiveMsg:{tag=" + messageExt.getTags() + ", content=" + new String(messageExt.getBody()));
String tags = messageExt.getTags();
String msgId = messageExt.getMsgId();
MQTagEnum mqTagEnum = MQTagEnum.getEnumByCode(tags);
ConsumeConcurrentlyStatus consumeConcurrentlyStatus = ConsumeConcurrentlyStatus.RECONSUME_LATER;
switch (mqTagEnum) {
case SHOWKER_SIGNUP_REWARD: {
Long userId = paramObject.getLong("userId");
Long fatherId = paramObject.getLong("fatherId");
try {
ShowkerInvitation showkerInvitation = showkerInvitationService.findByUserId(userId);
if (showkerInvitation != null && showkerInvitation.getForefatherId() != null) {
distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(showkerInvitation.getForefatherId() + ""),
() -> distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(fatherId + ""),
() -> showkerInvitationService.handleSignUpReward(showkerInvitation.getForefatherId(), fatherId, userId)));
} else {
distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(fatherId + ""),
() -> showkerInvitationService.handleSignUpReward(null, fatherId, userId));
}
if (showkerInvitation != null && showkerInvitation.getForefatherId() != null) {
userService.evictUserCache(showkerInvitation.getForefatherId());
}
userService.evictUserCache(fatherId);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch (CommonException ce) {
if ("dont_resubmit".equals(ce.getErrorCode())) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
case SHOWKER_BINDING_WANGWANG_REWARD: {
Long userId = paramObject.getLong("userId");
Long fatherId = paramObject.getLong("fatherId");
Long forefatherId = paramObject.getLong("forefatherId");
try {
if (fatherId != null && forefatherId != null) {
distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(forefatherId + ""),
() -> distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(fatherId + ""),
() -> showkerInvitationService.handleBindingWangwangReward(forefatherId, fatherId, userId)));
} else if (fatherId != null) {
distributedLock.lock(LockKeyUtils.getShowkerInvitationLockKey(fatherId + ""),
() -> showkerInvitationService.handleBindingWangwangReward(null, fatherId, userId));
} else {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
userService.evictUserCache(fatherId);
userService.evictUserCache(forefatherId);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch (CommonException ce) {
if ("dont_resubmit".equals(ce.getErrorCode())) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
case SHOWKER_FINSH_SHOWKERTASK_REWARD: {
Long showkerId = paramObject.getLong("showkerId");
Long showkerTaskId = paramObject.getLong("showkerTaskId");
boolean ifFirst = paramObject.getBoolean("ifFirst");
try {
if (showkerId != null) {
userService.handleShowkerTaskReward(showkerId, ifFirst, showkerTaskId);
} else {
logger.info("SHOWKER_FINSH_SHOWKERTASK_REWARD:没有showkerId");
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch (CommonException ce) {
if ("dont_resubmit".equals(ce.getErrorCode())) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
case SELLER_INVITATION_REWARD_FATHER: {
Long fatherId = paramObject.getLong("fatherId");
Long userId = paramObject.getLong("userId");
Long reward = paramObject.getLong("reward");
Long taskId = paramObject.getLong("taskId");
Long tradId = paramObject.getLong("tradId");
Integer initiatorType = paramObject.getInteger("initiatorType");
try {
if (fatherId != null) {
distributedLock.lock(LockKeyUtils.getTradLockKeyUid(fatherId),
() -> sellerInvitationService.rewardSellerFather(userId, fatherId, reward, initiatorType, msgId, taskId, tradId));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
logger.info("SELLER_INVITATION_REWARD_FATHER:没有fatherId");
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (CommonException ce) {
if ("dont_resubmit".equals(ce.getErrorCode())) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
case SELLER_INVITATION_REWARD_FOREFATHER: {
Long forefatherId = paramObject.getLong("forefatherId");
Long reward = paramObject.getLong("reward");
Long userId = paramObject.getLong("userId");
Integer initiatorType = paramObject.getInteger("initiatorType");
Long taskId = paramObject.getLong("taskId");
Long tradId = paramObject.getLong("tradId");
try {
if (forefatherId != null) {
distributedLock.lock(LockKeyUtils.getTradLockKeyUid(forefatherId),
() -> sellerInvitationService.rewardSellerForefather(userId, forefatherId, reward, initiatorType, msgId, taskId, tradId));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
logger.info("SELLER_INVITATION_REWARD_FATHER:没有forefatherId");
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (CommonException ce) {
if ("dont_resubmit".equals(ce.getErrorCode())) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} else {
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
default:
break;
}
return consumeConcurrentlyStatus;
}
}
⑥、SHOWKER_SIGNUP_REWARD消费逻辑:
@Override
@Transactional(rollbackFor = Exception.class)
public boolean handleSignUpReward(Long forefatherId, Long fatherId, Long userId) throws CommonException {
long rewardFather = 0L;
long rewardForefather = 0L;
long reward = 0;
Date now = new Date();
SysConfig validSysConfigFather = sysConfigService.getValidSysConfig(UserConfigParam.SHOWKER_INVITATION_REWARD_SIGN_UP_FATHER);
SysConfig validSysConfigForefather = sysConfigService.getValidSysConfig(UserConfigParam.SHOWKER_INVITATION_REWARD_SIGN_UP_FOREFATHER);
if (validSysConfigFather != null) {
rewardFather = Long.parseLong(validSysConfigFather.getConfigValue());
}
if (validSysConfigForefather != null) {
rewardForefather = Long.parseLong(validSysConfigForefather.getConfigValue());
}
if (fatherId != null && rewardFather > 0L) {
ShowkerExtension showkerExtension = showkerExtensionRepository.findByUserId(fatherId);
User father = userRepository.findOne(fatherId);
UserAccount fatherAccount = father.getUserAccount();
// fatherAccount.setInvitationReward((fatherAccount.getInvitationReward() == null ? 0L : fatherAccount.getInvitationReward()) + rewardFather);
// fatherAccount.setLastUpdateTime(new Date());
// userAccountRepository.save(fatherAccount);
fatherAccount = complexEntityService.addInvitationReward(fatherId, fatherAccount.getId(), rewardFather);
ShowkerInvitationRewardLog temp1 = new ShowkerInvitationRewardLog();
temp1.setBeneficiaryId(fatherId);
temp1.setInitiatorId(userId);
temp1.setInitiatorType(ShowkerInvitationRewardLog.InitiatorTypeEnum.REWARD_SIGN_UP.getCode());
temp1.setOfferType(ShowkerInvitationRewardLog.OfferTypeEnum.REWARD_FATHER.getCode());
List<ShowkerInvitationRewardLog> all = showkerInvitationRewardLogRepository.findAll(Example.of(temp1));
if (all != null && all.size() > 0) {
throw new CommonException("dont_resubmit", "请不要重复奖励");
}
try {
momentQueue.push(Moment.TypeEnum.SHOWKER_REG_REWARD, null, father.getPortraitPic(), father, rewardFather,
new JSONObject().fluentPut(Moment.TypeEnum.SHOWKER_REG_REWARD.getInfoKey(), userId)
.fluentPut("sonNickname", PhoneUtil.hideNickname(userRepository.findOne(userId).getNickname())));
} catch (Exception e) {
e.printStackTrace();
}
ShowkerInvitationRewardLog showkerInvitationRewardLog = new ShowkerInvitationRewardLog();
showkerInvitationRewardLog.setBeneficiaryId(fatherId);
showkerInvitationRewardLog.setBeneficiaryRole(showkerExtension.getRole());
showkerInvitationRewardLog.setInitiatorId(userId);
showkerInvitationRewardLog.setInitiatorType(ShowkerInvitationRewardLog.InitiatorTypeEnum.REWARD_SIGN_UP.getCode());
showkerInvitationRewardLog.setOfferType(ShowkerInvitationRewardLog.OfferTypeEnum.REWARD_FATHER.getCode());
showkerInvitationRewardLog.setRewardFee(rewardFather);
showkerInvitationRewardLog.setCreateTime(now);
showkerInvitationRewardLogRepository.save(showkerInvitationRewardLog);
reward += rewardFather;
}
if (forefatherId != null && rewardForefather > 0L) {
ShowkerExtension showkerExtension = showkerExtensionRepository.findByUserId(forefatherId);
User forefather = userRepository.findOne(forefatherId);
UserAccount forefatherAccount = forefather.getUserAccount();
// forefatherAccount.setInvitationReward((forefatherAccount.getInvitationReward() == null ? 0L : forefatherAccount.getInvitationReward()) + rewardForefather);
// forefatherAccount.setLastUpdateTime(new Date());
// userAccountRepository.save(forefatherAccount);
forefatherAccount = complexEntityService.addInvitationReward(forefatherId, forefatherAccount.getId(), rewardForefather);
ShowkerInvitationRewardLog temp2 = new ShowkerInvitationRewardLog();
temp2.setBeneficiaryId(forefatherId);
temp2.setInitiatorId(userId);
temp2.setInitiatorType(ShowkerInvitationRewardLog.InitiatorTypeEnum.REWARD_SIGN_UP.getCode());
temp2.setOfferType(ShowkerInvitationRewardLog.OfferTypeEnum.REWARD_FOREFATHER.getCode());
List<ShowkerInvitationRewardLog> all = showkerInvitationRewardLogRepository.findAll(Example.of(temp2));
if (all != null && all.size() > 0) {
throw new CommonException("dont_resubmit", "请不要重复奖励");
}
ShowkerInvitationRewardLog showkerInvitationRewardLog = new ShowkerInvitationRewardLog();
showkerInvitationRewardLog.setBeneficiaryId(forefatherId);
showkerInvitationRewardLog.setBeneficiaryRole(showkerExtension.getRole());
showkerInvitationRewardLog.setInitiatorId(userId);
showkerInvitationRewardLog.setInitiatorType(ShowkerInvitationRewardLog.InitiatorTypeEnum.REWARD_SIGN_UP.getCode());
showkerInvitationRewardLog.setOfferType(ShowkerInvitationRewardLog.OfferTypeEnum.REWARD_FOREFATHER.getCode());
showkerInvitationRewardLog.setRewardFee(rewardForefather);
showkerInvitationRewardLog.setCreateTime(now);
showkerInvitationRewardLogRepository.save(showkerInvitationRewardLog);
reward += rewardForefather;
}
if (reward > 0) {
//平台账户交易记录
TradingRecord pt = new TradingRecord(Constants.PING_TAI_ID, null, -reward, now,
TradingRecord.AccountChangeTypeEnum.XIUBA_RECORD.getCode(),
0L, UserRoleEnum.PING_TAI.getCode(),
TradingRecord.TradStateEnum.SUCCESS.getCode());
pt.setReferTradId(null);
pt.setReferUserId(userId);
pt.setTradTime(now);
pt.setFirstTradTime(now);
tradingRecordRepository.save(pt);
TradingRecordDetail trd = new TradingRecordDetail();
trd.setPlatform(TradingRecord.PlatformEnum.MOBILE_WAP_WECHAT.getCode());
trd.setCreateTime(now);
trd.setRole(UserRoleEnum.PING_TAI.getCode());
trd.setState(TradingRecordDetail.TradDetailStateEnum.SUCCESS.getCode());
trd.setTradAmount(-reward);
trd.setTradName(TradingRecordDetail.TradNameEnum.XIUBA_PLATFORM_PAY_FOR_INVITE_REWARDS_TO_WALLET_SHOWKER.getCode());
trd.setTradTime(now);
trd.setTradId(pt.getId());
trd.init(RandomStringUtils.random(5, true, true));
tradingRecordDetailRepository.save(trd);
}
return true;
}