package com.ydtech.modules.partner.utils; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ydtech.modules.partner.dao.PartnerPremiumDetailsMapper; import com.ydtech.modules.partner.dao.PartnerUserMapper; import com.ydtech.modules.partner.model.PartnerCommissionRules; import com.ydtech.modules.partner.model.PartnerPremiumDetails; import com.ydtech.modules.partner.model.PartnerRatio; import com.ydtech.modules.partner.model.PartnerUser; import com.ydtech.modules.partner.model.param.CommissionValidityPeriod; import com.ydtech.modules.partner.model.vo.CommissionRulesVo; import com.ydtech.modules.partner.model.vo.PartnerRulesRatio; import com.ydtech.modules.partner.service.PartnerCommissionService; import com.ydtech.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.PostConstruct; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @Component public class CalculateCommissionUtils { private static final Logger log = LoggerFactory.getLogger(CalculateCommissionUtils.class); private static PartnerCommissionService commissionService; private static PartnerUserMapper partnerUserMapper; private static PartnerPremiumDetailsMapper partnerPremiumDetailsMapper; @Autowired public void setCommissionService(PartnerCommissionService commissionService, PartnerUserMapper partnerUserMapper, PartnerPremiumDetailsMapper partnerPremiumDetailsMapper) { CalculateCommissionUtils.commissionService = commissionService; CalculateCommissionUtils.partnerUserMapper = partnerUserMapper; CalculateCommissionUtils.partnerPremiumDetailsMapper = partnerPremiumDetailsMapper; } @PostConstruct public void init() { } private static class CommissionValues { BigDecimal sumPremium; BigDecimal number; BigDecimal grBf; CommissionValues(BigDecimal sumPremium, BigDecimal number,BigDecimal grBf) { this.sumPremium = sumPremium; this.number = number; this.grBf = grBf; } } private static CommissionValues calculateCommonValues(String grade, String userId, PartnerCommissionRules rules,String type,String userId3,String userId4) { CommissionValidityPeriod period = new CommissionValidityPeriod(); Set userIdList = Collections.emptySet(); BigDecimal grBf = null; if (StringUtils.equals("gzs", type)){ period = getCommissionValidityPeriod(rules, userId4, "4"); grBf = queryPersonalInsurancePremiums(userId4,period); userIdList = partnerUserMapper.querySubordinateUserId(userId4); }else if (StringUtils.equals("hh", type)){ period = getCommissionValidityPeriod(rules, userId3, "3"); grBf = queryPersonalInsurancePremiums(userId3,period); userIdList = partnerUserMapper.querySubordinate(userId3); } BigDecimal sumPremium = BigDecimal.ZERO; if (CollectionUtil.isNotEmpty(userIdList)) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.in("user_id", userIdList); if (StringUtils.isNotEmpty(period.getStartDate()) && StringUtils.isNotEmpty(period.getEndDate())) { queryWrapper.between("create_time", period.getStartDate(), period.getEndDate()); } BigDecimal totalSumPremium = partnerPremiumDetailsMapper.selectTotalSumPremium(queryWrapper); sumPremium = Optional.ofNullable(totalSumPremium).orElse(BigDecimal.ZERO); } Integer number = 0; if (StringUtils.equals("gzs", type)){ number = partnerUserMapper.selectNumber(userId4, "5", period); }else if (StringUtils.equals("hh", type)){ number = partnerUserMapper.selectNumber(userId3, "4", period); } if (log.isInfoEnabled()) { log.info("用户id{}++{}级用户++出单人的上级用户{}++统计的保单金额{}++统计的邀请人数{}", userId, grade, userId3, sumPremium, number); } return new CommissionValues(sumPremium, new BigDecimal(number),grBf); } public static BigDecimal queryPersonalInsurancePremiums(String userId,CommissionValidityPeriod period){ BigDecimal bigDecimal = partnerUserMapper.selectOwnSumPremium(userId, period); return null == bigDecimal ? BigDecimal.ZERO : bigDecimal; } public static String getReason(String grade, String userId,String userId3,String userId4) { CommissionRulesVo rulesVo = commissionService.queryAll(); if (rulesVo == null) return null; if (StringUtils.equals("1", grade)){ return null; } if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){ return obtainReason(grade, rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),"hh",userId3,userId4); } if (StringUtils.equals("4", grade)){ return obtainReason(grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),"gzs",userId3,userId4); } return null; } public static String querySuperiorAndSubordinate(String issuerId,String grade){ QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", issuerId); PartnerUser issuerUser = partnerUserMapper.selectOne(queryWrapper); if (Objects.isNull(issuerUser)){ return null; } return getLevelUserId(issuerUser.getUserId(), issuerUser.getGrade(), grade); } public static BigDecimal calculateCommission(String grade, String userId,String userId3,String userId4) { CommissionRulesVo rulesVo = commissionService.queryAll(); if (rulesVo == null) return BigDecimal.ZERO; BigDecimal gl = BigDecimal.ZERO; if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){ gl = ladderCommission(grade,rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),"hh", userId3, userId4); } BigDecimal hh = BigDecimal.ZERO; if (StringUtils.equals("4", grade) || StringUtils.equals("3", grade)){ hh = ladderCommission(grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),"gzs",userId3, userId4); } if (StringUtils.equals("4", grade)){ BigDecimal bigDecimal = partnerUserMapper.selectFixedRatio(userId4, grade); if (null != bigDecimal){ return bigDecimal; } }else if (StringUtils.equals("3", grade)){ BigDecimal gzs = partnerUserMapper.selectFixedRatio(userId4, String.valueOf(Integer.valueOf(grade) + 1)); BigDecimal hhr = partnerUserMapper.selectFixedRatio(userId3, grade); if (null != gzs && null != hhr){ BigDecimal a1 = new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(gzs); return a1.add(hhr); }else if (null == gzs && null != hhr){ if (isZero(hh)){ return hhr.add(new BigDecimal(rulesVo.getPartner().getDefaultRatio())); }else { return hhr.add(new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(hh)); } }if (null != gzs && null == hhr){ BigDecimal a2; if (isZero(gl)){ a2 = new BigDecimal(rulesVo.getAdministrator().getSharedRatio()).subtract(new BigDecimal(rulesVo.getAdministrator().getDefaultRatio())); }else { a2 = gl; } return new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(gzs).add(a2); } }else if (StringUtils.equals("2", grade)){ BigDecimal hhr = partnerUserMapper.selectFixedRatio(userId3, String.valueOf(Integer.valueOf(grade) + 1)); if (null != hhr){ return new BigDecimal(rulesVo.getAdministrator().getSharedRatio()).subtract(hhr); } } return calculateProportion(grade,rulesVo,gl,hh); } public static BigDecimal calculateProportion(String grade, CommissionRulesVo rulesVo,BigDecimal gl,BigDecimal hh) { if (StringUtils.equals("1", grade)) { return new BigDecimal(rulesVo.getOriginator()); } if (StringUtils.equals("2", grade)) { PartnerCommissionRules administrator = rulesVo.getAdministrator(); if (isZero(gl)){ return new BigDecimal(administrator.getDefaultRatio()); }else { return new BigDecimal(administrator.getSharedRatio()).subtract(gl); } } if (StringUtils.equals("3", grade)) { PartnerCommissionRules partner = rulesVo.getPartner(); if (isZero(gl) && isZero(hh)) { return new BigDecimal(partner.getDefaultRatio()) .add(subtractRatios(rulesVo.getAdministrator().getSharedRatio(), rulesVo.getAdministrator().getDefaultRatio())); } else if (isZero(hh) && !isZero(gl)) { return gl.add(new BigDecimal(partner.getDefaultRatio())); } else if (isZero(gl) && !isZero(hh)) { return new BigDecimal(partner.getSharedRatio()).subtract(hh) .add(subtractRatios(rulesVo.getAdministrator().getSharedRatio(), rulesVo.getAdministrator().getDefaultRatio())); }else{ return gl.add(new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(hh)); } } if (StringUtils.equals("4", grade)) { return isZero(hh) ? subtractRatios(rulesVo.getPartner().getSharedRatio(), rulesVo.getPartner().getDefaultRatio()) : hh; } return BigDecimal.ZERO; } private static boolean isZero(BigDecimal value) { return value.compareTo(BigDecimal.ZERO) == 0; } private static BigDecimal subtractRatios(String a, String b) { return new BigDecimal(a).subtract(new BigDecimal(b)); } public static BigDecimal ladderCommission(String grade, List rulesRatioList, String userId, PartnerCommissionRules rules, String type,String userId3,String userId4) { CommissionValues values = calculateCommonValues(grade, userId, rules,type,userId3,userId4); List sortedList = rulesRatioList.stream() .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed()) .collect(Collectors.toList()); for (PartnerRulesRatio ratio : sortedList) { BigDecimal result = handleRatioCondition(ratio, values.number, values.sumPremium,values.grBf); if (result.compareTo(BigDecimal.ZERO) > 0) { return result; } } return BigDecimal.ZERO; } private static BigDecimal handleRatioCondition(PartnerRulesRatio ratio, BigDecimal numberBD, BigDecimal sumPremium, BigDecimal grBf) { List ratioList = ratio.getPartnerRatioList(); if (CollectionUtil.isEmpty(ratioList)) { return BigDecimal.ZERO; } boolean[] conditions = { ratioList.get(0).isRy(), ratioList.get(1).isBf(), ratioList.get(2).isGr() }; BigDecimal[] values = {numberBD, sumPremium, grBf}; BigDecimal[] min = { ratioList.get(0).getMin(), ratioList.get(1).getMin(), ratioList.get(2).getMin() }; int allSatisfied = ratio.getAllSatisfied(); boolean anyConditionMet = false; boolean allConditionsMet = true; for (int i = 0; i < conditions.length; i++) { if (conditions[i]) { int comparison = values[i].compareTo(min[i]); anyConditionMet = anyConditionMet || (comparison >= 0); allConditionsMet = allConditionsMet && (comparison >= 0); } } if ((allSatisfied == 1 && allConditionsMet) || (allSatisfied != 1 && anyConditionMet)) { return ratio.getKickback(); } return BigDecimal.ZERO; } public static String obtainReason(String grade, List rulesRatioList, String userId, PartnerCommissionRules rules,String type,String userId3,String userId4) { List sortedList = rulesRatioList.stream() .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed()) .collect(Collectors.toList()); CommissionValues values = calculateCommonValues(grade, userId, rules,type,userId3,userId4); BigDecimal numberBD = values.number; BigDecimal sumPremium = values.sumPremium; BigDecimal grBf = values.grBf; for (PartnerRulesRatio ratio : sortedList) { int allSatisfied = ratio.getAllSatisfied(); List ratioList = ratio.getPartnerRatioList(); if (CollectionUtil.isEmpty(ratioList)) continue; BigDecimal min = ratioList.get(0).getMin(); BigDecimal min1 = ratioList.get(1).getMin(); BigDecimal grb = ratioList.get(2).getMin(); boolean ry = ratioList.get(0).isRy(); boolean bf = ratioList.get(1).isBf(); boolean gr = ratioList.get(2).isGr(); if (ry && bf && gr) { if (allSatisfied == 1) { if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0 && grBf.compareTo(grb) >= 0) { return "邀请人达" + min + "人,累计保费达" + min1 + "元" + ",个人保费达" + grb + "元"; } } else { if (numberBD.compareTo(min) >= 0) { return "邀请人达" + min + "人"; }else if(sumPremium.compareTo(min1) >= 0){ return "累计保费达" + min1 + "元"; }else if(grBf.compareTo(grb) >= 0){ return "个人保费达" + grb + "元"; } } }else if (ry && gr && !bf ){ if (allSatisfied != 1) { if (numberBD.compareTo(min) >= 0 && grBf.compareTo(grb) >= 0) { return "邀请人达" + min + "人" + ",个人保费达" + grb + "元"; } } }else if (!ry && gr && bf){ if (allSatisfied != 1) { if (sumPremium.compareTo(min1) >= 0 && grBf.compareTo(grb) >= 0) { return "累计保费达" + min1 + "元" + ",个人保费达" + grb + "元"; } } }else if (ry && !gr && bf){ if (allSatisfied != 1) { if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0) { return "邀请人达" + min + "人" + ",累计保费达" + min1 + "元"; } } } } return null; } public static String getLevelUserId(String userId,Integer grade,String queryLevel){ PartnerUser partnerUser = partnerUserMapper.getLevelUserId(userId,grade); while (partnerUser != null){ Integer userGrade = partnerUser.getGrade(); if (userGrade != null && userGrade.toString().equals(queryLevel)){ return partnerUser.getUserId(); } userId = partnerUser.getReferrerId(); if (userId == null) { return null; } grade--; partnerUser = partnerUserMapper.getLevelUserId(userId, grade); } return null; } public static CommissionValidityPeriod getCommissionValidityPeriod(PartnerCommissionRules rules, String userId, String grade) { CommissionValidityPeriod period = new CommissionValidityPeriod(); if (rules == null || StringUtils.isBlank(rules.getValidityPeriod())) { return period; } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { if (StringUtils.equals("1", rules.getValidityPeriod())) { return period; } else if (StringUtils.equals("2", rules.getValidityPeriod())) { Date assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade); if (assessmentTime == null) { partnerUserMapper.updateAssessmentTime(userId); assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade); if (Objects.isNull(assessmentTime)){ return period; } } if (!PartnerDateUtils.isWithinDays(assessmentTime, rules.getFixedDays())) { updateAssessmentTimeRecursively(assessmentTime,rules.getFixedDays(),userId,grade ); assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade); } period.setStartDate(dateFormat.format(assessmentTime)); period.setEndDate(dateFormat.format(PartnerDateUtils.addDays(assessmentTime, rules.getFixedDays()))); } else if (StringUtils.equals("3", rules.getValidityPeriod())) { Date fixedCycle = partnerUserMapper.selectFixedCycleTime(userId, grade); if (fixedCycle == null) { partnerUserMapper.updateFixedCycleTime(userId); fixedCycle = partnerUserMapper.selectFixedCycleTime(userId, grade); if (fixedCycle == null){ return period; } } period.setStartDate(rules.getStartDate()); period.setEndDate(rules.getEndDate()); } } catch (Exception e) { log.error("获取佣金有效期异常,userId:{}, grade:{}", userId, grade, e); } return period; } private static void updateAssessmentTimeRecursively(Date assessmentTime, int days, String userId,String grade) { Date newDate = PartnerDateUtils.addDaysToday(assessmentTime, days); while (!PartnerDateUtils.isWithinDays(newDate, days)) { newDate = PartnerDateUtils.addDaysToday(newDate, days); } partnerUserMapper.updateAssessmentTimeByDate(userId,newDate,grade); } }