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 ed0c14e90..94d6dd315 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 000000000..5ab2156a5 --- /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 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 setter, final Supplier 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 7524a9248..39ee62f06 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 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 9518aea7f..c247950a8 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 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 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 6b8b286cc..bb7b14e3a 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 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 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 3045df024..4bc891fe9 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 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 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 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));