diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java index ba433b419..45cfddd75 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java @@ -546,18 +546,24 @@ public class ClientSavingsIntegrationTest { cal.set(Calendar.YEAR, (Integer) dates.get(0)); cal.set(Calendar.MONTH, (Integer) dates.get(1) - 1); cal.set(Calendar.DAY_OF_MONTH, (Integer) dates.get(2)); + int n = 0; + Calendar current = Calendar.getInstance(); + while (cal.compareTo(current) < 0) { + n++; + cal.set(Calendar.YEAR, (Integer) dates.get(0) + n); + } + cal.set(Calendar.YEAR, (Integer) dates.get(0)); + cal.set(Calendar.MONTH, (Integer) dates.get(1) - 1); + cal.set(Calendar.DAY_OF_MONTH, (Integer) dates.get(2)); - this.savingsAccountHelper.payCharge((Integer) savingsChargeForPay.get("id"), savingsId, - ((Float) savingsChargeForPay.get("amount")).toString(), sdf.format(cal.getTime())); - HashMap paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, (Integer) savingsChargeForPay.get("id")); - assertEquals(savingsChargeForPay.get("amount"), paidCharge.get("amountPaid")); - - // temporary fix, this test case needs to be re-factored (will fail - // again on Jan 15 2016) - cal.set(Calendar.YEAR, (Integer) dates.get(0) + 1); - this.savingsAccountHelper.payCharge((Integer) savingsChargeForPay.get("id"), savingsId, - ((Float) savingsChargeForPay.get("amount")).toString(), sdf.format(cal.getTime())); - paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, (Integer) savingsChargeForPay.get("id")); + for (int i = 1; i <= n; i++) { + this.savingsAccountHelper.payCharge((Integer) savingsChargeForPay.get("id"), savingsId, + ((Float) savingsChargeForPay.get("amount")).toString(), sdf.format(cal.getTime())); + HashMap paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, (Integer) savingsChargeForPay.get("id")); + Float expectedValue = (Float) savingsChargeForPay.get("amount") * i; + assertEquals(expectedValue, paidCharge.get("amountPaid")); + cal.set(Calendar.YEAR, (Integer) dates.get(0) + i); + } Integer inactivatedChargeId = (Integer) this.savingsAccountHelper.inactivateCharge(annualSavingsChargeId, savingsId, CommonConstants.RESPONSE_RESOURCE_ID); @@ -618,7 +624,7 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper.payCharge((Integer) savingsChargeForPay.get("id"), savingsId, ((Float) savingsChargeForPay.get("amount")).toString(), sdf.format(cal.getTime())); - paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, (Integer) savingsChargeForPay.get("id")); + HashMap paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsId, (Integer) savingsChargeForPay.get("id")); assertEquals(savingsChargeForPay.get("amount"), paidCharge.get("amountPaid")); List nextDueDates = (List) paidCharge.get("dueDate"); LocalDate nextDueDate = new LocalDate((Integer) nextDueDates.get(0), (Integer) nextDueDates.get(1), (Integer) nextDueDates.get(2)); diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupSavingsIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupSavingsIntegrationTest.java index 0ba4d1d52..bb323c803 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupSavingsIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupSavingsIntegrationTest.java @@ -516,6 +516,10 @@ public class GroupSavingsIntegrationTest { LocalDate expectedNextDueDate = new LocalDate((Integer) dates.get(0), (Integer) dates.get(1), (Integer) dates.get(2)) .plusWeeks((Integer) paidCharge.get("feeInterval")); assertEquals(expectedNextDueDate, nextDueDate); + cal = Calendar.getInstance(); + + this.savingsAccountHelper.closeSavingsAccountAndGetBackRequiredField(savingsId, "true", null, sdf.format(cal.getTime())); + } public static Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 946a37156..b68eafe7f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -302,6 +302,7 @@ public class Loan extends AbstractPersistable { // see // http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags @LazyCollection(LazyCollectionOption.FALSE) + @OrderBy(value = "installmentNumber") @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true) private final List repaymentScheduleInstallments = new ArrayList<>(); @@ -5627,6 +5628,15 @@ public class Loan extends AbstractPersistable { } public int fetchNumberOfInstallmensAfterExceptions() { + if(this.repaymentScheduleInstallments.size() > 0){ + int numberOfInstallments = 0; + for (final LoanRepaymentScheduleInstallment installment : this.repaymentScheduleInstallments) { + if(!installment.isRecalculatedInterestComponent()){ + numberOfInstallments++; + } + } + return numberOfInstallments; + } return this.repaymentScheduleDetail().getNumberOfRepayments() + adjustNumberOfRepayments(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index 63cff273b..11a7281da 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -304,7 +304,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener installment = handleRecalculationForTransactions(mc, loanApplicationTerms, holidayDetailDTO, currency, scheduleParams, loanRepaymentScheduleTransactionProcessor, totalInterestChargedForFullLoanTerm, lastRestDate, scheduledDueDate, periodStartDateApplicableForInterest, applicableTransactions, currentPeriodParams, - lastTotalOutstandingInterestPaymentDueToGrace, installment); + lastTotalOutstandingInterestPaymentDueToGrace, installment, loanCharges); periods.add(installment); // Updates principal paid map with efective date for reducing @@ -424,7 +424,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener final Money totalInterestChargedForFullLoanTerm, final LocalDate lastRestDate, final LocalDate scheduledDueDate, final LocalDate periodStartDateApplicableForInterest, final Collection applicableTransactions, final ScheduleCurrentPeriodParams currentPeriodParams, final Money lastTotalOutstandingInterestPaymentDueToGrace, - final LoanScheduleModelPeriod installment) { + final LoanScheduleModelPeriod installment, Set loanCharges) { LoanScheduleModelPeriod modifiedInstallment = installment; if (scheduleParams.applyInterestRecalculation() && loanRepaymentScheduleTransactionProcessor != null) { Money principalProcessed = Money.zero(currency); @@ -446,7 +446,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener modifiedInstallment = handlePrepaymentOfLoan(mc, loanApplicationTerms, holidayDetailDTO, scheduleParams, totalInterestChargedForFullLoanTerm, scheduledDueDate, periodStartDateApplicableForInterest, currentPeriodParams.getInterestCalculationGraceOnRepaymentPeriodFraction(), currentPeriodParams, - lastTotalOutstandingInterestPaymentDueToGrace, transactionDate, modifiedInstallment); + lastTotalOutstandingInterestPaymentDueToGrace, transactionDate, modifiedInstallment, loanCharges); Money addToPrinciapal = Money.zero(currency); if (scheduleParams.getOutstandingBalance().isLessThanZero()) { @@ -486,7 +486,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener final Money totalInterestChargedForFullLoanTerm, final LocalDate scheduledDueDate, LocalDate periodStartDateApplicableForInterest, final double interestCalculationGraceOnRepaymentPeriodFraction, final ScheduleCurrentPeriodParams currentPeriodParams, final Money lastTotalOutstandingInterestPaymentDueToGrace, - final LocalDate transactionDate, final LoanScheduleModelPeriod installment) { + final LocalDate transactionDate, final LoanScheduleModelPeriod installment, Set loanCharges) { LoanScheduleModelPeriod modifiedInstallment = installment; if (!scheduleParams.getOutstandingBalance().isGreaterThan(currentPeriodParams.getInterestForThisPeriod()) && !scheduledDueDate.equals(transactionDate)) { @@ -510,20 +510,31 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener lastTotalOutstandingInterestPaymentDueToGrace, scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms, scheduleParams.getPeriodNumber(), mc, mergeVariationsToMap(scheduleParams), scheduleParams.getCompoundingMap(), periodStartDateApplicableForInterest, calculateTill, interestRates); - Money diff = currentPeriodParams.getInterestForThisPeriod().minus(interestTillDate.interest()); + // applies charges for the period + final ScheduleCurrentPeriodParams tempPeriod = new ScheduleCurrentPeriodParams( + totalInterestChargedForFullLoanTerm.getCurrency(), interestCalculationGraceOnRepaymentPeriodFraction); + tempPeriod.setInterestForThisPeriod(interestTillDate.interest()); + applyChargesForCurrentPeriod(loanCharges, totalInterestChargedForFullLoanTerm.getCurrency(), scheduleParams, calculateTill, + tempPeriod); + Money interestDiff = currentPeriodParams.getInterestForThisPeriod().minus(tempPeriod.getInterestForThisPeriod()); + Money chargeDiff = currentPeriodParams.getFeeChargesForInstallment().minus(tempPeriod.getFeeChargesForInstallment()); + Money penaltyDiff = currentPeriodParams.getPenaltyChargesForInstallment().minus(tempPeriod.getPenaltyChargesForInstallment()); + + Money diff = interestDiff.plus(chargeDiff).plus(penaltyDiff); if (!scheduleParams.getOutstandingBalance().minus(diff).isGreaterThanZero()) { scheduleParams.reduceOutstandingBalance(diff); - currentPeriodParams.minusInterestForThisPeriod(diff); + currentPeriodParams.minusInterestForThisPeriod(interestDiff); + currentPeriodParams.minusFeeChargesForInstallment(chargeDiff); + currentPeriodParams.minusPenaltyChargesForInstallment(penaltyDiff); currentPeriodParams.plusPrincipalForThisPeriod(diff); - final Money totalDue = currentPeriodParams.getPrincipalForThisPeriod().plus(currentPeriodParams.getInterestForThisPeriod()); // create and replaces repayment period // from parts modifiedInstallment = LoanScheduleModelRepaymentPeriod.repayment(scheduleParams.getInstalmentNumber(), scheduleParams.getPeriodStartDate(), transactionDate, currentPeriodParams.getPrincipalForThisPeriod(), scheduleParams.getOutstandingBalance(), currentPeriodParams.getInterestForThisPeriod(), - currentPeriodParams.getFeeChargesForInstallment(), currentPeriodParams.getPenaltyChargesForInstallment(), totalDue, - false); + currentPeriodParams.getFeeChargesForInstallment(), currentPeriodParams.getPenaltyChargesForInstallment(), + currentPeriodParams.fetchTotalAmountForPeriod(), false); scheduleParams.setTotalOutstandingInterestPaymentDueToGrace(interestTillDate.interestPaymentDueToGrace()); } @@ -602,7 +613,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener && scheduleParams.getLoanRepaymentScheduleTransactionProcessor() .isInterestFirstRepaymentScheduleTransactionProcessor()) { List currentTransactions = createCurrentTransactionList(detail); - if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.getInstalmentNumber() == 1) { + if (!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) || scheduleParams.getInstalmentNumber() == 1) { int periodDays = Days.daysBetween(scheduleParams.getPeriodStartDate(), transactionDate).getDays(); // calculates period start date for interest @@ -2603,6 +2614,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener this.feeChargesForInstallment = feeChargesForInstallment; } + public void minusFeeChargesForInstallment(Money feeChargesForInstallment) { + this.feeChargesForInstallment = this.feeChargesForInstallment.minus(feeChargesForInstallment); + } + public Money getPenaltyChargesForInstallment() { return this.penaltyChargesForInstallment; } @@ -2611,6 +2626,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener this.penaltyChargesForInstallment = penaltyChargesForInstallment; } + public void minusPenaltyChargesForInstallment(Money penaltyChargesForInstallment) { + this.penaltyChargesForInstallment = this.penaltyChargesForInstallment.minus(penaltyChargesForInstallment); + } + public Money fetchTotalAmountForPeriod() { return this.principalForThisPeriod.plus(interestForThisPeriod).plus(feeChargesForInstallment) .plus(penaltyChargesForInstallment); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index 55ddfdb70..72be8222f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -310,7 +310,7 @@ public class SavingsAccount extends AbstractPersistable { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance, - final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft, + final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation) { final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL; @@ -345,7 +345,7 @@ public class SavingsAccount extends AbstractPersistable { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean enforceMinRequiredBalance, - final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft, + final BigDecimal minRequiredBalance, final BigDecimal nominalAnnualInterestRateOverdraft, final BigDecimal minOverdraftForInterestCalculation) { this.client = client; this.group = group; @@ -457,33 +457,33 @@ public class SavingsAccount extends AbstractPersistable { final SavingsAccountTransaction postingTransaction = findInterestPostingTransactionFor(interestPostingTransactionDate); if (postingTransaction == null) { - SavingsAccountTransaction newPostingTransaction; - if(interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))){ - newPostingTransaction = SavingsAccountTransaction.interestPosting(this, office(), - interestPostingTransactionDate, interestEarnedToBePostedForPeriod); - }else{ - newPostingTransaction = SavingsAccountTransaction.overdraftInterest(this, office(), - interestPostingTransactionDate, interestEarnedToBePostedForPeriod.negated()); - } + SavingsAccountTransaction newPostingTransaction; + if (interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))) { + newPostingTransaction = SavingsAccountTransaction.interestPosting(this, office(), interestPostingTransactionDate, + interestEarnedToBePostedForPeriod); + } else { + newPostingTransaction = SavingsAccountTransaction.overdraftInterest(this, office(), interestPostingTransactionDate, + interestEarnedToBePostedForPeriod.negated()); + } this.transactions.add(newPostingTransaction); recalucateDailyBalanceDetails = true; } else { boolean correctionRequired = false; - if(postingTransaction.isInterestPostingAndNotReversed()){ - correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod); - }else{ - correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod.negated()); + if (postingTransaction.isInterestPostingAndNotReversed()) { + correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod); + } else { + correctionRequired = postingTransaction.hasNotAmount(interestEarnedToBePostedForPeriod.negated()); } if (correctionRequired) { postingTransaction.reverse(); - SavingsAccountTransaction newPostingTransaction; - if(interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))){ + SavingsAccountTransaction newPostingTransaction; + if (interestEarnedToBePostedForPeriod.isGreaterThanOrEqualTo(Money.zero(currency))) { newPostingTransaction = SavingsAccountTransaction.interestPosting(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod); - }else{ + } else { newPostingTransaction = SavingsAccountTransaction.overdraftInterest(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod.negated()); - } + } this.transactions.add(newPostingTransaction); recalucateDailyBalanceDetails = true; } @@ -510,7 +510,8 @@ public class SavingsAccount extends AbstractPersistable { SavingsAccountTransaction postingTransation = null; for (final SavingsAccountTransaction transaction : this.transactions) { - if ((transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) && transaction.occursOn(postingDate)) { + if ((transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) + && transaction.occursOn(postingDate)) { postingTransation = transaction; break; } @@ -634,10 +635,10 @@ public class SavingsAccount extends AbstractPersistable { } private BigDecimal getEffectiveOverdraftInterestRateAsFraction(MathContext mc) { - return this.nominalAnnualInterestRateOverdraft.divide(BigDecimal.valueOf(100l), mc); + return this.nominalAnnualInterestRateOverdraft.divide(BigDecimal.valueOf(100l), mc); } - @SuppressWarnings("unused") + @SuppressWarnings("unused") protected BigDecimal getEffectiveInterestRateAsFraction(final MathContext mc, final LocalDate upToInterestCalculationDate) { return this.nominalAnnualInterestRate.divide(BigDecimal.valueOf(100l), mc); } @@ -648,7 +649,8 @@ public class SavingsAccount extends AbstractPersistable { final List orderedNonInterestPostingTransactions = new ArrayList<>(); for (final SavingsAccountTransaction transaction : listOfTransactionsSorted) { - if (!(transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) && transaction.isNotReversed()) { + if (!(transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) + && transaction.isNotReversed()) { orderedNonInterestPostingTransactions.add(transaction); } } @@ -727,9 +729,8 @@ public class SavingsAccount extends AbstractPersistable { LocalDate endOfBalanceDate = interestPostingUpToDate; for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) { final SavingsAccountTransaction transaction = accountTransactionsSorted.get(i); - if (transaction.isNotReversed() - && !(transaction.isInterestPostingAndNotReversed() - || transaction.isOverdraftInterestAndNotReversed())) { + if (transaction.isNotReversed() + && !(transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed())) { transaction.updateCumulativeBalanceAndDates(this.currency, endOfBalanceDate); // this transactions transaction date is end of balance date for // previous transaction. @@ -888,7 +889,8 @@ public class SavingsAccount extends AbstractPersistable { boolean transactionBeforeLastInterestPosting = false; for (final SavingsAccountTransaction transaction : retreiveListOfTransactions()) { - if ((transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) && transaction.isAfter(transactionDate)) { + if ((transaction.isInterestPostingAndNotReversed() || transaction.isOverdraftInterestAndNotReversed()) + && transaction.isAfter(transactionDate)) { transactionBeforeLastInterestPosting = true; break; } @@ -897,7 +899,8 @@ public class SavingsAccount extends AbstractPersistable { return transactionBeforeLastInterestPosting; } - public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transactionAmount, final boolean isException,final List depositAccountOnHoldTransactions) { + public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transactionAmount, final boolean isException, + final List depositAccountOnHoldTransactions) { final List transactionsSortedByDate = retreiveListOfTransactions(); Money runningBalance = Money.zero(this.currency); Money minRequiredBalance = minRequiredBalanceDerived(getCurrency()); @@ -911,27 +914,28 @@ public class SavingsAccount extends AbstractPersistable { continue; } - - final BigDecimal withdrawalFee = null; - /* Loop through the onHold funds and see if we need to deduct or add to minimum required balance - and the point in time the transaction was made: */ - if(depositAccountOnHoldTransactions !=null){ - for(final DepositAccountOnHoldTransaction onHoldTransaction: depositAccountOnHoldTransactions) { + /* + * Loop through the onHold funds and see if we need to deduct or add + * to minimum required balance and the point in time the transaction + * was made: + */ + if (depositAccountOnHoldTransactions != null) { + for (final DepositAccountOnHoldTransaction onHoldTransaction : depositAccountOnHoldTransactions) { // Compare the balance of the on hold: - if((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) || onHoldTransaction.getTransactionDate().isEqual(transaction.transactionLocalDate())) + if ((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) || onHoldTransaction + .getTransactionDate().isEqual(transaction.transactionLocalDate())) && (lastSavingsDate == null || onHoldTransaction.getTransactionDate().isAfter(lastSavingsDate))) { - if(onHoldTransaction.getTransactionType().isHold()) { + if (onHoldTransaction.getTransactionType().isHold()) { minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmountMoney(this.currency)); - }else{ + } else { minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmountMoney(this.currency)); } } } } - // deal with potential minRequiredBalance and // enforceMinRequiredBalance if (!isException && transaction.canProcessBalanceCheck()) { @@ -943,7 +947,8 @@ public class SavingsAccount extends AbstractPersistable { } } - public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction,final List depositAccountOnHoldTransactions) { + public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction, + final List depositAccountOnHoldTransactions) { final List transactionsSortedByDate = retreiveListOfTransactions(); Money runningBalance = Money.zero(this.currency); @@ -956,16 +961,20 @@ public class SavingsAccount extends AbstractPersistable { runningBalance = runningBalance.minus(transaction.getAmount(this.currency)); } - /* Loop through the onHold funds and see if we need to deduct or add to minimum required balance - and the point in time the transaction was made: */ - if(depositAccountOnHoldTransactions !=null){ - for(final DepositAccountOnHoldTransaction onHoldTransaction: depositAccountOnHoldTransactions) { + /* + * Loop through the onHold funds and see if we need to deduct or add + * to minimum required balance and the point in time the transaction + * was made: + */ + if (depositAccountOnHoldTransactions != null) { + for (final DepositAccountOnHoldTransaction onHoldTransaction : depositAccountOnHoldTransactions) { // Compare the balance of the on hold: - if((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) || onHoldTransaction.getTransactionDate().isEqual(transaction.transactionLocalDate())) + if ((onHoldTransaction.getTransactionDate().isBefore(transaction.transactionLocalDate()) || onHoldTransaction + .getTransactionDate().isEqual(transaction.transactionLocalDate())) && (lastSavingsDate == null || onHoldTransaction.getTransactionDate().isAfter(lastSavingsDate))) { - if(onHoldTransaction.getTransactionType().isHold()) { + if (onHoldTransaction.getTransactionType().isHold()) { minRequiredBalance = minRequiredBalance.plus(onHoldTransaction.getAmountMoney(this.currency)); - }else{ + } else { minRequiredBalance = minRequiredBalance.minus(onHoldTransaction.getAmountMoney(this.currency)); } } @@ -1172,15 +1181,19 @@ public class SavingsAccount extends AbstractPersistable { this.overdraftLimit = newValue; } - if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(nominalAnnualInterestRateOverdraftParamName, this.nominalAnnualInterestRateOverdraft)) { - final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(nominalAnnualInterestRateOverdraftParamName); + if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(nominalAnnualInterestRateOverdraftParamName, + this.nominalAnnualInterestRateOverdraft)) { + final BigDecimal newValue = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(nominalAnnualInterestRateOverdraftParamName); actualChanges.put(nominalAnnualInterestRateOverdraftParamName, newValue); actualChanges.put(localeParamName, localeAsInput); this.nominalAnnualInterestRateOverdraft = newValue; } - if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minOverdraftForInterestCalculationParamName, this.minOverdraftForInterestCalculation)) { - final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minOverdraftForInterestCalculationParamName); + if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minOverdraftForInterestCalculationParamName, + this.minOverdraftForInterestCalculation)) { + final BigDecimal newValue = command + .bigDecimalValueOfParameterNamedDefaultToNullIfZero(minOverdraftForInterestCalculationParamName); actualChanges.put(minOverdraftForInterestCalculationParamName, newValue); actualChanges.put(localeParamName, localeAsInput); this.minOverdraftForInterestCalculation = newValue; @@ -1208,21 +1221,20 @@ public class SavingsAccount extends AbstractPersistable { validateLockinDetails(baseDataValidator); esnureOverdraftLimitsSetForOverdraftAccounts(); } - + /** * If overdrafts are allowed and the overdraft limit is not set, set the * same to Zero **/ private void esnureOverdraftLimitsSetForOverdraftAccounts() { - if (this.allowOverdraft) { - this.overdraftLimit = this.overdraftLimit == null? BigDecimal.ZERO : this.overdraftLimit; - this.nominalAnnualInterestRateOverdraft = this.nominalAnnualInterestRateOverdraft == null? BigDecimal.ZERO : this.nominalAnnualInterestRateOverdraft; - this.minOverdraftForInterestCalculation = this.minOverdraftForInterestCalculation == null? BigDecimal.ZERO : this.minOverdraftForInterestCalculation; - } + this.overdraftLimit = this.overdraftLimit == null ? BigDecimal.ZERO : this.overdraftLimit; + this.nominalAnnualInterestRateOverdraft = this.nominalAnnualInterestRateOverdraft == null ? BigDecimal.ZERO + : this.nominalAnnualInterestRateOverdraft; + this.minOverdraftForInterestCalculation = this.minOverdraftForInterestCalculation == null ? BigDecimal.ZERO + : this.minOverdraftForInterestCalculation; } - private void validateLockinDetails(final DataValidatorBuilder baseDataValidator) { /*