diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java index cde266c61..5f09e6835 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/FixedDepositAccount.java @@ -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(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java index 8e276a933..4ad538e3e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/RecurringDepositAccount.java @@ -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(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java index 3f2da48e0..3def00ae5 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java @@ -749,7 +749,7 @@ public class SavingsAccount extends AbstractPersistableCustom { retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd, - overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting); + overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting, financialYearBeginningMonth); periodStartingBalance = postingPeriod.closingBalance(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java index 2341288cf..6e4070c23 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java @@ -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 orderedListOfTransactions, final MonetaryCurrency currency, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear, final LocalDate upToInterestCalculationDate, Collection 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 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 accountEndOfDayBalances = new ArrayList<>(); boolean interestTransfered = false; @@ -143,12 +146,12 @@ public class PostingPeriod { } final List 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 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 compoundingPeriodsInPostingPeriod(final LocalDateInterval postingPeriodInterval, final SavingsCompoundingInterestPeriodType interestPeriodType, final List allEndOfDayBalances, - final LocalDate upToInterestCalculationDate) { + final LocalDate upToInterestCalculationDate, int financialYearBeginningMonth) { final List 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 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; + } + + } \ No newline at end of file