FINERACT-2107: update related relationship for interest refund transaction
This commit is contained in:
committed by
Adam Saghy
parent
87ad93216e
commit
75ad6082d0
+3
-1
@@ -69,7 +69,9 @@ public enum DefaultLoanProduct implements LoanProduct {
|
||||
LP1_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY;//
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION, //
|
||||
;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
+22
@@ -990,6 +990,28 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT,
|
||||
loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseLastInstallmentResponse);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual + interest refund with
|
||||
// Merchant issued and Payment refund + interest recalculation
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION)
|
||||
String name48 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculation = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.name(name48)//
|
||||
.supportedInterestRefundTypes(Arrays.asList("MERCHANT_ISSUED_REFUND", "PAYOUT_REFUND"))//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "LAST_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculation = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculation).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculation);
|
||||
}
|
||||
|
||||
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
||||
|
||||
+26
@@ -22,6 +22,7 @@ import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.AD
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
@@ -41,6 +42,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -56,6 +58,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdDelinquencySummary;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargePaidByData;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdLoanTermVariations;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdLoanTransactionRelation;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||
@@ -2498,6 +2501,29 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
});
|
||||
}
|
||||
|
||||
@Then("In Loan Transactions the {string}th Transaction has relationship type={} with the {string}th Transaction")
|
||||
public void loanTransactionsRelationshipCheck(String nthTransactionFromStr, String relationshipType, String nthTransactionToStr)
|
||||
throws IOException {
|
||||
final Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
final long loanId = loanCreateResponse.body().getLoanId();
|
||||
|
||||
final Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
|
||||
final List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
final int nthTransactionFrom = nthTransactionFromStr == null ? transactions.size() - 1
|
||||
: Integer.parseInt(nthTransactionFromStr) - 1;
|
||||
final int nthTransactionTo = nthTransactionToStr == null ? transactions.size() - 1 : Integer.parseInt(nthTransactionToStr) - 1;
|
||||
final GetLoansLoanIdTransactions transactionFrom = transactions.get(nthTransactionFrom);
|
||||
final GetLoansLoanIdTransactions transactionTo = transactions.get(nthTransactionTo);
|
||||
|
||||
final Optional<GetLoansLoanIdLoanTransactionRelation> relationshipOptional = transactionFrom.getTransactionRelations().stream()
|
||||
.filter(r -> r.getRelationType().equals(relationshipType))
|
||||
.filter(r -> r.getToLoanTransaction().equals(transactionTo.getId())).findFirst();
|
||||
|
||||
assertTrue(relationshipOptional.isPresent(), "Missed relationship between transactions");
|
||||
}
|
||||
|
||||
private void createCustomizedLoan(final List<String> loanData, final boolean withEmi) throws IOException {
|
||||
final String loanProduct = loanData.get(0);
|
||||
final String submitDate = loanData.get(1);
|
||||
|
||||
+1
@@ -102,6 +102,7 @@ public abstract class TestContextKey {
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefund";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL = "loanProductCreateResponseLP1ProgressiveLoanScheduleHorizontal";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreCloseWholeTerm";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefundFInterestRecalculation";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
||||
|
||||
@@ -3397,3 +3397,42 @@ Feature: LoanRepayment
|
||||
When Admin makes Credit Balance Refund transaction on "10 September 2024" with 91.21 EUR transaction amount
|
||||
When Customer undo "1"th "Repayment" transaction made on "24 June 2024"
|
||||
Then Loan status will be "ACTIVE"
|
||||
|
||||
Scenario: Verify the relationship for Interest Refund transaction after repayment by reverting related transaction
|
||||
When Admin sets the business date to "30 January 2024"
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION | 01 January 2024 | 200 | 15 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 4 | MONTHS | 1 | MONTHS | 4 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 January 2024" with "200" amount and expected disbursement date on "01 January 2024"
|
||||
And Admin successfully disburse the loan on "01 January 2024" with "200" EUR transaction amount
|
||||
When Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "15 January 2024" with 50 EUR transaction amount and self-generated Idempotency key
|
||||
And Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type on "16 January 2024" with 50 EUR transaction amount and self-generated Idempotency key
|
||||
Then Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||
| 01 January 2024 | Disbursement | 200.0 | 0.0 | 0.0 | 0.0 | 0.0 | 200.0 | false |
|
||||
| 15 January 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 150.0 | false |
|
||||
| 15 January 2024 | Interest Refund | 0.29 | 0.29 | 0.0 | 0.0 | 0.0 | 149.71 | false |
|
||||
| 16 January 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 99.71 | false |
|
||||
| 16 January 2024 | Interest Refund | 0.31 | 0.31 | 0.0 | 0.0 | 0.0 | 99.4 | false |
|
||||
When Customer makes "AUTOPAY" repayment on "10 January 2024" with 25 EUR transaction amount (and transaction fails because of wrong date)
|
||||
Then Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||
| 01 January 2024 | Disbursement | 200.0 | 0.0 | 0.0 | 0.0 | 0.0 | 200.0 | false |
|
||||
| 10 January 2024 | Repayment | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 175.0 | false |
|
||||
| 15 January 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 125.0 | false |
|
||||
| 15 January 2024 | Interest Refund | 0.29 | 0.29 | 0.0 | 0.0 | 0.0 | 124.71 | false |
|
||||
| 16 January 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 74.71 | false |
|
||||
| 16 January 2024 | Interest Refund | 0.31 | 0.31 | 0.0 | 0.0 | 0.0 | 74.4 | false |
|
||||
Then In Loan Transactions the "4"th Transaction has relationship type=RELATED with the "3"th Transaction
|
||||
Then In Loan Transactions the "6"th Transaction has relationship type=RELATED with the "5"th Transaction
|
||||
When Customer undo "1"th "Merchant Issued Refund" transaction made on "15 January 2024"
|
||||
When Customer undo "1"th "Payout Refund" transaction made on "16 January 2024"
|
||||
Then Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||
| 01 January 2024 | Disbursement | 200.0 | 0.0 | 0.0 | 0.0 | 0.0 | 200.0 | false |
|
||||
| 10 January 2024 | Repayment | 25.0 | 25.0 | 0.0 | 0.0 | 0.0 | 175.0 | false |
|
||||
| 15 January 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 125.0 | true |
|
||||
| 15 January 2024 | Interest Refund | 0.29 | 0.29 | 0.0 | 0.0 | 0.0 | 124.71 | true |
|
||||
| 16 January 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 125.0 | true |
|
||||
| 16 January 2024 | Interest Refund | 0.31 | 0.31 | 0.0 | 0.0 | 0.0 | 124.69 | true |
|
||||
+2
@@ -27,6 +27,7 @@ import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
|
||||
@Getter
|
||||
@@ -38,6 +39,7 @@ public class LoanTransactionRelation extends AbstractAuditableWithUTCDateTimeCus
|
||||
@JoinColumn(name = "from_loan_transaction_id", nullable = false)
|
||||
private LoanTransaction fromTransaction;
|
||||
|
||||
@Setter
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_loan_transaction_id")
|
||||
private LoanTransaction toTransaction;
|
||||
|
||||
+14
-1
@@ -743,9 +743,22 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void createNewTransaction(LoanTransaction oldTransaction, LoanTransaction newTransaction, TransactionCtx ctx) {
|
||||
protected void createNewTransaction(final LoanTransaction oldTransaction, final LoanTransaction newTransaction,
|
||||
final TransactionCtx ctx) {
|
||||
oldTransaction.updateExternalId(null);
|
||||
oldTransaction.getLoanChargesPaid().clear();
|
||||
|
||||
if (newTransaction.getTypeOf().isInterestRefund()) {
|
||||
newTransaction.getLoanTransactionRelations().stream().filter(
|
||||
r -> r.getToTransaction().getTypeOf().isMerchantIssuedRefund() || r.getToTransaction().getTypeOf().isPayoutRefund())
|
||||
.filter(r -> r.getToTransaction().isReversed())
|
||||
.forEach(newRelation -> oldTransaction.getLoanTransactionRelations().stream()
|
||||
.filter(oldRelation -> LoanTransactionRelationTypeEnum.RELATED.equals(oldRelation.getRelationType()))
|
||||
.findFirst().map(oldRelation -> oldRelation.getToTransaction().getId())
|
||||
.ifPresent(oldToTransactionId -> newRelation.setToTransaction(
|
||||
ctx.getChangedTransactionDetail().getNewTransactionMappings().get(oldToTransactionId))));
|
||||
}
|
||||
|
||||
// Adding Replayed relation from newly created transaction to reversed transaction
|
||||
newTransaction.getLoanTransactionRelations()
|
||||
.add(LoanTransactionRelation.linkToTransaction(newTransaction, oldTransaction, LoanTransactionRelationTypeEnum.REPLAYED));
|
||||
|
||||
Reference in New Issue
Block a user