apzl_leasing/src_tenwa/com/tenwa/loan/calc/FundCalculateHelper.java
2018-06-03 22:26:41 +08:00

1017 lines
42 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.tenwa.loan.calc;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jbo.loan.LOAN_CORPUS_PLAN;
import jbo.loan.LOAN_INTEREST_PLAN;
import jbo.loan.LOAN_RATE_ADJUST;
import org.apache.log4j.Logger;
import com.amarsoft.are.jbo.BizObject;
import com.amarsoft.are.jbo.BizObjectManager;
import com.amarsoft.are.jbo.JBOException;
import com.amarsoft.are.jbo.JBOFactory;
import com.amarsoft.are.jbo.JBOTransaction;
import com.tenwa.comm.util.jboutil.DataOperatorUtil;
import com.tenwa.reckon.constant.Scale;
import com.tenwa.reckon.util.DateTools;
import com.tenwa.reckon.util.DateUtils;
import com.tenwa.reckon.util.NumberUtils;
public class FundCalculateHelper {
private static Logger logger = Logger.getLogger(FundCalculateHelper.class);
/**
* 构建日期计算函数createplandate输入参数起算日期、计算方式、还款日输出下一还款日期
手工---不计算不调用createplandate
季末月---取距起算日期最近的3、6、9、12月份的年月+还款日
半年末月---取距起算日期最近的6、12月份的年月+还款日
年末月---取距起算日期最近的12月份的年月+还款日
月---起算日期+1个月的年月+还款日
3个月--- 起算日期+3个月的年月+还款日
6个月--- 起算日期+6个月的年月+还款日
12个月--- 起算日期+12个月的年月+还款日
到期一次还清---返回到期日不调用createplandate
* @param startDate
* @param calcType
* @param payDay
* @return
* @throws Exception
*/
public static String createPlanDate(String startDate, String calcType, String payDay) throws Exception {
String planDate = "";
if ("corpus_pay_type02".equals(calcType) || "interestpaytype02".equals(calcType)) {// 季末月取距起算日期最近的3、6、9、12月份的年月+还款日
planDate = getQuarterTerminalDate(startDate, payDay);
} else if ("corpus_pay_type03".equals(calcType) || "interestpaytype03".equals(calcType)) {// 半年末月取距起算日期最近的6、12月份的年月+还款日
planDate = getHalfYearTerminalDate(startDate, payDay);
} else if ("corpus_pay_type04".equals(calcType) || "interestpaytype04".equals(calcType)) {// 年末月取距起算日期最近的12月份的年月+还款日
planDate = getYearTerminalDate(startDate, payDay);
} else if ("corpus_pay_type05".equals(calcType) || "interestpaytype01".equals(calcType)) {// 月:起算日期+1个月的年月+还款日
planDate = DateTools.dateAdd("month", 1, startDate);
planDate = DateTools.setDateDay(planDate, payDay);
} else if ("corpus_pay_type06".equals(calcType)) {// 3个月 起算日期+3个月的年月+还款日
planDate = DateTools.dateAdd("month", 3, startDate);
planDate = DateTools.setDateDay(planDate, payDay);
} else if ("corpus_pay_type07".equals(calcType)) {// 6个月 起算日期+6个月的年月+还款日
planDate = DateTools.dateAdd("month", 6, startDate);
planDate = DateTools.setDateDay(planDate, payDay);
} else if ("corpus_pay_type08".equals(calcType)) {// 12个月 起算日期+12个月的年月+还款日
planDate = DateTools.dateAdd("month", 12, startDate);
planDate = DateTools.setDateDay(planDate, payDay);
}
return planDate;
}
/**
* 获得计划日期列表
* @param payType还本方式、利息还款方式
* @param startDate放款日
* @param endDate到期日
* @param payDay还本、付息、结息日
* @param lastInterestFlag:是否最后一笔利随本金
* @return 计划日期列表
* @throws Exception
*/
public static List<String> getPlanDateList(String payType, String startDate, String endDate, String payDay, String lastInterestFlag) throws Exception {
List<String> list = new ArrayList<String>();
if("corpus_pay_type01".equals(payType) || "interestpaytype05".equals(payType)){//手工
return list;
}else if("corpus_pay_type09".equals(payType) || "interestpaytype07".equals(payType)){//到期一次还清
list.add(endDate);
return list;
}else{
String planDate = startDate;
int dateFlag = 0;
do{
planDate = FundCalculateHelper.createPlanDate(planDate, payType, payDay);
dateFlag = DateTools.compareToDate(planDate, endDate);
if(dateFlag<0){
list.add(planDate);
}
}while(dateFlag<0);
if("".equals(lastInterestFlag)){//利息是否最后一笔利随本金
list.add(planDate);
}else{
list.add(endDate);
}
return list;
}
}
/**
* 获得本金列表
* @param amount:借款金额
* @param term还款次数
* @return 本金列表
*/
public static List<BigDecimal> getCorpusList(BigDecimal amount, int term){
List<BigDecimal> list = new ArrayList<BigDecimal>();
BigDecimal corpus = BigDecimal.ZERO;
BigDecimal totalCorpus = BigDecimal.ZERO;
if(term>0){
corpus = amount.divide(new BigDecimal(term), Scale.CORPUS_SCALE, BigDecimal.ROUND_HALF_UP);
for(int i=0; i<term; i++){
if(i == term-1){//最后一期本金处理
corpus = amount.subtract(totalCorpus);
}
list.add(corpus);
totalCorpus = totalCorpus.add(corpus);
}
}
return list;
}
/**
* 获得利息列表
* @param amount:借款金额
* @param startDate放款日期
* @param settlementDateList有序的结息日列表
* @param corpusPlanDate有序的本金还款日列表
* @param corpusList有序的本金列表
* @param dayRate日息率
* @return 利息列表
* @throws ParseException
*/
public static List<BigDecimal> getInterestList(BigDecimal overageCorpus, String startDate, List<String> settlementDateList, List<String> corpusPlanDate, List<BigDecimal> corpusList, BigDecimal dayRate) throws Exception{
List<BigDecimal> list = new ArrayList<BigDecimal>();
String calcStartDate = startDate;
String calcEndDate = startDate;
String settleDate = startDate;
BigDecimal interest = BigDecimal.ZERO;
long days = 0;
int j=0;
int size = settlementDateList.size();
for(int i=0; i<size; i++){
interest = BigDecimal.ZERO;
settleDate = settlementDateList.get(i);
//结息日大于还款日
for(; j<corpusList.size() && DateTools.compareToDate(settleDate, corpusPlanDate.get(j))==1; j++){
calcEndDate = corpusPlanDate.get(j);//还款日
days = DateTools.getDateDiff(calcEndDate, calcStartDate);//返回两时间间隔天数
//上次结息日与还款日之间的利息
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
overageCorpus = overageCorpus.subtract(corpusList.get(j));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
}
calcEndDate = settleDate;
//这次的还款日与结息日之间的天数
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
//这次的还款日与结息日之间的利息
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
interest = interest.setScale(Scale.INTEREST_SCALE, BigDecimal.ROUND_HALF_UP);
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
list.add(interest);
}
return list;
}
/**
* 获得利息列表
* @param amount:借款金额
* @param startDate放款日期
* @param settlementDateList有序的结息日列表
* @param corpusPlanDate有序的本金还款日列表
* @param corpusList有序的本金列表
* @param rateList 利率变化列表
* @param rateYearDays 年计息天数
* @return
* @throws Exception
*/
public static List<BigDecimal> getInterestList(BigDecimal overageCorpus, String startDate, List<String> settlementDateList, List<String> corpusPlanDate, List<BigDecimal> corpusList, List<Map<String, String>> rateList, String rateYearDays) throws Exception{
List<BigDecimal> list = new ArrayList<BigDecimal>();
String calcStartDate = startDate;
String calcEndDate = startDate;
String settleDate = startDate;
BigDecimal interest = BigDecimal.ZERO;
BigDecimal dayRate = BigDecimal.ZERO;
Map<String, String> rateMap;
//利率List的第一个值为借据的年利率和放款日
String yearRate = rateList.get(0).get("yearRate");
String rateDate = rateList.get(0).get("startDate");
String corpusDate = "";
long days = 0;
int j=0;
int k = 0;
int size = settlementDateList.size();
//计算开始日期startDate后的最初利率
for(;k<rateList.size() && DateTools.compareToDate(calcStartDate, rateList.get(k).get("startDate"))>=0;k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
yearRate = rateMap.get("yearRate");
}
for(int i=0; i<size; i++){
interest = BigDecimal.ZERO;
settleDate = settlementDateList.get(i);
for(; j<corpusList.size() && DateTools.compareToDate(settleDate, corpusPlanDate.get(j))==1; j++){
corpusDate = corpusPlanDate.get(j);
//根据央行调息记录在日期区间【calcStartDate,corpusDate】作分段处理
for(; k<rateList.size() && DateTools.compareToDate(corpusDate, rateList.get(k).get("startDate"))==1; k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
calcEndDate = rateDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
dayRate = getDayRate(new BigDecimal(yearRate), rateYearDays);
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
yearRate = rateMap.get("yearRate");
}
calcEndDate = corpusDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
dayRate = getDayRate(new BigDecimal(yearRate), rateYearDays);
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
overageCorpus = overageCorpus.subtract(corpusList.get(j));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
}
//根据央行调息记录在日期区间【calcStartDate,settleDate】作分段处理
for(; k<rateList.size() && DateTools.compareToDate(settleDate, rateList.get(k).get("startDate"))==1; k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
calcEndDate = rateDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
dayRate = getDayRate(new BigDecimal(yearRate), rateYearDays);
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
yearRate = rateMap.get("yearRate");
}
calcEndDate = settleDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
dayRate = getDayRate(new BigDecimal(yearRate), rateYearDays);
interest = interest.add(overageCorpus.multiply(new BigDecimal(days)).multiply(dayRate));
interest = interest.setScale(Scale.INTEREST_SCALE, BigDecimal.ROUND_HALF_UP);
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
list.add(interest);
}
return list;
}
/**
* 获得利息计算公式列表
* @param overageCorpus 剩余本金
* @param startDate 起算日期
* @param settlementDateList 结算日期列表
* @param corpusPlanDate 本金计划日期
* @param corpusList 本金计划
* @param yearRate 年利率
* @param rateYearDays 年计息天数
* @return
*/
public static List<String> getCalcInterestInfo(BigDecimal overageCorpus, String startDate, List<String> settlementDateList, List<String> corpusPlanDate, List<BigDecimal> corpusList, String yearRate, String rateYearDays){
List<String> list = new ArrayList<String>();
String calcStartDate = startDate;
String calcEndDate = startDate;
String settleDate = startDate;
long days = 0;
int j=0;
int size = settlementDateList.size();
StringBuffer msg = new StringBuffer();
DecimalFormat df = new DecimalFormat("###0.0#####");
yearRate = df.format(new BigDecimal(yearRate));
for(int i=0; i<size; i++){
settleDate = settlementDateList.get(i);
//msg = new StringBuffer();
msg.setLength(0);
//
try{
for(; j<corpusList.size() && DateTools.compareToDate(settleDate, corpusPlanDate.get(j))==1; j++){
calcEndDate = corpusPlanDate.get(j);//还款日
//上次结息日与还款日之间的天数
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
//logger.debug(days + "=" + calcEndDate + "-" + calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(overageCorpus)
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append(";");
}
overageCorpus = overageCorpus.subtract(corpusList.get(j));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
}
} catch (ParseException e) {
e.printStackTrace();
}
calcEndDate = settleDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
//logger.debug(days + "=" + calcEndDate + "-" + calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(overageCorpus)
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append("");
}
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
list.add(msg.toString());
}
return list;
}
/**
* 获得利息计算公式列表
* @param overageCorpus 剩余本金
* @param startDate 起算日期
* @param settlementDateList 结算日期列表
* @param corpusPlanDate 本金计划日期
* @param corpusList 本金计划
* @param rateList 利率变化列表
* @param rateYearDays 年计息天数
* @return
* @throws Exception
*/
public static List<String> getCalcInterestInfo(BigDecimal overageCorpus, String startDate, List<String> settlementDateList, List<String> corpusPlanDate, List<BigDecimal> corpusList, List<Map<String, String>> rateList, String rateYearDays){
List<String> list = new ArrayList<String>();
String calcStartDate = startDate;
String calcEndDate = startDate;
String settleDate = startDate;
Map<String, String> rateMap;
//利率List的第一个值为借据的年利率和放款日
String yearRate = rateList.get(0).get("yearRate");
String rateDate = rateList.get(0).get("startDate");
String corpusDate = "";
long days = 0;
int j = 0;
int k = 0;
int size = settlementDateList.size();
StringBuffer msg = new StringBuffer();
//DecimalFormat df = new DecimalFormat("###0.0");
DecimalFormat df = new DecimalFormat("###0.0#####");
try{
//计算开始日期startDate后的最初利率
for(; k<rateList.size() && DateTools.compareToDate(calcStartDate, rateList.get(k).get("startDate"))>=0; k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
yearRate = rateMap.get("yearRate");
}
yearRate = df.format(new BigDecimal(yearRate));
for(int i=0; i<size; i++){
settleDate = settlementDateList.get(i);
//msg = new StringBuffer();
msg.setLength(0);
//
for(; j<corpusList.size() && DateTools.compareToDate(settleDate, corpusPlanDate.get(j))==1; j++){
corpusDate = corpusPlanDate.get(j);
//根据央行调息记录在日期区间【calcStartDate,corpusDate】作分段处理
for(; k<rateList.size() && DateTools.compareToDate(corpusDate, rateList.get(k).get("startDate"))==1; k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
calcEndDate = rateDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(NumberUtils.formatNumberDoubleQian(overageCorpus.toString()))
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append(";");
}
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
yearRate = rateMap.get("yearRate");
yearRate = df.format(new BigDecimal(yearRate));
}
calcEndDate = corpusDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
//logger.debug(days + "=" + calcEndDate + "-" + calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(NumberUtils.formatNumberDoubleQian(overageCorpus.toString()))
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append(";");
}
overageCorpus = overageCorpus.subtract(corpusList.get(j));
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
}
//根据央行调息记录在日期区间【calcStartDate,settleDate】作分段处理
for(; k<rateList.size() && DateTools.compareToDate(settleDate, rateList.get(k).get("startDate"))==1; k++){
rateMap = rateList.get(k);
rateDate = rateMap.get("startDate");
calcEndDate = rateDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(NumberUtils.formatNumberDoubleQian(overageCorpus.toString()))
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append(";");
}
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
yearRate = rateMap.get("yearRate");
yearRate = df.format(new BigDecimal(yearRate));
}
calcEndDate = settleDate;
days = DateTools.getDateDiff(calcEndDate, calcStartDate);
//logger.debug(days + "=" + calcEndDate + "-" + calcStartDate);
if(days!=0){
msg.append(days).append("天*剩余本金").append(NumberUtils.formatNumberDoubleQian(overageCorpus.toString()))
.append("*日利率(").append(yearRate).append("/100/").append(rateYearDays).append("),开始: ").append(calcStartDate)
.append("结束:").append(calcEndDate).append("");
}
calcStartDate = calcEndDate;//将本次的结束日期设为下次的开始日期
list.add(msg.toString());
}
} catch (ParseException e) {
e.printStackTrace();
}
return list;
}
/**
* 取季末月日期取距起算日期最近的3、6、9、12月份的年月+还款日
* @param startDate
* @param payDay还款日
* @return
* @throws ParseException
*/
public static String getQuarterTerminalDate(String startDate, String payDay) throws ParseException{
String planDate = "";
planDate = DateTools.setDateDay(startDate, payDay);
if(DateTools.compareToDate(planDate, startDate) <= 0){
planDate = DateTools.dateAdd("month", 1, planDate);
}
int month = Integer.parseInt(DateTools.getDateMonth(planDate));
if(month<=3){
planDate = DateTools.setDateMonth(planDate, "3");
}else if(month<=6){
planDate = DateTools.setDateMonth(planDate, "6");
}else if(month<=9){
planDate = DateTools.setDateMonth(planDate, "9");
}else if(month<=12){
planDate = DateTools.setDateMonth(planDate, "12");
}
//再次设定日期天数是由于前面处理时对日期做了月末处理天数可能与payDay不一致
planDate = DateTools.setDateDay(planDate, payDay);
return planDate;
}
/**
* 取半年末月日期取距起算日期最近的6、12月份的年月+还款日
* @param startDate
* @param payDay还款日
* @return
* @throws ParseException
*/
public static String getHalfYearTerminalDate(String startDate, String payDay) throws ParseException{
String planDate = "";
planDate = DateTools.setDateDay(startDate, payDay);
if(DateTools.compareToDate(planDate, startDate) <= 0){
planDate = DateTools.dateAdd("month", 1, planDate);
}
int month = Integer.parseInt(DateTools.getDateMonth(planDate));
if(month<=6){
planDate = DateTools.setDateMonth(planDate, "6");
}else if(month<=12){
planDate = DateTools.setDateMonth(planDate, "12");
}
//再次设定日期天数是由于前面处理时对日期做了月末处理天数可能与payDay不一致
planDate = DateTools.setDateDay(planDate, payDay);
return planDate;
}
/**
* 取年末月日期取距起算日期最近的12月份的年月+还款日
* @param startDate
* @param payDay还款日
* @return
* @throws ParseException
*/
public static String getYearTerminalDate(String startDate, String payDay) throws ParseException{
String planDate = "";
planDate = DateTools.setDateDay(startDate, payDay);
if(DateTools.compareToDate(planDate, startDate) <= 0){
planDate = DateTools.dateAdd("month", 1, planDate);
}
planDate = DateTools.setDateMonth(planDate, "12");
//再次设定日期天数是由于前面处理时对日期做了月末处理天数可能与payDay不一致
planDate = DateTools.setDateDay(planDate, payDay);
return planDate;
}
/**
* 根据借款借据信息获得本金计划
* @param billInfo借款借据信息
* @return
* @throws Exception
*/
public static List<BizObject> calculateCorpusPlan(BizObject billInfo) throws Exception{
List<BizObject> list = new ArrayList<BizObject>();
List<String> planDateList = null;
List<BigDecimal> corpusList = null;
String payType = billInfo.getAttribute("CORPUS_PAY_TYPE").getString();//还本方式
String payDay =billInfo.getAttribute("PAY_CORPUS_DAY").getString();//还本日
String startDate = billInfo.getAttribute("LOAN_START_DATE").getString();//放款日
String endDate = billInfo.getAttribute("LOAN_END_DATE").getString();
BigDecimal amount =new BigDecimal(billInfo.getAttribute("LOAN_AMOUNT").getString());
String currency=billInfo.getAttribute("CURRENCY").getString();
int size = 0;
planDateList = FundCalculateHelper.getPlanDateList(payType, startDate, endDate, payDay, "");
size = planDateList.size();
corpusList = FundCalculateHelper.getCorpusList(amount, size);
BizObjectManager bm=JBOFactory.getBizObjectManager(LOAN_CORPUS_PLAN.CLASS_NAME);
String creattime=DateUtils.getSystemDate(0);
for(int i=0; i<size; i++){
BizObject plan=bm.newObject();
plan.setAttributeValue("plan_list", i+1);
plan.setAttributeValue("plan_date", planDateList.get(i));
plan.setAttributeValue("real_date", planDateList.get(i));
plan.setAttributeValue("corpus", corpusList.get(i));
plan.setAttributeValue("bill_id", billInfo.getAttribute("id").getString());
plan.setAttributeValue("CURRENCY", currency);
plan.setAttributeValue("create_date",creattime);
list.add(plan);
}
return list;
}
/**
* 根据借款借据信息和本金计划获得利息计划
* @param billInfo借款借据信息
* @param corpusPlanList本金计划列表
* @param lastDate上次结息日
* @return
* @throws Exception
*/
public static List<BizObject> calculateInterestPlan(BizObject billInfo, List<BizObject> corpusPlanList, String lastDate, int startList, List<BizObject> rateInfoList,JBOTransaction tx) throws Exception{
List<BizObject> list = new ArrayList<BizObject>();
List<BigDecimal> interestList = new ArrayList<BigDecimal>();
List<String> calcInterestInfoList = new ArrayList<String>();
List<BigDecimal> corpusList = new ArrayList<BigDecimal>();
List<String> corpusDateList = new ArrayList<String>();
List<String> planDateList = null;
List<String> settlementDateList = null;
String payType = billInfo.getAttribute("Interest_Pay_Type").getString(); //利息还款方式
String payDay = billInfo.getAttribute("Pay_Interest_Day").getInt()+""; //付息日
String settlementDay = billInfo.getAttribute("Settlement_Day").getInt()+""; //结息日
String startDate = billInfo.getAttribute("Loan_Start_Date").getString(); //本次计息开始日,默认放款日
String endDate = billInfo.getAttribute("Loan_End_Date").getString(); //到期日
BigDecimal corpusOverage =new BigDecimal( billInfo.getAttribute("Loan_Amount").getString()); //剩余本金
String currency = billInfo.getAttribute("Currency").getString(); //币种
BigDecimal yearRate =new BigDecimal( billInfo.getAttribute("Rate").getString()); //最终借款利率
String rateYearDays = billInfo.getAttribute("Rate_Year_Days").getInt()+""; //年计息天数
String lastInterestFlag = billInfo.getAttribute("LAST_INTERESTFLAG").getString(); //是否最后一笔利随本金
String interestCalculationMethod = billInfo.getAttribute("Interest_Calculation_Method").getString(); //还款利息计算方法
String startPlanDate = billInfo.getAttribute("Loan_Start_Date").getString();
String rateType = billInfo.getAttribute("Rate_Type").getString(); //利率类型
if(lastDate!=null && !"".equals(lastDate)){
//将本次计息开始日设为上次结息日
startDate = lastDate;
startPlanDate = DateTools.setDateDay(startDate, payDay);//哪个日期小,就取哪个
}
//还款利息计算方法:手工制作法、剩余本金计息法
if("interestcalculationmethod02".equals(interestCalculationMethod)){//手工制作法
return list;
}
if("interestpaytype06".equals(payType)){//利随本清
payType = billInfo.getAttribute("Corpus_Pay_Type").getString();//利息还款方式为利随本清时,利息还款方式与还本方式一致。
}
int size = 0;
//付息日
planDateList = FundCalculateHelper.getPlanDateList(payType, startPlanDate, endDate, payDay, lastInterestFlag);
//结息日
settlementDateList = FundCalculateHelper.getPlanDateList(payType, startDate, endDate, settlementDay, "");
size = settlementDateList.size();
//为了保证本金列表的有序性按日期排序
//Collections.sort(corpusPlanList);
//本金相关列表及剩余本金处理,计算利息时只考虑本次计息开始日之后的本金相关数据
for(int i=0; i<corpusPlanList.size(); i++){
//本次计息开始日大于等于第i期本金还款日
if(DateTools.compareToDate(startDate, corpusPlanList.get(i).getAttribute("Plan_Date").getString()) >= 0){
//剩余本金减去第i期本金
corpusOverage = corpusOverage.subtract(new BigDecimal( corpusPlanList.get(i).getAttribute("Corpus").getString()));
}else{
corpusList.add(new BigDecimal( corpusPlanList.get(i).getAttribute("Corpus").getString()));
corpusDateList.add( corpusPlanList.get(i).getAttribute("Plan_Date").getString());
}
}
//获得利息列表
if("ratetype02".equals(rateType)){//固定利率
BigDecimal dayRate = getDayRate(yearRate, rateYearDays);//天利率
//存的利息列表
interestList = FundCalculateHelper.getInterestList(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, dayRate);
//利息计算公式
calcInterestInfoList = FundCalculateHelper.getCalcInterestInfo(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, yearRate.toString(), rateYearDays);
}else{//浮动利率需考虑调息
List<Map<String,String>> rateList = new ArrayList<Map<String,String>>();
Map<String, String> rateMap = new HashMap<String, String>();
rateMap.put("startDate", billInfo.getAttribute("Loan_Start_Date").getString());
rateMap.put("yearRate", yearRate.toString());
rateList.add(rateMap);
Map<String,String> adjustmap = new HashMap<String,String>();
adjustmap.put("bill_Id", billInfo.getAttribute("id").getString());
adjustmap.put("status_","rate_adjust");
List<BizObject> adjustlist =DataOperatorUtil.getSetJBO(LOAN_RATE_ADJUST.CLASS_NAME, adjustmap, tx);
for(int i=0; adjustlist!=null && i<adjustlist.size(); i++){
//得到的调息日和新的年利率的map
Map<String, String> map = new HashMap<String, String>();
map.put("startDate",adjustlist.get(i).getAttribute("Adjust_Date").getString());
map.put("yearRate",adjustlist.get(i).getAttribute("Rate_New").getString());
rateList.add(map);
}
interestList = FundCalculateHelper.getInterestList(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, rateList, rateYearDays);
calcInterestInfoList = FundCalculateHelper.getCalcInterestInfo(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, rateList, rateYearDays);
}
if(size>0 && planDateList.size()>0){
if(size == planDateList.size() && DateTools.compareToDate(settlementDateList.get(0), planDateList.get(0)) == 1){
//planDateList =[2015-12-01, 2016-06-01, 2016-12-01, 2017-06-01, 2017-12-01, 2018-06-01, 2018-11-12]
//settlementDateList=[2015-12-10, 2016-06-10, 2016-12-10, 2017-06-10, 2017-12-10, 2018-06-10, 2018-11-12]
}
if(size + 1 == planDateList.size() && DateTools.compareToDate(settlementDateList.get(0), planDateList.get(0)) == -1){
planDateList.remove(0);//
}
if(size>1 && size - 1 == planDateList.size() && DateTools.compareToDate(settlementDateList.get(size-1), planDateList.get(size-2)) == 0){
planDateList.add(settlementDateList.get(size-1));
}
}
String currentTime=DateUtils.getSystemDate(0);
BizObjectManager bm=JBOFactory.getBizObjectManager(LOAN_INTEREST_PLAN.CLASS_NAME);
for(int i=0; i<size; i++){
BizObject interestPlan =bm.newObject();
int interestDays = 0;
interestPlan.setAttributeValue("bill_id", billInfo.getAttribute("id").getString());
interestPlan.setAttributeValue("plan_list",i+startList);
interestPlan.setAttributeValue("plan_date", planDateList.get(i));
interestPlan.setAttributeValue("real_date",planDateList.get(i));
interestPlan.setAttributeValue("Settlement_Date", settlementDateList.get(i));
interestPlan.setAttributeValue("Interest",interestList.get(i));
interestPlan.setAttributeValue("Calculation_Gs",calcInterestInfoList.get(i));
interestPlan.setAttributeValue("Currency",currency);
if(i == 0){
interestDays = (int) DateTools.getDateDiff(settlementDateList.get(i),startDate );
}else{
interestDays = (int) DateTools.getDateDiff( settlementDateList.get(i),settlementDateList.get(i-1));
}
interestPlan.setAttributeValue("Interest_Days", interestDays);
interestPlan.setAttributeValue("Create_Date", currentTime);
list.add(interestPlan);
}
return list;
}
/**
* 新增借据时,根据借款借据信息和本金计划获得利息计划
* @param billInfo借款借据信息
* @param corpusPlanList本金计划列表
* @param lastDate上次结息日
* @return
* @throws Exception
*/
public static List<BizObject> calculateInterestPlan1(BizObject billInfo, List<BizObject> corpusPlanList, String lastDate, int startList, List<BizObject> rateInfoList) throws Exception{
List<BizObject> list = new ArrayList<BizObject>();
List<BigDecimal> interestList = new ArrayList<BigDecimal>();
List<String> calcInterestInfoList = new ArrayList<String>();
List<BigDecimal> corpusList = new ArrayList<BigDecimal>();
List<String> corpusDateList = new ArrayList<String>();
List<String> planDateList = null;
List<String> settlementDateList = null;
String payType = billInfo.getAttribute("INTEREST_PAY_TYPE").getString(); //利息还款方式
String payDay =billInfo.getAttribute("PAY_INTEREST_DAY").getString(); //付息日
String settlementDay =billInfo.getAttribute("SETTLEMENT_DAY").getString(); //结息日
String startDate = billInfo.getAttribute("LOAN_StART_DATE").getString(); //本次计息开始日,默认放款日
String endDate = billInfo.getAttribute("LOAN_END_DATE").getString(); //到期日
BigDecimal corpusOverage =new BigDecimal(billInfo.getAttribute("LOAN_AMOUNT").getString()); //剩余本金
String currency = billInfo.getAttribute("CURRENCY").getString(); //币种
BigDecimal yearRate =new BigDecimal( billInfo.getAttribute("rate").getString()); //最终借款利率
String rateYearDays = billInfo.getAttribute("RATE_YEAR_DAYS").getString(); //年计息天数
String lastInterestFlag = billInfo.getAttribute("LAST_INTERESTFLAG").getString(); //是否最后一笔利随本金
String interestCalculationMethod = billInfo.getAttribute("INTEREST_CALCULATION_METHOD").getString(); //还款利息计算方法
String startPlanDate = billInfo.getAttribute("LOAN_StART_DATE").getString();
String rateType = billInfo.getAttribute("RATE_TYPE").getString(); //利率类型
if(lastDate!=null && !"".equals(lastDate)){
//将本次计息开始日设为上次结息日
startDate = lastDate;
startPlanDate = DateTools.setDateDay(startDate, payDay);//哪个日期小,就取哪个
}
//还款利息计算方法:手工制作法、剩余本金计息法
if("interestcalculationmethod02".equals(interestCalculationMethod)){//手工制作法
return list;
}
if("interestpaytype06".equals(payType)){//利随本清
payType = billInfo.getAttribute("CORPUS_PAY_TYPE").getString();//利息还款方式为利随本清时,利息还款方式与还本方式一致。
}
int size = 0;
//付息日
planDateList = FundCalculateHelper.getPlanDateList(payType, startPlanDate, endDate, payDay, lastInterestFlag);
//结息日
settlementDateList = FundCalculateHelper.getPlanDateList(payType, startDate, endDate, settlementDay, "");
size = settlementDateList.size();
//为了保证本金列表的有序性按日期排序
//Collections.sort(corpusPlanList);
//本金相关列表及剩余本金处理,计算利息时只考虑本次计息开始日之后的本金相关数据
for(int i=0; i<corpusPlanList.size(); i++){
//本次计息开始日大于等于第i期本金还款日
if(DateTools.compareToDate(startDate, corpusPlanList.get(i).getAttribute("plan_date").getString()) >= 0){
//剩余本金减去第i期本金
corpusOverage = corpusOverage.subtract(new BigDecimal( corpusPlanList.get(i).getAttribute("corpus").getString()));
}else{
corpusList.add(new BigDecimal( corpusPlanList.get(i).getAttribute("corpus").getString()));
corpusDateList.add(corpusPlanList.get(i).getAttribute("plan_date").getString());
}
}
//获得利息列表
if("ratetype02".equals(rateType)){//固定利率
BigDecimal dayRate = getDayRate(yearRate, rateYearDays);//天利率
//存的利息列表
interestList = FundCalculateHelper.getInterestList(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, dayRate);
//利息计算公式
calcInterestInfoList = FundCalculateHelper.getCalcInterestInfo(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, yearRate.toString(), rateYearDays);
}else{//浮动利率需考虑调息
List<Map<String,String>> rateList = new ArrayList<Map<String,String>>();
Map<String, String> rateMap = new HashMap<String, String>();
rateMap.put("startDate", startPlanDate);
rateMap.put("yearRate", yearRate.toString());
rateList.add(rateMap);
logger.debug("调息生效记录:"+rateList);
interestList = FundCalculateHelper.getInterestList(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, rateList, rateYearDays);
calcInterestInfoList = FundCalculateHelper.getCalcInterestInfo(corpusOverage, startDate, settlementDateList, corpusDateList, corpusList, rateList, rateYearDays);
}
logger.debug("planDateList="+planDateList);
logger.debug("settlementDateList="+settlementDateList);
if(size>0 && planDateList.size()>0){
if(size == planDateList.size() && DateTools.compareToDate(settlementDateList.get(0), planDateList.get(0)) == 1){
//planDateList =[2015-12-01, 2016-06-01, 2016-12-01, 2017-06-01, 2017-12-01, 2018-06-01, 2018-11-12]
//settlementDateList=[2015-12-10, 2016-06-10, 2016-12-10, 2017-06-10, 2017-12-10, 2018-06-10, 2018-11-12]
}
if(size + 1 == planDateList.size() && DateTools.compareToDate(settlementDateList.get(0), planDateList.get(0)) == -1){
planDateList.remove(0);//
}
if(size>1 && size - 1 == planDateList.size() && DateTools.compareToDate(settlementDateList.get(size-1), planDateList.get(size-2)) == 0){
planDateList.add(settlementDateList.get(size-1));
}
}
BizObjectManager bm=JBOFactory.getBizObjectManager(LOAN_INTEREST_PLAN.CLASS_NAME);
String creattime=DateUtils.getSystemDate(0);
for(int i=0; i<size; i++){
BizObject interestPlan = bm.newObject();
int interestDays = 0;
interestPlan.setAttributeValue("bill_id", billInfo.getAttribute("id").getString());
interestPlan.setAttributeValue("plan_list", i+startList);
interestPlan.setAttributeValue("plan_date", planDateList.get(i));
interestPlan.setAttributeValue("real_date", planDateList.get(i));
interestPlan.setAttributeValue("Settlement_Date", settlementDateList.get(i));
interestPlan.setAttributeValue("Interest", interestList.get(i));
interestPlan.setAttributeValue("CALCULATION_GS", calcInterestInfoList.get(i));
interestPlan.setAttributeValue("Currency", currency);
if(i == 0){
interestDays = (int) DateTools.getDateDiff( settlementDateList.get(i),startDate);
}else{
interestDays = (int) DateTools.getDateDiff( settlementDateList.get(i),settlementDateList.get(i-1));
}
interestPlan.setAttributeValue("INTEREST_DAYS", interestDays);
interestPlan.setAttributeValue("create_date", creattime);
list.add(interestPlan);
}
return list;
}
/**
* 获得借据的调息开始日和新年利率
* @param billInfo 借据信息
* @param rateInfo 央行基准利率信息
* @return {调息开始日,新年利率}
* @throws Exception
*/
public static Map<String,String> getTransRateAndDate(BizObject billInfo, BizObject rateInfo) throws Exception{
Map<String,String> rateMap = new HashMap<String, String>();
String rateType = billInfo.getAttribute("RATE_TYPE").getString(); //利率类型、浮动利率
String adjustPeriod = billInfo.getAttribute("Adjust_Period").getString(); //浮动周期
String adjustDay = billInfo.getAttribute("Adjust_Day").getInt()+""; //调息日
String rateTerm = billInfo.getAttribute("Rate_Term").getString(); //利率参照年限
String adjustType = billInfo.getAttribute("Adjust_Type").getString(); //浮动类型
BigDecimal floatRange = new BigDecimal(billInfo.getAttribute("Float_Range").getString()); //浮动幅度
String startDate = rateInfo.getAttribute("Start_Date").getString(); //央行调息日
String realStartDate = startDate; //贷款实际调息日
String yearRate = "0";
if("ratetype02".equals(rateType)){//固定利率
realStartDate = billInfo.getAttribute("Loan_Start_Date").getString();
yearRate = billInfo.getAttribute("rate").getString();
rateMap.put("startDate", realStartDate);
rateMap.put("yearRate", yearRate);
}else{//浮动利率
realStartDate = getTransRateStartDate(startDate, adjustPeriod, adjustDay);//得到处理后的调息日
yearRate = getTransNewRate(rateInfo, rateTerm, adjustType, floatRange).toString();
rateMap.put("startDate", realStartDate);
rateMap.put("yearRate", yearRate);
}
return rateMap;
}
/**
* 根据央行基准日、调息周期、调息日获得调息开始日,每月/季/半年/年未实现
* @param startDate 央行基准日
* @param adjustPeriod 调息周期
* @param adjustDay 调息日
* @return 调息开始日
* @throws Exception
*/
public static String getTransRateStartDate(String startDate, String adjustPeriod, String adjustDay) throws Exception{
String realDate = startDate;
if("adjust_period01".equals(adjustPeriod)){//日
realDate = DateTools.dateAdd("day", 1, startDate);
}else if("adjust_period02".equals(adjustPeriod)){//月:起算日期+1个月的年月+调息日
realDate = DateTools.dateAdd("month", 1, startDate);
realDate = DateTools.setDateDay(realDate, adjustDay);
}else if("adjust_period03".equals(adjustPeriod)){//季
realDate = DateTools.dateAdd("month", 3, startDate);
realDate = DateTools.setDateDay(realDate, adjustDay);
}else if("adjust_period04".equals(adjustPeriod)){//半年
realDate = DateTools.dateAdd("month", 6, startDate);
realDate = DateTools.setDateDay(realDate, adjustDay);
}else if("adjust_period05".equals(adjustPeriod)){//年
realDate = DateTools.dateAdd("year", 1, startDate);
realDate = DateTools.setDateDay(realDate, adjustDay);
}else if("adjust_period06".equals(adjustPeriod)){//每月
realDate = startDate;
}else if("adjust_period07".equals(adjustPeriod)){//每季
realDate = startDate;
}else if("adjust_period08".equals(adjustPeriod)){//每半年
realDate = startDate;
}else if("adjust_period09".equals(adjustPeriod)){//每年
realDate = startDate;
}
return realDate;
}
/**
* 获得调息后的新年利率
* @param rateInfo 央行基准利率信息
* @param rateTerm 利率参照年限
* @param adjustType 浮动类型
* @param floatRange 浮动幅度
* @return 新年利率
* @throws JBOException
*/
public static BigDecimal getTransNewRate(BizObject rateInfo, String rateTerm, String adjustType, BigDecimal floatRange) throws JBOException{
BigDecimal yearRate = BigDecimal.ZERO;
BigDecimal baseRate = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
if("基准利率6个月(含6月)".equals(rateTerm)){
baseRate = new BigDecimal(rateInfo.getAttribute("Base_Rate_Half").getString());
}else if("基准利率1年(含1年)".equals(rateTerm)){
baseRate = new BigDecimal(rateInfo.getAttribute("Base_Rate_One").getString());
}else if("基准利率1-3年(含3年)".equals(rateTerm)){
baseRate = new BigDecimal(rateInfo.getAttribute("Base_Rate_Three").getString());
}else if("基准利率3-5年(含5年)".equals(rateTerm)){
baseRate = new BigDecimal(rateInfo.getAttribute("Base_Rate_Five").getString());
}else if("基准利率5年以上".equals(rateTerm)){
baseRate = new BigDecimal(rateInfo.getAttribute("Base_Rate_Above_five").getString());
}
if("adjust_type01".equals(adjustType)){//基准
yearRate = baseRate;
}else if("adjust_type02".equals(adjustType)){//上浮
yearRate = baseRate.multiply(one.add(floatRange));//
}else if("adjust_type03".equals(adjustType)){//下浮
yearRate = baseRate.multiply(one.subtract(floatRange));
}else if("adjust_type04".equals(adjustType)){//增加
yearRate = baseRate.add(floatRange);
}else if("adjust_type05".equals(adjustType)){//减少
yearRate = baseRate.subtract(floatRange);
}
yearRate = yearRate.setScale(Scale.GENERAL_RATE, BigDecimal.ROUND_HALF_UP);
return yearRate;
}
/**
* 获得日利率
* @param yearRate 年利率%
* @param rateYearDays 年计息天数
* @return 日利率
*/
public static BigDecimal getDayRate(BigDecimal yearRate, String rateYearDays){
BigDecimal dayRate = yearRate.divide(new BigDecimal(rateYearDays).multiply(new BigDecimal("100")), Scale.RATE_SCALE, BigDecimal.ROUND_HALF_UP);
return dayRate;
}
public static void main(String[] args) {
try {
String startDate = "2015-03-28";
String endDate = "2016-03-27";
String corpusDay = "31";
String interestDay = "5";
String settleDay = "10";
BigDecimal amount = new BigDecimal("5000000");
String payType = "interestpaytype02";
String yearRate = "8";
String yearDays = "360";
BigDecimal dayRate = getDayRate(new BigDecimal(yearRate), yearDays);
List<String> corpusDateList = new ArrayList<String>();
List<BigDecimal> corpusList = new ArrayList<BigDecimal>();
List<String> interestDateList = new ArrayList<String>();
List<String> settleDatelist = new ArrayList<String>();
List<BigDecimal> interestList = new ArrayList<BigDecimal>();
corpusDateList = getPlanDateList(payType, startDate, endDate, corpusDay,"");
interestDateList = getPlanDateList(payType, startDate, endDate, interestDay,"");
settleDatelist = getPlanDateList(payType, startDate, endDate, settleDay,"");
corpusList = getCorpusList(amount, corpusDateList.size());
interestList = getInterestList(amount, startDate, settleDatelist, corpusDateList, corpusList, dayRate);
logger.debug("corpusDateList"+corpusDateList);
logger.debug("interestDateList"+interestDateList);
logger.debug("settleDatelist"+settleDatelist);
logger.debug("corpusList"+corpusList);
logger.debug("interestList"+interestList);
} catch (Exception e) {
e.printStackTrace();
}
}
}