Skip to content

Commit

Permalink
FINERACT-2107: Merchant issued refund linked to related interest refund
Browse files Browse the repository at this point in the history
- on reversal reverse interest refund aswell
  • Loading branch information
magyari-adam authored and adamsaghy committed Oct 30, 2024
1 parent b053c90 commit 745dc80
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2686,6 +2686,19 @@ public ChangedTransactionDetail adjustExistingTransaction(final LoanTransaction
transactionForAdjustment.reverse(reversalExternalId);
transactionForAdjustment.manuallyAdjustedOrReversed();

if (transactionForAdjustment.getTypeOf().equals(LoanTransactionType.MERCHANT_ISSUED_REFUND)
|| transactionForAdjustment.getTypeOf().equals(LoanTransactionType.PAYOUT_REFUND)) {
getLoanTransactions().stream() //
.filter(LoanTransaction::isNotReversed)
.filter(loanTransaction -> loanTransaction.getLoanTransactionRelations().stream()
.anyMatch(relation -> relation.getRelationType().equals(LoanTransactionRelationTypeEnum.RELATED)
&& relation.getToTransaction().getId().equals(transactionForAdjustment.getId())))
.forEach(loanTransaction -> {
loanTransaction.reverse();
loanTransaction.manuallyAdjustedOrReversed();
});
}

if (isClosedWrittenOff()) {
// find write off transaction and reverse it
final LoanTransaction writeOffTransaction = findWriteOffTransaction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public enum LoanTransactionRelationTypeEnum {
INVALID(0, "loanTransactionType.invalid"), //
CHARGEBACK(1, "loanTransactionRelationType.chargeback"), //
CHARGE_ADJUSTMENT(2, "loanTransactionRelationType.chargeAdjustment"), //
REPLAYED(3, "loanTransactionRelationType.replayed");
REPLAYED(3, "loanTransactionRelationType.replayed"), //
RELATED(4, "loanTransactionRelationType.related");

private final Integer value;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,10 @@ public Pair<LoanTransaction, LoanTransaction> makeRefund(final Loan loan, final

if (shouldCreateInterestRefundTransaction) {
interestRefundTransaction = createInterestRefundLoanTransaction(loan, transactionDate, transactionAmount);
if (interestRefundTransaction != null) {
interestRefundTransaction.getLoanTransactionRelations().add(LoanTransactionRelation
.linkToTransaction(interestRefundTransaction, refundTransaction, LoanTransactionRelationTypeEnum.RELATED));
}
}

final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = transactionProcessorFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansRequest;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
Expand All @@ -44,6 +47,7 @@
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
Expand Down Expand Up @@ -226,6 +230,68 @@ public void uc2() {
});
}

@Test
public void testMerchantIssuedRefundCreatesAndReversesInterestRefund() {
runAt("01 July 2024", () -> {
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
final Long loanId = createLoanForMerchantIssuedRefundWithInterestRefund(clientId);
final PostLoansLoanIdTransactionsResponse merchantIssuedRefundResponse = loanTransactionHelper.makeMerchantIssuedRefund(loanId,
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("01 July 2024").locale("en")
.transactionAmount(100.0));

GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertTrue(
loanDetails.getTransactions().stream().anyMatch(transaction -> transaction.getType().getMerchantIssuedRefund()
&& Boolean.FALSE.equals(transaction.getManuallyReversed())));

Assertions.assertTrue(loanDetails.getTransactions().stream()
.anyMatch(transaction -> transaction.getType().getCode().equals("loanTransactionType.interestRefund")
&& Boolean.FALSE.equals(transaction.getManuallyReversed())));

loanTransactionHelper.reverseLoanTransaction(loanId.intValue(), merchantIssuedRefundResponse.getResourceId(), "01 July 2024",
responseSpec);

loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertTrue(
loanDetails.getTransactions().stream().anyMatch(transaction -> transaction.getType().getMerchantIssuedRefund()
&& Boolean.TRUE.equals(transaction.getManuallyReversed())));

Assertions.assertTrue(loanDetails.getTransactions().stream()
.anyMatch(transaction -> transaction.getType().getCode().equals("loanTransactionType.interestRefund")
&& Boolean.TRUE.equals(transaction.getManuallyReversed())));
});
}

@Test
public void testPayoutRefundCreatesAndReversesInterestRefund() {
runAt("01 July 2024", () -> {
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
final Long loanId = createLoanForPayoutRefundWithInterestRefund(clientId);
final PostLoansLoanIdTransactionsResponse payoutRefundResponse = loanTransactionHelper.makePayoutRefund(loanId,
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("01 July 2024").locale("en")
.transactionAmount(100.0));

GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertTrue(loanDetails.getTransactions().stream().anyMatch(
transaction -> transaction.getType().getPayoutRefund() && Boolean.FALSE.equals(transaction.getManuallyReversed())));

Assertions.assertTrue(loanDetails.getTransactions().stream()
.anyMatch(transaction -> transaction.getType().getCode().equals("loanTransactionType.interestRefund")
&& Boolean.FALSE.equals(transaction.getManuallyReversed())));

loanTransactionHelper.reverseLoanTransaction(loanId.intValue(), payoutRefundResponse.getResourceId(), "01 July 2024",
responseSpec);

loanDetails = loanTransactionHelper.getLoanDetails(loanId);
Assertions.assertTrue(loanDetails.getTransactions().stream().anyMatch(
transaction -> transaction.getType().getPayoutRefund() && Boolean.TRUE.equals(transaction.getManuallyReversed())));

Assertions.assertTrue(loanDetails.getTransactions().stream()
.anyMatch(transaction -> transaction.getType().getCode().equals("loanTransactionType.interestRefund")
&& Boolean.TRUE.equals(transaction.getManuallyReversed())));
});
}

private String buildJsonBody(final BigDecimal principal, final BigDecimal interest, final BigDecimal feeCharges,
final BigDecimal penaltyCharges, final BigDecimal overpayment) {
final HashMap<String, BigDecimal> map = new HashMap<>();
Expand All @@ -240,4 +306,22 @@ private String buildJsonBody(final BigDecimal principal, final BigDecimal intere
return new Gson().toJson(map);
}

private Long createLoanForMerchantIssuedRefundWithInterestRefund(Long clientId) {
return createLoanForRefundWithInterestRefund(clientId, "MERCHANT_ISSUED_REFUND");
}

private Long createLoanForPayoutRefundWithInterestRefund(Long clientId) {
return createLoanForRefundWithInterestRefund(clientId, "PAYOUT_REFUND");
}

private Long createLoanForRefundWithInterestRefund(Long clientId, String refundType) {
final PostLoanProductsResponse loanProductsResponse = loanProductHelper.createLoanProduct(
create4IProgressive().supportedInterestRefundTypes(new ArrayList<>()).addSupportedInterestRefundTypesItem(refundType));
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(
applyPin4ProgressiveLoanRequest(clientId, loanProductsResponse.getResourceId(), "01 June 2024", 1000.0, 10.0, 4, null));
Long loanId = postLoansResponse.getLoanId();
loanTransactionHelper.approveLoan(loanId, approveLoanRequest(1000.0, "01 June 2024"));
disburseLoan(loanId, BigDecimal.valueOf(1000.0), "01 June 2024");
return loanId;
}
}

0 comments on commit 745dc80

Please sign in to comment.