From 22bcccb17b582b146963e1d9da51bc1e17c70b2a Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Fri, 14 Oct 2022 14:55:16 -0500 Subject: [PATCH] Loan summary with principal adjustments --- .../main/avro/loan/v1/LoanSummaryDataV1.avsc | 8 +++ .../api/LoansApiResourceSwagger.java | 2 + .../loanaccount/data/LoanSummaryData.java | 27 ++++---- .../loanaccount/domain/LoanSummary.java | 11 ++- .../domain/LoanSummaryWrapper.java | 11 ++- .../service/LoanReadPlatformServiceImpl.java | 68 +++++++++---------- .../api/SelfLoansApiResourceSwagger.java | 2 + .../db/changelog/tenant/changelog-tenant.xml | 1 + ...0057_add_principal_adjustments_to_loan.xml | 30 ++++++++ .../LoanTransactionChargebackTest.java | 21 +++++- 10 files changed, 132 insertions(+), 49 deletions(-) create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0057_add_principal_adjustments_to_loan.xml diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc index 88dd74402..f19879e95 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanSummaryDataV1.avsc @@ -19,6 +19,14 @@ "bigdecimal" ] }, + { + "default": null, + "name": "principalAdjustments", + "type": [ + "null", + "bigdecimal" + ] + }, { "default": null, "name": "principalPaid", diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java index 98bc435ff..34a066364 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java @@ -478,6 +478,8 @@ final class LoansApiResourceSwagger { public Double principalDisbursed; @Schema(example = "0.000000") public Double principalPaid; + @Schema(example = "0.00") + public Double principalAdjustments; @Schema(example = "0.000000") public Double principalWrittenOff; @Schema(example = "1000000.000000") diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java index efd710378..d9f33e2d7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java @@ -31,6 +31,7 @@ public class LoanSummaryData { private final CurrencyData currency; private final BigDecimal principalDisbursed; + private final BigDecimal principalAdjustments; private final BigDecimal principalPaid; private final BigDecimal principalWrittenOff; private final BigDecimal principalOutstanding; @@ -67,20 +68,22 @@ public class LoanSummaryData { private final Long writeoffReasonId; private final String writeoffReason; - public LoanSummaryData(final CurrencyData currency, final BigDecimal principalDisbursed, final BigDecimal principalPaid, - final BigDecimal principalWrittenOff, final BigDecimal principalOutstanding, final BigDecimal principalOverdue, - final BigDecimal interestCharged, final BigDecimal interestPaid, final BigDecimal interestWaived, - final BigDecimal interestWrittenOff, final BigDecimal interestOutstanding, final BigDecimal interestOverdue, - final BigDecimal feeChargesCharged, final BigDecimal feeChargesDueAtDisbursementCharged, final BigDecimal feeChargesPaid, - final BigDecimal feeChargesWaived, final BigDecimal feeChargesWrittenOff, final BigDecimal feeChargesOutstanding, - final BigDecimal feeChargesOverdue, final BigDecimal penaltyChargesCharged, final BigDecimal penaltyChargesPaid, - final BigDecimal penaltyChargesWaived, final BigDecimal penaltyChargesWrittenOff, final BigDecimal penaltyChargesOutstanding, - final BigDecimal penaltyChargesOverdue, final BigDecimal totalExpectedRepayment, final BigDecimal totalRepayment, - final BigDecimal totalExpectedCostOfLoan, final BigDecimal totalCostOfLoan, final BigDecimal totalWaived, - final BigDecimal totalWrittenOff, final BigDecimal totalOutstanding, final BigDecimal totalOverdue, - final LocalDate overdueSinceDate, final Long writeoffReasonId, final String writeoffReason, final BigDecimal totalRecovered) { + public LoanSummaryData(final CurrencyData currency, final BigDecimal principalDisbursed, final BigDecimal principalAdjustments, + final BigDecimal principalPaid, final BigDecimal principalWrittenOff, final BigDecimal principalOutstanding, + final BigDecimal principalOverdue, final BigDecimal interestCharged, final BigDecimal interestPaid, + final BigDecimal interestWaived, final BigDecimal interestWrittenOff, final BigDecimal interestOutstanding, + final BigDecimal interestOverdue, final BigDecimal feeChargesCharged, final BigDecimal feeChargesDueAtDisbursementCharged, + final BigDecimal feeChargesPaid, final BigDecimal feeChargesWaived, final BigDecimal feeChargesWrittenOff, + final BigDecimal feeChargesOutstanding, final BigDecimal feeChargesOverdue, final BigDecimal penaltyChargesCharged, + final BigDecimal penaltyChargesPaid, final BigDecimal penaltyChargesWaived, final BigDecimal penaltyChargesWrittenOff, + final BigDecimal penaltyChargesOutstanding, final BigDecimal penaltyChargesOverdue, final BigDecimal totalExpectedRepayment, + final BigDecimal totalRepayment, final BigDecimal totalExpectedCostOfLoan, final BigDecimal totalCostOfLoan, + final BigDecimal totalWaived, final BigDecimal totalWrittenOff, final BigDecimal totalOutstanding, + final BigDecimal totalOverdue, final LocalDate overdueSinceDate, final Long writeoffReasonId, final String writeoffReason, + final BigDecimal totalRecovered) { this.currency = currency; this.principalDisbursed = principalDisbursed; + this.principalAdjustments = principalAdjustments; this.principalPaid = principalPaid; this.principalWrittenOff = principalWrittenOff; this.principalOutstanding = principalOutstanding; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummary.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummary.java index 9eea2641d..902094070 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummary.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummary.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Set; import javax.persistence.Column; import javax.persistence.Embeddable; +import lombok.Getter; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -33,12 +34,16 @@ import org.apache.fineract.organisation.monetary.domain.Money; * */ @Embeddable +@Getter public final class LoanSummary { // derived totals fields @Column(name = "principal_disbursed_derived", scale = 6, precision = 19) private BigDecimal totalPrincipalDisbursed; + @Column(name = "principal_adjustments_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalAdjustments; + @Column(name = "principal_repaid_derived", scale = 6, precision = 19) private BigDecimal totalPrincipalRepaid; @@ -182,6 +187,7 @@ public final class LoanSummary { */ public void zeroFields() { this.totalPrincipalDisbursed = BigDecimal.ZERO; + this.totalPrincipalAdjustments = BigDecimal.ZERO; this.totalPrincipalRepaid = BigDecimal.ZERO; this.totalPrincipalWrittenOff = BigDecimal.ZERO; this.totalPrincipalOutstanding = BigDecimal.ZERO; @@ -214,11 +220,14 @@ public final class LoanSummary { final Boolean disbursed, Set charges) { this.totalPrincipalDisbursed = principal.getAmount(); + this.totalPrincipalAdjustments = summaryWrapper.calculateTotalPrincipalAdjusted(repaymentScheduleInstallments, currency) + .getAmount(); this.totalPrincipalRepaid = summaryWrapper.calculateTotalPrincipalRepaid(repaymentScheduleInstallments, currency).getAmount(); this.totalPrincipalWrittenOff = summaryWrapper.calculateTotalPrincipalWrittenOff(repaymentScheduleInstallments, currency) .getAmount(); - this.totalPrincipalOutstanding = principal.minus(this.totalPrincipalRepaid).minus(this.totalPrincipalWrittenOff).getAmount(); + this.totalPrincipalOutstanding = principal.plus(this.totalPrincipalAdjustments).minus(this.totalPrincipalRepaid) + .minus(this.totalPrincipalWrittenOff).getAmount(); final Money totalInterestCharged = summaryWrapper.calculateTotalInterestCharged(repaymentScheduleInstallments, currency); this.totalInterestCharged = totalInterestCharged.getAmount(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryWrapper.java index 437eead01..5bd79a814 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryWrapper.java @@ -35,7 +35,16 @@ public final class LoanSummaryWrapper { final MonetaryCurrency currency) { Money total = Money.zero(currency); for (final LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { - total = total.plus(installment.getPrincipalCompleted(currency)).minus(installment.getCredits(currency)); + total = total.plus(installment.getPrincipalCompleted(currency)); + } + return total; + } + + public Money calculateTotalPrincipalAdjusted(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (final LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getCredits(currency)); } return total; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 54d901578..a80bbde22 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -264,7 +264,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { * TODO Vishwas: Remove references to "Contra" from the codebase ***/ final String sql = "select " + rm.loanPaymentsSchema() + " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 3) " - + " and (tr.is_reversed=false or tr.manually_adjusted_or_reversed = true) " + " order by tr.transaction_date ASC,id "; + + " and (tr.is_reversed=false or tr.manually_adjusted_or_reversed = true) order by tr.transaction_date ASC,id "; Collection loanTransactionData = this.jdbcTemplate.query(sql, rm, loanId); // NOSONAR for (LoanTransactionData loanTransaction : loanTransactionData) { if (loanTransaction.getType().isRepaymentType()) { @@ -615,14 +615,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + sqlGenerator.escape("name") + " as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, " + " l.loan_officer_id as loanOfficerId, s.display_name as loanOfficerName, " - + " l.principal_disbursed_derived as principalDisbursed," + " l.principal_repaid_derived as principalPaid," - + " l.principal_writtenoff_derived as principalWrittenOff," - + " l.principal_outstanding_derived as principalOutstanding," + " l.interest_charged_derived as interestCharged," - + " l.interest_repaid_derived as interestPaid," + " l.interest_waived_derived as interestWaived," - + " l.interest_writtenoff_derived as interestWrittenOff," + " l.interest_outstanding_derived as interestOutstanding," + + " l.principal_disbursed_derived as principalDisbursed, l.principal_repaid_derived as principalPaid," + + " l.principal_adjustments_derived as principalAdjustments, l.principal_writtenoff_derived as principalWrittenOff," + + " l.principal_outstanding_derived as principalOutstanding, l.interest_charged_derived as interestCharged," + + " l.interest_repaid_derived as interestPaid, l.interest_waived_derived as interestWaived," + + " l.interest_writtenoff_derived as interestWrittenOff, l.interest_outstanding_derived as interestOutstanding," + " l.fee_charges_charged_derived as feeChargesCharged," + " l.total_charges_due_at_disbursement_derived as feeChargesDueAtDisbursementCharged," - + " l.fee_charges_repaid_derived as feeChargesPaid," + " l.fee_charges_waived_derived as feeChargesWaived," + + " l.fee_charges_repaid_derived as feeChargesPaid, l.fee_charges_waived_derived as feeChargesWaived," + " l.fee_charges_writtenoff_derived as feeChargesWrittenOff," + " l.fee_charges_outstanding_derived as feeChargesOutstanding," + " l.penalty_charges_charged_derived as penaltyChargesCharged," @@ -630,15 +630,15 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.penalty_charges_waived_derived as penaltyChargesWaived," + " l.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff," + " l.penalty_charges_outstanding_derived as penaltyChargesOutstanding," - + " l.total_expected_repayment_derived as totalExpectedRepayment," + " l.total_repayment_derived as totalRepayment," - + " l.total_expected_costofloan_derived as totalExpectedCostOfLoan," + " l.total_costofloan_derived as totalCostOfLoan," - + " l.total_waived_derived as totalWaived," + " l.total_writtenoff_derived as totalWrittenOff," - + " l.writeoff_reason_cv_id as writeoffReasonId," + " codev.code_value as writeoffReason," - + " l.total_outstanding_derived as totalOutstanding," + " l.total_overpaid_derived as totalOverpaid," - + " l.fixed_emi_amount as fixedEmiAmount," + " l.max_outstanding_loan_balance as outstandingLoanBalance," - + " l.loan_sub_status_id as loanSubStatusId," + " la.principal_overdue_derived as principalOverdue," - + " la.interest_overdue_derived as interestOverdue," + " la.fee_charges_overdue_derived as feeChargesOverdue," - + " la.penalty_charges_overdue_derived as penaltyChargesOverdue," + " la.total_overdue_derived as totalOverdue," + + " l.total_expected_repayment_derived as totalExpectedRepayment, l.total_repayment_derived as totalRepayment," + + " l.total_expected_costofloan_derived as totalExpectedCostOfLoan, l.total_costofloan_derived as totalCostOfLoan," + + " l.total_waived_derived as totalWaived, l.total_writtenoff_derived as totalWrittenOff," + + " l.writeoff_reason_cv_id as writeoffReasonId, codev.code_value as writeoffReason," + + " l.total_outstanding_derived as totalOutstanding, l.total_overpaid_derived as totalOverpaid," + + " l.fixed_emi_amount as fixedEmiAmount, l.max_outstanding_loan_balance as outstandingLoanBalance," + + " l.loan_sub_status_id as loanSubStatusId, la.principal_overdue_derived as principalOverdue," + + " la.interest_overdue_derived as interestOverdue, la.fee_charges_overdue_derived as feeChargesOverdue," + + " la.penalty_charges_overdue_derived as penaltyChargesOverdue, la.total_overdue_derived as totalOverdue," + " la.overdue_since_date_derived as overdueSinceDate," + " l.sync_disbursement_with_meeting as syncDisbursementWithMeeting," + " l.loan_counter as loanCounter, l.loan_product_counter as loanProductCounter," @@ -659,21 +659,21 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.interest_rate_differential as interestRateDifferential, " + " l.create_standing_instruction_at_disbursement as createStandingInstructionAtDisbursement, " + " lpvi.minimum_gap as minimuminstallmentgap, lpvi.maximum_gap as maximuminstallmentgap, " - + " lp.can_use_for_topup as canUseForTopup, " + " l.is_topup as isTopup, " + " topup.closure_loan_id as closureLoanId, " - + " l.total_recovered_derived as totalRecovered" + ", topuploan.account_no as closureLoanAccountNo, " - + " topup.topup_amount as topupAmount " + " from m_loan l" // + + " lp.can_use_for_topup as canUseForTopup, l.is_topup as isTopup, topup.closure_loan_id as closureLoanId, " + + " l.total_recovered_derived as totalRecovered, topuploan.account_no as closureLoanAccountNo, " + + " topup.topup_amount as topupAmount from m_loan l" // + " join m_product_loan lp on lp.id = l.product_id" // - + " left join m_loan_recalculation_details lir on lir.loan_id = l.id " + " join m_currency rc on rc." + + " left join m_loan_recalculation_details lir on lir.loan_id = l.id join m_currency rc on rc." + sqlGenerator.escape("code") + " = l.currency_code" // + " left join m_client c on c.id = l.client_id" // + " left join m_group g on g.id = l.group_id" // + " left join m_loan_arrears_aging la on la.loan_id = l.id" // + " left join m_fund f on f.id = l.fund_id" // + " left join m_staff s on s.id = l.loan_officer_id" // - + " left join m_appuser sbu on sbu.id = l.created_by" + " left join m_appuser rbu on rbu.id = l.rejectedon_userid" + + " left join m_appuser sbu on sbu.id = l.created_by left join m_appuser rbu on rbu.id = l.rejectedon_userid" + " left join m_appuser wbu on wbu.id = l.withdrawnon_userid" + " left join m_appuser abu on abu.id = l.approvedon_userid" - + " left join m_appuser dbu on dbu.id = l.disbursedon_userid" + " left join m_appuser cbu on cbu.id = l.closedon_userid" + + " left join m_appuser dbu on dbu.id = l.disbursedon_userid left join m_appuser cbu on cbu.id = l.closedon_userid" + " left join m_code_value cv on cv.id = l.loanpurpose_cv_id" + " left join m_code_value codev on codev.id = l.writeoff_reason_cv_id" + " left join ref_loan_transaction_processing_strategy lps on lps.id = l.loan_transaction_strategy_id" @@ -851,6 +851,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { // loan summary final BigDecimal principalDisbursed = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDisbursed"); + final BigDecimal principalAdjustments = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalAdjustments"); final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid"); final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff"); final BigDecimal principalOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalOutstanding"); @@ -892,14 +893,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { inArrears = true; } - loanSummary = new LoanSummaryData(currencyData, principalDisbursed, principalPaid, principalWrittenOff, - principalOutstanding, principalOverdue, interestCharged, interestPaid, interestWaived, interestWrittenOff, - interestOutstanding, interestOverdue, feeChargesCharged, feeChargesDueAtDisbursementCharged, feeChargesPaid, - feeChargesWaived, feeChargesWrittenOff, feeChargesOutstanding, feeChargesOverdue, penaltyChargesCharged, - penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, penaltyChargesOutstanding, - penaltyChargesOverdue, totalExpectedRepayment, totalRepayment, totalExpectedCostOfLoan, totalCostOfLoan, - totalWaived, totalWrittenOff, totalOutstanding, totalOverdue, overdueSinceDate, writeoffReasonId, writeoffReason, - totalRecovered); + loanSummary = new LoanSummaryData(currencyData, principalDisbursed, principalAdjustments, principalPaid, + principalWrittenOff, principalOutstanding, principalOverdue, interestCharged, interestPaid, interestWaived, + interestWrittenOff, interestOutstanding, interestOverdue, feeChargesCharged, feeChargesDueAtDisbursementCharged, + feeChargesPaid, feeChargesWaived, feeChargesWrittenOff, feeChargesOutstanding, feeChargesOverdue, + penaltyChargesCharged, penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, + penaltyChargesOutstanding, penaltyChargesOverdue, totalExpectedRepayment, totalRepayment, totalExpectedCostOfLoan, + totalCostOfLoan, totalWaived, totalWrittenOff, totalOutstanding, totalOverdue, overdueSinceDate, writeoffReasonId, + writeoffReason, totalRecovered); } GroupGeneralData groupData = null; @@ -1015,8 +1016,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " ls.fee_charges_amount as feeChargesDue, ls.fee_charges_completed_derived as feeChargesPaid, ls.fee_charges_waived_derived as feeChargesWaived, ls.fee_charges_writtenoff_derived as feeChargesWrittenOff, " + " ls.penalty_charges_amount as penaltyChargesDue, ls.penalty_charges_completed_derived as penaltyChargesPaid, ls.penalty_charges_waived_derived as penaltyChargesWaived, ls.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff, " + " ls.total_paid_in_advance_derived as totalPaidInAdvanceForPeriod, ls.total_paid_late_derived as totalPaidLateForPeriod, " - + " mc.amount,mc.id as chargeId " + " from m_loan_repayment_schedule ls " - + " inner join m_loan ml on ml.id = ls.loan_id " + + " mc.amount,mc.id as chargeId from m_loan_repayment_schedule ls " + " inner join m_loan ml on ml.id = ls.loan_id " + " join m_product_loan_charge plc on plc.product_loan_id = ml.product_id " + " join m_charge mc on mc.id = plc.charge_id "; @@ -1326,7 +1326,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " totran.description as toTransferDescription from m_loan l join m_loan_transaction tr on tr.loan_id = l.id " + " join m_currency rc on rc." + sqlGenerator.escape("code") + " = l.currency_code " + " left JOIN m_payment_detail pd ON tr.payment_detail_id = pd.id" - + " left join m_payment_type pt on pd.payment_type_id = pt.id" + " left join m_office office on office.id=tr.office_id" + + " left join m_payment_type pt on pd.payment_type_id = pt.id left join m_office office on office.id=tr.office_id" + " left join m_account_transfer_transaction fromtran on fromtran.from_loan_transaction_id = tr.id " + " left join m_account_transfer_transaction totran on totran.to_loan_transaction_id = tr.id "; } @@ -2067,7 +2067,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + ", tr.amount as total, tr.principal_portion_derived as principal, tr.interest_portion_derived as interest, " + " tr.fee_charges_portion_derived as fees, tr.penalty_charges_portion_derived as penalties, " + " tr.overpayment_portion_derived as overpayment, tr.outstanding_loan_balance_derived as outstandingLoanBalance, " - + " tr.unrecognized_income_portion as unrecognizedIncome " + " from m_loan_transaction tr "; + + " tr.unrecognized_income_portion as unrecognizedIncome from m_loan_transaction tr "; } @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResourceSwagger.java index 36c943c19..40fe21e89 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResourceSwagger.java @@ -357,6 +357,8 @@ final class SelfLoansApiResourceSwagger { public Double principalDisbursed; @Schema(example = "0.000000") public Double principalPaid; + @Schema(example = "0.00") + public Double principalAdjustments; @Schema(example = "0.000000") public Double principalWrittenOff; @Schema(example = "1000000.000000") diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 118402238..d4d072406 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -76,4 +76,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0057_add_principal_adjustments_to_loan.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0057_add_principal_adjustments_to_loan.xml new file mode 100644 index 000000000..63ae38916 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0057_add_principal_adjustments_to_loan.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java index aa031f3a1..ba4dc1cb3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java @@ -37,6 +37,7 @@ import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod; import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule; import org.apache.fineract.client.models.GetLoansLoanIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdSummary; import org.apache.fineract.client.models.GetLoansLoanIdTransactions; import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; import org.apache.fineract.client.models.GetPaymentTypesResponse; @@ -128,7 +129,8 @@ public class LoanTransactionChargebackTest { loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse); - Float amount = Float.valueOf("333.33"); + final String baseAmount = "333.33"; + Float amount = Float.valueOf(baseAmount); final LocalDate transactionDate = this.todaysDate.minusMonths(numberOfRepayments - 1).plusDays(3); String operationDate = Utils.dateFormatter.format(transactionDate); @@ -155,6 +157,8 @@ public class LoanTransactionChargebackTest { assertEquals(Double.valueOf("666.67"), period.getTotalDueForPeriod()); } } + + evaluateLoanSummaryAdjustments(getLoansLoanIdResponse, Double.valueOf(baseAmount)); } @Test @@ -377,6 +381,8 @@ public class LoanTransactionChargebackTest { getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("200.00")); + evaluateLoanSummaryAdjustments(getLoansLoanIdResponse, Double.valueOf("200.00")); + // Second round, array size equal to 1 reviewLoanTransactionRelations(loanId, transactionId, 1); @@ -385,6 +391,8 @@ public class LoanTransactionChargebackTest { getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("500.00")); + evaluateLoanSummaryAdjustments(getLoansLoanIdResponse, Double.valueOf("500.00")); + // Third round, array size equal to 2 reviewLoanTransactionRelations(loanId, transactionId, 2); @@ -392,6 +400,8 @@ public class LoanTransactionChargebackTest { getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("1000.00")); + + evaluateLoanSummaryAdjustments(getLoansLoanIdResponse, Double.valueOf("1000.00")); } private Integer createAccounts(final Integer daysToSubtract, final Integer numberOfRepayments) { @@ -464,4 +474,13 @@ public class LoanTransactionChargebackTest { log.info("Loan with {} Chargeback Transactions", getLoansTransactionResponse.getTransactionRelations().size()); } + private void evaluateLoanSummaryAdjustments(GetLoansLoanIdResponse getLoansLoanIdResponse, Double amountExpected) { + // Evaluate The Loan Summary Principal Adjustments + GetLoansLoanIdSummary getLoansLoanIdSummary = getLoansLoanIdResponse.getSummary(); + if (getLoansLoanIdSummary != null) { + log.info("Loan with Principal Adjustments {} expected {}", getLoansLoanIdSummary.getPrincipalAdjustments(), amountExpected); + assertEquals(amountExpected, getLoansLoanIdSummary.getPrincipalAdjustments()); + } + } + }