package com.tenwa.reckon.help; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.tenwa.reckon.bean.ConditionBean; import com.tenwa.reckon.bean.FundRentPlanBean; import com.tenwa.reckon.constant.Scale; import com.tenwa.reckon.util.DateTools; import com.tenwa.reckon.util.DateUtil; import com.tenwa.reckon.util.DateUtils; import com.tenwa.reckon.util.InterestTools; import com.tenwa.reckon.util.NumTools; import com.tenwa.reckon.util.RateTools; import com.tenwa.reckon.util.RentTools; /** * * @author SHIHONGFEI * @version 1.0 * @copyright (C) TENWA 2011 * @date 2011-3-3 * @desc ( 租金测算利息计算类,如有宽限期,延迟期等利息特殊算法也在此类中重构方法来实现) */ public class InterestCalServiceImpl { /** * * (正常租金测算 获得 利息list列表) * * @param rent_list * @param leaseMoney * @param calRate * @param periodType * @param sgrace * @param Income_number_year * @param endValue * @return */ public List getInterestList(List rent_list, String leaseMoney, String calRate, String periodType, int sgrace, String Income_number_year, String endValue,String rateType) { // 第一期的特别处理,包括期初期末等利息的特别处理 // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; String corpus_overage = "0"; // 本金余额, corpus_overage = new BigDecimal(leaseMoney).toString(); // 1.根据年利率等信息, // 中的getPreRate得到测算的租金利率 String preRate = RateTools.getPreRate(calRate, Income_number_year,rateType); // 得到宽限期利息 int grace = getGraceInterest(sgrace, rent_list, interests); for (int i = grace; i < rent_list.size(); i++) {// 循环租金list // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(periodType) && i == grace) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法 // 期初时第一期本金的精度和租金的精度是一样的 corpus = new BigDecimal(rent_list.get(i).toString()).setScale(RentTools.getRentAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); inte = "0"; } else { // 利息 inte = new BigDecimal(corpus_overage).multiply(new BigDecimal(preRate)).setScale(2,BigDecimal.ROUND_HALF_UP).toString();// 剩余本金*利率 // 本金, 租金-利息 corpus = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(inte)).toString();// 租金-利息 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 // if (i == rent_list.size() - 1) { // // 本金 --总的本金-以前的本金和-期末残值 // corpus = new BigDecimal(leaseMoney).subtract(new BigDecimal(corpus_total)).subtract(new BigDecimal(endValue)).toString(); // // 利息 // inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).toString(); // } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).toString(); // 本金余额 corpus_overage = new BigDecimal(corpus_overage).subtract(new BigDecimal(corpus)).toString(); // 添加list interests.add(inte); // logger.debug("合同第"+i+"利息:"+inte); } return interests; } /** * * (等额租金 按日利率测算 获得 利息list列表) * * @param rent_list * @param leaseMoney * @param calRate * @param periodType * @param sgrace * @param Income_number_year * @param endValue * @return * @throws Exception * @throws NumberFormatException */ public List getInterestList(List rent_list,List dateList,String startDate, String leaseMoney, String calRate, String periodType, int sgrace, String Income_number_year, String endValue,String rateType,ConditionBean cb) throws NumberFormatException, Exception { // 第一期的特别处理,包括期初期末等利息的特别处理 // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; String corpus_overage = "0"; // 本金余额, corpus_overage = new BigDecimal(leaseMoney).toString(); // 1.根据年利率等信息, BigDecimal preRate =RateTools.getPreDayRate(calRate); // 得到宽限期利息 int grace = getGraceInterest(sgrace, rent_list, interests); if(grace>0){ startDate=dateList.get(grace-1); } for (int i = grace; i < rent_list.size(); i++) {// 循环租金list String planDate =dateList.get(i); Long dayDiff = DateTools.getDateDiff(planDate,startDate ); if(cb.getRentOrRate().equals("rent_period_360")){ dayDiff=Long.parseLong(DateUtils.days360(startDate,planDate)+""); } startDate = planDate; // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(periodType) && i == grace) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法 // 期初时第一期本金的精度和租金的精度是一样的 corpus = new BigDecimal(rent_list.get(i).toString()).setScale(RentTools.getRentAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); inte = "0"; } else { // 利息 inte = new BigDecimal(corpus_overage).multiply(preRate.multiply(new BigDecimal(dayDiff))).toString();// 剩余本金*利率 // 本金, 租金-利息 corpus = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(inte).setScale(2,BigDecimal.ROUND_HALF_UP)).toString();// 租金-利息 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 if (i == rent_list.size() - 1&&!cb.getLastPlanDayRate()) { // 本金 --总的本金-以前的本金和-期末残值 corpus = new BigDecimal(leaseMoney).subtract(new BigDecimal(corpus_total)).subtract(new BigDecimal(endValue)).toString(); // 利息 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).toString(); } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).toString(); // 本金余额 corpus_overage = new BigDecimal(corpus_overage).subtract(new BigDecimal(corpus)).toString(); // 添加list interests.add(inte); // logger.debug("合同第"+i+"利息:"+inte); } return interests; } /** * 已知租金表 拆分利息 * @param rent_list 租金列表 * @param dateList 日期列表 * @param startDate 起租日 * @param leaseMoney 融资额 * @param calRate XIRR * @param periodType 期初/期末 * @param sgrace 宽限期 * @param endValue 期末余值 * @return */ public List getInterestList(List rent_list,List dateList,String startDate,String leaseMoney, String calRate, String periodType, int sgrace, String endValue) { // 第一期的特别处理,包括期初期末等利息的特别处理 // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; // 得到宽限期利息 int grace = getGraceInterest(sgrace, rent_list, interests); if(grace>0){ startDate=dateList.get(grace-1); } for (int i = grace; i < rent_list.size(); i++) {// 循环租金list String planDate =dateList.get(i); Long dayDiff = DateTools.getDateDiff(planDate,startDate ); // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(periodType) && i == grace) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法 // 期初时第一期本金的精度和租金的精度是一样的 corpus = new BigDecimal(rent_list.get(i).toString()).setScale(RentTools.getRentAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); inte = "0"; } else { // 本金 corpus = new BigDecimal(rent_list.get(i)).multiply(new BigDecimal(Math.pow(BigDecimal.ONE.divide(BigDecimal.ONE.add(new BigDecimal(calRate).divide(new BigDecimal(100))),20,BigDecimal.ROUND_HALF_UP).doubleValue(),new BigDecimal(dayDiff).divide(new BigDecimal(365),20,BigDecimal.ROUND_HALF_UP).doubleValue()))).toString();// // 利息, 租金-本金 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus).setScale(2,BigDecimal.ROUND_HALF_UP)).toString();// 租金-本金 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 if (i == rent_list.size() - 1) { // 本金 --总的本金-以前的本金和-期末残值 corpus = new BigDecimal(leaseMoney).subtract(new BigDecimal(corpus_total)).subtract(new BigDecimal(endValue)).toString(); // 利息 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).toString(); } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).toString(); // 添加list interests.add(inte); // logger.debug("合同第"+i+"利息:"+inte); } return interests; } /** * * ( 租金调整下的利息测算方法) * * @param rent_list * 租金列表 * @param leaseMoney * 最原始的测算本金,如果宽限期不调整则和corpusCon相同 * @param corpusCon * 宽限期调整过之后的测算总本金 * @param year_rate * 年利率集合 * @param periodType * 期初/期末 * @param sgrace * 宽限期 * @param Income_number_year * 年还款次数 * @param endValue * 期末残值 * @param rentAdjustList * 调整租金 * @return */ public List getInterestList(List rent_list, String leaseMoney, String corpusCon, List year_rate, String periodType, int sgrace, String Income_number_year, String endValue, String[] rentAdjustList,String rateAdjustType) { // 第一期的特别处理,包括期初期末等利息的特别处理 // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; String corpus_overage = "0"; // 本金余额, corpus_overage = new BigDecimal(corpusCon).toString();// 9950 // 1.根据年利率等信息, // 中的getPreRate得到测算的租金利率 String preRate = "";// RateTools.getPreRate(calRate, // Income_number_year); // 得到宽限期利息 int grace = sgrace; interests = getGraceInterest(year_rate, leaseMoney, Arrays.asList(rentAdjustList), grace, Income_number_year,rateAdjustType); leaseMoney = corpus_overage;// 9950 for (int i = grace; i < rent_list.size(); i++) {// 循环租金list preRate = RateTools.getPreRate(year_rate.get(i), Income_number_year,rateAdjustType); // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(periodType) && i == grace) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法 // firstCorpusAndInteCal(corpus, inte, // rent_list.get(i).toString()); corpus = rent_list.get(i).toString(); inte = "0"; } else { // 利息 inte = new BigDecimal(corpus_overage).multiply(new BigDecimal(preRate)).toString();// 剩余本金*利率 // 本金, 租金-利息 corpus = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(inte)).toString();// 租金-利息 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 if (i == rent_list.size() - 1) { // 本金 --总的本金-以前的本金和-期末残值 corpus = new BigDecimal(leaseMoney).subtract(new BigDecimal(corpus_total)).subtract(new BigDecimal(endValue)).toString(); // 2011-06-27修改 // corpus = new BigDecimal(leaseMoney).subtract(new // BigDecimal(corpus_total)).toString(); // .subtract(new BigDecimal(endValue)).toString(); // 利息 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).toString(); } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).toString(); // 本金余额 corpus_overage = new BigDecimal(corpus_overage).subtract(new BigDecimal(corpus)).toString(); // 添加list interests.add(inte); } return interests; } /** * * 宽限期利息) * * @param cb * @param rent_list * @param interests * @return */ private int getGraceInterest(int sgrace, List rent_list, List interests) { // 判断宽限期,计算宽限期利息 int grace = sgrace; for (int i = 0; i < sgrace; i++) { interests.add(rent_list.get(i)); } return grace; } /** * * (租金调整下的宽限期利息方法) * * @param cb * @param l_rent_adjust * @param grace * @return */ private List getGraceInterest(List year_rate, String corpus, List l_rent_adjust, int grace, String income_number_year,String rateAdjustType) { List devGrace = new ArrayList(); String preRate = ""; // 因为宽限期不多,就每一期单独计算 /* * for(int i=0;i getFinacInterestList(ConditionBean cb, List rent_list, String leaseMoney) { // [KEY:scl]2012-12-24 因为出现 手续费分摊在后面过高 所以采用 不包含宽限期的隐藏IRR做本息计算 所以在宽限期的时候 // 不分摊手续费 // String preRate = RateTools.getPreRate(cb.getPlan_irr(), cb // .getIncome_number_year()); // String preRate = RateTools.getPreRate(cb.getNoGraceIRR(), cb.getIncomeNumberYear(), cb.getIfretry()); // logger.info("财务利率:" + cb.getNoGraceIRR() + "总本金:" + leaseMoney + "计算利率:" + preRate); // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; String corpus_overage = "0"; // 本金余额 corpus_overage = new BigDecimal(leaseMoney).toString(); // [KEY:scl]2012-12-24 手续费分摊比例 //注释cb.getGraceMultiply() BigDecimal rent_total = new BigDecimal(NumTools.getSumCorpusOverage(rent_list, 1)).multiply(new BigDecimal(0)); for (int i = 0; i < rent_list.size(); i++) {// 循环租金list // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(cb.getPeriodType()) && i == 0) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法调用 corpus = rent_list.get(i).toString(); inte = "0"; } else { if (cb.getGrace() > i) {// 在会计租金计划中宽限期的利息就等于租金 // 利息=租金+手续/总期数[key:scl]马经理调整的在宽限期中手续费分摊额为手续/总期数 // inte=new BigDecimal(rent_list.get(i).toString()).add( // new BigDecimal(cb.getHandling_charge_money()).divide( // new BigDecimal(cb.getIncome_number()).add(new // BigDecimal(cb.getGrace())), // 20,BigDecimal.ROUND_HALF_UP)).setScale(2, // BigDecimal.ROUND_HALF_UP).toString(); // [KEY:scl]2012-12-24 款期限的手续费分摊为 租金/总租金*手续费 inte = new BigDecimal(rent_list.get(i).toString()).add(new BigDecimal(rent_list.get(i).toString()).divide(rent_total, 20, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(cb.getHandlingChargeMoney()))).setScale(2, BigDecimal.ROUND_HALF_UP).toString(); } else { // 利息 inte = new BigDecimal(corpus_overage).multiply(new BigDecimal(0)).setScale(RentTools.getInterestAccuracy(), BigDecimal.ROUND_HALF_UP).toString();// 剩余本金*利率 } // 本金, 租金-利息 corpus = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(inte)).setScale(RentTools.getAccuracy(), BigDecimal.ROUND_HALF_UP).toString();// 租金-利息 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 if (i == rent_list.size() - 1) { // 本金 --总的本金-以前的本金和-期末残值 //注释1行 corpus = new BigDecimal(cb.getCalTotalByFinac()).subtract(new BigDecimal(corpus_total)).subtract(new BigDecimal(cb.getPmtEndValue())).setScale(RentTools.getAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); // logger.info("cb.getPmtEndValue():财务利息:"+cb.getPmtEndValue()); // 2011-06-27修改 // corpus = new BigDecimal(leaseMoney).subtract(new // BigDecimal(corpus_total)).toString(); // .subtract(new BigDecimal(endValue)).toString(); // 利息 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).setScale(RentTools.getAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).setScale(RentTools.getAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); // 本金余额 corpus_overage = new BigDecimal(corpus_overage).subtract(new BigDecimal(corpus)).setScale(RentTools.getAccuracy(), BigDecimal.ROUND_HALF_UP).toString(); // 添加list interests.add(inte); } return interests; } /** * 2013-1-6 孙传良 在计算会计利息的时候 采用财务利息加手续费分摊值来计算 会计利息 * * @param cb * 商务条件bean * @param frpb * 租金计划bean 本次测算出来的bean * @param frpb_old * 租金计划bean 数据库中bean 主要用于计算已分摊手续费 * @param startList * 计算开始期项(调息和租金计划变更的话就是对于的开始期项,如果是租金测算就是1) * @return 返回会计利息 */ public List getFinacInterestListNew(ConditionBean cb, FundRentPlanBean frpb, FundRentPlanBean frpb_old, int startList) { List interest = new ArrayList(); BigDecimal handling_charge_money_total = new BigDecimal(cb.getHandlingChargeMoney());// 总手续费 if (handling_charge_money_total.compareTo(BigDecimal.ZERO) == 0) {// 偷懒做法,如果没有手续费就返回财务利息 // 因为 // 财务利息和会计利息就差在手续费上 interest = new ArrayList(frpb.getInterestBusinessList()); } else {// 开始计算手续费分摊值 List handling_charge_money_share = new ArrayList(); handling_charge_money_share = new InterestTools().getHandlingChargeMoneyShare(cb, frpb, frpb_old, startList); for (int i = 0; i < frpb.getInterestBusinessList().size(); i++) { interest.add(NumTools.calculationStr(frpb.getInterestBusinessList().get(i).toString(), handling_charge_money_share.get(i).toString(), NumTools.ADD, 2)); } } return interest; } /** * * scl 不规则租金调整,根据利率List和rent_list算每期的利息 * * @param rent_list * 租金集合 * @param year_rate_list * 利率集合 需要转换为对应的租金间隔的利率 * @param leaseMoney * 剩余本金 * @param calRate * 精确小数位 * @param periodType * 期初/期末 * @return interests 利息集合 */ public List getInterestList(List rent_list, List year_rate_list, String leaseMoney, String calRate, String periodType) { // 用于保留利息 List interests = new ArrayList(); String corpus_total = "0"; // 该期的利息 String inte = "0"; String corpus = "0"; String corpus_overage = "0"; // 本金余额, corpus_overage = new BigDecimal(leaseMoney).toString(); for (int i = 0; i < rent_list.size(); i++) {// 循环租金list // 第一期的特别处理,包括期初期末等利息的特别处理 // 起租类型 注意: 期初 数字 1 字符串 period_type_1 #分割线# 期末 数字0 字符串 period_type_0 if ("1".equals(periodType) && i == 0) {// 第一期且是期初时 // 第一期利息计算,如有特别的计算则可在此写方法 // firstCorpusAndInteCal(corpus, inte, // rent_list.get(i).toString()); corpus = rent_list.get(i).toString(); inte = "0"; } else { // 利息 inte = new BigDecimal(corpus_overage).multiply(new BigDecimal(year_rate_list.get(i).toString())).toString();// 剩余本金*利率 // 本金, 租金-利息 corpus = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(inte)).toString();// 租金-利息 } // 最后一期的利息=剩余的利息总合,本金仍然=租金-利息 if (i == rent_list.size() - 1) { // 本金 --总的本金-以前的本金和 corpus = new BigDecimal(leaseMoney).subtract(new BigDecimal(corpus_total)).toString(); // 利息 inte = new BigDecimal(rent_list.get(i).toString()).subtract(new BigDecimal(corpus)).toString(); } // 计算中的本金和 corpus_total = new BigDecimal(corpus_total).add(new BigDecimal(corpus)).toString(); // 本金余额 corpus_overage = new BigDecimal(corpus_overage).subtract(new BigDecimal(corpus)).toString(); // 添加list interests.add(inte); } return interests; } /** * scl ( 获得均息法下的利息列表 均息法 不区分期初期末的利息) * * @param leaseMoney * 总本金 * @param lease_term * 租赁期限 * @param Income_number * 还款次数 * @param endValue * 剩余本金 * @param calRate * 年利率 * @return */ public List getInterestList(String leaseMoney, int leaseTerm, int incomeNumber, String endValue, String yearRate) { List interestList = new ArrayList(); //本金*(期限/12)*(年利率/100)/还款次数 //本金*期限*年利率/12/100/还款次数 BigDecimal leaseAmt = new BigDecimal(leaseMoney); BigDecimal interest = leaseAmt.multiply(new BigDecimal(yearRate)).multiply(new BigDecimal(leaseTerm)); interest = interest.divide(new BigDecimal(1200).multiply(new BigDecimal(incomeNumber)), Scale.INTEREST_SCALE, BigDecimal.ROUND_HALF_UP); for (int i = 0; i < incomeNumber; i++) { interestList.add(interest.toString()); } return interestList; } }