package com.ydtech.modules.partner; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.extra.spring.SpringUtil; 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.*; 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.modules.partner.service.PartnerKickbackChangeService; import com.ydtech.modules.partner.service.PartnerUserService; import com.ydtech.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; @Component public class UpdateRatioUtils { private static final Logger log = LoggerFactory.getLogger(UpdateRatioUtils.class); private static PartnerCommissionService commissionService; private static PartnerUserMapper partnerUserMapper; private static PartnerPremiumDetailsMapper partnerPremiumDetailsMapper; private static PartnerUserService partnerUserService; private static PartnerKickbackChangeService kickbackChangeService; @Autowired public void setCommissionService(PartnerCommissionService commissionService, PartnerUserMapper partnerUserMapper, PartnerKickbackChangeService kickbackChangeService, PartnerPremiumDetailsMapper partnerPremiumDetailsMapper, PartnerUserService partnerUserService) { UpdateRatioUtils.commissionService = commissionService; UpdateRatioUtils.partnerUserMapper = partnerUserMapper; UpdateRatioUtils.partnerPremiumDetailsMapper = partnerPremiumDetailsMapper; UpdateRatioUtils.partnerUserService = partnerUserService; UpdateRatioUtils.kickbackChangeService = kickbackChangeService; } @PostConstruct public void init() { } public void loginBefore(String userId){ Map allByUserId = getAllByUserId(userId); allByUserId.forEach((key, value) -> { BigDecimal latest = calculateCommission(String.valueOf(key),value.getUserId(),allByUserId); initializeCommissionRatio(value, latest); }); } private void initializeCommissionRatio(PartnerUser value, BigDecimal latest) { BigDecimal mostRecent = SpringUtil.getBean(PartnerKickbackChangeService.class).mostRecentRecord(value.getUserId(),String.valueOf(value.getGrade())); if (mostRecent == null){ PartnerKickbackChange change = new PartnerKickbackChange(); change.setUserId(value.getUserId()); change.setUserGrade(String.valueOf(value.getGrade())); change.setOriginalCommission(latest); change.setAfterChange(null); change.setDeptId(value.getDeptId()); change.setChangeTime(new Date()); kickbackChangeService.saveKickbackChange(change); } } public void loginChange(String userId){ Map allByUserId = getAllByUserId(userId); saveChange(allByUserId); } public Map getAllByUserId(String userId) { Map map = new HashMap<>(); List userList = partnerUserMapper.queryByUserId(userId); if (CollectionUtil.isNotEmpty(userList)) { for (PartnerUser user : userList) { getMap(map, user); } } return map; } private static void saveChange(Map map) { List kickbackChange = new ArrayList<>(); for (Map.Entry entry : map.entrySet()) { String key = String.valueOf(entry.getKey()); PartnerUser value = entry.getValue(); BigDecimal latest = calculateCommission(key,value.getUserId(),map); BigDecimal mostRecent = SpringUtil.getBean(PartnerKickbackChangeService.class).mostRecentRecord(value.getUserId(),key); getPartnerKickbackChange(latest, mostRecent, value, kickbackChange,map); } for (PartnerKickbackChange change : kickbackChange) { kickbackChangeService.saveKickbackChange(change); } } private static void getMap(Map map, PartnerUser user) { map.put(user.getGrade(), user); while (true) { Integer userGrade = user.getGrade(); int i = userGrade - 1; if (0 == i) { break; } user = partnerUserMapper.queryUser(user.getReferrerId(),i ); if (user == null) { break; } map.put(user.getGrade(),user); } } public void before(String referrerId, Integer grade){ Map map = new HashMap<>(); PartnerUser user = partnerUserMapper.queryUser(referrerId, grade); if (user != null) { getMap(map, user); } for (Map.Entry entry : map.entrySet()) { String key = String.valueOf(entry.getKey()); PartnerUser value = entry.getValue(); BigDecimal latest = calculateCommission(key,value.getUserId(),map); initializeCommissionRatio(value, latest); } } public void addChangeRecord(String userId){ Map allByUserId = getAllByUserId(userId); saveChange(allByUserId); } public static void getPartnerKickbackChange(BigDecimal latest,BigDecimal mostRecent,PartnerUser details,List list,Map map){ if (mostRecent == null){ PartnerKickbackChange change = getChange(null, latest, details,map); list.add( change); }else { if (latest.compareTo(mostRecent) != 0){ PartnerKickbackChange change = getChange(latest, mostRecent, details,map); list.add( change); } } } private static PartnerKickbackChange getChange(BigDecimal bigDecimal, BigDecimal mostRecent, PartnerUser details,Map map) { PartnerKickbackChange change = new PartnerKickbackChange(); change.setUserId(details.getUserId()); change.setUserGrade(String.valueOf(details.getGrade())); change.setOriginalCommission(mostRecent); change.setAfterChange(bigDecimal); String reason = getReason(String.valueOf(details.getGrade()), details.getUserId(),map); change.setChangeReason(reason); change.setDeptId(details.getDeptId()); change.setChangeTime(new Date()); return change; } public String getValue(Map map, Integer grade) { if (map == null) { return ""; } String value = map.get(grade); return value != null ? value : ""; } public static BigDecimal calculateCommission(String grade, String userId,Map map) { CommissionRulesVo rulesVo = commissionService.queryAll(); if (rulesVo == null) return BigDecimal.ZERO; BigDecimal gl = BigDecimal.ZERO; if (StringUtils.equals("1", grade)){ gl = BigDecimal.ZERO; } if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){ gl = ladderCommission("gl" , grade, rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),map); } BigDecimal hh = BigDecimal.ZERO; if (StringUtils.equals("3", grade) || StringUtils.equals("4", grade)){ hh = ladderCommission(StringUtils.equals("3",grade) ? "levelGzs" :"gzs",grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),map); } 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; } public static String getReason(String grade, String userId,Map map) { CommissionRulesVo rulesVo = commissionService.queryAll(); if (rulesVo == null) return null; BigDecimal gl = BigDecimal.ZERO; if (StringUtils.equals("1", grade)){ return ""; } if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){ return obtainReason("gl" , grade, rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),map); } BigDecimal hh = BigDecimal.ZERO; if (StringUtils.equals("3", grade) || StringUtils.equals("4", grade)){ return obtainReason(StringUtils.equals("3",grade) ? "levelGzs" :"gzs",grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),map); } return null; } public static String obtainReason(String type, String grade, List rulesRatioList, String userId, PartnerCommissionRules rules,Map map) { CommissionValidityPeriod period = CalculateCommissionUtils.getCommissionValidityPeriod(rules, userId, grade); List sortedList = rulesRatioList.stream() .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed()) .collect(Collectors.toList()); BigDecimal sumPremium = BigDecimal.ZERO; Set userIdList = new HashSet<>(0); if(StringUtils.equals("2",grade)){ PartnerUser s = map.get(3); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } if (StringUtils.equals("3",grade) ){ PartnerUser s = map.get(4); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } if (StringUtils.equals("4",grade)){ PartnerUser s = map.get(4); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } 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; switch (type) { case "gl": PartnerUser s = map.get(3); if (!Objects.isNull( s)){ number = partnerUserMapper.selectNumber(s.getUserId(), "4", period); } break; case "levelGzs": PartnerUser s1 = map.get(4); if (!Objects.isNull( s1)){ number = partnerUserMapper.selectNumber4(s1.getUserId(), "5", period); } break; case "gzs": number = partnerUserMapper.selectByUserIdNumber(userId, "5", period); break; default: return null; } BigDecimal numberBD = BigDecimal.valueOf(number); 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(); boolean ry = ratioList.get(0).isRy(); boolean bf = ratioList.get(1).isBf(); if (ry && bf) { if (allSatisfied == 1) { if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0) { return "邀请人达" + min + "人,累计保费达" + min1 + "元"; } } else { if (numberBD.compareTo(min) >= 0) { return "邀请人达" + min + "人"; }else if(sumPremium.compareTo(min1) >= 0){ return "累计保费达" + min1 + "元"; } } }else if (ry && !bf){ if (allSatisfied != 1) { if (numberBD.compareTo(min) >= 0) { return "邀请人达" + min + "人"; } } }else if (!ry && bf){ if (allSatisfied != 1) { if (sumPremium.compareTo(min1) >= 0) { return "累计保费达" + min1 + "元"; } } } } return null; } public static BigDecimal ladderCommission(String type, String grade, List rulesRatioList, String userId, PartnerCommissionRules rules,Map map) { CommissionValidityPeriod period = CalculateCommissionUtils.getCommissionValidityPeriod(rules, userId, grade); List sortedList = rulesRatioList.stream() .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed()) .collect(Collectors.toList()); BigDecimal sumPremium = BigDecimal.ZERO; Set userIdList = new HashSet<>(0); if (StringUtils.equals("2",grade)){ PartnerUser s = map.get(3); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } if (StringUtils.equals("3",grade)){ PartnerUser s = map.get(4); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } if (StringUtils.equals("4",grade)){ PartnerUser s = map.get(4); if (!Objects.isNull(s)){ userIdList = CalculateCommissionUtils.getUserIdList(s.getUserId()); } } 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; switch (type) { case "gl": PartnerUser s = map.get(3); if (!Objects.isNull( s)){ number = partnerUserMapper.selectNumber(s.getUserId(), "4", period); } break; case "levelGzs": PartnerUser s1 = map.get(4); if (!Objects.isNull( s1)){ number = partnerUserMapper.selectNumber4(s1.getUserId(), "5", period); } break; case "gzs": number = partnerUserMapper.selectByUserIdNumber(userId, "5", period); break; default: return BigDecimal.ZERO; } BigDecimal numberBD = BigDecimal.valueOf(number); 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(); boolean ry = ratioList.get(0).isRy(); boolean bf = ratioList.get(1).isBf(); if (ry && bf) { if (allSatisfied == 1) { if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0) { return ratio.getKickback(); } } else { if (numberBD.compareTo(min) >= 0 || sumPremium.compareTo(min1) >= 0) { return ratio.getKickback(); } } }else if (ry && !bf){ if (allSatisfied != 1) { if (numberBD.compareTo(min) >= 0) { return ratio.getKickback(); } } }else if (!ry && bf){ if (allSatisfied != 1) { if (sumPremium.compareTo(min1) >= 0) { return ratio.getKickback(); } } } } 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)); } }