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 88105c3cac FINERACT-2273: Make sure the setters of Loan repayment
installment entity balances maintain the scaling of 6 and set null in case the
value is zero
88105c3cac is described below
commit 88105c3caca0fcc05bbf718cb5737417bddf17ba
Author: mariiaKraievska <[email protected]>
AuthorDate: Thu May 22 15:06:43 2025 +0300
FINERACT-2273: Make sure the setters of Loan repayment installment entity
balances maintain the scaling of 6 and set null in case the value is zero
---
.../domain/LoanRepaymentScheduleInstallment.java | 352 ++++++++++++---------
.../LoanRepaymentScheduleInstallmentTest.java | 209 ++++++++++++
...cyWritePlatformServiceRangeChangeEventTest.java | 18 ++
.../ClientLoanIntegrationTest.java | 20 +-
...LoanSpecificDueDateChargeAfterMaturityTest.java | 16 +-
.../integrationtests/SchedulerJobsTestResults.java | 6 +-
6 files changed, 454 insertions(+), 167 deletions(-)
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
index ed0c14e90b..94d6dd3151 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
@@ -40,6 +40,7 @@ import
org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
import org.apache.fineract.portfolio.loanproduct.domain.AllocationType;
import
org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks;
@@ -196,17 +197,17 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
this.installmentNumber = installmentNumber;
this.fromDate = fromDate;
this.dueDate = dueDate;
- this.principal = defaultToNullIfZero(principal);
- this.interestCharged = defaultToNullIfZero(interest);
- this.feeChargesCharged = defaultToNullIfZero(feeCharges);
- this.penaltyCharges = defaultToNullIfZero(penaltyCharges);
+ setPrincipal(principal);
+ setInterestCharged(interest);
+ setFeeChargesCharged(feeCharges);
+ setPenaltyCharges(penaltyCharges);
this.obligationsMet = false;
this.recalculatedInterestComponent = recalculatedInterestComponent;
if (compoundingDetails != null) {
compoundingDetails.forEach(cd ->
cd.setLoanRepaymentScheduleInstallment(this));
}
this.loanCompoundingDetails = compoundingDetails;
- this.rescheduleInterestPortion = rescheduleInterestPortion;
+ setRescheduleInterestPortion(rescheduleInterestPortion);
this.isDownPayment = isDownPayment;
}
@@ -218,10 +219,10 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
this.installmentNumber = installmentNumber;
this.fromDate = fromDate;
this.dueDate = dueDate;
- this.principal = defaultToNullIfZero(principal);
- this.interestCharged = defaultToNullIfZero(interest);
- this.feeChargesCharged = defaultToNullIfZero(feeCharges);
- this.penaltyCharges = defaultToNullIfZero(penaltyCharges);
+ setPrincipal(principal);
+ setInterestCharged(interest);
+ setFeeChargesCharged(feeCharges);
+ setPenaltyCharges(penaltyCharges);
this.obligationsMet = false;
this.recalculatedInterestComponent = recalculatedInterestComponent;
if (compoundingDetails != null) {
@@ -246,14 +247,14 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
this.installmentNumber = installmentNumber;
this.fromDate = fromDate;
this.dueDate = dueDate;
- this.principal = principal;
- this.interestCharged = interestCharged;
- this.feeChargesCharged = feeChargesCharged;
- this.penaltyCharges = penaltyCharges;
- this.creditedPrincipal = creditedPrincipal;
- this.creditedInterest = creditedInterest;
- this.creditedFee = creditedFee;
- this.creditedPenalty = creditedPenalty;
+ setPrincipal(principal);
+ setInterestCharged(interestCharged);
+ setFeeChargesCharged(feeChargesCharged);
+ setPenaltyCharges(penaltyCharges);
+ setCreditedPrincipal(creditedPrincipal);
+ setCreditedInterest(creditedInterest);
+ setCreditedFee(creditedFee);
+ setCreditedPenalty(creditedPenalty);
this.additional = additional;
this.isDownPayment = isDownPayment;
this.isReAged = isReAged;
@@ -269,14 +270,6 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
return installments.stream().filter(i ->
!i.isDownPayment()).reduce((first, second) -> second).orElseThrow();
}
- private BigDecimal defaultToNullIfZero(final BigDecimal value) {
- BigDecimal result = value;
- if (BigDecimal.ZERO.compareTo(value) == 0) {
- result = null;
- }
- return result;
- }
-
public Money getCreditedPrincipal(final MonetaryCurrency currency) {
return Money.of(currency, this.creditedPrincipal);
}
@@ -393,6 +386,106 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
.plus(getPenaltyChargesOutstanding(currency));
}
+ public void setPrincipal(final BigDecimal principal) {
+ this.principal = setScaleAndDefaultToNullIfZero(principal);
+ }
+
+ public void setPrincipalCompleted(final BigDecimal principalCompleted) {
+ this.principalCompleted =
setScaleAndDefaultToNullIfZero(principalCompleted);
+ }
+
+ public void setPrincipalWrittenOff(final BigDecimal principalWrittenOff) {
+ this.principalWrittenOff =
setScaleAndDefaultToNullIfZero(principalWrittenOff);
+ }
+
+ public void setInterestCharged(final BigDecimal interestCharged) {
+ this.interestCharged = setScaleAndDefaultToNullIfZero(interestCharged);
+ }
+
+ public void setInterestPaid(final BigDecimal interestPaid) {
+ this.interestPaid = setScaleAndDefaultToNullIfZero(interestPaid);
+ }
+
+ public void setInterestWaived(final BigDecimal interestWaived) {
+ this.interestWaived = setScaleAndDefaultToNullIfZero(interestWaived);
+ }
+
+ public void setInterestWrittenOff(final BigDecimal interestWrittenOff) {
+ this.interestWrittenOff =
setScaleAndDefaultToNullIfZero(interestWrittenOff);
+ }
+
+ public void setInterestAccrued(final BigDecimal interestAccrued) {
+ this.interestAccrued = setScaleAndDefaultToNullIfZero(interestAccrued);
+ }
+
+ public void setRescheduleInterestPortion(final BigDecimal
rescheduleInterestPortion) {
+ this.rescheduleInterestPortion =
setScaleAndDefaultToNullIfZero(rescheduleInterestPortion);
+ }
+
+ public void setFeeChargesCharged(final BigDecimal feeChargesCharged) {
+ this.feeChargesCharged =
setScaleAndDefaultToNullIfZero(feeChargesCharged);
+ }
+
+ public void setFeeChargesPaid(final BigDecimal feeChargesPaid) {
+ this.feeChargesPaid = setScaleAndDefaultToNullIfZero(feeChargesPaid);
+ }
+
+ public void setFeeChargesWrittenOff(final BigDecimal feeChargesWrittenOff)
{
+ this.feeChargesWrittenOff =
setScaleAndDefaultToNullIfZero(feeChargesWrittenOff);
+ }
+
+ public void setFeeChargesWaived(final BigDecimal feeChargesWaived) {
+ this.feeChargesWaived =
setScaleAndDefaultToNullIfZero(feeChargesWaived);
+ }
+
+ public void setFeeAccrued(final BigDecimal feeAccrued) {
+ this.feeAccrued = setScaleAndDefaultToNullIfZero(feeAccrued);
+ }
+
+ public void setPenaltyCharges(final BigDecimal penaltyCharges) {
+ this.penaltyCharges = setScaleAndDefaultToNullIfZero(penaltyCharges);
+ }
+
+ public void setPenaltyChargesPaid(final BigDecimal penaltyChargesPaid) {
+ this.penaltyChargesPaid =
setScaleAndDefaultToNullIfZero(penaltyChargesPaid);
+ }
+
+ public void setPenaltyChargesWrittenOff(final BigDecimal
penaltyChargesWrittenOff) {
+ this.penaltyChargesWrittenOff =
setScaleAndDefaultToNullIfZero(penaltyChargesWrittenOff);
+ }
+
+ public void setPenaltyChargesWaived(final BigDecimal penaltyChargesWaived)
{
+ this.penaltyChargesWaived =
setScaleAndDefaultToNullIfZero(penaltyChargesWaived);
+ }
+
+ public void setPenaltyAccrued(final BigDecimal penaltyAccrued) {
+ this.penaltyAccrued = setScaleAndDefaultToNullIfZero(penaltyAccrued);
+ }
+
+ public void setTotalPaidInAdvance(final BigDecimal totalPaidInAdvance) {
+ this.totalPaidInAdvance =
setScaleAndDefaultToNullIfZero(totalPaidInAdvance);
+ }
+
+ public void setTotalPaidLate(final BigDecimal totalPaidLate) {
+ this.totalPaidLate = setScaleAndDefaultToNullIfZero(totalPaidLate);
+ }
+
+ public void setCreditedPrincipal(final BigDecimal creditedPrincipal) {
+ this.creditedPrincipal =
setScaleAndDefaultToNullIfZero(creditedPrincipal);
+ }
+
+ public void setCreditedInterest(final BigDecimal creditedInterest) {
+ this.creditedInterest =
setScaleAndDefaultToNullIfZero(creditedInterest);
+ }
+
+ public void setCreditedFee(final BigDecimal creditedFee) {
+ this.creditedFee = setScaleAndDefaultToNullIfZero(creditedFee);
+ }
+
+ public void setCreditedPenalty(final BigDecimal creditedPenalty) {
+ this.creditedPenalty = setScaleAndDefaultToNullIfZero(creditedPenalty);
+ }
+
void updateLoan(final Loan loan) {
this.loan = loan;
}
@@ -436,19 +529,19 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
this.obligationsMet = false;
this.obligationsMetOnDate = null;
if (this.creditedPrincipal != null) {
- this.principal = this.principal.subtract(this.creditedPrincipal);
+ setPrincipal(this.principal != null ?
this.principal.subtract(this.creditedPrincipal) : null);
this.creditedPrincipal = null;
}
if (this.creditedInterest != null) {
- this.interestCharged =
this.interestCharged.subtract(this.creditedInterest);
+ setInterestCharged(this.interestCharged != null ?
this.interestCharged.subtract(this.creditedInterest) : null);
this.creditedInterest = null;
}
if (this.creditedFee != null) {
- this.feeChargesCharged =
this.feeChargesCharged.subtract(this.creditedFee);
+ setFeeChargesCharged(this.feeChargesCharged != null ?
this.feeChargesCharged.subtract(this.creditedFee) : null);
this.creditedFee = null;
}
if (this.creditedPenalty != null) {
- this.penaltyCharges =
this.penaltyCharges.subtract(this.creditedPenalty);
+ setPenaltyCharges(this.penaltyCharges != null ?
this.penaltyCharges.subtract(this.creditedPenalty) : null);
this.creditedPenalty = null;
}
}
@@ -464,6 +557,14 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
this.penaltyCharges = null;
}
+ public void resetInterestDue() {
+ this.interestCharged = null;
+ }
+
+ public void resetPrincipalDue() {
+ this.principal = null;
+ }
+
public interface PaymentFunction {
Money accept(LocalDate transactionDate, Money
transactionAmountRemaining);
@@ -483,7 +584,6 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
public Money payPenaltyChargesComponent(final LocalDate transactionDate,
final Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money penaltyPortionOfTransaction = Money.zero(currency);
@@ -493,24 +593,20 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
final Money penaltyChargesDue = getPenaltyChargesOutstanding(currency);
if
(transactionAmountRemaining.isGreaterThanOrEqualTo(penaltyChargesDue)) {
- this.penaltyChargesPaid =
getPenaltyChargesPaid(currency).plus(penaltyChargesDue).getAmount();
+
setPenaltyChargesPaid(getPenaltyChargesPaid(currency).plus(penaltyChargesDue).getAmount());
penaltyPortionOfTransaction =
penaltyPortionOfTransaction.plus(penaltyChargesDue);
} else {
- this.penaltyChargesPaid =
getPenaltyChargesPaid(currency).plus(transactionAmountRemaining).getAmount();
+
setPenaltyChargesPaid(getPenaltyChargesPaid(currency).plus(transactionAmountRemaining).getAmount());
penaltyPortionOfTransaction =
penaltyPortionOfTransaction.plus(transactionAmountRemaining);
}
- this.penaltyChargesPaid = defaultToNullIfZero(this.penaltyChargesPaid);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
trackAdvanceAndLateTotalsForRepaymentPeriod(transactionDate, currency,
penaltyPortionOfTransaction);
return penaltyPortionOfTransaction;
}
public Money payFeeChargesComponent(final LocalDate transactionDate, final
Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money feePortionOfTransaction = Money.zero(currency);
if (transactionAmountRemaining.isZero()) {
@@ -518,24 +614,20 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
final Money feeChargesDue = getFeeChargesOutstanding(currency);
if (transactionAmountRemaining.isGreaterThanOrEqualTo(feeChargesDue)) {
- this.feeChargesPaid =
getFeeChargesPaid(currency).plus(feeChargesDue).getAmount();
+
setFeeChargesPaid(getFeeChargesPaid(currency).plus(feeChargesDue).getAmount());
feePortionOfTransaction =
feePortionOfTransaction.plus(feeChargesDue);
} else {
- this.feeChargesPaid =
getFeeChargesPaid(currency).plus(transactionAmountRemaining).getAmount();
+
setFeeChargesPaid(getFeeChargesPaid(currency).plus(transactionAmountRemaining).getAmount());
feePortionOfTransaction =
feePortionOfTransaction.plus(transactionAmountRemaining);
}
- this.feeChargesPaid = defaultToNullIfZero(this.feeChargesPaid);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
trackAdvanceAndLateTotalsForRepaymentPeriod(transactionDate, currency,
feePortionOfTransaction);
return feePortionOfTransaction;
}
public Money payInterestComponent(final LocalDate transactionDate, final
Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money interestPortionOfTransaction = Money.zero(currency);
if (transactionAmountRemaining.isZero()) {
@@ -543,24 +635,20 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
final Money interestDue = getInterestOutstanding(currency);
if (transactionAmountRemaining.isGreaterThanOrEqualTo(interestDue)) {
- this.interestPaid =
getInterestPaid(currency).plus(interestDue).getAmount();
+
setInterestPaid(getInterestPaid(currency).plus(interestDue).getAmount());
interestPortionOfTransaction =
interestPortionOfTransaction.plus(interestDue);
} else {
- this.interestPaid =
getInterestPaid(currency).plus(transactionAmountRemaining).getAmount();
+
setInterestPaid(getInterestPaid(currency).plus(transactionAmountRemaining).getAmount());
interestPortionOfTransaction =
interestPortionOfTransaction.plus(transactionAmountRemaining);
}
- this.interestPaid = defaultToNullIfZero(this.interestPaid);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
trackAdvanceAndLateTotalsForRepaymentPeriod(transactionDate, currency,
interestPortionOfTransaction);
return interestPortionOfTransaction;
}
public Money payPrincipalComponent(final LocalDate transactionDate, final
Money transactionAmount) {
-
final MonetaryCurrency currency = transactionAmount.getCurrency();
Money principalPortionOfTransaction = Money.zero(currency);
if (transactionAmount.isZero()) {
@@ -568,17 +656,14 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
final Money principalDue = getPrincipalOutstanding(currency);
if (transactionAmount.isGreaterThanOrEqualTo(principalDue)) {
- this.principalCompleted =
getPrincipalCompleted(currency).plus(principalDue).getAmount();
+
setPrincipalCompleted(getPrincipalCompleted(currency).plus(principalDue).getAmount());
principalPortionOfTransaction =
principalPortionOfTransaction.plus(principalDue);
} else {
- this.principalCompleted =
getPrincipalCompleted(currency).plus(transactionAmount).getAmount();
+
setPrincipalCompleted(getPrincipalCompleted(currency).plus(transactionAmount).getAmount());
principalPortionOfTransaction =
principalPortionOfTransaction.plus(transactionAmount);
}
- this.principalCompleted = defaultToNullIfZero(this.principalCompleted);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
trackAdvanceAndLateTotalsForRepaymentPeriod(transactionDate, currency,
principalPortionOfTransaction);
return principalPortionOfTransaction;
@@ -592,15 +677,13 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
final Money interestDue = getInterestOutstanding(currency);
if (transactionAmountRemaining.isGreaterThanOrEqualTo(interestDue)) {
- this.interestWaived =
getInterestWaived(currency).plus(interestDue).getAmount();
+
setInterestWaived(getInterestWaived(currency).plus(interestDue).getAmount());
waivedInterestPortionOfTransaction =
waivedInterestPortionOfTransaction.plus(interestDue);
} else {
- this.interestWaived =
getInterestWaived(currency).plus(transactionAmountRemaining).getAmount();
+
setInterestWaived(getInterestWaived(currency).plus(transactionAmountRemaining).getAmount());
waivedInterestPortionOfTransaction =
waivedInterestPortionOfTransaction.plus(transactionAmountRemaining);
}
- this.interestWaived = defaultToNullIfZero(this.interestWaived);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
return waivedInterestPortionOfTransaction;
@@ -612,17 +695,15 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
if (transactionAmountRemaining.isZero()) {
return waivedPenaltyChargesPortionOfTransaction;
}
- final Money penanltiesDue = getPenaltyChargesOutstanding(currency);
- if (transactionAmountRemaining.isGreaterThanOrEqualTo(penanltiesDue)) {
- this.penaltyChargesWaived =
getPenaltyChargesWaived(currency).plus(penanltiesDue).getAmount();
- waivedPenaltyChargesPortionOfTransaction =
waivedPenaltyChargesPortionOfTransaction.plus(penanltiesDue);
+ final Money penaltiesDue = getPenaltyChargesOutstanding(currency);
+ if (transactionAmountRemaining.isGreaterThanOrEqualTo(penaltiesDue)) {
+
setPenaltyChargesWaived(getPenaltyChargesWaived(currency).plus(penaltiesDue).getAmount());
+ waivedPenaltyChargesPortionOfTransaction =
waivedPenaltyChargesPortionOfTransaction.plus(penaltiesDue);
} else {
- this.penaltyChargesWaived =
getPenaltyChargesWaived(currency).plus(transactionAmountRemaining).getAmount();
+
setPenaltyChargesWaived(getPenaltyChargesWaived(currency).plus(transactionAmountRemaining).getAmount());
waivedPenaltyChargesPortionOfTransaction =
waivedPenaltyChargesPortionOfTransaction.plus(transactionAmountRemaining);
}
- this.penaltyChargesWaived =
defaultToNullIfZero(this.penaltyChargesWaived);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
return waivedPenaltyChargesPortionOfTransaction;
@@ -636,55 +717,43 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
final Money feesDue = getFeeChargesOutstanding(currency);
if (transactionAmountRemaining.isGreaterThanOrEqualTo(feesDue)) {
- this.feeChargesWaived =
getFeeChargesWaived(currency).plus(feesDue).getAmount();
+
setFeeChargesWaived(getFeeChargesWaived(currency).plus(feesDue).getAmount());
waivedFeeChargesPortionOfTransaction =
waivedFeeChargesPortionOfTransaction.plus(feesDue);
} else {
- this.feeChargesWaived =
getFeeChargesWaived(currency).plus(transactionAmountRemaining).getAmount();
+
setFeeChargesWaived(getFeeChargesWaived(currency).plus(transactionAmountRemaining).getAmount());
waivedFeeChargesPortionOfTransaction =
waivedFeeChargesPortionOfTransaction.plus(transactionAmountRemaining);
}
- this.feeChargesWaived = defaultToNullIfZero(this.feeChargesWaived);
-
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
return waivedFeeChargesPortionOfTransaction;
}
public Money writeOffOutstandingPrincipal(final LocalDate transactionDate,
final MonetaryCurrency currency) {
-
final Money principalDue = getPrincipalOutstanding(currency);
- this.principalWrittenOff =
defaultToNullIfZero(principalDue.getAmount());
-
+ setPrincipalWrittenOff(principalDue.getAmount());
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
return principalDue;
}
public Money writeOffOutstandingInterest(final LocalDate transactionDate,
final MonetaryCurrency currency) {
-
final Money interestDue = getInterestOutstanding(currency);
- this.interestWrittenOff = defaultToNullIfZero(interestDue.getAmount());
-
+ setInterestWrittenOff(interestDue.getAmount());
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
return interestDue;
}
public Money writeOffOutstandingFeeCharges(final LocalDate
transactionDate, final MonetaryCurrency currency) {
final Money feeChargesOutstanding = getFeeChargesOutstanding(currency);
- this.feeChargesWrittenOff =
defaultToNullIfZero(feeChargesOutstanding.getAmount());
-
+ setFeeChargesWrittenOff(feeChargesOutstanding.getAmount());
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
return feeChargesOutstanding;
}
public Money writeOffOutstandingPenaltyCharges(final LocalDate
transactionDate, final MonetaryCurrency currency) {
final Money penaltyChargesOutstanding =
getPenaltyChargesOutstanding(currency);
- this.penaltyChargesWrittenOff =
defaultToNullIfZero(penaltyChargesOutstanding.getAmount());
-
+ setPenaltyChargesWrittenOff(penaltyChargesOutstanding.getAmount());
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
return penaltyChargesOutstanding;
}
@@ -694,32 +763,29 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
public void updateChargePortion(final Money feeChargesDue, final Money
feeChargesWaived, final Money feeChargesWrittenOff,
final Money penaltyChargesDue, final Money penaltyChargesWaived,
final Money penaltyChargesWrittenOff) {
- this.feeChargesCharged =
MathUtil.zeroToNull(MathUtil.toBigDecimal(feeChargesDue));
- this.feeChargesWaived =
MathUtil.zeroToNull(MathUtil.toBigDecimal(feeChargesWaived));
- this.feeChargesWrittenOff =
MathUtil.zeroToNull(MathUtil.toBigDecimal(feeChargesWrittenOff));
- this.penaltyCharges =
MathUtil.zeroToNull(MathUtil.toBigDecimal(penaltyChargesDue));
- this.penaltyChargesWaived =
MathUtil.zeroToNull(MathUtil.toBigDecimal(penaltyChargesWaived));
- this.penaltyChargesWrittenOff =
MathUtil.zeroToNull(MathUtil.toBigDecimal(penaltyChargesWrittenOff));
+ setFeeChargesCharged(feeChargesDue.getAmount());
+ setFeeChargesWaived(feeChargesWaived.getAmount());
+ setFeeChargesWrittenOff(feeChargesWrittenOff.getAmount());
+ setPenaltyCharges(penaltyChargesDue.getAmount());
+ setPenaltyChargesWaived(penaltyChargesWaived.getAmount());
+ setPenaltyChargesWrittenOff(penaltyChargesWrittenOff.getAmount());
}
public void addToChargePortion(final Money feeChargesDue, final Money
feeChargesWaived, final Money feeChargesWrittenOff,
final Money penaltyChargesDue, final Money penaltyChargesWaived,
final Money penaltyChargesWrittenOff) {
- this.feeChargesCharged =
MathUtil.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(feeChargesDue),
this.feeChargesCharged));
- this.feeChargesWaived =
MathUtil.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(feeChargesWaived),
this.feeChargesWaived));
- this.feeChargesWrittenOff = MathUtil
-
.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(feeChargesWrittenOff),
this.feeChargesWrittenOff));
- this.penaltyCharges =
MathUtil.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(penaltyChargesDue),
this.penaltyCharges));
- this.penaltyChargesWaived = MathUtil
-
.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(penaltyChargesWaived),
this.penaltyChargesWaived));
- this.penaltyChargesWrittenOff = MathUtil
-
.zeroToNull(MathUtil.add(MathUtil.toBigDecimal(penaltyChargesWrittenOff),
this.penaltyChargesWrittenOff));
+ setFeeChargesCharged(MathUtil.add(feeChargesDue.getAmount(),
this.feeChargesCharged));
+ setFeeChargesWaived(MathUtil.add(feeChargesWaived.getAmount(),
this.feeChargesWaived));
+ setFeeChargesWrittenOff(MathUtil.add(feeChargesWrittenOff.getAmount(),
this.feeChargesWrittenOff));
+ setPenaltyCharges(MathUtil.add(penaltyChargesDue.getAmount(),
this.penaltyCharges));
+ setPenaltyChargesWaived(MathUtil.add(penaltyChargesWaived.getAmount(),
this.penaltyChargesWaived));
+
setPenaltyChargesWrittenOff(MathUtil.add(penaltyChargesWrittenOff.getAmount(),
this.penaltyChargesWrittenOff));
checkIfRepaymentPeriodObligationsAreMet(getObligationsMetOnDate(),
feeChargesDue.getCurrency());
}
public void updateAccrualPortion(final Money interest, final Money
feeCharges, final Money penalityCharges) {
- this.interestAccrued =
MathUtil.zeroToNull(MathUtil.toBigDecimal(interest));
- this.feeAccrued =
MathUtil.zeroToNull(MathUtil.toBigDecimal(feeCharges));
- this.penaltyAccrued =
MathUtil.zeroToNull(MathUtil.toBigDecimal(penalityCharges));
+ setInterestAccrued(interest.getAmount());
+ setFeeAccrued(feeCharges.getAmount());
+ setPenaltyAccrued(penalityCharges.getAmount());
}
public void updateObligationsMet(final MonetaryCurrency currency, final
LocalDate transactionDate) {
@@ -735,9 +801,9 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
private void trackAdvanceAndLateTotalsForRepaymentPeriod(final LocalDate
transactionDate, final MonetaryCurrency currency,
final Money amountPaidInRepaymentPeriod) {
if (isInAdvance(transactionDate)) {
- this.totalPaidInAdvance = asMoney(this.totalPaidInAdvance,
currency).plus(amountPaidInRepaymentPeriod).getAmount();
+ setTotalPaidInAdvance(asMoney(this.totalPaidInAdvance,
currency).plus(amountPaidInRepaymentPeriod).getAmount());
} else if (isLatePayment(transactionDate)) {
- this.totalPaidLate = asMoney(this.totalPaidLate,
currency).plus(amountPaidInRepaymentPeriod).getAmount();
+ setTotalPaidLate(asMoney(this.totalPaidLate,
currency).plus(amountPaidInRepaymentPeriod).getAmount());
}
}
@@ -785,7 +851,7 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
public void updateInterestCharged(final BigDecimal interestCharged) {
- this.interestCharged = interestCharged;
+ setInterestCharged(interestCharged);
}
public void updateObligationMet(final Boolean obligationMet) {
@@ -797,72 +863,71 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
public void updatePrincipal(final BigDecimal principal) {
- this.principal = principal;
+ setPrincipal(principal);
}
public void addToPrincipal(final LocalDate transactionDate, final Money
transactionAmount) {
if (this.principal == null) {
- this.principal = transactionAmount.getAmount();
+ setPrincipal(transactionAmount.getAmount());
} else {
- this.principal = this.principal.add(transactionAmount.getAmount());
+ setPrincipal(this.principal.add(transactionAmount.getAmount()));
}
checkIfRepaymentPeriodObligationsAreMet(transactionDate,
transactionAmount.getCurrency());
}
public void addToInterest(final LocalDate transactionDate, final Money
transactionAmount) {
if (this.interestCharged == null) {
- this.interestCharged = transactionAmount.getAmount();
+ setInterestCharged(transactionAmount.getAmount());
} else {
- this.interestCharged =
this.interestCharged.add(transactionAmount.getAmount());
+
setInterestCharged(this.interestCharged.add(transactionAmount.getAmount()));
}
checkIfRepaymentPeriodObligationsAreMet(transactionDate,
transactionAmount.getCurrency());
}
public void addToCreditedInterest(final BigDecimal amount) {
if (this.creditedInterest == null) {
- this.creditedInterest = amount;
+ setCreditedInterest(amount);
} else {
- this.creditedInterest = this.creditedInterest.add(amount);
+ setCreditedInterest(this.creditedInterest.add(amount));
}
}
public void addToCreditedPrincipal(final BigDecimal amount) {
if (this.creditedPrincipal == null) {
- this.creditedPrincipal = amount;
+ setCreditedPrincipal(amount);
} else {
- this.creditedPrincipal = this.creditedPrincipal.add(amount);
+ setCreditedPrincipal(this.creditedPrincipal.add(amount));
}
}
public void addToCreditedFee(final BigDecimal amount) {
if (this.creditedFee == null) {
- this.creditedFee = amount;
+ setCreditedFee(amount);
} else {
- this.creditedFee = this.creditedFee.add(amount);
+ setCreditedFee(this.creditedFee.add(amount));
}
}
public void addToCreditedPenalty(final BigDecimal amount) {
if (this.creditedPenalty == null) {
- this.creditedPenalty = amount;
+ setCreditedPenalty(amount);
} else {
- this.creditedPenalty = this.creditedPenalty.add(amount);
+ setCreditedPenalty(this.creditedPenalty.add(amount));
}
}
/********** UNPAY COMPONENTS ****/
public Money unpayPenaltyChargesComponent(final LocalDate transactionDate,
final Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money penaltyPortionOfTransactionDeducted;
final Money penaltyChargesCompleted = getPenaltyChargesPaid(currency);
if
(transactionAmountRemaining.isGreaterThanOrEqualTo(penaltyChargesCompleted)) {
- this.penaltyChargesPaid = Money.zero(currency).getAmount();
+ this.penaltyChargesPaid = null;
penaltyPortionOfTransactionDeducted = penaltyChargesCompleted;
} else {
- this.penaltyChargesPaid =
penaltyChargesCompleted.minus(transactionAmountRemaining).getAmount();
+
setPenaltyChargesPaid(penaltyChargesCompleted.minus(transactionAmountRemaining).getAmount());
penaltyPortionOfTransactionDeducted = transactionAmountRemaining;
}
@@ -872,63 +937,57 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
}
public Money unpayFeeChargesComponent(final LocalDate transactionDate,
final Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money feePortionOfTransactionDeducted;
final Money feeChargesCompleted = getFeeChargesPaid(currency);
if
(transactionAmountRemaining.isGreaterThanOrEqualTo(feeChargesCompleted)) {
- this.feeChargesPaid = Money.zero(currency).getAmount();
+ this.feeChargesPaid = null;
feePortionOfTransactionDeducted = feeChargesCompleted;
} else {
- this.feeChargesPaid =
feeChargesCompleted.minus(transactionAmountRemaining).getAmount();
+
setFeeChargesPaid(feeChargesCompleted.minus(transactionAmountRemaining).getAmount());
feePortionOfTransactionDeducted = transactionAmountRemaining;
}
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
reduceAdvanceAndLateTotalsForRepaymentPeriod(transactionDate,
currency, feePortionOfTransactionDeducted);
return feePortionOfTransactionDeducted;
}
public Money unpayInterestComponent(final LocalDate transactionDate, final
Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money interestPortionOfTransactionDeducted;
final Money interestCompleted = getInterestPaid(currency);
if
(transactionAmountRemaining.isGreaterThanOrEqualTo(interestCompleted)) {
- this.interestPaid = Money.zero(currency).getAmount();
+ this.interestPaid = null;
interestPortionOfTransactionDeducted = interestCompleted;
} else {
- this.interestPaid =
interestCompleted.minus(transactionAmountRemaining).getAmount();
+
setInterestPaid(interestCompleted.minus(transactionAmountRemaining).getAmount());
interestPortionOfTransactionDeducted = transactionAmountRemaining;
}
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
reduceAdvanceAndLateTotalsForRepaymentPeriod(transactionDate,
currency, interestPortionOfTransactionDeducted);
return interestPortionOfTransactionDeducted;
}
public Money unpayPrincipalComponent(final LocalDate transactionDate,
final Money transactionAmountRemaining) {
-
final MonetaryCurrency currency =
transactionAmountRemaining.getCurrency();
Money principalPortionOfTransactionDeducted;
final Money principalCompleted = getPrincipalCompleted(currency);
if
(transactionAmountRemaining.isGreaterThanOrEqualTo(principalCompleted)) {
- this.principalCompleted = Money.zero(currency).getAmount();
+ this.principalCompleted = null;
principalPortionOfTransactionDeducted = principalCompleted;
} else {
- this.principalCompleted =
principalCompleted.minus(transactionAmountRemaining).getAmount();
+
setPrincipalCompleted(principalCompleted.minus(transactionAmountRemaining).getAmount());
principalPortionOfTransactionDeducted = transactionAmountRemaining;
}
checkIfRepaymentPeriodObligationsAreMet(transactionDate, currency);
-
reduceAdvanceAndLateTotalsForRepaymentPeriod(transactionDate,
currency, principalPortionOfTransactionDeducted);
return principalPortionOfTransactionDeducted;
@@ -936,23 +995,22 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
private void reduceAdvanceAndLateTotalsForRepaymentPeriod(final LocalDate
transactionDate, final MonetaryCurrency currency,
final Money amountDeductedInRepaymentPeriod) {
-
if (isInAdvance(transactionDate)) {
- Money mTotalPaidInAdvance = Money.of(currency,
this.totalPaidInAdvance);
+ final Money mTotalPaidInAdvance = Money.of(currency,
this.totalPaidInAdvance);
if (mTotalPaidInAdvance.isLessThan(amountDeductedInRepaymentPeriod)
||
mTotalPaidInAdvance.isEqualTo(amountDeductedInRepaymentPeriod)) {
- this.totalPaidInAdvance = Money.zero(currency).getAmount();
+ this.totalPaidInAdvance = null;
} else {
- this.totalPaidInAdvance =
mTotalPaidInAdvance.minus(amountDeductedInRepaymentPeriod).getAmount();
+
setTotalPaidInAdvance(mTotalPaidInAdvance.minus(amountDeductedInRepaymentPeriod).getAmount());
}
} else if (isLatePayment(transactionDate)) {
- Money mTotalPaidLate = Money.of(currency, this.totalPaidLate);
+ final Money mTotalPaidLate = Money.of(currency,
this.totalPaidLate);
if (mTotalPaidLate.isLessThan(amountDeductedInRepaymentPeriod) ||
mTotalPaidLate.isEqualTo(amountDeductedInRepaymentPeriod)) {
- this.totalPaidLate = Money.zero(currency).getAmount();
+ this.totalPaidLate = null;
} else {
- this.totalPaidLate =
mTotalPaidLate.minus(amountDeductedInRepaymentPeriod).getAmount();
+
setTotalPaidLate(mTotalPaidLate.minus(amountDeductedInRepaymentPeriod).getAmount());
}
}
}
@@ -983,14 +1041,6 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
resetInterestDue();
}
- public void resetInterestDue() {
- this.interestCharged = null;
- }
-
- public void resetPrincipalDue() {
- this.principal = null;
- }
-
public enum PaymentAction {
PAY, //
UNPAY //
@@ -1155,4 +1205,14 @@ public class LoanRepaymentScheduleInstallment extends
AbstractAuditableWithUTCDa
private static boolean nonNullAndEqual(Object a, Object b) {
return a != null && b != null && Objects.equals(a, b);
}
+
+ private BigDecimal setScaleAndDefaultToNullIfZero(final BigDecimal value) {
+ if (value == null) {
+ return null;
+ }
+ if (value.compareTo(BigDecimal.ZERO) == 0) {
+ return null;
+ }
+ return value.setScale(6, MoneyHelper.getRoundingMode());
+ }
}
diff --git
a/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentTest.java
b/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentTest.java
new file mode 100644
index 0000000000..5ab2156a5e
--- /dev/null
+++
b/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentTest.java
@@ -0,0 +1,209 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.domain;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+class LoanRepaymentScheduleInstallmentTest {
+
+ private static final int SCALE = 6;
+ private static final int PRECISION = 19;
+ private static final MockedStatic<MoneyHelper> MONEY_HELPER =
mockStatic(MoneyHelper.class);
+ private static final MathContext MATH_CONTEXT = new MathContext(PRECISION,
RoundingMode.HALF_EVEN);
+
+ private LoanRepaymentScheduleInstallment installment;
+
+ @BeforeAll
+ static void init() {
+
MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
+
MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(MATH_CONTEXT);
+ }
+
+ @BeforeEach
+ void setUp() {
+ final Loan loan = mock(Loan.class);
+ installment = new LoanRepaymentScheduleInstallment(loan, 1,
LocalDate.now(ZoneId.systemDefault()),
+ LocalDate.now(ZoneId.systemDefault()).plusMonths(1),
BigDecimal.valueOf(1000), BigDecimal.valueOf(100),
+ BigDecimal.valueOf(50), BigDecimal.valueOf(25),
BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false,
+ false, false);
+ }
+
+ @AfterAll
+ static void tearDown() {
+ MONEY_HELPER.close();
+ }
+
+ @Test
+ void testPrincipalSetters() {
+ testBigDecimalSetter(installment::setPrincipal,
installment::getPrincipal);
+ }
+
+ @Test
+ void testPrincipalCompletedSetters() {
+ testBigDecimalSetter(installment::setPrincipalCompleted,
installment::getPrincipalCompleted);
+ }
+
+ @Test
+ void testPrincipalWrittenOffSetters() {
+ testBigDecimalSetter(installment::setPrincipalWrittenOff,
installment::getPrincipalWrittenOff);
+ }
+
+ @Test
+ void testInterestChargedSetters() {
+ testBigDecimalSetter(installment::setInterestCharged,
installment::getInterestCharged);
+ }
+
+ @Test
+ void testInterestPaidSetters() {
+ testBigDecimalSetter(installment::setInterestPaid,
installment::getInterestPaid);
+ }
+
+ @Test
+ void testInterestWaivedSetters() {
+ testBigDecimalSetter(installment::setInterestWaived,
installment::getInterestWaived);
+ }
+
+ @Test
+ void testInterestWrittenOffSetters() {
+ testBigDecimalSetter(installment::setInterestWrittenOff,
installment::getInterestWrittenOff);
+ }
+
+ @Test
+ void testInterestAccruedSetters() {
+ testBigDecimalSetter(installment::setInterestAccrued,
installment::getInterestAccrued);
+ }
+
+ @Test
+ void testRescheduleInterestPortionSetters() {
+ testBigDecimalSetter(installment::setRescheduleInterestPortion,
installment::getRescheduleInterestPortion);
+ }
+
+ @Test
+ void testFeeChargesChargedSetters() {
+ testBigDecimalSetter(installment::setFeeChargesCharged,
installment::getFeeChargesCharged);
+ }
+
+ @Test
+ void testFeeChargesPaidSetters() {
+ testBigDecimalSetter(installment::setFeeChargesPaid,
installment::getFeeChargesPaid);
+ }
+
+ @Test
+ void testFeeChargesWrittenOffSetters() {
+ testBigDecimalSetter(installment::setFeeChargesWrittenOff,
installment::getFeeChargesWrittenOff);
+ }
+
+ @Test
+ void testFeeChargesWaivedSetters() {
+ testBigDecimalSetter(installment::setFeeChargesWaived,
installment::getFeeChargesWaived);
+ }
+
+ @Test
+ void testFeeAccruedSetters() {
+ testBigDecimalSetter(installment::setFeeAccrued,
installment::getFeeAccrued);
+ }
+
+ @Test
+ void testPenaltyChargesSetters() {
+ testBigDecimalSetter(installment::setPenaltyCharges,
installment::getPenaltyCharges);
+ }
+
+ @Test
+ void testPenaltyChargesPaidSetters() {
+ testBigDecimalSetter(installment::setPenaltyChargesPaid,
installment::getPenaltyChargesPaid);
+ }
+
+ @Test
+ void testPenaltyChargesWrittenOffSetters() {
+ testBigDecimalSetter(installment::setPenaltyChargesWrittenOff,
installment::getPenaltyChargesWrittenOff);
+ }
+
+ @Test
+ void testPenaltyChargesWaivedSetters() {
+ testBigDecimalSetter(installment::setPenaltyChargesWaived,
installment::getPenaltyChargesWaived);
+ }
+
+ @Test
+ void testPenaltyAccruedSetters() {
+ testBigDecimalSetter(installment::setPenaltyAccrued,
installment::getPenaltyAccrued);
+ }
+
+ @Test
+ void testTotalPaidInAdvanceSetters() {
+ testBigDecimalSetter(installment::setTotalPaidInAdvance,
installment::getTotalPaidInAdvance);
+ }
+
+ @Test
+ void testTotalPaidLateSetters() {
+ testBigDecimalSetter(installment::setTotalPaidLate,
installment::getTotalPaidLate);
+ }
+
+ @Test
+ void testCreditedAmountsSetters() {
+ testBigDecimalSetter(installment::setCreditedPrincipal,
installment::getCreditedPrincipal);
+ testBigDecimalSetter(installment::setCreditedInterest,
installment::getCreditedInterest);
+ testBigDecimalSetter(installment::setCreditedFee,
installment::getCreditedFee);
+ testBigDecimalSetter(installment::setCreditedPenalty,
installment::getCreditedPenalty);
+ }
+
+ @Test
+ void testPrecisionAndScale() {
+ final BigDecimal value = new BigDecimal("123456789.123456789");
+
+ // Test that value is properly scaled
+ installment.setPrincipal(value);
+ assertEquals(SCALE, installment.getPrincipal().scale());
+
+ // Test that value is properly rounded
+ final BigDecimal expected = new BigDecimal("123456789.123457");
+ assertEquals(expected, installment.getPrincipal());
+ }
+
+ private void testBigDecimalSetter(final Consumer<BigDecimal> setter, final
Supplier<BigDecimal> getter) {
+ // Test non-zero value
+ final BigDecimal value = new BigDecimal("123.456789");
+ setter.accept(value);
+ assertEquals(value.setScale(SCALE, RoundingMode.HALF_EVEN),
getter.get());
+
+ // Test zero value
+ setter.accept(BigDecimal.ZERO);
+ assertNull(getter.get());
+
+ // Test null value
+ setter.accept(null);
+ assertNull(getter.get());
+ }
+}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
index 7524a9248b..39ee62f061 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
@@ -26,11 +26,13 @@ import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
@@ -50,6 +52,7 @@ import
org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import
org.apache.fineract.infrastructure.event.business.domain.loan.LoanAccountDelinquencyPauseChangedBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.domain.loan.LoanDelinquencyRangeChangeBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappingsRepository;
@@ -79,19 +82,24 @@ import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
+import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class DelinquencyWritePlatformServiceRangeChangeEventTest {
+ private static final MockedStatic<MoneyHelper> MONEY_HELPER =
mockStatic(MoneyHelper.class);
+
@Mock
private DelinquencyBucketParseAndValidator dataValidatorBucket;
@Mock
@@ -127,6 +135,11 @@ public class
DelinquencyWritePlatformServiceRangeChangeEventTest {
private DelinquencyWritePlatformServiceImpl underTest;
+ @BeforeAll
+ static void init() {
+
MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
+ }
+
@BeforeEach
public void setUp() {
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L,
"default", "Default", "Asia/Kolkata", null));
@@ -143,6 +156,11 @@ public class
DelinquencyWritePlatformServiceRangeChangeEventTest {
delinquencyWritePlatformServiceHelper);
}
+ @AfterAll
+ static void cleanUp() {
+ MONEY_HELPER.close();
+ }
+
@AfterEach
public void tearDown() {
ThreadLocalContextUtil.reset();
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index 9518aea7f0..c247950a83 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -5348,8 +5348,8 @@ public class ClientLoanIntegrationTest extends
BaseLoanIntegrationTest {
ArrayList<HashMap> loanSchedule =
LOAN_TRANSACTION_HELPER.getLoanRepaymentSchedule(REQUEST_SPEC, RESPONSE_SPEC,
loanID);
assertEquals(2, loanSchedule.size());
- assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
- assertEquals(0.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
+ assertEquals(0,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(1000.0f,
loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(1000.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
LocalDate targetDate = LocalDate.of(2022, 9, 7);
@@ -5944,10 +5944,10 @@ public class ClientLoanIntegrationTest extends
BaseLoanIntegrationTest {
ArrayList<HashMap> loanSchedule =
LOAN_TRANSACTION_HELPER.getLoanRepaymentSchedule(REQUEST_SPEC, RESPONSE_SPEC,
loanID);
assertEquals(2, loanSchedule.size());
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
- assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
- assertEquals(0.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(1000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(1000.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
LocalDate targetDate = LocalDate.of(2022, 9, 7);
@@ -6013,11 +6013,11 @@ public class ClientLoanIntegrationTest extends
BaseLoanIntegrationTest {
assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
assertEquals(0, loanSchedule.get(1).get("feeChargesWaived"));
assertEquals(10.0f, loanSchedule.get(1).get("penaltyChargesDue"));
- assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesWaived"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesWaived"));
assertEquals(10.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(1010.0f, loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(1010.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
- assertEquals(0.0f, loanSchedule.get(1).get("totalWaivedForPeriod"));
+ assertEquals(0, loanSchedule.get(1).get("totalWaivedForPeriod"));
loanSummary = LOAN_TRANSACTION_HELPER.getLoanDetail(REQUEST_SPEC,
RESPONSE_SPEC, loanID, "summary");
assertEquals(10.0f, loanSummary.get("penaltyChargesCharged"));
@@ -6146,13 +6146,13 @@ public class ClientLoanIntegrationTest extends
BaseLoanIntegrationTest {
assertEquals(2, loanSchedule.size());
assertEquals(10.0f, loanSchedule.get(1).get("feeChargesDue"));
assertEquals(10.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesWaived"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesWaived"));
assertEquals(10.0f, loanSchedule.get(1).get("penaltyChargesDue"));
assertEquals(0, loanSchedule.get(1).get("penaltyChargesWaived"));
assertEquals(10.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(1020.0f, loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(1020.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
- assertEquals(0.0f, loanSchedule.get(1).get("totalWaivedForPeriod"));
+ assertEquals(0, loanSchedule.get(1).get("totalWaivedForPeriod"));
loanSummary = LOAN_TRANSACTION_HELPER.getLoanDetail(REQUEST_SPEC,
RESPONSE_SPEC, loanID, "summary");
assertEquals(10.0f, loanSummary.get("penaltyChargesCharged"));
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 6b8b286cc2..bb7b14e3a4 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
@@ -173,10 +173,10 @@ public class LoanSpecificDueDateChargeAfterMaturityTest
extends BaseLoanIntegrat
ArrayList<HashMap> loanSchedule =
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID);
assertEquals(2, loanSchedule.size());
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
- assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
- assertEquals(0.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(10000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(10000.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
targetDate = LocalDate.of(2011, 4, 5);
@@ -306,10 +306,10 @@ public class LoanSpecificDueDateChargeAfterMaturityTest
extends BaseLoanIntegrat
ArrayList<HashMap> loanSchedule =
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID);
assertEquals(2, loanSchedule.size());
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
- assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
- assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
- assertEquals(0.0f,
loanSchedule.get(1).get("penaltyChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
+ assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
assertEquals(10000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
assertEquals(10000.0f,
loanSchedule.get(1).get("totalOutstandingForPeriod"));
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
index 3045df0243..4bc891fe9b 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
@@ -844,7 +844,7 @@ public class SchedulerJobsTestResults extends
IntegrationTest {
ArrayList<HashMap> repaymentScheduleDataAfter =
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID);
- Assertions.assertEquals(0.0f,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+ Assertions.assertEquals(0,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment after
Successful completion of Scheduler Job");
}
@@ -1085,7 +1085,7 @@ public class SchedulerJobsTestResults extends
IntegrationTest {
this.schedulerJobHelper.executeAndAwaitJob(jobName);
List<HashMap> repaymentScheduleDataAfter =
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID);
- Assertions.assertEquals(0.0f,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+ Assertions.assertEquals(0,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment
after Successful completion of Scheduler Job");
LocalDate lastBusinessDateBeforeFastForward = LocalDate.of(2019,
4, 2);
@@ -1153,7 +1153,7 @@ public class SchedulerJobsTestResults extends
IntegrationTest {
this.schedulerJobHelper.executeAndAwaitJob(jobName);
List<HashMap> repaymentScheduleDataAfter =
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID2);
- Assertions.assertEquals(0.0f,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+ Assertions.assertEquals(0,
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment
after Successful completion of Scheduler Job");
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec,
BusinessDateType.COB_DATE, LocalDate.of(2020, 5, 3));