package cc.mrbird.febs.mall.service.impl; import cc.mrbird.febs.common.enumerates.*; import cc.mrbird.febs.common.utils.AppContants; import cc.mrbird.febs.mall.entity.*; import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.*; import cc.mrbird.febs.mall.vo.AdminAgentLevelVo; import cc.mrbird.febs.mall.vo.AdminAgentMemberVo; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import jdk.nashorn.internal.ir.IfNode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; /** * @author wzy * @date 2021-09-26 **/ @Slf4j @Service @RequiredArgsConstructor public class AgentServiceImpl implements IAgentService { private final DataDictionaryCustomMapper dataDictionaryCustomMapper; private final MallMemberMapper memberMapper; private final MallOrderInfoMapper mallOrderInfoMapper; private final MallOrderItemMapper mallOrderItemMapper; private final IApiMallMemberWalletService iApiMallMemberWalletService; private final IMallMoneyFlowService mallMoneyFlowService; private final MallMemberMapper mallMemberMapper; @Override @Transactional(rollbackFor = Exception.class) public void autoUpAgentLevel(Long memberId) { MallMember member = memberMapper.selectById(memberId); if(StrUtil.isBlank(member.getReferrerIds())) { return; } List ids = StrUtil.split(member.getReferrerIds(), ','); List parentMembers = memberMapper.selectByInviteIds(ids); for (MallMember parent : parentMembers) { //level为v6,升级董事,则看团队下有没有两个V6 List mallMemberTeamMembers = memberMapper.selectAllChildAgentListByInviteId(parent.getInviteId()); if(CollUtil.isNotEmpty(mallMemberTeamMembers)){ List levelV6List = mallMemberTeamMembers.stream() .filter(teamMember -> teamMember.getLevel().equals(MemberLevelEnum.V6.getType())) .collect(Collectors.toList()); if(CollUtil.isNotEmpty(levelV6List) && levelV6List.size() >= 2){ parent.setLevel(MemberLevelEnum.V_DIRECTOR.getType()); parent.setDirector(AppContants.OPTION_YES); memberMapper.updateById(parent); continue; } } /** * 升级到董事就无法升级了 */ String nextLevelName = MemberLevelEnum.NORMAL.getNextLevel(parent.getLevel()); int levelCode = MemberLevelEnum.NORMAL.getLevelCode(nextLevelName); DataDictionaryCustom newLevelDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode("AGENT_PERK_SET", nextLevelName); if(ObjectUtil.isEmpty(newLevelDic)){ continue; } AdminAgentInfo adminAgentInfo = JSONObject.parseObject(newLevelDic.getValue(), AdminAgentInfo.class); if (!directMemberCnt(parent, adminAgentInfo)) { continue; } if (!teamIncome(parent, adminAgentInfo)) { continue; } parent.setLevel(nextLevelName); memberMapper.updateById(parent); } } /** * 判断直推人数是否达标 * * @param member * @return */ private boolean directMemberCnt(MallMember member, AdminAgentInfo agentInfo) { List childs = memberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(childs)) { return false; } if (childs.size() >= agentInfo.getDirectCnt()) { return true; } log.info("用户:{}直推数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), childs.size(), agentInfo.getDirectCnt()); return false; } /** * 判断下级代理数量是否达标 * * @return */ private boolean agentCntFinish(MallMember member, AgentInfo agentInfo) { if (agentInfo.getLastAgentCnt() == null || agentInfo.getLastAgentCnt() == 0) { return true; } // 直推用户 List directMember = memberMapper.selectByRefererId(member.getInviteId()); if (CollUtil.isEmpty(directMember)) { return false; } // 用户团队达到指定代理数量,且都不在同一条线 int i = 0; for (MallMember child : directMember) { List mallMembers = memberMapper.selectChildAgentList(child.getInviteId(), member.getLevel()); if (CollUtil.isNotEmpty(mallMembers)) { i++; } } if (i >= agentInfo.getLastAgentCnt()) { return true; } log.info("用户:{}代理数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getPhone(), member.getLevel(), i, agentInfo.getLastAgentCnt()); return false; } /** * 团队业绩是否达标 * 除去直属的最大的一个业绩团队,剩余的所有业绩之和 * * @param * @param agentInfo * @return */ private boolean teamIncome(MallMember member, AdminAgentInfo agentInfo) { BigDecimal teamIncome = agentInfo.getTeamIncome(); //业绩集合 List list = new ArrayList<>(); //总业绩 BigDecimal teamIncomeMax = BigDecimal.ZERO; //所有直推团队,就是这个会员的所有区域的业绩。 List mallMembers = mallMemberMapper.selectByRefererId(member.getInviteId()); List mallMemberInviteIds = mallMembers.stream().map(MallMember::getInviteId).collect(Collectors.toList()); for(String inviteId : mallMemberInviteIds){ BigDecimal totalIncomeMember = memberMapper.selectAllAchieveByInviteId(inviteId); teamIncomeMax = teamIncomeMax.add(totalIncomeMember); list.add(totalIncomeMember); } //去掉一个最大区的业绩 BigDecimal bigMax = list.stream().max(BigDecimal::compareTo).get(); teamIncomeMax = teamIncomeMax.subtract(bigMax); if (teamIncomeMax.compareTo(teamIncome) >= 0) { return true; } log.info("用户:{}团队业绩未达标, 当前等级:{}, 当前业绩:{}, 目标业绩:{}", member.getPhone(), member.getLevel(), teamIncomeMax, teamIncome); return false; } // public static void main(String[] args) { // BigDecimal q = new BigDecimal("100"); // BigDecimal q1 = new BigDecimal("99"); // BigDecimal q2 = new BigDecimal("100"); // BigDecimal q3= new BigDecimal("88"); // // List list = new ArrayList<>(); // list.add(q); // list.add(q1); // list.add(q2); // list.add(q3); // // BigDecimal bigMax = list.stream().max(BigDecimal::compareTo).get(); // System.out.println(bigMax); // } @Override @Transactional(rollbackFor = Exception.class) public void returnMoneyToAgent(Long orderId) { /** * 1、购买人获得固定比例的H金劵 * 2、直推获取8%的现金->余额,4%的H金劵->H金劵 * 3、不同代理级别获取不用的比例的现金和H金劵 * 4、董事享受全公司入单分红2%加权(现金) * 5、合伙人享全公司入单分红5%加权(现金) * 6、入单后,50%入现金池 35%的H金劵入H金劵池,更新价格 */ //获取当前订单子表信息 List mallOrderItemList = mallOrderItemMapper.selectbyOrderId(orderId); if(CollUtil.isEmpty(mallOrderItemList)){ return; } //获取订单中套餐的信息 List mallOrderItemIsTCs = mallOrderItemList.stream().filter(mallOrderItem -> mallOrderItem.getIsNormal() == 2).collect(Collectors.toList()); if(CollUtil.isEmpty(mallOrderItemIsTCs)){ return; } //获取订单中套餐总数金额 BigDecimal amountTCAll = mallOrderItemIsTCs.stream().map(MallOrderItem::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if(BigDecimal.ZERO.compareTo(amountTCAll) >= 0){ return; } BigDecimal amountTC = new BigDecimal(1000); //购买套餐按照1000的基数去补贴,如5000,则补贴5次1000 int times = amountTCAll.divideToIntegralValue(amountTC).intValue(); if(times < 1){ return; } for(int i = 0; i < times; i++){ MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(orderId); String orderNo = mallOrderInfo.getOrderNo(); //购买人 Long memberId = mallOrderInfo.getMemberId(); /** * 1、购买人获得固定比例的H金劵 * = amountTC * 固定比例 */ perkMember(memberId, PerkEnum.BUY_SET_MEAL_PERK_PERCENT, amountTC, "score", MoneyFlowTypeEnum.BUY_SET_MEAL_PERK.getValue(), memberId, FlowTypeEnum.SCORE.getValue(), orderNo); /** * 2、直推获取8%的现金->余额,4%的H金劵->H金劵 */ MallMember mallMember = mallMemberMapper.selectById(memberId); if(ObjectUtil.isNotEmpty(mallMember.getReferrerId())){ String referrerId = mallMember.getReferrerId(); MallMember mallMemberDirect = mallMemberMapper.selectInfoByInviteId(referrerId); Long directMemberId = mallMemberDirect.getId(); perkMember(directMemberId, PerkEnum.DIRECT_CASH_PERK_PERCENT, amountTC, "balance", MoneyFlowTypeEnum.DIRECT_CASH_PERK.getValue(), memberId, FlowTypeEnum.BALANCE.getValue(), orderNo); perkMember(directMemberId, PerkEnum.DIRECT_SCORE_PERK_PERCENT, amountTC, "score", MoneyFlowTypeEnum.DIRECT_SCORE_PERK.getValue(), memberId, FlowTypeEnum.SCORE.getValue(), orderNo); } /** * 4、董事享受全公司入单分红2%加权(现金) */ List mallMembersDirectors = mallMemberMapper.selectDirectorsOrStoreMaster(1); if(CollUtil.isNotEmpty(mallMembersDirectors)){ perkMembersLevel(mallMembersDirectors, PerkEnum.DIRECTOR_CASH_PERK_PERCENT, amountTC, "balance", MoneyFlowTypeEnum.DIRECTOR_CASH_PERK.getValue(), memberId, FlowTypeEnum.BALANCE.getValue(), orderNo); } /** * 5、合伙人享全公司入单分红5%加权(现金) */ List mallMemberPartners = mallMemberMapper.selectDirectorsOrStoreMaster(3); if(CollUtil.isNotEmpty(mallMemberPartners)){ perkMembersLevel(mallMemberPartners, PerkEnum.PARTNER_CASH_PERK_PERCENT, amountTC, "balance", MoneyFlowTypeEnum.PARTNER_CASH_PERK.getValue(), memberId, FlowTypeEnum.BALANCE.getValue(), orderNo); } /** * 3、团队下不同代理级别获取不用的比例的现金和H金劵 */ if(StrUtil.isNotEmpty(mallMember.getReferrerIds())){ //团队补贴对象 // List mallMemberTeamPerk = new ArrayList<>(); String referrerIds = mallMember.getReferrerIds(); List referrerIdList = StrUtil.splitTrim(referrerIds, ","); if(CollUtil.isNotEmpty(referrerIdList)){ List mallMemberTeamPerk = mallMemberMapper.selectByInviteIds(referrerIdList); if(CollUtil.isNotEmpty(mallMemberTeamPerk)){ String levelNormal = MemberLevelEnum.V1.getType(); BigDecimal cashPercentNormal = BigDecimal.ZERO; BigDecimal scorePercentNormal = BigDecimal.ZERO; DataDictionaryCustom poolScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_SCORE_PRICE.getType(), PerkEnum.POOL_SCORE_PRICE.getCode()); BigDecimal poolScorePrice = new BigDecimal(poolScorePriceDic.getValue() == null ? "1" : poolScorePriceDic.getValue()); for(MallMember teamPerkMember : mallMemberTeamPerk){ String level = teamPerkMember.getLevel(); //比较两个级别的大小,level大于levelNormal返回1 int compareMin = MemberLevelEnum.V1.compareLevel(level, levelNormal); int compareMax = MemberLevelEnum.V1.compareLevel(MemberLevelEnum.V6.getType(), level); if(compareMin >= 1 && compareMax >= 1){ Long teamPerkMemberId = teamPerkMember.getId(); DataDictionaryCustom teamPerkMemberDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( "AGENT_PERK_SET", level); AdminAgentInfo adminAgentInfo = JSONObject.parseObject(teamPerkMemberDic.getValue(), AdminAgentInfo.class); BigDecimal cashPercent = adminAgentInfo.getCashPercent().multiply(AppContants.PERCENTAGE); BigDecimal scorePercent = adminAgentInfo.getScorePercent().multiply(AppContants.PERCENTAGE); //极差 cashPercent = cashPercent.subtract(cashPercentNormal); scorePercent = scorePercent.subtract(scorePercentNormal); BigDecimal cashAmount = amountTC.multiply(cashPercent).setScale(2, BigDecimal.ROUND_DOWN); //如果是H金劵,除以当前价格,得到数量。 BigDecimal scoreCnt = amountTC.multiply(scorePercent).setScale(2, BigDecimal.ROUND_DOWN); scoreCnt = scoreCnt.divide(poolScorePrice, 2 ,BigDecimal.ROUND_DOWN); if(cashAmount.compareTo(BigDecimal.ZERO) > 0){ addWalletInfoAndMoneyFlow(cashAmount, teamPerkMemberId, "balance", MoneyFlowTypeEnum.AGENT_CASH_PERK.getValue(), memberId, FlowTypeEnum.BALANCE.getValue(), orderNo); } if(scoreCnt.compareTo(BigDecimal.ZERO) > 0){ addWalletInfoAndMoneyFlow(scoreCnt, teamPerkMemberId, "score", MoneyFlowTypeEnum.AGENT_SCORE_PERK.getValue(), memberId, FlowTypeEnum.SCORE.getValue(), orderNo); } levelNormal = level; cashPercentNormal = adminAgentInfo.getCashPercent().multiply(AppContants.PERCENTAGE); scorePercentNormal = adminAgentInfo.getScorePercent().multiply(AppContants.PERCENTAGE); } } } } } /** * 6、入单后,50%入现金池 35%的H金劵入H金劵池,更新价格 */ DataDictionaryCustom poolCashPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_CASH_PERCENT.getType(), PerkEnum.POOL_CASH_PERCENT.getCode()); DataDictionaryCustom poolScorePercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_SCORE_PERCENT.getType(), PerkEnum.POOL_SCORE_PERCENT.getCode()); if(ObjectUtil.isNotEmpty(poolCashPercentDic)){ BigDecimal poolCashPercent = new BigDecimal(poolCashPercentDic.getValue()).multiply(AppContants.PERCENTAGE); //新增现金数量 BigDecimal poolCashAdd = amountTC.multiply(poolCashPercent); DataDictionaryCustom poolCashDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_CASH.getType(), PerkEnum.POOL_CASH.getCode()); //当前现金池数量 BigDecimal poolCash = new BigDecimal(poolCashDic.getValue()); poolCash = poolCash.add(poolCashAdd).setScale(2,BigDecimal.ROUND_DOWN); dataDictionaryCustomMapper.updateDicValueByTypeAndCode( PerkEnum.POOL_CASH.getType(), PerkEnum.POOL_CASH.getCode(), poolCash.toString() ); DataDictionaryCustom poolScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_SCORE_PRICE.getType(), PerkEnum.POOL_SCORE_PRICE.getCode()); BigDecimal poolScorePrice = new BigDecimal(poolScorePriceDic.getValue() == null ? "1" : poolScorePriceDic.getValue()); BigDecimal poolScorePercent = new BigDecimal(poolScorePercentDic.getValue()).multiply(AppContants.PERCENTAGE); //新增H金劵数量 BigDecimal poolScoreAdd = amountTC.multiply(poolScorePercent); poolScoreAdd = poolScoreAdd.divide(poolScorePrice,2,BigDecimal.ROUND_DOWN); DataDictionaryCustom poolScoreDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_SCORE.getType(), PerkEnum.POOL_SCORE.getCode()); //当前H金劵池数量 BigDecimal poolScore = new BigDecimal(poolScoreDic.getValue()); poolScore = poolScore.add(poolScoreAdd).setScale(2,BigDecimal.ROUND_DOWN); dataDictionaryCustomMapper.updateDicValueByTypeAndCode( PerkEnum.POOL_SCORE.getType(), PerkEnum.POOL_SCORE.getCode(), poolScore.toString() ); if(poolScore.compareTo(BigDecimal.ZERO) > 0 && poolCash.compareTo(BigDecimal.ZERO) > 0){ BigDecimal divide = poolCash.divide(poolScore, 7, BigDecimal.ROUND_DOWN); dataDictionaryCustomMapper.updateDicValueByTypeAndCode( PerkEnum.POOL_SCORE_PRICE.getType(), PerkEnum.POOL_SCORE_PRICE.getCode(), divide.toString() ); } } } } /** * 给某一个用户根据订单金额去加权平分 * @param memberId 用户ID * @param perkEnum 比例的枚举值 * @param amountTC 总金额 * @param walletField 类型:score:H金劵 balance:余额 * @param type 流水类型 * @param flowType 流水分类 * @param orderNo 订单编号 */ private void perkMember(Long memberId,PerkEnum perkEnum,BigDecimal amountTC,String walletField,int type,Long rtMemberId,int flowType,String orderNo){ DataDictionaryCustom perkEnumDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( perkEnum.getType(), perkEnum.getCode()); if(ObjectUtil.isNotEmpty(perkEnumDic)){ BigDecimal perkEnumDicPercent = new BigDecimal(perkEnumDic.getValue() == null ? "0" : perkEnumDic.getValue()); //获得数量 BigDecimal perkEnumDicPercentPerk = perkEnumDicPercent.multiply(AppContants.PERCENTAGE).multiply(amountTC).setScale(2, BigDecimal.ROUND_DOWN); //如果是H金劵,除以当前价格,得到数量。 if(walletField.equals("score")){ DataDictionaryCustom poolScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( PerkEnum.POOL_SCORE_PRICE.getType(), PerkEnum.POOL_SCORE_PRICE.getCode()); BigDecimal poolScorePrice = new BigDecimal(poolScorePriceDic.getValue() == null ? "1" : poolScorePriceDic.getValue()); perkEnumDicPercentPerk = perkEnumDicPercentPerk.divide(poolScorePrice, 2 ,BigDecimal.ROUND_DOWN); } if(perkEnumDicPercentPerk.compareTo(BigDecimal.ZERO) > 0){ addWalletInfoAndMoneyFlow(perkEnumDicPercentPerk,memberId,walletField,type,rtMemberId,flowType,orderNo); } } } /** * 操作用户钱包数据,增加流水 * @param amount * @param memberId * @param walletField * @param type * @param flowType * @param orderNo */ private void addWalletInfoAndMoneyFlow(BigDecimal amount,Long memberId,String walletField,int type,Long rtMemberId,int flowType,String orderNo){ //增加 iApiMallMemberWalletService.add(amount,memberId,walletField); //增加一个流水记录 mallMoneyFlowService.addMoneyFlow( memberId, amount, type, orderNo, rtMemberId, flowType, AppContants.IS_RETURN_YES); } /** * 按照级别,根据订单金额去加权平分 * @param mallMembers 用户 * @param perkEnum 比例的枚举值 * @param amountTC 总金额 * @param walletField 类型:score:积分 balance:余额 * @param type 流水类型 * @param flowType 流水分类 * @param orderNo 订单编号 */ private void perkMembersLevel(List mallMembers,PerkEnum perkEnum,BigDecimal amountTC,String walletField,int type,Long rtMemberId,int flowType,String orderNo){ DataDictionaryCustom perkEnumDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( perkEnum.getType(), perkEnum.getCode()); if(ObjectUtil.isNotEmpty(perkEnumDic)){ BigDecimal perkEnumDicPercent = new BigDecimal(perkEnumDic.getValue() == null ? "0" : perkEnumDic.getValue()); //获得的现金 BigDecimal perkEnumDicPercentPerkSum = perkEnumDicPercent.multiply(AppContants.PERCENTAGE).multiply(amountTC).setScale(2, BigDecimal.ROUND_DOWN); //然后董事平分 BigDecimal perkEnumDicPercentPerk = perkEnumDicPercentPerkSum.divide(new BigDecimal(mallMembers.size()), 2, BigDecimal.ROUND_DOWN); if(perkEnumDicPercentPerk.compareTo(BigDecimal.ZERO) > 0){ for(MallMember mallMember : mallMembers){ Long memberId = mallMember.getId(); addWalletInfoAndMoneyFlow(perkEnumDicPercentPerk,memberId,walletField,type,rtMemberId,flowType,orderNo); } } } } @Override public void rankReturnMoney(Long orderId) { } public static void main(String[] args) { BigDecimal total = new BigDecimal(100000); BigDecimal amountTotal = BigDecimal.ZERO; BigDecimal scoreTotal = BigDecimal.ZERO; BigDecimal amountBasic = new BigDecimal(100); BigDecimal price = new BigDecimal(0.01); BigDecimal amountPercent = new BigDecimal(0.5); BigDecimal scorePercent = new BigDecimal(0.35); int times = total.divideToIntegralValue(amountBasic).intValue(); System.out.println("循环次数:"+times); for(int i = 0; i < times; i++){ BigDecimal amount = amountBasic.multiply(amountPercent); amountTotal = amountTotal.add(amount); BigDecimal score = amountBasic.multiply(scorePercent).divide(price, 2 ,BigDecimal.ROUND_DOWN); scoreTotal = scoreTotal.add(score); price = amountTotal.divide(scoreTotal, 7 ,BigDecimal.ROUND_DOWN); System.out.println("现金池:"+amountTotal+",积分池:"+scoreTotal+",增长现金:"+amount+"增长积分:"+score+",价格:"+price); } } }