This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 629d2da7f FINERACT-1724: Fee's are not included in total balance
amount, when we have multiple disbursements on first day
629d2da7f is described below
commit 629d2da7f9ed2ed3e3d914052ff75d1016e3affb
Author: Adam Saghy <[email protected]>
AuthorDate: Tue May 2 20:57:48 2023 +0200
FINERACT-1724: Fee's are not included in total balance amount, when we have
multiple disbursements on first day
---
.../portfolio/loanaccount/domain/Loan.java | 30 +++++-----
.../domain/LoanAccountDomainServiceJpa.java | 12 ++--
.../portfolio/loanaccount/domain/LoanCharge.java | 15 ++++-
.../LoanRepaymentScheduleProcessingWrapper.java | 62 ++++++++++----------
...tLoanRepaymentScheduleTransactionProcessor.java | 8 +--
.../loanschedule/data/LoanScheduleParams.java | 4 ++
.../domain/AbstractLoanScheduleGenerator.java | 56 +++++++++---------
.../LoanChargeSpecificDueDateTest.java | 67 +++++++++++++++++++++-
...LoanSpecificDueDateChargeAfterMaturityTest.java | 61 --------------------
9 files changed, 167 insertions(+), 148 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 6b030c295..3773ff3b5 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -655,7 +655,7 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
getId(), loanCharge.name());
}
- validateChargeHasValidSpecifiedDateIfApplicable(loanCharge,
getDisbursementDate(), getLastRepaymentPeriodDueDate(false));
+ validateChargeHasValidSpecifiedDateIfApplicable(loanCharge,
getDisbursementDate());
loanCharge.update(this);
@@ -770,18 +770,18 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
final LoanRepaymentScheduleTransactionProcessor
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
.determineProcessor(this.transactionProcessingStrategyCode);
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments
= new ArrayList<>();
- LocalDate startDate = getDisbursementDate();
List<LoanRepaymentScheduleInstallment> installments =
getRepaymentScheduleInstallments();
for (final LoanRepaymentScheduleInstallment installment :
installments) {
- if (installmentNumber == null &&
charge.isDueForCollectionFromAndUpToAndIncluding(startDate,
installment.getDueDate())) {
-
+ boolean isDue = installment.isFirstPeriod()
+ ?
charge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(),
installment.getDueDate())
+ :
charge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(),
installment.getDueDate());
+ if (installmentNumber == null && isDue) {
chargePaymentInstallments.add(installment);
break;
} else if (installmentNumber != null &&
installment.getInstallmentNumber().equals(installmentNumber)) {
chargePaymentInstallments.add(installment);
break;
}
- startDate = installment.getDueDate();
}
final Set<LoanCharge> loanCharges = new HashSet<>(1);
loanCharges.add(charge);
@@ -808,13 +808,11 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
}
}
- private void validateChargeHasValidSpecifiedDateIfApplicable(final
LoanCharge loanCharge, final LocalDate disbursementDate,
- final LocalDate lastRepaymentPeriodDueDate) {
- if (isInterestBearing() && loanCharge.isSpecifiedDueDate()
- &&
!loanCharge.isDueForCollectionFromAndUpToAndIncluding(disbursementDate,
lastRepaymentPeriodDueDate)) {
+ private void validateChargeHasValidSpecifiedDateIfApplicable(final
LoanCharge loanCharge, final LocalDate disbursementDate) {
+ if (loanCharge.isSpecifiedDueDate() &&
loanCharge.getDueLocalDate().isBefore(disbursementDate)) {
final String defaultUserMessage = "This charge with specified due
date cannot be added as the it is not in schedule range.";
throw new LoanChargeCannotBeAddedException("loanCharge",
"specified.due.date.outside.range", defaultUserMessage,
- getDisbursementDate(), lastRepaymentPeriodDueDate,
loanCharge.name());
+ getDisbursementDate(), loanCharge.name());
}
}
@@ -1745,7 +1743,7 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
if (loanCharge.isActive()) {
clearLoanInstallmentChargesBeforeRegeneration(loanCharge);
loanCharge.update(chargeAmt, loanCharge.getDueLocalDate(), amount,
fetchNumberOfInstallmensAfterExceptions(), totalChargeAmt);
- validateChargeHasValidSpecifiedDateIfApplicable(loanCharge,
getDisbursementDate(), getLastRepaymentPeriodDueDate(false));
+ validateChargeHasValidSpecifiedDateIfApplicable(loanCharge,
getDisbursementDate());
}
}
@@ -5560,7 +5558,10 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
List<LoanCharge> loanCharges = new ArrayList<>();
List<LoanInstallmentCharge> loanInstallmentCharges = new ArrayList<>();
for (LoanCharge loanCharge : this.getActiveCharges()) {
- if (loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate,
toDate)) {
+ boolean isDue = fromDate.isEqual(this.getDisbursementDate())
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate, toDate)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, toDate);
+ if (isDue) {
if (loanCharge.isPenaltyCharge() &&
!loanCharge.isInstalmentFee()) {
penalties = penalties.add(loanCharge.amount());
loanCharges.add(loanCharge);
@@ -6569,7 +6570,10 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
interestAccountedForCurrentPeriod =
installment.getInterestWaived(getCurrency()).plus(installment.getInterestPaid(getCurrency()));
for (LoanCharge loanCharge : this.charges) {
if (loanCharge.isActive() && !loanCharge.isDueAtDisbursement()) {
- if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(),
paymentDate)) {
+ boolean isDue = installment.isFirstPeriod()
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(),
paymentDate)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(),
paymentDate);
+ if (isDue) {
if (loanCharge.isPenaltyCharge()) {
penaltyForCurrentPeriod =
penaltyForCurrentPeriod.plus(loanCharge.getAmount(getCurrency()));
penaltyAccoutedForCurrentPeriod =
penaltyAccoutedForCurrentPeriod
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index b7a6e3dc8..b49497411 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -641,7 +641,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
}
for (final LoanCharge loanCharge : loanCharges) {
- if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(),
chargesTillDate)) {
+ boolean isDue = installment.isFirstPeriod()
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(installment.getFromDate(),
chargesTillDate)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(),
chargesTillDate);
+ if (isDue) {
if (loanCharge.isFeeCharge()) {
dueDateFeeIncome =
dueDateFeeIncome.add(loanCharge.amount());
} else if (loanCharge.isPenaltyCharge()) {
@@ -792,9 +795,10 @@ public class LoanAccountDomainServiceJpa implements
LoanAccountDomainService {
loan.addLoanTransaction(accrualTransaction);
Set<LoanChargePaidBy> accrualCharges =
accrualTransaction.getLoanChargesPaid();
for (LoanCharge loanCharge : loan.getActiveCharges()) {
- if (loanCharge.isActive() && !loanCharge.isPaid()
- &&
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate)
- || loanCharge.isInstalmentFee())) {
+ boolean isDue =
fromDate.isEqual(loan.getDisbursementDate())
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(fromDate,
foreClosureDate)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(fromDate, foreClosureDate);
+ if (loanCharge.isActive() && !loanCharge.isPaid() &&
(isDue || loanCharge.isInstalmentFee())) {
final LoanChargePaidBy loanChargePaidBy = new
LoanChargePaidBy(accrualTransaction, loanCharge,
loanCharge.getAmountOutstanding(currency).getAmount(), null);
accrualCharges.add(loanChargePaidBy);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
index eea10227a..905a8ae81 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
@@ -625,14 +625,25 @@ public class LoanCharge extends AbstractPersistableCustom
{
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate
fromNotInclusive, final LocalDate upToAndInclusive) {
final LocalDate dueDate = getDueLocalDate();
- return occursOnDayFromAndUpToAndIncluding(fromNotInclusive,
upToAndInclusive, dueDate);
+ return occursOnDayFromExclusiveAndUpToAndIncluding(fromNotInclusive,
upToAndInclusive, dueDate);
}
- private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate
fromNotInclusive, final LocalDate upToAndInclusive,
+ public boolean isDueForCollectionFromIncludingAndUpToAndIncluding(final
LocalDate fromAndInclusive, final LocalDate upToAndInclusive) {
+ final LocalDate dueDate = getDueLocalDate();
+ return occursOnDayFromAndUpToAndIncluding(fromAndInclusive,
upToAndInclusive, dueDate);
+ }
+
+ private boolean occursOnDayFromExclusiveAndUpToAndIncluding(final
LocalDate fromNotInclusive, final LocalDate upToAndInclusive,
final LocalDate target) {
return target != null && target.isAfter(fromNotInclusive) &&
!target.isAfter(upToAndInclusive);
}
+ private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate
fromAndInclusive, final LocalDate upToAndInclusive,
+ final LocalDate target) {
+ return target != null && (target.isEqual(fromAndInclusive) ||
target.isAfter(fromAndInclusive))
+ && !target.isAfter(upToAndInclusive);
+ }
+
public boolean isFeeCharge() {
return !this.penaltyCharge;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java
index f65f6c703..04ded2c13 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java
@@ -47,14 +47,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
final Money feeChargesWaivedForRepaymentPeriod =
cumulativeFeeChargesWaivedWithin(startDate, period.getDueDate(), loanCharges,
currency, !period.isRecalculatedInterestComponent(),
period.isFirstPeriod());
final Money feeChargesWrittenOffForRepaymentPeriod =
cumulativeFeeChargesWrittenOffWithin(startDate, period.getDueDate(),
- loanCharges, currency,
!period.isRecalculatedInterestComponent());
+ loanCharges, currency,
!period.isRecalculatedInterestComponent(), period.isFirstPeriod());
final Money penaltyChargesDueForRepaymentPeriod =
cumulativePenaltyChargesDueWithin(startDate, period.getDueDate(), loanCharges,
currency, period, totalPrincipal, totalInterest,
!period.isRecalculatedInterestComponent());
final Money penaltyChargesWaivedForRepaymentPeriod =
cumulativePenaltyChargesWaivedWithin(startDate, period.getDueDate(),
loanCharges, currency,
!period.isRecalculatedInterestComponent(), period.isFirstPeriod());
final Money penaltyChargesWrittenOffForRepaymentPeriod =
cumulativePenaltyChargesWrittenOffWithin(startDate,
- period.getDueDate(), loanCharges, currency,
!period.isRecalculatedInterestComponent());
+ period.getDueDate(), loanCharges, currency,
!period.isRecalculatedInterestComponent(), period.isFirstPeriod());
period.updateChargePortion(feeChargesDueForRepaymentPeriod,
feeChargesWaivedForRepaymentPeriod,
feeChargesWrittenOffForRepaymentPeriod,
penaltyChargesDueForRepaymentPeriod, penaltyChargesWaivedForRepaymentPeriod,
@@ -71,6 +71,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
Money cumulative = Money.zero(monetaryCurrency);
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement())
{
+ boolean isDue = period.isFirstPeriod()
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
if (loanCharge.getChargeCalculation().isPercentageBased())
{
BigDecimal amount = BigDecimal.ZERO;
@@ -87,12 +90,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
} else {
cumulative =
cumulative.plus(loanCharge.amountOrPercentage());
}
- } else if (loanCharge.isOverdueInstallmentCharge()
- &&
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (loanCharge.isOverdueInstallmentCharge() && isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative = cumulative.plus(loanCharge.chargeAmount());
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
BigDecimal amount = BigDecimal.ZERO;
if
(loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
amount =
amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
@@ -116,10 +116,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
}
BigDecimal loanChargeAmt =
amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
cumulative = cumulative.plus(loanChargeAmt);
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
- cumulative = cumulative.plus(loanCharge.amount());
- // Special case for Loan Charges (Due Date) added the same
disbursement date
- } else if (period.isFirstPeriod() &&
periodStart.equals(loanCharge.getDueDate())) {
+ } else if (isDue) {
cumulative = cumulative.plus(loanCharge.amount());
}
}
@@ -136,15 +133,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement())
{
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
LoanInstallmentCharge loanChargePerInstallment =
loanCharge.getInstallmentLoanCharge(periodEnd);
if (loanChargePerInstallment != null) {
cumulative =
cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
}
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
- cumulative =
cumulative.plus(loanCharge.getAmountWaived(currency));
- // Special case for Loan Charges (Due Date) added the same
disbursement date
- } else if (isFirstPeriod &&
periodStart.equals(loanCharge.getDueDate())) {
+ } else if (isDue) {
cumulative =
cumulative.plus(loanCharge.getAmountWaived(currency));
}
}
@@ -154,18 +150,21 @@ public class LoanRepaymentScheduleProcessingWrapper {
}
private Money cumulativeFeeChargesWrittenOffWithin(final LocalDate
periodStart, final LocalDate periodEnd,
- final Set<LoanCharge> loanCharges, final MonetaryCurrency
currency, boolean isInstallmentChargeApplicable) {
+ final Set<LoanCharge> loanCharges, final MonetaryCurrency
currency, boolean isInstallmentChargeApplicable,
+ boolean isFirstPeriod) {
Money cumulative = Money.zero(currency);
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isFeeCharge() && !loanCharge.isDueAtDisbursement())
{
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
LoanInstallmentCharge loanChargePerInstallment =
loanCharge.getInstallmentLoanCharge(periodEnd);
if (loanChargePerInstallment != null) {
cumulative =
cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
}
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
+ } else if (isDue) {
cumulative =
cumulative.plus(loanCharge.getAmountWrittenOff(currency));
}
}
@@ -182,6 +181,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isPenaltyCharge()) {
+ boolean isDue = period.isFirstPeriod()
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
if (loanCharge.getChargeCalculation().isPercentageBased())
{
BigDecimal amount = BigDecimal.ZERO;
@@ -198,12 +200,9 @@ public class LoanRepaymentScheduleProcessingWrapper {
} else {
cumulative =
cumulative.plus(loanCharge.amountOrPercentage());
}
- } else if (loanCharge.isOverdueInstallmentCharge()
- &&
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (loanCharge.isOverdueInstallmentCharge() && isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative = cumulative.plus(loanCharge.chargeAmount());
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
BigDecimal amount = BigDecimal.ZERO;
if
(loanCharge.getChargeCalculation().isPercentageOfAmountAndInterest()) {
amount =
amount.add(totalPrincipal.getAmount()).add(totalInterest.getAmount());
@@ -214,10 +213,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
}
BigDecimal loanChargeAmt =
amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100));
cumulative = cumulative.plus(loanChargeAmt);
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
- cumulative = cumulative.plus(loanCharge.amount());
- // Special case for Loan Charges (Due Date) added the same
disbursement date
- } else if (period.isFirstPeriod() &&
periodStart.equals(loanCharge.getDueDate())) {
+ } else if (isDue) {
cumulative = cumulative.plus(loanCharge.amount());
}
}
@@ -234,15 +230,14 @@ public class LoanRepaymentScheduleProcessingWrapper {
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isPenaltyCharge()) {
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
LoanInstallmentCharge loanChargePerInstallment =
loanCharge.getInstallmentLoanCharge(periodEnd);
if (loanChargePerInstallment != null) {
cumulative =
cumulative.plus(loanChargePerInstallment.getAmountWaived(currency));
}
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
- cumulative =
cumulative.plus(loanCharge.getAmountWaived(currency));
- // Special case for Loan Charges (Due Date) added the same
disbursement date
- } else if (isFirstPeriod &&
periodStart.equals(loanCharge.getDueDate())) {
+ } else if (isDue) {
cumulative =
cumulative.plus(loanCharge.getAmountWaived(currency));
}
}
@@ -252,18 +247,21 @@ public class LoanRepaymentScheduleProcessingWrapper {
}
private Money cumulativePenaltyChargesWrittenOffWithin(final LocalDate
periodStart, final LocalDate periodEnd,
- final Set<LoanCharge> loanCharges, final MonetaryCurrency
currency, boolean isInstallmentChargeApplicable) {
+ final Set<LoanCharge> loanCharges, final MonetaryCurrency
currency, boolean isInstallmentChargeApplicable,
+ final boolean isFirstPeriod) {
Money cumulative = Money.zero(currency);
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isPenaltyCharge()) {
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
LoanInstallmentCharge loanChargePerInstallment =
loanCharge.getInstallmentLoanCharge(periodEnd);
if (loanChargePerInstallment != null) {
cumulative =
cumulative.plus(loanChargePerInstallment.getAmountWrittenOff(currency));
}
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
+ } else if (isDue) {
cumulative =
cumulative.plus(loanCharge.getAmountWrittenOff(currency));
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
index 6994ed8bd..72750cb1a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
@@ -110,10 +110,10 @@ public abstract class
AbstractLoanRepaymentScheduleTransactionProcessor implemen
LocalDate startDate = disbursementDate;
for (final LoanRepaymentScheduleInstallment installment :
installments) {
for (final LoanCharge loanCharge : transferCharges) {
- if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(startDate,
installment.getDueDate())
- // Special case for Loan Charges (Due Date)
added the same disbursement date
- || (startDate.equals(disbursementDate) &&
loanCharge.getDueDate() != null
- &&
loanCharge.getDueDate().equals(disbursementDate))) {
+ boolean isDue = installment.isFirstPeriod()
+ ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(startDate,
installment.getDueDate())
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(startDate,
installment.getDueDate());
+ if (isDue) {
Money amountForProcess =
loanCharge.getAmount(currency);
if
(amountForProcess.isGreaterThan(loanTransaction.getAmount(currency))) {
amountForProcess =
loanTransaction.getAmount(currency);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
index c5c0bec83..0f28b88a7 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
@@ -477,4 +477,8 @@ public final class LoanScheduleParams {
public void setUnCompoundedAmount(Money unCompoundedAmount) {
this.unCompoundedAmount = unCompoundedAmount;
}
+
+ public boolean isFirstPeriod() {
+ return 1 == instalmentNumber;
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index 796508e59..f6193dfe2 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -437,12 +437,12 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
LoanScheduleParams scheduleParams, LocalDate scheduledDueDate,
ScheduleCurrentPeriodParams currentPeriodParams) {
PrincipalInterest principalInterest = new
PrincipalInterest(currentPeriodParams.getPrincipalForThisPeriod(),
currentPeriodParams.getInterestForThisPeriod(), null);
- currentPeriodParams.setFeeChargesForInstallment(
-
cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(),
scheduledDueDate, loanCharges, currency,
- principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativeInterest(), true));
- currentPeriodParams.setPenaltyChargesForInstallment(
-
cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
scheduledDueDate, loanCharges, currency,
- principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativeInterest(), true));
+
currentPeriodParams.setFeeChargesForInstallment(cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(),
scheduledDueDate,
+ loanCharges, currency, principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
+ scheduleParams.getTotalCumulativeInterest(), true,
scheduleParams.isFirstPeriod()));
+
currentPeriodParams.setPenaltyChargesForInstallment(cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
+ scheduledDueDate, loanCharges, currency, principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
+ scheduleParams.getTotalCumulativeInterest(), true,
scheduleParams.isFirstPeriod()));
scheduleParams.addTotalFeeChargesCharged(currentPeriodParams.getFeeChargesForInstallment());
scheduleParams.addTotalPenaltyChargesCharged(currentPeriodParams.getPenaltyChargesForInstallment());
}
@@ -456,11 +456,11 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
Money feeChargesForInstallment =
cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
loanScheduleModelPeriod.periodDueDate(),
nonCompoundingCharges, currency, principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativeInterest(),
-
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
+
!loanScheduleModelPeriod.isRecalculatedInterestComponent(),
scheduleParams.isFirstPeriod());
Money penaltyChargesForInstallment =
cumulativePenaltyChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
loanScheduleModelPeriod.periodDueDate(),
nonCompoundingCharges, currency, principalInterest,
scheduleParams.getPrincipalToBeScheduled(),
scheduleParams.getTotalCumulativeInterest(),
-
!loanScheduleModelPeriod.isRecalculatedInterestComponent());
+
!loanScheduleModelPeriod.isRecalculatedInterestComponent(),
scheduleParams.isFirstPeriod());
scheduleParams.addTotalFeeChargesCharged(feeChargesForInstallment);
scheduleParams.addTotalPenaltyChargesCharged(penaltyChargesForInstallment);
scheduleParams.addTotalRepaymentExpected(feeChargesForInstallment.plus(penaltyChargesForInstallment));
@@ -561,10 +561,10 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
currentPeriodParams.getInterestForThisPeriod(), null);
oustanding =
oustanding.minus(cumulativeFeeChargesDueWithin(transactionDate,
scheduledDueDate, loanCharges,
totalInterestChargedForFullLoanTerm.getCurrency(),
tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
- scheduleParams.getTotalCumulativeInterest(), true));
+ scheduleParams.getTotalCumulativeInterest(), true,
scheduleParams.isFirstPeriod()));
oustanding =
oustanding.minus(cumulativePenaltyChargesDueWithin(transactionDate,
scheduledDueDate, loanCharges,
totalInterestChargedForFullLoanTerm.getCurrency(),
tempPrincipalInterest, scheduleParams.getPrincipalToBeScheduled(),
- scheduleParams.getTotalCumulativeInterest(), true));
+ scheduleParams.getTotalCumulativeInterest(), true,
scheduleParams.isFirstPeriod()));
if
(!oustanding.isGreaterThan(currentPeriodParams.getInterestForThisPeriod()) &&
!scheduledDueDate.equals(transactionDate)) {
final Collection<LoanTermVariationsData> interestRates =
loanApplicationTerms.getLoanTermVariations().getInterestRateChanges();
@@ -717,7 +717,7 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
processTransactions.clear();
currentTransactions.addAll(createCurrentTransactionList(detail));
- if
(!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) ||
scheduleParams.getInstalmentNumber() == 1) {
+ if
(!transactionDate.isEqual(scheduleParams.getPeriodStartDate()) ||
scheduleParams.isFirstPeriod()) {
int periodDays =
Math.toIntExact(ChronoUnit.DAYS.between(scheduleParams.getPeriodStartDate(),
transactionDate));
// calculates period start date for interest
@@ -758,10 +758,10 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
null);
Money feeChargesForInstallment =
cumulativeFeeChargesDueWithin(scheduleParams.getPeriodStartDate(),
transactionDate, loanCharges, currency,
principalInterest, scheduleParams.getPrincipalToBeScheduled(),
-
scheduleParams.getTotalCumulativeInterest(), false);
+
scheduleParams.getTotalCumulativeInterest(), false,
scheduleParams.isFirstPeriod());
Money penaltyChargesForInstallment =
cumulativePenaltyChargesDueWithin(scheduleParams.getPeriodStartDate(),
transactionDate, loanCharges, currency,
principalInterest, scheduleParams.getPrincipalToBeScheduled(),
-
scheduleParams.getTotalCumulativeInterest(), false);
+
scheduleParams.getTotalCumulativeInterest(), false,
scheduleParams.isFirstPeriod());
// sum up real totalInstallmentDue from
// components
@@ -1788,9 +1788,9 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
if (compoundingDate.isBefore(endDate)) {
Money feeChargesForInstallment =
cumulativeFeeChargesDueWithin(lastCompoundingDate, compoundingDate, charges,
currency,
- null, loanApplicationTerms.getPrincipal(), null,
false);
+ null, loanApplicationTerms.getPrincipal(), null,
false, lastCompoundingDate.isEqual(startDate));
Money penaltyChargesForInstallment =
cumulativePenaltyChargesDueWithin(lastCompoundingDate, compoundingDate, charges,
- currency, null,
loanApplicationTerms.getPrincipal(), null, false);
+ currency, null,
loanApplicationTerms.getPrincipal(), null, false,
lastCompoundingDate.isEqual(startDate));
Money compoundAmount =
feeChargesForInstallment.plus(penaltyChargesForInstallment);
if (addUncompounded) {
compoundAmount =
compoundAmount.plus(scheduleParams.getUnCompoundedAmount());
@@ -1987,23 +1987,22 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart,
final LocalDate periodEnd, final Set<LoanCharge> loanCharges,
final MonetaryCurrency monetaryCurrency, final PrincipalInterest
principalInterestForThisPeriod, final Money principalDisbursed,
- final Money totalInterestChargedForFullLoanTerm, boolean
isInstallmentChargeApplicable) {
+ final Money totalInterestChargedForFullLoanTerm, boolean
isInstallmentChargeApplicable, final boolean isFirstPeriod) {
Money cumulative = Money.zero(monetaryCurrency);
for (final LoanCharge loanCharge : loanCharges) {
if (!loanCharge.isDueAtDisbursement() && loanCharge.isFeeCharge())
{
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
cumulative =
calculateInstallmentCharge(principalInterestForThisPeriod, cumulative,
loanCharge);
- } else if (loanCharge.isOverdueInstallmentCharge()
- &&
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (loanCharge.isOverdueInstallmentCharge() && isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative = cumulative.plus(loanCharge.chargeAmount());
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative =
calculateSpecificDueDateChargeWithPercentage(principalDisbursed,
totalInterestChargedForFullLoanTerm,
cumulative, loanCharge);
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
+ } else if (isDue) {
cumulative = cumulative.plus(loanCharge.amount());
}
}
@@ -2050,23 +2049,22 @@ public abstract class AbstractLoanScheduleGenerator
implements LoanScheduleGener
private Money cumulativePenaltyChargesDueWithin(final LocalDate
periodStart, final LocalDate periodEnd,
final Set<LoanCharge> loanCharges, final MonetaryCurrency
monetaryCurrency,
final PrincipalInterest principalInterestForThisPeriod, final
Money principalDisbursed,
- final Money totalInterestChargedForFullLoanTerm, boolean
isInstallmentChargeApplicable) {
+ final Money totalInterestChargedForFullLoanTerm, boolean
isInstallmentChargeApplicable, final boolean isFirstPeriod) {
Money cumulative = Money.zero(monetaryCurrency);
for (final LoanCharge loanCharge : loanCharges) {
if (loanCharge.isPenaltyCharge()) {
+ boolean isDue = isFirstPeriod ?
loanCharge.isDueForCollectionFromIncludingAndUpToAndIncluding(periodStart,
periodEnd)
+ :
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd);
if (loanCharge.isInstalmentFee() &&
isInstallmentChargeApplicable) {
cumulative =
calculateInstallmentCharge(principalInterestForThisPeriod, cumulative,
loanCharge);
- } else if (loanCharge.isOverdueInstallmentCharge()
- &&
loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (loanCharge.isOverdueInstallmentCharge() && isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative = cumulative.plus(loanCharge.chargeAmount());
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)
- &&
loanCharge.getChargeCalculation().isPercentageBased()) {
+ } else if (isDue &&
loanCharge.getChargeCalculation().isPercentageBased()) {
cumulative =
calculateSpecificDueDateChargeWithPercentage(principalDisbursed,
totalInterestChargedForFullLoanTerm,
cumulative, loanCharge);
- } else if
(loanCharge.isDueForCollectionFromAndUpToAndIncluding(periodStart, periodEnd)) {
+ } else if (isDue) {
cumulative = cumulative.plus(loanCharge.amount());
}
}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeSpecificDueDateTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeSpecificDueDateTest.java
index d52f64dc9..7e942b3fb 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeSpecificDueDateTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeSpecificDueDateTest.java
@@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
+import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
@@ -37,6 +38,7 @@ import
org.apache.fineract.client.models.JournalEntryTransactionItem;
import org.apache.fineract.client.models.PostChargesResponse;
import
org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
@@ -505,6 +507,64 @@ public class LoanChargeSpecificDueDateTest {
}
}
+ @Test
+ public void
testApplyLoanSpecificDueDatePenaltyWithDisbursementDateWithMultipleDisbursement()
{
+
+ final LocalDate todaysDate = Utils.getLocalDateOfTenant();
+
+ // Client and Loan account creation
+ final Integer clientId = ClientHelper.createClient(this.requestSpec,
this.responseSpec, "01 January 2012");
+ final GetLoanProductsProductIdResponse getLoanProductsProductResponse
= createLoanProductWithPeriodicAccrual(loanTransactionHelper,
+ null);
+ assertNotNull(getLoanProductsProductResponse);
+
+ // Older date to have more than one overdue installment
+ LocalDate transactionDate = todaysDate;
+ String operationDate = Utils.dateFormatter.format(transactionDate);
+ log.info("Operation date {}", transactionDate);
+
+ // Create Loan Account
+ final Integer loanId = createLoanAccount(loanTransactionHelper,
clientId.toString(),
+ getLoanProductsProductResponse.getId().toString(),
operationDate, "12", "0");
+
+ // Get loan details
+ GetLoansLoanIdResponse getLoansLoanIdResponse =
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+ validateLoanAccount(getLoansLoanIdResponse,
Double.valueOf(principalAmount), Double.valueOf("0.00"), true);
+
+ // Apply Loan Charge with specific due date
+
+ final String feeAmount = "10.00";
+ String payloadJSON =
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
feeAmount, true);
+ final PostChargesResponse postChargesResponse =
ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON);
+ assertNotNull(postChargesResponse);
+ final Long loanChargeId = postChargesResponse.getResourceId();
+ assertNotNull(loanChargeId);
+
+ payloadJSON =
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(),
operationDate, feeAmount);
+ PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse =
loanTransactionHelper.addChargeForLoan(loanId, payloadJSON,
+ responseSpec);
+ assertNotNull(postLoansLoanIdChargesResponse);
+
+ // Get loan details expecting to have a delinquency classification
+ getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec,
responseSpec, loanId);
+ validateLoanAccount(getLoansLoanIdResponse,
Double.valueOf(principalAmount), Double.valueOf("10.00"), true);
+
+ loanTransactionHelper.disburseLoan((long) loanId, new
PostLoansLoanIdRequest().actualDisbursementDate(operationDate)
+ .transactionAmount(new
BigDecimal("1000")).locale("en").dateFormat("dd MMMM yyyy"));
+
+ // Get loan details expecting to have a delinquency classification
+ getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec,
responseSpec, loanId);
+ validateLoanAccount(getLoansLoanIdResponse,
Double.parseDouble(principalAmount) * 2, Double.valueOf("10.00"), true);
+
+ operationDate =
Utils.dateFormatter.format(transactionDate.plusMonths(1));
+ payloadJSON =
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(),
operationDate, feeAmount);
+ postLoansLoanIdChargesResponse =
loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, responseSpec);
+
+ // Get loan details expecting to have a delinquency classification
+ getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec,
responseSpec, loanId);
+ validateLoanAccount(getLoansLoanIdResponse,
Double.parseDouble(principalAmount) * 2, Double.valueOf("20.00"), true);
+ }
+
private GetLoanProductsProductIdResponse createLoanProduct(final
LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) {
final HashMap<String, Object> loanProductMap = new
LoanProductTestBuilder().build(null, delinquencyBucketId);
@@ -515,13 +575,14 @@ public class LoanChargeSpecificDueDateTest {
private GetLoanProductsProductIdResponse
createLoanProductWithPeriodicAccrual(final LoanTransactionHelper
loanTransactionHelper,
final Integer delinquencyBucketId) {
final Account assetAccount = this.accountHelper.createAssetAccount();
- final Account assetFeeAndPenaltyAccount =
this.accountHelper.createAssetAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount =
this.accountHelper.createExpenseAccount();
final Account overpaymentAccount =
this.accountHelper.createLiabilityAccount();
- final HashMap<String, Object> loanProductMap = new
LoanProductTestBuilder()
+ final HashMap<String, Object> loanProductMap = new
LoanProductTestBuilder().withMultiDisburse()
+
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withInterestTypeAsDecliningBalance()
.withAccountingRulePeriodicAccrual(new Account[] {
assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
+ .withDisallowExpectedDisbursements(true) //
.build(null, delinquencyBucketId);
final Integer loanProductId =
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId);
@@ -539,7 +600,7 @@ public class LoanChargeSpecificDueDateTest {
.build(clientId, loanProductId, null);
final Integer loanId =
loanTransactionHelper.getLoanId(loanApplicationJSON);
loanTransactionHelper.approveLoan(operationDate, principalAmount,
loanId, null);
-
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId,
principalAmount);
+ loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate,
loanId, principalAmount);
return loanId;
}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
index 243595c5c..6945f57d1 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
@@ -95,53 +95,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
this.periodicAccrualAccountingHelper = new
PeriodicAccrualAccountingHelper(requestSpec, responseSpec);
}
- @Test
- public void onlyNonInterestBearingLoanCanAcceptChargeAfterMaturity() {
- final Account assetAccount = this.accountHelper.createAssetAccount();
- final Account incomeAccount = this.accountHelper.createIncomeAccount();
- final Account expenseAccount =
this.accountHelper.createExpenseAccount();
- final Account overpaymentAccount =
this.accountHelper.createLiabilityAccount();
-
- final Integer loanProductID =
createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(assetAccount,
- incomeAccount, expenseAccount, overpaymentAccount);
-
- final Integer clientID = ClientHelper.createClient(requestSpec,
responseSpec, DATE_OF_JOINING);
-
- final Integer loanID = applyForLoanApplication(clientID,
loanProductID, "1");
-
- final float PENALTY_PORTION = 100.0f;
-
- Integer flatSpecifiedDueDate =
ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper
-
.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
String.valueOf(PENALTY_PORTION), true));
-
- HashMap<String, Object> loanStatusHashMap =
LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
- LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
-
- loanStatusHashMap =
this.loanTransactionHelper.approveLoan(EXPECTED_DISBURSAL_DATE, loanID);
- LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
- LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
-
- LocalDate targetDate = LocalDate.of(2011, 3, 4);
- final String loanDisbursementDate = dateFormatter.format(targetDate);
-
- String loanDetails =
this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
- loanStatusHashMap =
this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(loanDisbursementDate,
loanID,
-
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
- LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
-
- targetDate = LocalDate.of(2011, 4, 5);
- final String penaltyCharge1AddedDate =
dateFormatter.format(targetDate);
-
- final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" +
loanID + "/charges?" + Utils.TENANT_IDENTIFIER;
- ResponseSpecification response403Spec = new
ResponseSpecBuilder().expectStatusCode(403).build();
- final HashMap response = Utils.performServerPost(requestSpec,
response403Spec, ADD_CHARGES_URL,
-
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(flatSpecifiedDueDate),
penaltyCharge1AddedDate,
- String.valueOf(PENALTY_PORTION)),
- "");
- assertEquals("validation.msg.domain.rule.violation",
response.get("userMessageGlobalisationCode"));
-
- }
-
@Test
public void checkPeriodicAccrualAccountingAPIFlow() {
final Account assetAccount = this.accountHelper.createAssetAccount();
@@ -458,20 +411,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
- private Integer
createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(final
Account... accounts) {
- LOG.info("------------------------------CREATING NEW LOAN PRODUCT
---------------------------------------");
- final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal("10000.0").withNumberOfRepayments("1")
-
.withinterestRatePerPeriod("1").withInterestRateFrequencyTypeAsYear().withInterestTypeAsDecliningBalance()
- .withInterestCalculationPeriodTypeAsDays()
-
.withInterestRecalculationDetails(LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
-
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
-
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE)
-
.withInterestRecalculationRestFrequencyDetails(LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY,
"0", null, null)
- .withInterestRecalculationCompoundingFrequencyDetails(null,
null, null, null).withMoratorium("0", "0")
-
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withAccountingRulePeriodicAccrual(accounts).build(null);
- return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
- }
-
private Integer
createLoanProductWithPeriodicAccrualAccountingNoInterest(final Account...
accounts) {
LOG.info("------------------------------CREATING NEW LOAN PRODUCT
---------------------------------------");
final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal(LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth()