FINERACT-1958-Down-Payment-transaction-type

This commit is contained in:
Ruchi Dhamankar
2023-08-18 15:09:33 +02:00
committed by Adam Saghy
parent baa447196e
commit a4f9b167f2
13 changed files with 378 additions and 5 deletions
@@ -3646,4 +3646,12 @@ public class CommandWrapperBuilder {
this.href = "/external-asset-owners/transfers/" + id;
return this;
}
public CommandWrapperBuilder downPayment(final Long loanId) {
this.actionName = "DOWNPAYMENT";
this.entityName = "LOAN";
this.loanId = loanId;
this.href = "/loans/" + loanId + "/transactions?command=downPayment";
return this;
}
}
@@ -0,0 +1,35 @@
/**
* 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.infrastructure.event.business.domain.loan.transaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
public class LoanTransactionDownPaymentPostBusinessEvent extends LoanTransactionBusinessEvent {
private static final String TYPE = "LoanTransactionDownPaymentPostBusinessEvent";
public LoanTransactionDownPaymentPostBusinessEvent(LoanTransaction value) {
super(value);
}
@Override
public String getType() {
return TYPE;
}
}
@@ -0,0 +1,37 @@
/**
* 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.infrastructure.event.business.domain.loan.transaction;
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBusinessEvent;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
public class LoanTransactionDownPaymentPreBusinessEvent extends LoanBusinessEvent {
private static final String TYPE = "LoanTransactionDownPaymentPreBusinessEvent";
public LoanTransactionDownPaymentPreBusinessEvent(Loan value) {
super(value);
}
@Override
public String getType() {
return TYPE;
}
}
@@ -26,4 +26,5 @@
<include relativeToChangelogFile="true" file="parts/1001_add_audit_fields_to_loan_charge.xml"/>
<include relativeToChangelogFile="true" file="parts/1002_add_payment_allocation_rule.xml"/>
<include relativeToChangelogFile="true" file="parts/1003_add_loan_product_auto_repayment_down_payment_configuration.xml"/>
<include relativeToChangelogFile="true" file="parts/1004_add_external_event_configuration_for_down_payment_transaction_event.xml"/>
</databaseChangeLog>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="1">
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionDownPaymentPreBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
<insert tableName="m_external_event_configuration">
<column name="type" value="LoanTransactionDownPaymentPostBusinessEvent"/>
<column name="enabled" valueBoolean="false"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -80,6 +80,7 @@ public class LoanTransactionsApiResource {
public static final String CHARGE_OFF_COMMAND_VALUE = "charge-off";
public static final String UNDO_CHARGE_OFF_COMMAND_VALUE = "undo-charge-off";
public static final String DOWN_PAYMENT = "downPayment";
private final Set<String> responseDataParameters = new HashSet<>(Arrays.asList("id", "type", "date", "currency", "amount", "externalId",
LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME, LoanApiConstants.REVERSED_ON_DATE_PARAMNAME));
@@ -108,7 +109,7 @@ public class LoanTransactionsApiResource {
+ "loans/1/transactions/template?command=refundbycash" + "\n" + "loans/1/transactions/template?command=refundbytransfer" + "\n"
+ "loans/1/transactions/template?command=foreclosure" + "\n"
+ "loans/1/transactions/template?command=creditBalanceRefund (returned 'amount' field will have the overpaid value)" + "\n"
+ "loans/1/transactions/template?command=charge-off" + "\n")
+ "loans/1/transactions/template?command=charge-off" + "\n" + "loans/1/transactions/template?command=downPayment" + "\n")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTemplateResponse.class))) })
public String retrieveTransactionTemplate(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
@@ -137,7 +138,7 @@ public class LoanTransactionsApiResource {
+ "loans/1/transactions/template?command=refundbycash" + "\n" + "loans/1/transactions/template?command=refundbytransfer" + "\n"
+ "loans/1/transactions/template?command=foreclosure" + "\n"
+ "loans/1/transactions/template?command=creditBalanceRefund (returned 'amount' field will have the overpaid value)" + "\n"
+ "loans/1/transactions/template?command=charge-off" + "\n")
+ "loans/1/transactions/template?command=charge-off" + "\n" + "loans/1/transactions/template?command=downPayment" + "\n")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTemplateResponse.class))) })
public String retrieveTransactionTemplate(
@@ -235,7 +236,8 @@ public class LoanTransactionsApiResource {
+ "loans/1/transactions?command=refundByCash" + " | Make a Refund of an Active Loan by Cash | \n"
+ "loans/1/transactions?command=foreclosure" + " | Foreclosure of an Active Loan | \n"
+ "loans/1/transactions?command=creditBalanceRefund" + " | Credit Balance Refund" + " | \n"
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=charge-off" + " | Charge-off Loan" + " | \n")
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=charge-off" + " | Charge-off Loan" + " | \n"
+ "loans/1/transactions?command=downPayment" + " | Down Payment" + " | \n")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
@@ -269,6 +271,7 @@ public class LoanTransactionsApiResource {
+ " | Foreclosure of an Active Loan | \n"
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=creditBalanceRefund" + " | Credit Balance Refund"
+ " | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=charge-off" + " | Charge-off Loan"
+ " | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=downPayment" + " | Down Payment"
+ " | \n")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsRequest.class)))
@ApiResponses({
@@ -472,6 +475,8 @@ public class LoanTransactionsApiResource {
commandRequest = builder.chargeOff(resolvedLoanId).build();
} else if (CommandParameterUtil.is(commandParam, UNDO_CHARGE_OFF_COMMAND_VALUE)) {
commandRequest = builder.undoChargeOff(resolvedLoanId).build();
} else if (CommandParameterUtil.is(commandParam, DOWN_PAYMENT)) {
commandRequest = builder.downPayment(resolvedLoanId).build();
}
if (commandRequest == null) {
@@ -547,6 +552,8 @@ public class LoanTransactionsApiResource {
transactionData = this.loanReadPlatformService.retrieveCreditBalanceRefundTemplate(resolvedLoanId);
} else if (CommandParameterUtil.is(commandParam, CHARGE_OFF_COMMAND_VALUE)) {
transactionData = this.loanReadPlatformService.retrieveLoanChargeOffTemplate(resolvedLoanId);
} else if (CommandParameterUtil.is(commandParam, DOWN_PAYMENT)) {
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId);
} else {
throw new UnrecognizedQueryParamException("command", commandParam);
}
@@ -53,6 +53,8 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanRefundPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionDownPaymentPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionDownPaymentPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPostBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionGoodwillCreditPreBusinessEvent;
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionMakeRepaymentPostBusinessEvent;
@@ -289,6 +291,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
repaymentEvent = new LoanChargePaymentPreBusinessEvent(loan);
} else if (isRecoveryRepayment) {
repaymentEvent = new LoanTransactionRecoveryPaymentPreBusinessEvent(loan);
} else if (repaymentTransactionType.isDownPayment()) {
repaymentEvent = new LoanTransactionDownPaymentPreBusinessEvent(loan);
}
return repaymentEvent;
}
@@ -308,6 +312,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
repaymentEvent = new LoanChargePaymentPostBusinessEvent(transaction);
} else if (isRecoveryRepayment) {
repaymentEvent = new LoanTransactionRecoveryPaymentPostBusinessEvent(transaction);
} else if (repaymentTransactionType.isDownPayment()) {
repaymentEvent = new LoanTransactionDownPaymentPostBusinessEvent(transaction);
}
return repaymentEvent;
}
@@ -0,0 +1,53 @@
/**
* 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.handler;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.DataIntegrityErrorHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
@CommandType(entity = "LOAN", action = "DOWNPAYMENT")
public class LoanDownPaymentCommandHandler implements NewCommandSourceHandler {
private final LoanWritePlatformService writePlatformService;
private final DataIntegrityErrorHandler dataIntegrityErrorHandler;
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
try {
boolean isRecoveryRepayment = false;
return this.writePlatformService.makeLoanRepayment(LoanTransactionType.DOWN_PAYMENT, command.getLoanId(), command,
isRecoveryRepayment);
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
dataIntegrityErrorHandler.handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve, "loan.downPayment",
"Down Payment");
return CommandProcessingResult.empty();
}
}
}
@@ -96,7 +96,8 @@ public class ExternalEventConfigurationValidationServiceTest {
"LoanChargeAdjustmentPostBusinessEvent", "LoanChargeAdjustmentPreBusinessEvent", "LoanDelinquencyRangeChangeBusinessEvent",
"LoanAccountsStayedLockedBusinessEvent", "MockBusinessEvent", "LoanChargeOffPreBusinessEvent",
"LoanChargeOffPostBusinessEvent", "LoanUndoChargeOffBusinessEvent", "LoanAccrualTransactionCreatedBusinessEvent",
"LoanRescheduledDueAdjustScheduleBusinessEvent", "LoanOwnershipTransferBusinessEvent", "LoanAccountSnapshotBusinessEvent");
"LoanRescheduledDueAdjustScheduleBusinessEvent", "LoanOwnershipTransferBusinessEvent", "LoanAccountSnapshotBusinessEvent",
"LoanTransactionDownPaymentPostBusinessEvent", "LoanTransactionDownPaymentPreBusinessEvent");
List<FineractPlatformTenant> tenants = Arrays
.asList(new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null));
@@ -174,7 +175,8 @@ public class ExternalEventConfigurationValidationServiceTest {
"LoanChargeAdjustmentPostBusinessEvent", "LoanChargeAdjustmentPreBusinessEvent", "LoanDelinquencyRangeChangeBusinessEvent",
"LoanAccountsStayedLockedBusinessEvent", "LoanChargeOffPreBusinessEvent", "LoanChargeOffPostBusinessEvent",
"LoanUndoChargeOffBusinessEvent", "LoanAccrualTransactionCreatedBusinessEvent",
"LoanRescheduledDueAdjustScheduleBusinessEvent", "LoanOwnershipTransferBusinessEvent", "LoanAccountSnapshotBusinessEvent");
"LoanRescheduledDueAdjustScheduleBusinessEvent", "LoanOwnershipTransferBusinessEvent", "LoanAccountSnapshotBusinessEvent",
"LoanTransactionDownPaymentPostBusinessEvent", "LoanTransactionDownPaymentPreBusinessEvent");
List<FineractPlatformTenant> tenants = Arrays
.asList(new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null));
@@ -0,0 +1,171 @@
/**
* 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 static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.HashMap;
import java.util.UUID;
import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(LoanTestLifecycleExtension.class)
public class LoanDownPaymentTransactionTypeTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
private ClientHelper clientHelper;
@BeforeEach
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
}
@Test
public void loanDownPaymentTransactionTypeTest() {
DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
String loanExternalIdStr = UUID.randomUUID().toString();
// Delinquency Bucket
final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
delinquencyBucketId);
// client creation
final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
// Loan Product
GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, delinquencyBucketId);
assertNotNull(getLoanProductsProductResponse);
final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr);
// make down payment for loan
final PostLoansLoanIdTransactionsResponse downPaymentTransaction_1 = loanTransactionHelper.makeLoanDownPayment(loanExternalIdStr,
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("5 September 2022").locale("en")
.transactionAmount(100.0));
assertNotNull(downPaymentTransaction_1);
// verify details for down payment transaction
GetLoansLoanIdTransactionsTransactionIdResponse loanDownPaymentTransaction = loanTransactionHelper.getLoanTransaction(loanId,
downPaymentTransaction_1.getResourceId().intValue());
assertNotNull(loanDownPaymentTransaction);
assertEquals(loanDownPaymentTransaction.getAmount(), 100.0);
assertEquals(loanDownPaymentTransaction.getPrincipalPortion(), 100.0);
assertEquals("loanTransactionType.downPayment", loanDownPaymentTransaction.getType().getCode());
// undo/adjust down payment
LocalDate adjustmentDate = LocalDate.of(2022, 9, 7);
String formattedDate = dateFormatter.format(adjustmentDate);
PostLoansLoanIdTransactionsResponse adjustmentResult = loanTransactionHelper.reverseLoanTransaction(loanExternalIdStr,
loanDownPaymentTransaction.getId(), new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate)
.locale("en").dateFormat("dd MMMM yyyy").transactionAmount(0.0));
assertNotNull(adjustmentResult);
assertEquals(loanDownPaymentTransaction.getId(), adjustmentResult.getResourceId());
// Down Payment Transaction with External Id Test
// make downpayment with transaction external Id
String downPaymentExternalIdStr = UUID.randomUUID().toString();
final PostLoansLoanIdTransactionsResponse downPaymentTransaction_2 = loanTransactionHelper.makeLoanDownPayment(loanId.longValue(),
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("9 September 2022").locale("en")
.transactionAmount(200.0).externalId(downPaymentExternalIdStr));
assertNotNull(downPaymentTransaction_2);
assertEquals(downPaymentExternalIdStr, downPaymentTransaction_2.getResourceExternalId());
// verify details for down payment transaction
GetLoansLoanIdTransactionsTransactionIdResponse loanDownPaymentTransaction_1 = loanTransactionHelper.getLoanTransaction(loanId,
downPaymentTransaction_2.getResourceId().intValue());
assertNotNull(loanDownPaymentTransaction_1);
assertEquals(loanDownPaymentTransaction_1.getAmount(), 200.0);
assertEquals(loanDownPaymentTransaction_1.getPrincipalPortion(), 200.0);
assertEquals("loanTransactionType.downPayment", loanDownPaymentTransaction_1.getType().getCode());
// undo/adjust down payment
adjustmentDate = LocalDate.of(2022, 9, 12);
formattedDate = dateFormatter.format(adjustmentDate);
PostLoansLoanIdTransactionsResponse adjustmentResult_1 = loanTransactionHelper.reverseLoanTransaction(loanExternalIdStr,
downPaymentExternalIdStr, new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate).locale("en")
.dateFormat("dd MMMM yyyy").transactionAmount(0.0));
assertNotNull(adjustmentResult_1);
assertEquals(loanDownPaymentTransaction_1.getId(), adjustmentResult_1.getResourceId());
assertEquals(downPaymentExternalIdStr, adjustmentResult_1.getResourceExternalId());
}
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) {
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId);
}
private Integer createLoanAccount(final Integer clientID, final Long loanProductID, final String externalId) {
String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance()
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
.withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
.withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null);
final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON);
loanTransactionHelper.approveLoan("02 September 2022", "1000", loanId, null);
loanTransactionHelper.disburseLoanWithNetDisbursalAmount("03 September 2022", loanId, "1000");
return loanId;
}
}
@@ -480,6 +480,16 @@ public class ExternalEventConfigurationHelper {
loanAccountSnapshotBusinessEvent.put("enabled", false);
defaults.add(loanAccountSnapshotBusinessEvent);
Map<String, Object> loanTransactionDownPaymentPreBusinessEvent = new HashMap<>();
loanTransactionDownPaymentPreBusinessEvent.put("type", "LoanTransactionDownPaymentPreBusinessEvent");
loanTransactionDownPaymentPreBusinessEvent.put("enabled", false);
defaults.add(loanTransactionDownPaymentPreBusinessEvent);
Map<String, Object> loanTransactionDownPaymentPostBusinessEvent = new HashMap<>();
loanTransactionDownPaymentPostBusinessEvent.put("type", "LoanTransactionDownPaymentPostBusinessEvent");
loanTransactionDownPaymentPostBusinessEvent.put("enabled", false);
defaults.add(loanTransactionDownPaymentPostBusinessEvent);
return defaults;
}
@@ -1897,4 +1897,12 @@ public class LoanTransactionHelper extends IntegrationTest {
public PutLoanProductsProductIdResponse updateLoanProduct(Long id, PutLoanProductsProductIdRequest requestModifyLoan) {
return ok(fineract().loanProducts.updateLoanProduct(id, requestModifyLoan));
}
public PostLoansLoanIdTransactionsResponse makeLoanDownPayment(String loanExternalId, PostLoansLoanIdTransactionsRequest request) {
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "downPayment"));
}
public PostLoansLoanIdTransactionsResponse makeLoanDownPayment(Long loanId, PostLoansLoanIdTransactionsRequest request) {
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "downPayment"));
}
}