FINERACT-2311: Buy Down fees - External business events
This commit is contained in:
+3
-3
@@ -20,11 +20,11 @@ package org.apache.fineract.infrastructure.event.business.domain.loan.transactio
|
|||||||
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
|
||||||
public class LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent extends LoanTransactionBusinessEvent {
|
public class LoanBuyDownFeeAdjustmentTransactionBusinessEvent extends LoanTransactionBusinessEvent {
|
||||||
|
|
||||||
private static final String TYPE = "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent";
|
private static final String TYPE = "LoanBuyDownFeeAdjustmentTransactionBusinessEvent";
|
||||||
|
|
||||||
public LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent(LoanTransaction value) {
|
public LoanBuyDownFeeAdjustmentTransactionBusinessEvent(LoanTransaction value) {
|
||||||
super(value);
|
super(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-3
@@ -20,11 +20,11 @@ package org.apache.fineract.infrastructure.event.business.domain.loan.transactio
|
|||||||
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
|
||||||
public class LoanBuyDownFeeTransactionCreatedBusinessEvent extends LoanTransactionBusinessEvent {
|
public class LoanBuyDownFeeTransactionBusinessEvent extends LoanTransactionBusinessEvent {
|
||||||
|
|
||||||
private static final String TYPE = "LoanBuyDownFeeTransactionCreatedBusinessEvent";
|
private static final String TYPE = "LoanBuyDownFeeTransactionBusinessEvent";
|
||||||
|
|
||||||
public LoanBuyDownFeeTransactionCreatedBusinessEvent(LoanTransaction value) {
|
public LoanBuyDownFeeTransactionBusinessEvent(LoanTransaction value) {
|
||||||
super(value);
|
super(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-7
@@ -36,9 +36,8 @@ import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRu
|
|||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAdjustmentTransactionBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeTransactionBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeTransactionCreatedBusinessEvent;
|
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.client.domain.Client;
|
import org.apache.fineract.portfolio.client.domain.Client;
|
||||||
@@ -125,8 +124,7 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
|||||||
loanJournalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
loanJournalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
// Notify business events
|
// Notify business events
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBuyDownFeeTransactionCreatedBusinessEvent(buyDownFeeTransaction));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanBuyDownFeeTransactionBusinessEvent(buyDownFeeTransaction));
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withClientId(loan.getClientId()) //
|
.withClientId(loan.getClientId()) //
|
||||||
@@ -205,8 +203,7 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
|||||||
|
|
||||||
// Notify business events
|
// Notify business events
|
||||||
businessEventNotifierService
|
businessEventNotifierService
|
||||||
.notifyPostBusinessEvent(new LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent(savedBuyDownFeeAdjustment));
|
.notifyPostBusinessEvent(new LoanBuyDownFeeAdjustmentTransactionBusinessEvent(savedBuyDownFeeAdjustment));
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder().withEntityId(savedBuyDownFeeAdjustment.getId())
|
return new CommandProcessingResultBuilder().withEntityId(savedBuyDownFeeAdjustment.getId())
|
||||||
.withEntityExternalId(savedBuyDownFeeAdjustment.getExternalId()).withOfficeId(loan.getOfficeId())
|
.withEntityExternalId(savedBuyDownFeeAdjustment.getExternalId()).withOfficeId(loan.getOfficeId())
|
||||||
|
|||||||
+9
@@ -37,6 +37,9 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
|||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAdjustmentTransactionBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent;
|
||||||
|
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanBuyDownFeeTransactionBusinessEvent;
|
||||||
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
@@ -321,7 +324,11 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
|||||||
if (optAmortizationAdjustmentTransaction.isPresent()) {
|
if (optAmortizationAdjustmentTransaction.isPresent()) {
|
||||||
loan.addLoanTransaction(optAmortizationAdjustmentTransaction.get());
|
loan.addLoanTransaction(optAmortizationAdjustmentTransaction.get());
|
||||||
loanTransactionRepository.saveAndFlush(optAmortizationAdjustmentTransaction.get());
|
loanTransactionRepository.saveAndFlush(optAmortizationAdjustmentTransaction.get());
|
||||||
|
businessEventNotifierService
|
||||||
|
.notifyPostBusinessEvent(new LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent(
|
||||||
|
optAmortizationAdjustmentTransaction.get()));
|
||||||
}
|
}
|
||||||
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanBuyDownFeeTransactionBusinessEvent(transactionForAdjustment));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loan.isClosedWrittenOff()) {
|
if (loan.isClosedWrittenOff()) {
|
||||||
@@ -355,6 +362,8 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
|
|||||||
MathUtil.nullToZero(buyDownFeeBalance.getUnrecognizedAmount()).add(transactionForAdjustment.getAmount()));
|
MathUtil.nullToZero(buyDownFeeBalance.getUnrecognizedAmount()).add(transactionForAdjustment.getAmount()));
|
||||||
loanBuyDownFeeBalanceRepository.save(buyDownFeeBalance);
|
loanBuyDownFeeBalanceRepository.save(buyDownFeeBalance);
|
||||||
}
|
}
|
||||||
|
businessEventNotifierService
|
||||||
|
.notifyPostBusinessEvent(new LoanBuyDownFeeAdjustmentTransactionBusinessEvent(transactionForAdjustment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -211,4 +211,5 @@
|
|||||||
<include file="parts/0190_buy_down_fee_amortization.xml" relativeToChangelogFile="true" />
|
<include file="parts/0190_buy_down_fee_amortization.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0191_add_LoanApprovedAmountChangedBusinessEvent.xml" relativeToChangelogFile="true" />
|
<include file="parts/0191_add_LoanApprovedAmountChangedBusinessEvent.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0192_create_loan_approved_amount_history.xml" relativeToChangelogFile="true" />
|
<include file="parts/0192_create_loan_approved_amount_history.xml" relativeToChangelogFile="true" />
|
||||||
|
<include file="parts/0193_buy_down_fee_events.xml" relativeToChangelogFile="true" />
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+35
@@ -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.3.xsd">
|
||||||
|
<changeSet id="4" author="fineract">
|
||||||
|
<update tableName="m_external_event_configuration">
|
||||||
|
<column name="type" value="LoanBuyDownFeeTransactionBusinessEvent"/>
|
||||||
|
<where>type='LoanBuyDownFeeTransactionCreatedBusinessEvent'</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="m_external_event_configuration">
|
||||||
|
<column name="type" value="LoanBuyDownFeeAdjustmentTransactionBusinessEvent"/>
|
||||||
|
<where>type='LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent'</where>
|
||||||
|
</update>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+2
-2
@@ -110,7 +110,7 @@ public class ExternalEventConfigurationValidationServiceTest {
|
|||||||
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
||||||
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent",
|
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent",
|
||||||
"LoanBuyDownFeeTransactionCreatedBusinessEvent", "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent",
|
"LoanBuyDownFeeTransactionBusinessEvent", "LoanBuyDownFeeAdjustmentTransactionBusinessEvent",
|
||||||
"LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
"LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
||||||
"LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "LoanApprovedAmountChangedBusinessEvent");
|
"LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "LoanApprovedAmountChangedBusinessEvent");
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ public class ExternalEventConfigurationValidationServiceTest {
|
|||||||
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
"LoanCapitalizedIncomeAdjustmentTransactionCreatedBusinessEvent", "LoanTransactionContractTerminationPostBusinessEvent",
|
||||||
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
"LoanCapitalizedIncomeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||||
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent",
|
"LoanCapitalizedIncomeTransactionCreatedBusinessEvent", "LoanUndoContractTerminationBusinessEvent",
|
||||||
"LoanBuyDownFeeTransactionCreatedBusinessEvent", "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent",
|
"LoanBuyDownFeeTransactionBusinessEvent", "LoanBuyDownFeeAdjustmentTransactionBusinessEvent",
|
||||||
"LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
"LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
||||||
"LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "LoanApprovedAmountChangedBusinessEvent");
|
"LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "LoanApprovedAmountChangedBusinessEvent");
|
||||||
|
|
||||||
|
|||||||
+14
-9
@@ -1481,16 +1481,21 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
|
|||||||
|
|
||||||
protected void logBusinessEvents(List<ExternalEventResponse> allExternalEvents) {
|
protected void logBusinessEvents(List<ExternalEventResponse> allExternalEvents) {
|
||||||
allExternalEvents.forEach(externalEventDTO -> {
|
allExternalEvents.forEach(externalEventDTO -> {
|
||||||
Object amount = externalEventDTO.getPayLoad().get("amount");
|
|
||||||
Object outstandingLoanBalance = externalEventDTO.getPayLoad().get("outstandingLoanBalance");
|
|
||||||
Object principalPortion = externalEventDTO.getPayLoad().get("principalPortion");
|
|
||||||
Object interestPortion = externalEventDTO.getPayLoad().get("interestPortion");
|
|
||||||
Object feePortion = externalEventDTO.getPayLoad().get("feeChargesPortion");
|
|
||||||
Object penaltyPortion = externalEventDTO.getPayLoad().get("penaltyChargesPortion");
|
|
||||||
log.info("Event Received\n type:'{}'\n businessDate:'{}'", externalEventDTO.getType(), externalEventDTO.getBusinessDate());
|
log.info("Event Received\n type:'{}'\n businessDate:'{}'", externalEventDTO.getType(), externalEventDTO.getBusinessDate());
|
||||||
log.info(
|
if ("org.apache.fineract.avro.loan.v1.LoanTransactionDataV1".equals(externalEventDTO.getSchema())) {
|
||||||
"Values\n amount: {}\n outstandingLoanBalance: {}\n principalPortion: {}\n interestPortion: {}\n feePortion: {}\n penaltyPortion: {}",
|
Object amount = externalEventDTO.getPayLoad().get("amount");
|
||||||
amount, outstandingLoanBalance, principalPortion, interestPortion, feePortion, penaltyPortion);
|
Object outstandingLoanBalance = externalEventDTO.getPayLoad().get("outstandingLoanBalance");
|
||||||
|
Object principalPortion = externalEventDTO.getPayLoad().get("principalPortion");
|
||||||
|
Object interestPortion = externalEventDTO.getPayLoad().get("interestPortion");
|
||||||
|
Object feePortion = externalEventDTO.getPayLoad().get("feeChargesPortion");
|
||||||
|
Object penaltyPortion = externalEventDTO.getPayLoad().get("penaltyChargesPortion");
|
||||||
|
Object reversed = externalEventDTO.getPayLoad().get("reversed");
|
||||||
|
log.info(
|
||||||
|
"Values\n amount: {}\n outstandingLoanBalance: {}\n principalPortion: {}\n interestPortion: {}\n feePortion: {}\n penaltyPortion: {}\n reversed: {}",
|
||||||
|
amount, outstandingLoanBalance, principalPortion, interestPortion, feePortion, penaltyPortion, reversed);
|
||||||
|
} else {
|
||||||
|
log.info("Schema: {}", externalEventDTO.getSchema());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+180
-13
@@ -47,17 +47,18 @@ import org.apache.fineract.integrationtests.common.BusinessStepHelper;
|
|||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
import org.apache.fineract.integrationtests.common.accounting.Account;
|
import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||||
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
|
import org.apache.fineract.integrationtests.common.externalevents.BusinessEvent;
|
||||||
|
import org.apache.fineract.integrationtests.common.externalevents.ExternalEventHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.externalevents.LoanTransactionMinimalBusinessEvent;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for Buy Down Fee functionality in Progressive Loans
|
* Integration tests for Buy Down Fee functionality in Progressive Loans
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ExtendWith({ LoanTestLifecycleExtension.class })
|
|
||||||
public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
||||||
|
|
||||||
private Long clientId;
|
private Long clientId;
|
||||||
@@ -72,8 +73,21 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
private final Account feeReceivableAccount = accountHelper.createAssetAccount();
|
private final Account feeReceivableAccount = accountHelper.createAssetAccount();
|
||||||
private final Account penaltyReceivableAccount = accountHelper.createAssetAccount();
|
private final Account penaltyReceivableAccount = accountHelper.createAssetAccount();
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void teardown() {
|
||||||
|
ExternalEventHelper externalEventHelper = new ExternalEventHelper();
|
||||||
|
externalEventHelper.disableBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent");
|
||||||
|
externalEventHelper.disableBusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent");
|
||||||
|
externalEventHelper.disableBusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent");
|
||||||
|
externalEventHelper.disableBusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent");
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeEach() {
|
public void beforeEach() {
|
||||||
|
externalEventHelper.enableBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent");
|
||||||
|
externalEventHelper.enableBusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent");
|
||||||
|
externalEventHelper.enableBusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent");
|
||||||
|
externalEventHelper.enableBusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent");
|
||||||
runAt("01 September 2024", () -> {
|
runAt("01 September 2024", () -> {
|
||||||
clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
|
clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
|
||||||
final PostLoanProductsResponse loanProductsResponse = loanProductHelper
|
final PostLoanProductsResponse loanProductsResponse = loanProductHelper
|
||||||
@@ -96,8 +110,10 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
assertNotNull(loanDetailsBeforeTransaction);
|
assertNotNull(loanDetailsBeforeTransaction);
|
||||||
log.info("Loan Product: {}", loanDetailsBeforeTransaction.getLoanProductName());
|
log.info("Loan Product: {}", loanDetailsBeforeTransaction.getLoanProductName());
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
// Create buy down fee transaction
|
// Create buy down fee transaction
|
||||||
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 500.0, "02 September 2024");
|
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 500.0, "02 September 2024");
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "02 September 2024"));
|
||||||
|
|
||||||
assertNotNull(buyDownFeeTransactionId);
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
|
||||||
@@ -126,11 +142,14 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
String externalId = UUID.randomUUID().toString();
|
String externalId = UUID.randomUUID().toString();
|
||||||
String noteText = "Buy Down Fee - Test Note";
|
String noteText = "Buy Down Fee - Test Note";
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
PostLoansLoanIdTransactionsResponse response = loanTransactionHelper.makeLoanBuyDownFee(loanId,
|
PostLoansLoanIdTransactionsResponse response = loanTransactionHelper.makeLoanBuyDownFee(loanId,
|
||||||
new PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN).transactionDate("03 September 2024").locale("en")
|
new PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN).transactionDate("03 September 2024").locale("en")
|
||||||
.transactionAmount(250.0).externalId(externalId).note(noteText));
|
.transactionAmount(250.0).externalId(externalId).note(noteText));
|
||||||
|
|
||||||
assertNotNull(response.getResourceId());
|
assertNotNull(response.getResourceId());
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "03 September 2024"));
|
||||||
|
|
||||||
// Verify transaction details
|
// Verify transaction details
|
||||||
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
||||||
@@ -147,11 +166,17 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMultipleBuyDownFees() {
|
public void testMultipleBuyDownFees() {
|
||||||
runAt("04 September 2024", () -> {
|
runAt("04 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// Add first buy down fee
|
// Add first buy down fee
|
||||||
Long firstBuyDownFeeId = addBuyDownFeeForLoan(loanId, 200.0, "04 September 2024");
|
Long firstBuyDownFeeId = addBuyDownFeeForLoan(loanId, 200.0, "02 September 2024");
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "04 September 2024"));
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// Add second buy down fee
|
// Add second buy down fee
|
||||||
Long secondBuyDownFeeId = addBuyDownFeeForLoan(loanId, 150.0, "04 September 2024");
|
Long secondBuyDownFeeId = addBuyDownFeeForLoan(loanId, 150.0, "04 September 2024");
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "04 September 2024"));
|
||||||
|
|
||||||
assertNotNull(firstBuyDownFeeId);
|
assertNotNull(firstBuyDownFeeId);
|
||||||
assertNotNull(secondBuyDownFeeId);
|
assertNotNull(secondBuyDownFeeId);
|
||||||
@@ -258,14 +283,21 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testBuyDownFeeAdjustment() {
|
public void testBuyDownFeeAdjustment() {
|
||||||
runAt("06 September 2024", () -> {
|
runAt("06 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
// Add initial buy down fee
|
// Add initial buy down fee
|
||||||
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 500.0, "06 September 2024");
|
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 500.0, "06 September 2024");
|
||||||
assertNotNull(buyDownFeeTransactionId);
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "06 September 2024"));
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// Create buy down fee adjustment (use same date as business date)
|
// Create buy down fee adjustment (use same date as business date)
|
||||||
PostLoansLoanIdTransactionsResponse adjustmentResponse = loanTransactionHelper.buyDownFeeAdjustment(loanId,
|
PostLoansLoanIdTransactionsResponse adjustmentResponse = loanTransactionHelper.buyDownFeeAdjustment(loanId,
|
||||||
buyDownFeeTransactionId, "06 September 2024", 100.0);
|
buyDownFeeTransactionId, "06 September 2024", 100.0);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent",
|
||||||
|
"06 September 2024", 100.0, false));
|
||||||
|
|
||||||
assertNotNull(adjustmentResponse);
|
assertNotNull(adjustmentResponse);
|
||||||
assertNotNull(adjustmentResponse.getLoanId());
|
assertNotNull(adjustmentResponse.getLoanId());
|
||||||
assertNotNull(adjustmentResponse.getClientId());
|
assertNotNull(adjustmentResponse.getClientId());
|
||||||
@@ -286,6 +318,12 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
assertNotNull(adjustmentTransaction);
|
assertNotNull(adjustmentTransaction);
|
||||||
assertEquals(0, BigDecimal.valueOf(100.0).compareTo(adjustmentTransaction.getAmount()));
|
assertEquals(0, BigDecimal.valueOf(100.0).compareTo(adjustmentTransaction.getAmount()));
|
||||||
assertEquals("06 September 2024", adjustmentTransaction.getDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy")));
|
assertEquals("06 September 2024", adjustmentTransaction.getDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy")));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
loanTransactionHelper.reverseLoanTransaction(loanId, adjustmentResponse.getResourceId(), "06 September 2024");
|
||||||
|
verifyBusinessEvents(new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent",
|
||||||
|
"06 September 2024", 100.0, true));
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,20 +389,30 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMultipleBuyDownFeeAdjustments() {
|
public void testMultipleBuyDownFeeAdjustments() {
|
||||||
runAt("12 September 2024", () -> {
|
runAt("12 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// Add initial buy down fee
|
// Add initial buy down fee
|
||||||
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 600.0, "12 September 2024");
|
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 600.0, "12 September 2024");
|
||||||
assertNotNull(buyDownFeeTransactionId);
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "12 September 2024"));
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// First adjustment
|
// First adjustment
|
||||||
PostLoansLoanIdTransactionsResponse adjustment1 = loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionId,
|
PostLoansLoanIdTransactionsResponse adjustment1 = loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionId,
|
||||||
"12 September 2024", 100.0);
|
"12 September 2024", 100.0);
|
||||||
assertNotNull(adjustment1);
|
assertNotNull(adjustment1);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "12 September 2024"));
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
|
||||||
// Second adjustment
|
// Second adjustment
|
||||||
PostLoansLoanIdTransactionsResponse adjustment2 = loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionId,
|
PostLoansLoanIdTransactionsResponse adjustment2 = loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionId,
|
||||||
"12 September 2024", 150.0);
|
"12 September 2024", 150.0);
|
||||||
assertNotNull(adjustment2);
|
assertNotNull(adjustment2);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "12 September 2024"));
|
||||||
|
|
||||||
// Verify both adjustments are recorded
|
// Verify both adjustments are recorded
|
||||||
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
||||||
assertNotNull(loanDetails);
|
assertNotNull(loanDetails);
|
||||||
@@ -392,10 +440,12 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testBuyDownFeeAdjustmentWithExternalId() {
|
public void testBuyDownFeeAdjustmentWithExternalId() {
|
||||||
runAt("16 September 2024", () -> {
|
runAt("16 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
// Add initial buy down fee
|
// Add initial buy down fee
|
||||||
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 350.0, "16 September 2024");
|
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 350.0, "16 September 2024");
|
||||||
assertNotNull(buyDownFeeTransactionId);
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "16 September 2024"));
|
||||||
|
deleteAllExternalEvents();
|
||||||
// Create adjustment with external ID
|
// Create adjustment with external ID
|
||||||
String adjustmentExternalId = UUID.randomUUID().toString();
|
String adjustmentExternalId = UUID.randomUUID().toString();
|
||||||
PostLoansLoanIdTransactionsResponse adjustmentResponse = loanTransactionHelper.buyDownFeeAdjustment(loanId,
|
PostLoansLoanIdTransactionsResponse adjustmentResponse = loanTransactionHelper.buyDownFeeAdjustment(loanId,
|
||||||
@@ -407,6 +457,8 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
assertNotNull(adjustmentResponse);
|
assertNotNull(adjustmentResponse);
|
||||||
assertEquals(adjustmentExternalId, adjustmentResponse.getResourceExternalId());
|
assertEquals(adjustmentExternalId, adjustmentResponse.getResourceExternalId());
|
||||||
|
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "16 September 2024"));
|
||||||
|
|
||||||
// Verify adjustment transaction details
|
// Verify adjustment transaction details
|
||||||
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
final GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
|
||||||
GetLoansLoanIdTransactions adjustmentTransaction = loanDetails.getTransactions().stream()
|
GetLoansLoanIdTransactions adjustmentTransaction = loanDetails.getTransactions().stream()
|
||||||
@@ -462,13 +514,17 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
loanIdRef.set(loanId);
|
loanIdRef.set(loanId);
|
||||||
|
|
||||||
disburseLoan(loanId, BigDecimal.valueOf(100), "1 January 2024");
|
disburseLoan(loanId, BigDecimal.valueOf(100), "1 January 2024");
|
||||||
|
deleteAllExternalEvents();
|
||||||
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.makeLoanBuyDownFee(loanId, "1 January 2024",
|
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.makeLoanBuyDownFee(loanId, "1 January 2024",
|
||||||
50.0);
|
50.0);
|
||||||
buyDownFeeTransactionIdIdRef.set(transactionsResponse.getResourceId());
|
buyDownFeeTransactionIdIdRef.set(transactionsResponse.getResourceId());
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "01 January 2024"));
|
||||||
});
|
});
|
||||||
runAt("31 January 2024", () -> {
|
runAt("31 January 2024", () -> {
|
||||||
Long loanId = loanIdRef.get();
|
Long loanId = loanIdRef.get();
|
||||||
|
deleteAllExternalEvents();
|
||||||
executeInlineCOB(loanId);
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent", "30 January 2024"));
|
||||||
|
|
||||||
// summarized amortization
|
// summarized amortization
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
@@ -479,7 +535,9 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
});
|
});
|
||||||
runAt("1 February 2024", () -> {
|
runAt("1 February 2024", () -> {
|
||||||
Long loanId = loanIdRef.get();
|
Long loanId = loanIdRef.get();
|
||||||
|
deleteAllExternalEvents();
|
||||||
executeInlineCOB(loanId);
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent", "31 January 2024"));
|
||||||
|
|
||||||
// daily amortization
|
// daily amortization
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
@@ -490,11 +548,15 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
transaction(0.01, "Accrual", "31 January 2024"), //
|
transaction(0.01, "Accrual", "31 January 2024"), //
|
||||||
transaction(0.55, "Buy Down Fee Amortization", "31 January 2024"));
|
transaction(0.55, "Buy Down Fee Amortization", "31 January 2024"));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "1 February 2024", 10.0);
|
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "1 February 2024", 10.0);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "01 February 2024"));
|
||||||
});
|
});
|
||||||
runAt("2 February 2024", () -> {
|
runAt("2 February 2024", () -> {
|
||||||
Long loanId = loanIdRef.get();
|
Long loanId = loanIdRef.get();
|
||||||
|
deleteAllExternalEvents();
|
||||||
executeInlineCOB(loanId);
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent", "01 February 2024"));
|
||||||
|
|
||||||
// not backdated and not large buy down fee adjustment -> lowered daily amount
|
// not backdated and not large buy down fee adjustment -> lowered daily amount
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
@@ -508,11 +570,16 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
transaction(0.02, "Accrual", "01 February 2024"), //
|
transaction(0.02, "Accrual", "01 February 2024"), //
|
||||||
transaction(0.39, "Buy Down Fee Amortization", "01 February 2024"));
|
transaction(0.39, "Buy Down Fee Amortization", "01 February 2024"));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "10 January 2024", 10.0);
|
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "10 January 2024", 10.0);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "02 February 2024"));
|
||||||
});
|
});
|
||||||
runAt("3 February 2024", () -> {
|
runAt("3 February 2024", () -> {
|
||||||
Long loanId = loanIdRef.get();
|
Long loanId = loanIdRef.get();
|
||||||
|
deleteAllExternalEvents();
|
||||||
executeInlineCOB(loanId);
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new BusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "02 February 2024"));
|
||||||
|
|
||||||
// backdated buy down fee adjustment -> amortization adjustment
|
// backdated buy down fee adjustment -> amortization adjustment
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
@@ -529,11 +596,16 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
transaction(0.02, "Accrual", "02 February 2024"), //
|
transaction(0.02, "Accrual", "02 February 2024"), //
|
||||||
transaction(2.55, "Buy Down Fee Amortization Adjustment", "02 February 2024"));
|
transaction(2.55, "Buy Down Fee Amortization Adjustment", "02 February 2024"));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "03 February 2024", 20.0);
|
loanTransactionHelper.buyDownFeeAdjustment(loanId, buyDownFeeTransactionIdIdRef.get(), "03 February 2024", 20.0);
|
||||||
|
verifyBusinessEvents(new BusinessEvent("LoanBuyDownFeeAdjustmentTransactionBusinessEvent", "03 February 2024"));
|
||||||
});
|
});
|
||||||
runAt("4 February 2024", () -> {
|
runAt("4 February 2024", () -> {
|
||||||
Long loanId = loanIdRef.get();
|
Long loanId = loanIdRef.get();
|
||||||
|
deleteAllExternalEvents();
|
||||||
executeInlineCOB(loanId);
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new BusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent", "03 February 2024"));
|
||||||
|
|
||||||
// large (more than remaining unrecognized (15.13)) buy down fee adjustment -> amortization adjustment
|
// large (more than remaining unrecognized (15.13)) buy down fee adjustment -> amortization adjustment
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
@@ -630,7 +702,52 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReverseBuyDownFeeTransaction() {
|
public void tesReverseBuyDownFeeTransactionWithAmortizationAdjustmentTransaction() {
|
||||||
|
AtomicReference<Long> buyDownFeeTransactionIdRef = new AtomicReference<>();
|
||||||
|
runAt("2 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
// Add initial buy down fee
|
||||||
|
Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 400.0, "02 September 2024");
|
||||||
|
buyDownFeeTransactionIdRef.set(buyDownFeeTransactionId);
|
||||||
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "02 September 2024", 400.0, false));
|
||||||
|
});
|
||||||
|
runAt("10 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
inlineLoanCOBHelper.executeInlineCOB(loanId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
||||||
|
"09 September 2024", 8.79, false));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
Long buyDownFeeTransactionId = buyDownFeeTransactionIdRef.get();
|
||||||
|
// Reverse Buy Down Fee
|
||||||
|
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
|
||||||
|
buyDownFeeTransactionId, new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN)
|
||||||
|
.transactionDate("10 September 2024").note("Buy Down Fee reversed").transactionAmount(0.0).locale("en"));
|
||||||
|
Assertions.assertNotNull(transactionsResponse);
|
||||||
|
Assertions.assertNotNull(transactionsResponse.getResourceId());
|
||||||
|
Assertions.assertEquals(transactionsResponse.getResourceId(), buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||||
|
"10 September 2024", 8.79, false),
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "10 September 2024", 400.0, true));
|
||||||
|
|
||||||
|
verifyTransactions(loanId, //
|
||||||
|
transaction(1000.000000, "Disbursement", "01 September 2024", 1000.000000, 0, 0, 0, 0, 0, 0, false), //
|
||||||
|
transaction(400.000000, "Buy Down Fee", "02 September 2024", 0, 0, 0, 0, 0, 0, 0, true), //
|
||||||
|
transaction(2.220000, "Accrual", "09 September 2024", 0, 0, 2.220000, 0, 0, 0, 0, false), //
|
||||||
|
transaction(8.790000, "Buy Down Fee Amortization", "09 September 2024", 0, 0, 0, 8.790000, 0, 0, 0, false), //
|
||||||
|
transaction(8.790000, "Buy Down Fee Amortization Adjustment", "10 September 2024", 0, 0, 0, 8.790000, 0, 0, 0, false) //
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReverseBuyDownFeeTransactionWithoutAmortizationAdjustmentTransaction() {
|
||||||
final AtomicReference<Long> buyDownFeeTransactionIdIdRef = new AtomicReference<>();
|
final AtomicReference<Long> buyDownFeeTransactionIdIdRef = new AtomicReference<>();
|
||||||
|
|
||||||
runAt("10 September 2024", () -> {
|
runAt("10 September 2024", () -> {
|
||||||
@@ -646,11 +763,7 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
transaction(1000.0, "Disbursement", "01 September 2024"), //
|
transaction(1000.0, "Disbursement", "01 September 2024"), //
|
||||||
transaction(400.0, "Buy Down Fee", "10 September 2024"));
|
transaction(400.0, "Buy Down Fee", "10 September 2024"));
|
||||||
});
|
|
||||||
|
|
||||||
runAt("23 September 2024", () -> {
|
|
||||||
final Long buyDownFeeTransactionId = buyDownFeeTransactionIdIdRef.get();
|
|
||||||
executeInlineCOB(loanId);
|
|
||||||
// Reverse Buy Down Fee
|
// Reverse Buy Down Fee
|
||||||
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
|
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
|
||||||
buyDownFeeTransactionId, new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN)
|
buyDownFeeTransactionId, new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN)
|
||||||
@@ -659,15 +772,69 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
Assertions.assertNotNull(transactionsResponse.getResourceId());
|
Assertions.assertNotNull(transactionsResponse.getResourceId());
|
||||||
Assertions.assertEquals(transactionsResponse.getResourceId(), buyDownFeeTransactionId);
|
Assertions.assertEquals(transactionsResponse.getResourceId(), buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyTransactions(loanId, //
|
||||||
|
transaction(1000.000000, "Disbursement", "01 September 2024", 1000.000000, 0, 0, 0, 0, 0, 0, false), //
|
||||||
|
transaction(400.000000, "Buy Down Fee", "10 September 2024", 0, 0, 0, 0, 0, 0, 0, true) //
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReverseBuyDownFeeTransaction() {
|
||||||
|
final AtomicReference<Long> buyDownFeeTransactionIdIdRef = new AtomicReference<>();
|
||||||
|
|
||||||
|
runAt("10 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
// Add initial buy down fee
|
||||||
|
final Long buyDownFeeTransactionId = addBuyDownFeeForLoan(loanId, 400.0, "10 September 2024");
|
||||||
|
assertNotNull(buyDownFeeTransactionId);
|
||||||
|
buyDownFeeTransactionIdIdRef.set(buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "10 September 2024", 400.0, false));
|
||||||
|
|
||||||
|
// Verify initial buy down fee accounting entries
|
||||||
|
verifyTRJournalEntries(buyDownFeeTransactionId, debit(buyDownExpenseAccount, 400.0),
|
||||||
|
credit(deferredIncomeLiabilityAccount, 400.0));
|
||||||
|
|
||||||
|
verifyTransactions(loanId, //
|
||||||
|
transaction(1000.0, "Disbursement", "01 September 2024"), //
|
||||||
|
transaction(400.0, "Buy Down Fee", "10 September 2024"));
|
||||||
|
});
|
||||||
|
|
||||||
|
runAt("23 September 2024", () -> {
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
final Long buyDownFeeTransactionId = buyDownFeeTransactionIdIdRef.get();
|
||||||
|
executeInlineCOB(loanId);
|
||||||
|
verifyBusinessEvents(new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent",
|
||||||
|
"22 September 2024", 14.61, false));
|
||||||
|
|
||||||
|
deleteAllExternalEvents();
|
||||||
|
// Reverse Buy Down Fee
|
||||||
|
PostLoansLoanIdTransactionsResponse transactionsResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
|
||||||
|
buyDownFeeTransactionId, new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN)
|
||||||
|
.transactionDate("10 September 2024").note("Buy Down Fee reversed").transactionAmount(0.0).locale("en"));
|
||||||
|
Assertions.assertNotNull(transactionsResponse);
|
||||||
|
Assertions.assertNotNull(transactionsResponse.getResourceId());
|
||||||
|
Assertions.assertEquals(transactionsResponse.getResourceId(), buyDownFeeTransactionId);
|
||||||
|
|
||||||
|
verifyBusinessEvents(
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeAmortizationAdjustmentTransactionCreatedBusinessEvent",
|
||||||
|
"23 September 2024", 14.61, false),
|
||||||
|
new LoanTransactionMinimalBusinessEvent("LoanBuyDownFeeTransactionBusinessEvent", "23 September 2024", 400.0, true));
|
||||||
|
|
||||||
// Verify initial buy down fee reversed accounting entries
|
// Verify initial buy down fee reversed accounting entries
|
||||||
verifyTRJournalEntries(buyDownFeeTransactionId, debit(buyDownExpenseAccount, 400.0),
|
verifyTRJournalEntries(buyDownFeeTransactionId, debit(buyDownExpenseAccount, 400.0),
|
||||||
credit(deferredIncomeLiabilityAccount, 400.0), credit(buyDownExpenseAccount, 400.0),
|
credit(deferredIncomeLiabilityAccount, 400.0), credit(buyDownExpenseAccount, 400.0),
|
||||||
debit(deferredIncomeLiabilityAccount, 400.0));
|
debit(deferredIncomeLiabilityAccount, 400.0));
|
||||||
|
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
transaction(1000.0, "Disbursement", "01 September 2024"), //
|
transaction(1000.000000, "Disbursement", "01 September 2024", 1000.000000, 0, 0, 0, 0, 0, 0, false), //
|
||||||
reversedTransaction(400.0, "Buy Down Fee", "10 September 2024"), //
|
transaction(400.000000, "Buy Down Fee", "10 September 2024", 0, 0, 0, 0, 0, 0, 0, true), //
|
||||||
transaction(5.83, "Accrual", "22 September 2024"));
|
transaction(5.830000, "Accrual", "22 September 2024", 0, 0, 5.830000, 0, 0, 0, 0, false), //
|
||||||
|
transaction(14.610000, "Buy Down Fee Amortization", "22 September 2024", 0, 0, 0, 14.610000, 0, 0, 0, false), //
|
||||||
|
transaction(14.610000, "Buy Down Fee Amortization Adjustment", "23 September 2024", 0, 0, 0, 14.610000, 0, 0, 0, false) //
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -637,12 +637,12 @@ public class ExternalEventConfigurationHelper {
|
|||||||
defaults.add(loanTransactionUndoContractTerminationBusinessEvent);
|
defaults.add(loanTransactionUndoContractTerminationBusinessEvent);
|
||||||
|
|
||||||
Map<String, Object> loanTransactionBuyDownFeePostBusinessEvent = new HashMap<>();
|
Map<String, Object> loanTransactionBuyDownFeePostBusinessEvent = new HashMap<>();
|
||||||
loanTransactionBuyDownFeePostBusinessEvent.put("type", "LoanBuyDownFeeTransactionCreatedBusinessEvent");
|
loanTransactionBuyDownFeePostBusinessEvent.put("type", "LoanBuyDownFeeTransactionBusinessEvent");
|
||||||
loanTransactionBuyDownFeePostBusinessEvent.put("enabled", false);
|
loanTransactionBuyDownFeePostBusinessEvent.put("enabled", false);
|
||||||
defaults.add(loanTransactionBuyDownFeePostBusinessEvent);
|
defaults.add(loanTransactionBuyDownFeePostBusinessEvent);
|
||||||
|
|
||||||
Map<String, Object> loanTransactionBuyDownFeeAdjustmentPostBusinessEvent = new HashMap<>();
|
Map<String, Object> loanTransactionBuyDownFeeAdjustmentPostBusinessEvent = new HashMap<>();
|
||||||
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("type", "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent");
|
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("type", "LoanBuyDownFeeAdjustmentTransactionBusinessEvent");
|
||||||
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("enabled", false);
|
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("enabled", false);
|
||||||
defaults.add(loanTransactionBuyDownFeeAdjustmentPostBusinessEvent);
|
defaults.add(loanTransactionBuyDownFeeAdjustmentPostBusinessEvent);
|
||||||
|
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* 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.common.externalevents;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.apache.fineract.infrastructure.event.external.data.ExternalEventResponse;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class LoanTransactionMinimalBusinessEvent extends BusinessEvent {
|
||||||
|
|
||||||
|
public Double amount;
|
||||||
|
public Boolean reversed;
|
||||||
|
|
||||||
|
public LoanTransactionMinimalBusinessEvent(String type, String businessDate, Double amount, Boolean reversed) {
|
||||||
|
super(type, businessDate);
|
||||||
|
this.amount = amount;
|
||||||
|
this.reversed = reversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(ExternalEventResponse externalEvent, DateTimeFormatter formatter) {
|
||||||
|
Object actualAmount = externalEvent.getPayLoad().get("amount");
|
||||||
|
Object actualReversed = externalEvent.getPayLoad().get("reversed");
|
||||||
|
|
||||||
|
return super.verify(externalEvent, formatter) && Objects.equals(actualAmount, getAmount())
|
||||||
|
&& Objects.equals(actualReversed, getReversed());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user