CalculateCommissionUtils.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. package com.ydtech.modules.partner.utils;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.ydtech.modules.partner.dao.PartnerPremiumDetailsMapper;
  5. import com.ydtech.modules.partner.dao.PartnerUserMapper;
  6. import com.ydtech.modules.partner.model.PartnerCommissionRules;
  7. import com.ydtech.modules.partner.model.PartnerPremiumDetails;
  8. import com.ydtech.modules.partner.model.PartnerRatio;
  9. import com.ydtech.modules.partner.model.PartnerUser;
  10. import com.ydtech.modules.partner.model.param.CommissionValidityPeriod;
  11. import com.ydtech.modules.partner.model.vo.CommissionRulesVo;
  12. import com.ydtech.modules.partner.model.vo.PartnerRulesRatio;
  13. import com.ydtech.modules.partner.service.PartnerCommissionService;
  14. import com.ydtech.utils.StringUtils;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Component;
  17. import org.slf4j.Logger;
  18. import org.slf4j.LoggerFactory;
  19. import javax.annotation.PostConstruct;
  20. import java.math.BigDecimal;
  21. import java.text.SimpleDateFormat;
  22. import java.util.*;
  23. import java.util.stream.Collectors;
  24. @Component
  25. public class CalculateCommissionUtils {
  26. private static final Logger log = LoggerFactory.getLogger(CalculateCommissionUtils.class);
  27. private static PartnerCommissionService commissionService;
  28. private static PartnerUserMapper partnerUserMapper;
  29. private static PartnerPremiumDetailsMapper partnerPremiumDetailsMapper;
  30. @Autowired
  31. public void setCommissionService(PartnerCommissionService commissionService,
  32. PartnerUserMapper partnerUserMapper,
  33. PartnerPremiumDetailsMapper partnerPremiumDetailsMapper) {
  34. CalculateCommissionUtils.commissionService = commissionService;
  35. CalculateCommissionUtils.partnerUserMapper = partnerUserMapper;
  36. CalculateCommissionUtils.partnerPremiumDetailsMapper = partnerPremiumDetailsMapper;
  37. }
  38. @PostConstruct
  39. public void init() {
  40. }
  41. private static class CommissionValues {
  42. BigDecimal sumPremium;
  43. BigDecimal number;
  44. BigDecimal grBf;
  45. CommissionValues(BigDecimal sumPremium, BigDecimal number,BigDecimal grBf) {
  46. this.sumPremium = sumPremium;
  47. this.number = number;
  48. this.grBf = grBf;
  49. }
  50. }
  51. private static CommissionValues calculateCommonValues(String grade, String userId, PartnerCommissionRules rules,String type,String userId3,String userId4) {
  52. CommissionValidityPeriod period = new CommissionValidityPeriod();
  53. Set<String> userIdList = Collections.emptySet();
  54. BigDecimal grBf = null;
  55. if (StringUtils.equals("gzs", type)){
  56. period = getCommissionValidityPeriod(rules, userId4, "4");
  57. grBf = queryPersonalInsurancePremiums(userId4,period);
  58. userIdList = partnerUserMapper.querySubordinateUserId(userId4);
  59. }else if (StringUtils.equals("hh", type)){
  60. period = getCommissionValidityPeriod(rules, userId3, "3");
  61. grBf = queryPersonalInsurancePremiums(userId3,period);
  62. userIdList = partnerUserMapper.querySubordinate(userId3);
  63. }
  64. BigDecimal sumPremium = BigDecimal.ZERO;
  65. if (CollectionUtil.isNotEmpty(userIdList)) {
  66. QueryWrapper<PartnerPremiumDetails> queryWrapper = new QueryWrapper<>();
  67. queryWrapper.in("user_id", userIdList);
  68. if (StringUtils.isNotEmpty(period.getStartDate()) && StringUtils.isNotEmpty(period.getEndDate())) {
  69. queryWrapper.between("create_time", period.getStartDate(), period.getEndDate());
  70. }
  71. BigDecimal totalSumPremium = partnerPremiumDetailsMapper.selectTotalSumPremium(queryWrapper);
  72. sumPremium = Optional.ofNullable(totalSumPremium).orElse(BigDecimal.ZERO);
  73. }
  74. Integer number = 0;
  75. if (StringUtils.equals("gzs", type)){
  76. number = partnerUserMapper.selectNumber(userId4, "5", period);
  77. }else if (StringUtils.equals("hh", type)){
  78. number = partnerUserMapper.selectNumber(userId3, "4", period);
  79. }
  80. if (log.isInfoEnabled()) {
  81. log.info("用户id{}++{}级用户++出单人的上级用户{}++统计的保单金额{}++统计的邀请人数{}",
  82. userId, grade, userId3, sumPremium, number);
  83. }
  84. return new CommissionValues(sumPremium, new BigDecimal(number),grBf);
  85. }
  86. public static BigDecimal queryPersonalInsurancePremiums(String userId,CommissionValidityPeriod period){
  87. BigDecimal bigDecimal = partnerUserMapper.selectOwnSumPremium(userId, period);
  88. return null == bigDecimal ? BigDecimal.ZERO : bigDecimal;
  89. }
  90. public static String getReason(String grade, String userId,String userId3,String userId4) {
  91. CommissionRulesVo rulesVo = commissionService.queryAll();
  92. if (rulesVo == null) return null;
  93. if (StringUtils.equals("1", grade)){
  94. return null;
  95. }
  96. if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){
  97. return obtainReason(grade, rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),"hh",userId3,userId4);
  98. }
  99. if (StringUtils.equals("4", grade)){
  100. return obtainReason(grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),"gzs",userId3,userId4);
  101. }
  102. return null;
  103. }
  104. public static String querySuperiorAndSubordinate(String issuerId,String grade){
  105. QueryWrapper<PartnerUser> queryWrapper = new QueryWrapper<>();
  106. queryWrapper.eq("user_id", issuerId);
  107. PartnerUser issuerUser = partnerUserMapper.selectOne(queryWrapper);
  108. if (Objects.isNull(issuerUser)){
  109. return null;
  110. }
  111. return getLevelUserId(issuerUser.getUserId(), issuerUser.getGrade(), grade);
  112. }
  113. public static BigDecimal calculateCommission(String grade, String userId,String userId3,String userId4) {
  114. CommissionRulesVo rulesVo = commissionService.queryAll();
  115. if (rulesVo == null) return BigDecimal.ZERO;
  116. BigDecimal gl = BigDecimal.ZERO;
  117. if (StringUtils.equals("2", grade) || StringUtils.equals("3", grade)){
  118. gl = ladderCommission(grade,rulesVo.getAdministrator().getRulesRatioList(), userId, rulesVo.getAdministrator(),"hh", userId3, userId4);
  119. }
  120. BigDecimal hh = BigDecimal.ZERO;
  121. if (StringUtils.equals("4", grade) || StringUtils.equals("3", grade)){
  122. hh = ladderCommission(grade, rulesVo.getPartner().getRulesRatioList(), userId, rulesVo.getPartner(),"gzs",userId3, userId4);
  123. }
  124. if (StringUtils.equals("4", grade)){
  125. BigDecimal bigDecimal = partnerUserMapper.selectFixedRatio(userId4, grade);
  126. if (null != bigDecimal){
  127. return bigDecimal;
  128. }
  129. }else if (StringUtils.equals("3", grade)){
  130. BigDecimal gzs = partnerUserMapper.selectFixedRatio(userId4, String.valueOf(Integer.valueOf(grade) + 1));
  131. BigDecimal hhr = partnerUserMapper.selectFixedRatio(userId3, grade);
  132. if (null != gzs && null != hhr){
  133. BigDecimal a1 = new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(gzs);
  134. return a1.add(hhr);
  135. }else if (null == gzs && null != hhr){
  136. if (isZero(hh)){
  137. return hhr.add(new BigDecimal(rulesVo.getPartner().getDefaultRatio()));
  138. }else {
  139. return hhr.add(new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(hh));
  140. }
  141. }if (null != gzs && null == hhr){
  142. BigDecimal a2;
  143. if (isZero(gl)){
  144. a2 = new BigDecimal(rulesVo.getAdministrator().getSharedRatio()).subtract(new BigDecimal(rulesVo.getAdministrator().getDefaultRatio()));
  145. }else {
  146. a2 = gl;
  147. }
  148. return new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(gzs).add(a2);
  149. }
  150. }else if (StringUtils.equals("2", grade)){
  151. BigDecimal hhr = partnerUserMapper.selectFixedRatio(userId3, String.valueOf(Integer.valueOf(grade) + 1));
  152. if (null != hhr){
  153. return new BigDecimal(rulesVo.getAdministrator().getSharedRatio()).subtract(hhr);
  154. }
  155. }
  156. return calculateProportion(grade,rulesVo,gl,hh);
  157. }
  158. public static BigDecimal calculateProportion(String grade, CommissionRulesVo rulesVo,BigDecimal gl,BigDecimal hh) {
  159. if (StringUtils.equals("1", grade)) {
  160. return new BigDecimal(rulesVo.getOriginator());
  161. }
  162. if (StringUtils.equals("2", grade)) {
  163. PartnerCommissionRules administrator = rulesVo.getAdministrator();
  164. if (isZero(gl)){
  165. return new BigDecimal(administrator.getDefaultRatio());
  166. }else {
  167. return new BigDecimal(administrator.getSharedRatio()).subtract(gl);
  168. }
  169. }
  170. if (StringUtils.equals("3", grade)) {
  171. PartnerCommissionRules partner = rulesVo.getPartner();
  172. if (isZero(gl) && isZero(hh)) {
  173. return new BigDecimal(partner.getDefaultRatio())
  174. .add(subtractRatios(rulesVo.getAdministrator().getSharedRatio(), rulesVo.getAdministrator().getDefaultRatio()));
  175. } else if (isZero(hh) && !isZero(gl)) {
  176. return gl.add(new BigDecimal(partner.getDefaultRatio()));
  177. } else if (isZero(gl) && !isZero(hh)) {
  178. return new BigDecimal(partner.getSharedRatio()).subtract(hh)
  179. .add(subtractRatios(rulesVo.getAdministrator().getSharedRatio(), rulesVo.getAdministrator().getDefaultRatio()));
  180. }else{
  181. return gl.add(new BigDecimal(rulesVo.getPartner().getSharedRatio()).subtract(hh));
  182. }
  183. }
  184. if (StringUtils.equals("4", grade)) {
  185. return isZero(hh) ? subtractRatios(rulesVo.getPartner().getSharedRatio(), rulesVo.getPartner().getDefaultRatio()) : hh;
  186. }
  187. return BigDecimal.ZERO;
  188. }
  189. private static boolean isZero(BigDecimal value) {
  190. return value.compareTo(BigDecimal.ZERO) == 0;
  191. }
  192. private static BigDecimal subtractRatios(String a, String b) {
  193. return new BigDecimal(a).subtract(new BigDecimal(b));
  194. }
  195. public static BigDecimal ladderCommission(String grade, List<PartnerRulesRatio> rulesRatioList, String userId, PartnerCommissionRules rules,
  196. String type,String userId3,String userId4) {
  197. CommissionValues values = calculateCommonValues(grade, userId, rules,type,userId3,userId4);
  198. List<PartnerRulesRatio> sortedList = rulesRatioList.stream()
  199. .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed())
  200. .collect(Collectors.toList());
  201. for (PartnerRulesRatio ratio : sortedList) {
  202. BigDecimal result = handleRatioCondition(ratio, values.number, values.sumPremium,values.grBf);
  203. if (result.compareTo(BigDecimal.ZERO) > 0) {
  204. return result;
  205. }
  206. }
  207. return BigDecimal.ZERO;
  208. }
  209. private static BigDecimal handleRatioCondition(PartnerRulesRatio ratio, BigDecimal numberBD, BigDecimal sumPremium, BigDecimal grBf) {
  210. List<PartnerRatio> ratioList = ratio.getPartnerRatioList();
  211. if (CollectionUtil.isEmpty(ratioList)) {
  212. return BigDecimal.ZERO;
  213. }
  214. boolean[] conditions = {
  215. ratioList.get(0).isRy(),
  216. ratioList.get(1).isBf(),
  217. ratioList.get(2).isGr()
  218. };
  219. BigDecimal[] values = {numberBD, sumPremium, grBf};
  220. BigDecimal[] min = {
  221. ratioList.get(0).getMin(),
  222. ratioList.get(1).getMin(),
  223. ratioList.get(2).getMin()
  224. };
  225. int allSatisfied = ratio.getAllSatisfied();
  226. boolean anyConditionMet = false;
  227. boolean allConditionsMet = true;
  228. for (int i = 0; i < conditions.length; i++) {
  229. if (conditions[i]) {
  230. int comparison = values[i].compareTo(min[i]);
  231. anyConditionMet = anyConditionMet || (comparison >= 0);
  232. allConditionsMet = allConditionsMet && (comparison >= 0);
  233. }
  234. }
  235. if ((allSatisfied == 1 && allConditionsMet) || (allSatisfied != 1 && anyConditionMet)) {
  236. return ratio.getKickback();
  237. }
  238. return BigDecimal.ZERO;
  239. }
  240. public static String obtainReason(String grade, List<PartnerRulesRatio> rulesRatioList, String userId, PartnerCommissionRules rules,String type,String userId3,String userId4) {
  241. List<PartnerRulesRatio> sortedList = rulesRatioList.stream()
  242. .sorted(Comparator.comparing(PartnerRulesRatio::getKickback).reversed())
  243. .collect(Collectors.toList());
  244. CommissionValues values = calculateCommonValues(grade, userId, rules,type,userId3,userId4);
  245. BigDecimal numberBD = values.number;
  246. BigDecimal sumPremium = values.sumPremium;
  247. BigDecimal grBf = values.grBf;
  248. for (PartnerRulesRatio ratio : sortedList) {
  249. int allSatisfied = ratio.getAllSatisfied();
  250. List<PartnerRatio> ratioList = ratio.getPartnerRatioList();
  251. if (CollectionUtil.isEmpty(ratioList)) continue;
  252. BigDecimal min = ratioList.get(0).getMin();
  253. BigDecimal min1 = ratioList.get(1).getMin();
  254. BigDecimal grb = ratioList.get(2).getMin();
  255. boolean ry = ratioList.get(0).isRy();
  256. boolean bf = ratioList.get(1).isBf();
  257. boolean gr = ratioList.get(2).isGr();
  258. if (ry && bf && gr) {
  259. if (allSatisfied == 1) {
  260. if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0 && grBf.compareTo(grb) >= 0) {
  261. return "邀请人达" + min + "人,累计保费达" + min1 + "元" + ",个人保费达" + grb + "元";
  262. }
  263. } else {
  264. if (numberBD.compareTo(min) >= 0) {
  265. return "邀请人达" + min + "人";
  266. }else if(sumPremium.compareTo(min1) >= 0){
  267. return "累计保费达" + min1 + "元";
  268. }else if(grBf.compareTo(grb) >= 0){
  269. return "个人保费达" + grb + "元";
  270. }
  271. }
  272. }else if (ry && gr && !bf ){
  273. if (allSatisfied != 1) {
  274. if (numberBD.compareTo(min) >= 0 && grBf.compareTo(grb) >= 0) {
  275. return "邀请人达" + min + "人" + ",个人保费达" + grb + "元";
  276. }
  277. }
  278. }else if (!ry && gr && bf){
  279. if (allSatisfied != 1) {
  280. if (sumPremium.compareTo(min1) >= 0 && grBf.compareTo(grb) >= 0) {
  281. return "累计保费达" + min1 + "元" + ",个人保费达" + grb + "元";
  282. }
  283. }
  284. }else if (ry && !gr && bf){
  285. if (allSatisfied != 1) {
  286. if (numberBD.compareTo(min) >= 0 && sumPremium.compareTo(min1) >= 0) {
  287. return "邀请人达" + min + "人" + ",累计保费达" + min1 + "元";
  288. }
  289. }
  290. }
  291. }
  292. return null;
  293. }
  294. public static String getLevelUserId(String userId,Integer grade,String queryLevel){
  295. PartnerUser partnerUser = partnerUserMapper.getLevelUserId(userId,grade);
  296. while (partnerUser != null){
  297. Integer userGrade = partnerUser.getGrade();
  298. if (userGrade != null && userGrade.toString().equals(queryLevel)){
  299. return partnerUser.getUserId();
  300. }
  301. userId = partnerUser.getReferrerId();
  302. if (userId == null) {
  303. return null;
  304. }
  305. grade--;
  306. partnerUser = partnerUserMapper.getLevelUserId(userId, grade);
  307. }
  308. return null;
  309. }
  310. public static CommissionValidityPeriod getCommissionValidityPeriod(PartnerCommissionRules rules, String userId, String grade) {
  311. CommissionValidityPeriod period = new CommissionValidityPeriod();
  312. if (rules == null || StringUtils.isBlank(rules.getValidityPeriod())) {
  313. return period;
  314. }
  315. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  316. try {
  317. if (StringUtils.equals("1", rules.getValidityPeriod())) {
  318. return period;
  319. } else if (StringUtils.equals("2", rules.getValidityPeriod())) {
  320. Date assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade);
  321. if (assessmentTime == null) {
  322. partnerUserMapper.updateAssessmentTime(userId);
  323. assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade);
  324. if (Objects.isNull(assessmentTime)){
  325. return period;
  326. }
  327. }
  328. if (!PartnerDateUtils.isWithinDays(assessmentTime, rules.getFixedDays())) {
  329. updateAssessmentTimeRecursively(assessmentTime,rules.getFixedDays(),userId,grade );
  330. assessmentTime = partnerUserMapper.selectAssessmentTime(userId, grade);
  331. }
  332. period.setStartDate(dateFormat.format(assessmentTime));
  333. period.setEndDate(dateFormat.format(PartnerDateUtils.addDays(assessmentTime, rules.getFixedDays())));
  334. } else if (StringUtils.equals("3", rules.getValidityPeriod())) {
  335. Date fixedCycle = partnerUserMapper.selectFixedCycleTime(userId, grade);
  336. if (fixedCycle == null) {
  337. partnerUserMapper.updateFixedCycleTime(userId);
  338. fixedCycle = partnerUserMapper.selectFixedCycleTime(userId, grade);
  339. if (fixedCycle == null){
  340. return period;
  341. }
  342. }
  343. period.setStartDate(rules.getStartDate());
  344. period.setEndDate(rules.getEndDate());
  345. }
  346. } catch (Exception e) {
  347. log.error("获取佣金有效期异常,userId:{}, grade:{}", userId, grade, e);
  348. }
  349. return period;
  350. }
  351. private static void updateAssessmentTimeRecursively(Date assessmentTime, int days, String userId,String grade) {
  352. Date newDate = PartnerDateUtils.addDaysToday(assessmentTime, days);
  353. while (!PartnerDateUtils.isWithinDays(newDate, days)) {
  354. newDate = PartnerDateUtils.addDaysToday(newDate, days);
  355. }
  356. partnerUserMapper.updateAssessmentTimeByDate(userId,newDate,grade);
  357. }
  358. }