FINERACT-2148: return loan charge off behaviour with loan details

This commit is contained in:
adam.magyari
2024-11-29 12:24:23 +01:00
committed by Adam Saghy
parent 4cb849fa17
commit ff5e993b16
4 changed files with 83 additions and 4 deletions
@@ -24,6 +24,7 @@ import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiResourceSwagger.GetDelinquencyRangesResponse; import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiResourceSwagger.GetDelinquencyRangesResponse;
/** /**
@@ -1202,6 +1203,7 @@ final class LoansApiResourceSwagger {
public List<GetLoansLoanIdLoanTermVariations> emiAmountVariations; public List<GetLoansLoanIdLoanTermVariations> emiAmountVariations;
@Schema(description = "List of GetLoansLoanIdLoanTermVariations") @Schema(description = "List of GetLoansLoanIdLoanTermVariations")
public List<GetLoansLoanIdLoanTermVariations> loanTermVariations; public List<GetLoansLoanIdLoanTermVariations> loanTermVariations;
public StringEnumOptionData chargeOffBehaviour;
} }
@Schema(description = "GetLoansResponse") @Schema(description = "GetLoansResponse")
@@ -33,6 +33,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.monetary.data.CurrencyData;
@@ -269,6 +270,8 @@ public class LoanAccountData {
private EnumOptionData loanScheduleType; private EnumOptionData loanScheduleType;
private EnumOptionData loanScheduleProcessingType; private EnumOptionData loanScheduleProcessingType;
private StringEnumOptionData chargeOffBehaviour;
public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId, public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId,
Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments, Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments,
Integer repaymentEvery, EnumOptionData repaidEveryFrequencyEnums, Integer loanTermFrequency, Integer repaymentEvery, EnumOptionData repaidEveryFrequencyEnums, Integer loanTermFrequency,
@@ -453,7 +456,7 @@ public class LoanAccountData {
LocalDate lastClosedBusinessDate, LocalDate overpaidOnDate, final boolean chargedOff, final boolean enableDownPayment, LocalDate lastClosedBusinessDate, LocalDate overpaidOnDate, final boolean chargedOff, final boolean enableDownPayment,
final BigDecimal disbursedAmountPercentageForDownPayment, final boolean enableAutoRepaymentForDownPayment, final BigDecimal disbursedAmountPercentageForDownPayment, final boolean enableAutoRepaymentForDownPayment,
final boolean enableInstallmentLevelDelinquency, final EnumOptionData loanScheduleType, final boolean enableInstallmentLevelDelinquency, final EnumOptionData loanScheduleType,
final EnumOptionData loanScheduleProcessingType, final Integer fixedLength) { final EnumOptionData loanScheduleProcessingType, final Integer fixedLength, final StringEnumOptionData chargeOffBehaviour) {
final CollectionData delinquent = CollectionData.template(); final CollectionData delinquent = CollectionData.template();
@@ -497,7 +500,8 @@ public class LoanAccountData {
.setEnableDownPayment(enableDownPayment).setDisbursedAmountPercentageForDownPayment(disbursedAmountPercentageForDownPayment) .setEnableDownPayment(enableDownPayment).setDisbursedAmountPercentageForDownPayment(disbursedAmountPercentageForDownPayment)
.setEnableAutoRepaymentForDownPayment(enableAutoRepaymentForDownPayment) .setEnableAutoRepaymentForDownPayment(enableAutoRepaymentForDownPayment)
.setEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency).setLoanScheduleType(loanScheduleType) .setEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency).setLoanScheduleType(loanScheduleType)
.setLoanScheduleProcessingType(loanScheduleProcessingType).setFixedLength(fixedLength); .setLoanScheduleProcessingType(loanScheduleProcessingType).setFixedLength(fixedLength)
.setChargeOffBehaviour(chargeOffBehaviour);
} }
/* /*
@@ -107,6 +107,7 @@ import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
@@ -703,7 +704,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
+ " l.total_recovered_derived as totalRecovered, topuploan.account_no as closureLoanAccountNo, " + " l.total_recovered_derived as totalRecovered, topuploan.account_no as closureLoanAccountNo, "
+ " topup.topup_amount as topupAmount, l.last_closed_business_date as lastClosedBusinessDate,l.overpaidon_date as overpaidOnDate, " + " topup.topup_amount as topupAmount, l.last_closed_business_date as lastClosedBusinessDate,l.overpaidon_date as overpaidOnDate, "
+ " l.is_charged_off as isChargedOff, l.charge_off_reason_cv_id as chargeOffReasonId, codec.code_value as chargeOffReason, l.charged_off_on_date as chargedOffOnDate, l.enable_down_payment as enableDownPayment, l.disbursed_amount_percentage_for_down_payment as disbursedAmountPercentageForDownPayment, l.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment," + " l.is_charged_off as isChargedOff, l.charge_off_reason_cv_id as chargeOffReasonId, codec.code_value as chargeOffReason, l.charged_off_on_date as chargedOffOnDate, l.enable_down_payment as enableDownPayment, l.disbursed_amount_percentage_for_down_payment as disbursedAmountPercentageForDownPayment, l.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment,"
+ " cobu.username as chargedOffByUsername, cobu.firstname as chargedOffByFirstname, cobu.lastname as chargedOffByLastname, l.loan_schedule_type as loanScheduleType, l.loan_schedule_processing_type as loanScheduleProcessingType " + " cobu.username as chargedOffByUsername, cobu.firstname as chargedOffByFirstname, cobu.lastname as chargedOffByLastname, l.loan_schedule_type as loanScheduleType, l.loan_schedule_processing_type as loanScheduleProcessingType, "
+ " l.charge_off_behaviour as chargeOffBehaviour " //
+ " from m_loan l" // + " from m_loan l" //
+ " join m_product_loan lp on lp.id = l.product_id" // + " 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."
@@ -1068,6 +1070,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final String loanScheduleProcessingTypeStr = rs.getString("loanScheduleProcessingType"); final String loanScheduleProcessingTypeStr = rs.getString("loanScheduleProcessingType");
final LoanScheduleProcessingType loanScheduleProcessingType = LoanScheduleProcessingType.valueOf(loanScheduleProcessingTypeStr); final LoanScheduleProcessingType loanScheduleProcessingType = LoanScheduleProcessingType.valueOf(loanScheduleProcessingTypeStr);
final Integer fixedLength = JdbcSupport.getInteger(rs, "fixedLength"); final Integer fixedLength = JdbcSupport.getInteger(rs, "fixedLength");
final LoanChargeOffBehaviour chargeOffBehaviour = LoanChargeOffBehaviour.valueOf(rs.getString("chargeOffBehaviour"));
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientAccountNo, clientName,
clientOfficeId, clientExternalId, groupData, loanType, loanProductId, loanProductName, loanProductDescription, clientOfficeId, clientExternalId, groupData, loanType, loanProductId, loanProductName, loanProductDescription,
@@ -1086,7 +1089,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
fixedPrincipalPercentagePerInstallment, delinquencyRange, disallowExpectedDisbursements, isFraud, fixedPrincipalPercentagePerInstallment, delinquencyRange, disallowExpectedDisbursements, isFraud,
lastClosedBusinessDate, overpaidOnDate, isChargedOff, enableDownPayment, disbursedAmountPercentageForDownPayment, lastClosedBusinessDate, overpaidOnDate, isChargedOff, enableDownPayment, disbursedAmountPercentageForDownPayment,
enableAutoRepaymentForDownPayment, enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(), enableAutoRepaymentForDownPayment, enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(),
loanScheduleProcessingType.asEnumOptionData(), fixedLength); loanScheduleProcessingType.asEnumOptionData(), fixedLength, chargeOffBehaviour.getValueAsStringEnumOptionData());
} }
} }
@@ -0,0 +1,70 @@
/**
* 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.integrationtests;
import java.math.BigDecimal;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class LoanProductWithChargeOffBehaviourTest extends BaseLoanIntegrationTest {
private Long clientId;
private Long loanProductId;
private Long loanId;
// create client, progressive loan product with charge-off behaviour REGULAR (default), loan with disburse limit
// 1000 for the client,
// and disburse 250 on 01 June 2024
@BeforeEach
public void beforeEach() {
runAt("01 June 2024", () -> {
clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
final PostLoanProductsResponse loanProductsResponse = loanProductHelper.createLoanProduct(create4IProgressive());
loanProductId = loanProductsResponse.getResourceId();
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(
applyLP2ProgressiveLoanRequest(clientId, loanProductsResponse.getResourceId(), "01 June 2024", 1000.0, 10.0, 4, null));
loanId = postLoansResponse.getLoanId();
loanTransactionHelper.approveLoan(loanId, approveLoanRequest(1000.0, "01 June 2024"));
disburseLoan(loanId, BigDecimal.valueOf(250.0), "01 June 2024");
});
}
@Test
public void testSavedToLoanNotChangingWithProduct() {
runAt("01 June 2024", () -> {
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertEquals("REGULAR", loanDetails.getChargeOffBehaviour().getId());
loanProductHelper.updateLoanProductById(loanProductId,
new PutLoanProductsProductIdRequest().chargeOffBehaviour("ZERO_INTEREST"));
final GetLoanProductsProductIdResponse loanProduct = loanTransactionHelper.getLoanProduct(loanProductId.intValue());
Assertions.assertEquals("ZERO_INTEREST", loanProduct.getChargeOffBehaviour().getId());
loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertEquals("REGULAR", loanDetails.getChargeOffBehaviour().getId());
});
}
}