FINERACT-491 :fiscal month compounding

This commit is contained in:
nazeer shaik
2017-11-07 18:12:07 +05:30
parent d6accae348
commit 630c942fa3
4 changed files with 78 additions and 43 deletions
@@ -320,7 +320,7 @@ public class FixedDepositAccount extends SavingsAccount {
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions,
this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation,
isSavingsInterestPostingAtCurrentPeriodEnd, isUserPosting);
isSavingsInterestPostingAtCurrentPeriodEnd, isUserPosting, financialYearBeginningMonth);
periodStartingBalance = postingPeriod.closingBalance();
@@ -352,7 +352,7 @@ public class RecurringDepositAccount extends SavingsAccount {
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions,
this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation,
isSavingsInterestPostingAtCurrentPeriodEnd, isUserPosting);
isSavingsInterestPostingAtCurrentPeriodEnd, isUserPosting, financialYearBeginningMonth);
periodStartingBalance = postingPeriod.closingBalance();
@@ -749,7 +749,7 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType,
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions,
isInterestTransfer, minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd,
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting);
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth);
periodStartingBalance = postingPeriod.closingBalance();
@@ -22,8 +22,10 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeSet;
import org.apache.fineract.infrastructure.core.domain.LocalDateInterval;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
@@ -33,8 +35,7 @@ import org.joda.time.DateTime;
import org.joda.time.LocalDate;
public class PostingPeriod {
@SuppressWarnings("unused")
private final LocalDateInterval periodInterval;
private final MonetaryCurrency currency;
private final SavingsCompoundingInterestPeriodType interestCompoundingType;
@@ -60,13 +61,15 @@ public class PostingPeriod {
private final Money minBalanceForInterestCalculation;
private BigDecimal overdraftInterestRateAsFraction;
private Money minOverdraftForInterestCalculation;
private Integer financialYearBeginningMonth;
public static PostingPeriod createFrom(final LocalDateInterval periodInterval, final Money periodStartingBalance,
final List<SavingsAccountTransaction> orderedListOfTransactions, final MonetaryCurrency currency,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
final LocalDate upToInterestCalculationDate, Collection<Long> interestPostTransactions, boolean isInterestTransfer,
final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,final boolean isUserPosting) {
final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,final boolean isUserPosting, Integer financialYearBeginningMonth) {
final BigDecimal overdraftInterestRateAsFraction = BigDecimal.ZERO;
final Money minOverdraftForInterestCalculation = Money.zero(currency);
@@ -75,7 +78,7 @@ public class PostingPeriod {
interestCompoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYear,
upToInterestCalculationDate, interestPostTransactions, isInterestTransfer,
minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd,
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting);
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth);
}
// isInterestTransfer boolean is to identify newly created transaction is
@@ -86,7 +89,7 @@ public class PostingPeriod {
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
final LocalDate upToInterestCalculationDate, Collection<Long> interestPostTransactions, boolean isInterestTransfer,
final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final BigDecimal overdraftInterestRateAsFraction, final Money minOverdraftForInterestCalculation, boolean isUserPosting) {
final BigDecimal overdraftInterestRateAsFraction, final Money minOverdraftForInterestCalculation, boolean isUserPosting, int financialYearBeginningMonth) {
final List<EndOfDayBalance> accountEndOfDayBalances = new ArrayList<>();
boolean interestTransfered = false;
@@ -143,12 +146,12 @@ public class PostingPeriod {
}
final List<CompoundingPeriod> compoundingPeriods = compoundingPeriodsInPostingPeriod(periodInterval, interestCompoundingPeriodType,
accountEndOfDayBalances, upToInterestCalculationDate);
accountEndOfDayBalances, upToInterestCalculationDate, financialYearBeginningMonth);
return new PostingPeriod(periodInterval, currency, periodStartingBalance, openingDayBalance, interestCompoundingPeriodType,
interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods, interestTransfered,
minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd,
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting);
overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth);
}
private PostingPeriod(final LocalDateInterval periodInterval, final MonetaryCurrency currency, final Money openingBalance,
@@ -156,7 +159,7 @@ public class PostingPeriod {
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
final List<CompoundingPeriod> compoundingPeriods, boolean interestTransfered, final Money minBalanceForInterestCalculation,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final BigDecimal overdraftInterestRateAsFraction,
final Money minOverdraftForInterestCalculation, boolean isUserPosting) {
final Money minOverdraftForInterestCalculation, boolean isUserPosting, Integer financialYearBeginningMonth) {
this.periodInterval = periodInterval;
this.currency = currency;
this.openingBalance = openingBalance;
@@ -176,6 +179,7 @@ public class PostingPeriod {
this.overdraftInterestRateAsFraction = overdraftInterestRateAsFraction;
this.minOverdraftForInterestCalculation = minOverdraftForInterestCalculation;
this.isUserPosting = isUserPosting;
this.financialYearBeginningMonth = financialYearBeginningMonth;
}
public Money interest() {
@@ -211,7 +215,7 @@ public class PostingPeriod {
if (!SavingsCompoundingInterestPeriodType.DAILY.equals(this.interestCompoundingType)) {
compoundingPeriodEndDate = determineInterestPeriodEndDateFrom(
compoundingPeriod.getPeriodInterval().startDate(), this.interestCompoundingType,
compoundingPeriod.getPeriodInterval().endDate());
compoundingPeriod.getPeriodInterval().endDate(), this.getFinancialYearBeginningMonth());
}
if (compoundingPeriodEndDate.equals(compoundingPeriod.getPeriodInterval().endDate())) {
@@ -235,7 +239,7 @@ public class PostingPeriod {
private static List<CompoundingPeriod> compoundingPeriodsInPostingPeriod(final LocalDateInterval postingPeriodInterval,
final SavingsCompoundingInterestPeriodType interestPeriodType, final List<EndOfDayBalance> allEndOfDayBalances,
final LocalDate upToInterestCalculationDate) {
final LocalDate upToInterestCalculationDate, int financialYearBeginningMonth) {
final List<CompoundingPeriod> compoundingPeriods = new ArrayList<>();
@@ -256,7 +260,7 @@ public class PostingPeriod {
while (!periodStartDate.isAfter(postingPeriodEndDate) && !periodEndDate.isAfter(postingPeriodEndDate)) {
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate);
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth);
if (periodEndDate.isAfter(postingPeriodEndDate)) {
periodEndDate = postingPeriodEndDate;
}
@@ -285,7 +289,7 @@ public class PostingPeriod {
while (!periodStartDate.isAfter(qPostingPeriodEndDate) && !periodEndDate.isAfter(qPostingPeriodEndDate)) {
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate);
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth);
if (periodEndDate.isAfter(qPostingPeriodEndDate)) {
periodEndDate = qPostingPeriodEndDate;
}
@@ -310,7 +314,7 @@ public class PostingPeriod {
while (!periodStartDate.isAfter(bPostingPeriodEndDate) && !periodEndDate.isAfter(bPostingPeriodEndDate)) {
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate);
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth);
if (periodEndDate.isAfter(bPostingPeriodEndDate)) {
periodEndDate = bPostingPeriodEndDate;
}
@@ -335,7 +339,7 @@ public class PostingPeriod {
while (!periodStartDate.isAfter(aPostingPeriodEndDate) && !periodEndDate.isAfter(aPostingPeriodEndDate)) {
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate);
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType, upToInterestCalculationDate, financialYearBeginningMonth);
if (periodEndDate.isAfter(aPostingPeriodEndDate)) {
periodEndDate = aPostingPeriodEndDate;
}
@@ -360,10 +364,14 @@ public class PostingPeriod {
}
private static LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate,
final SavingsCompoundingInterestPeriodType interestPeriodType, final LocalDate upToInterestCalculationDate) {
final SavingsCompoundingInterestPeriodType interestPeriodType, final LocalDate upToInterestCalculationDate, int financialYearBeginningMonth) {
LocalDate periodEndDate = upToInterestCalculationDate;
int previousMonth = financialYearBeginningMonth-1;
if(previousMonth==0){
previousMonth = 12;
}
int periodsInMonth = 1;
switch (interestPeriodType) {
case INVALID:
break;
@@ -383,34 +391,20 @@ public class PostingPeriod {
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
case QUATERLY:
// // jan 1st to mar 31st, 1st apr to jun 30, jul 1st to sept
// 30,
// // oct 1st to dec 31
int year = periodStartDate.getYearOfEra();
int monthofYear = periodStartDate.getMonthOfYear();
if (monthofYear <= 3) {
periodEndDate = new DateTime().withDate(year, 3, 31).toLocalDate();
} else if (monthofYear <= 6) {
periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
} else if (monthofYear <= 9) {
periodEndDate = new DateTime().withDate(year, 9, 30).toLocalDate();
} else if (monthofYear <= 12) {
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
}
periodsInMonth = 4;
periodEndDate = getPeriodEndDate(periodEndDate, previousMonth, periodsInMonth, periodStartDate);
break;
case BI_ANNUAL:
// // jan 1st to 30, jul 1st to dec 31
year = periodStartDate.getYearOfEra();
monthofYear = periodStartDate.getMonthOfYear();
if (monthofYear <= 6) {
periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
} else if (monthofYear <= 12) {
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
}
case BI_ANNUAL:
periodsInMonth = 2;
periodEndDate = getPeriodEndDate(periodEndDate, previousMonth, periodsInMonth, periodStartDate);
break;
case ANNUAL:
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
periodEndDate = periodStartDate.withMonthOfYear(previousMonth);
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
if(periodEndDate.isBefore(periodStartDate)){
periodEndDate = periodEndDate.plusYears(1);
}
break;
// case NO_COMPOUNDING_SIMPLE_INTEREST:
@@ -422,6 +416,40 @@ public class PostingPeriod {
return periodEndDate;
}
private static LocalDate getPeriodEndDate(LocalDate periodEndDate, int previousMonth, int periodsInMonth, LocalDate periodStartDate) {
int year = periodStartDate.getYearOfEra();
int monthofYear = periodStartDate.getMonthOfYear();
LocalDate date = DateUtils.getLocalDateOfTenant();
TreeSet<Integer> monthSet = new TreeSet<>();
date = date.withMonthOfYear(previousMonth);
monthSet.add(date.getMonthOfYear());
int count =0;
while(count<(periodsInMonth-1)){
date = date.plusMonths((12/periodsInMonth));
monthSet.add(date.getMonthOfYear());
count++;
}
boolean notInRange = true;
/*
* if strt date is 2016-10-05
* if financial year set to 4 then applicable month will be march and september that is (3,9)
* if start date fall in month of oct,nov or dec then month will be 10, 11 or 12
* so period end date should be taken from next year for march month
*/
for (Integer month : monthSet) {
if(monthofYear<=month.intValue()){
periodEndDate = new DateTime().withDate(year, month, DateUtils.getLocalDateOfTenant().withMonthOfYear(month).dayOfMonth().withMaximumValue().getDayOfMonth()).toLocalDate();
notInRange = false;
break;
}
}
if(notInRange){
periodEndDate = new DateTime().withDate(year+1, monthSet.first(), DateUtils.getLocalDateOfTenant().withMonthOfYear(monthSet.first()).dayOfMonth().withMaximumValue().getDayOfMonth()).toLocalDate();
}
return periodEndDate;
}
public boolean isInterestTransfered() {
return this.interestTransfered;
}
@@ -433,4 +461,11 @@ public class PostingPeriod {
public boolean isUserPosting() {
return this.isUserPosting;
}
public Integer getFinancialYearBeginningMonth() {
return this.financialYearBeginningMonth;
}
}