FINERACT-2327: Allow to create Interest Refund transaction manually
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
59409550a7
commit
c2e19bb68f
+9
@@ -3885,4 +3885,13 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loans/" + loanId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder manualInterestRefund(final Long loanId, final Long transactionId) {
|
||||
this.actionName = "MANUAL_INTEREST_REFUND";
|
||||
this.entityName = "LOAN_TRANSACTION";
|
||||
this.loanId = loanId;
|
||||
this.entityId = transactionId;
|
||||
this.href = "/loans/" + loanId + "/transactions/" + transactionId + "?command=interest-refund";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -41,6 +41,7 @@ public enum TransactionType {
|
||||
BUY_DOWN_FEE("buyDownFee"), //
|
||||
BUY_DOWN_FEE_ADJUSTMENT("buyDownFeeAdjustment"), //
|
||||
BUY_DOWN_FEE_AMORTIZATION("buyDownFeeAmortization"), //
|
||||
INTEREST_REFUND("interestRefund"), //
|
||||
;
|
||||
|
||||
public final String value;
|
||||
|
||||
+4
@@ -68,6 +68,10 @@ public final class ErrorMessageHelper {
|
||||
return "Loan can't be disbursed, disburse amount is exceeding approved principal.";
|
||||
}
|
||||
|
||||
public static String addManualInterestRefundIfAlreadyExistsFailure() {
|
||||
return "Interest Refund already exists for this transaction";
|
||||
}
|
||||
|
||||
public static String addDisbursementExceedMaxAppliedAmountFailure(String totalDisbAmount, String maxDisbursalAmount) {
|
||||
return String.format("Loan disbursal amount can't be greater than maximum applied loan amount calculation. "
|
||||
+ "Total disbursed amount: %s Maximum disbursal amount: %s", totalDisbAmount, maxDisbursalAmount);
|
||||
|
||||
+4
-1
@@ -76,6 +76,7 @@ import org.apache.fineract.test.messaging.event.loan.transaction.LoanDisbursalTr
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanRefundPostBusinessEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionGoodwillCreditPostEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionInterestPaymentWaiverPostEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionInterestRefundPostEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionMakeRepaymentPostEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionMerchantIssuedRefundPostEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionPayoutRefundPostEvent;
|
||||
@@ -308,7 +309,8 @@ public class EventCheckHelper {
|
||||
Response<PostLoansLoanIdTransactionsResponse> transactionResponse, TransactionType transactionType, String externalOwnerId)
|
||||
throws IOException {
|
||||
Long loanId = transactionResponse.body().getLoanId();
|
||||
Long transactionId = transactionResponse.body().getResourceId();
|
||||
Long transactionId = transactionType.equals(TransactionType.INTEREST_REFUND) ? transactionResponse.body().getSubResourceId()
|
||||
: transactionResponse.body().getResourceId();
|
||||
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
GetLoansLoanIdTransactions transactionFound = transactions//
|
||||
@@ -324,6 +326,7 @@ public class EventCheckHelper {
|
||||
case MERCHANT_ISSUED_REFUND -> LoanTransactionMerchantIssuedRefundPostEvent.class;
|
||||
case REFUND_BY_CASH -> LoanRefundPostBusinessEvent.class;
|
||||
case INTEREST_PAYMENT_WAIVER -> LoanTransactionInterestPaymentWaiverPostEvent.class;
|
||||
case INTEREST_REFUND -> LoanTransactionInterestRefundPostEvent.class;
|
||||
default -> throw new IllegalStateException(String.format("transaction type %s cannot be found", transactionType.getValue()));
|
||||
};
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.test.messaging.event.loan.transaction;
|
||||
|
||||
public class LoanTransactionInterestRefundPostEvent extends AbstractLoanTransactionEvent {
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "LoanTransactionInterestRefundPostBusinessEvent";
|
||||
}
|
||||
}
|
||||
+74
@@ -433,6 +433,63 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Admin manually adds Interest Refund for {string} transaction made on {string} with {double} EUR interest refund amount")
|
||||
public void addInterestRefundTransactionManually(final String transactionTypeInput, final String transactionDate, final double amount)
|
||||
throws IOException {
|
||||
final Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
final long loanId = loanResponse.body().getLoanId();
|
||||
final TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
|
||||
|
||||
final Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
|
||||
assert loanDetailsResponse.body() != null;
|
||||
final List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
assert transactions != null;
|
||||
final GetLoansLoanIdTransactions refundTransaction = transactions.stream()
|
||||
.filter(t -> t.getType() != null
|
||||
&& (transactionType.equals(TransactionType.PAYOUT_REFUND) ? "Payout Refund" : "Merchant Issued Refund")
|
||||
.equals(t.getType().getValue())
|
||||
&& t.getDate() != null && transactionDate.equals(FORMATTER.format(t.getDate())))
|
||||
.findFirst().orElseThrow(() -> new IllegalStateException("No refund transaction found for loan " + loanId));
|
||||
|
||||
final Response<PostLoansLoanIdTransactionsResponse> adjustmentResponse = addInterestRefundTransaction(amount,
|
||||
refundTransaction.getId());
|
||||
testContext().set(TestContextKey.LOAN_INTEREST_REFUND_RESPONSE, adjustmentResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(adjustmentResponse);
|
||||
eventCheckHelper.transactionEventCheck(adjustmentResponse, TransactionType.INTEREST_REFUND, null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@Then("Admin fails to add duplicate Interest Refund for {string} transaction made on {string} with {double} EUR interest refund amount")
|
||||
public void failToAddManualInterestRefundIfAlreadyExists(final String transactionTypeInput, final String transactionDate,
|
||||
final double amount) throws IOException {
|
||||
final Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
final long loanId = loanResponse.body().getLoanId();
|
||||
final TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
|
||||
|
||||
final Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
|
||||
assert loanDetailsResponse.body() != null;
|
||||
final List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
assert transactions != null;
|
||||
final GetLoansLoanIdTransactions refundTransaction = transactions.stream()
|
||||
.filter(t -> t.getType() != null
|
||||
&& (transactionType.equals(TransactionType.PAYOUT_REFUND) ? "Payout Refund" : "Merchant Issued Refund")
|
||||
.equals(t.getType().getValue())
|
||||
&& t.getDate() != null && transactionDate.equals(FORMATTER.format(t.getDate())))
|
||||
.findFirst().orElseThrow(() -> new IllegalStateException("No refund transaction found for loan " + loanId));
|
||||
|
||||
final Response<PostLoansLoanIdTransactionsResponse> adjustmentResponse = addInterestRefundTransaction(amount,
|
||||
refundTransaction.getId());
|
||||
testContext().set(TestContextKey.LOAN_INTEREST_REFUND_RESPONSE, adjustmentResponse);
|
||||
final ErrorResponse errorDetails = ErrorResponse.from(adjustmentResponse);
|
||||
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.addManualInterestRefundIfAlreadyExistsFailure()).isEqualTo(403);
|
||||
assertThat(errorDetails.getSingleError().getDeveloperMessage())
|
||||
.isEqualTo(ErrorMessageHelper.addManualInterestRefundIfAlreadyExistsFailure());
|
||||
}
|
||||
|
||||
private void createTransactionWithAutoIdempotencyKeyAndWithExternalOwner(String transactionTypeInput, String transactionPaymentType,
|
||||
String transactionDate, double transactionAmount, String externalOwnerId) throws IOException {
|
||||
eventStore.reset();
|
||||
@@ -4984,4 +5041,21 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
}
|
||||
assertThat(developerMessage).isEqualTo(ErrorMessageHelper.updateApprovedLoanLessMinAllowedAmountFailure());
|
||||
}
|
||||
|
||||
private Response<PostLoansLoanIdTransactionsResponse> addInterestRefundTransaction(final double amount, final Long transactionId)
|
||||
throws IOException {
|
||||
final Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
assert loanResponse.body() != null;
|
||||
final long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
final DefaultPaymentType paymentType = DefaultPaymentType.AUTOPAY;
|
||||
final Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest interestRefundRequest = new PostLoansLoanIdTransactionsTransactionIdRequest()
|
||||
.dateFormat("dd MMMM yyyy").locale("en").transactionAmount(amount).paymentTypeId(paymentTypeValue)
|
||||
.externalId("EXT-INT-REF-" + UUID.randomUUID()).note("");
|
||||
|
||||
return loanTransactionsApi.adjustLoanTransaction(loanId, transactionId, interestRefundRequest, "interest-refund").execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -241,6 +241,7 @@ public abstract class TestContextKey {
|
||||
public static final String LOAN_DISBURSEMENT_DETAIL_RESPONSE = "loanDisbursementDetailResponse";
|
||||
public static final String LOAN_CAPITALIZED_INCOME_AMORTIZATION_ID = "loanCapitalizedIncomeAmortizationId";
|
||||
public static final String LOAN_CAPITALIZED_INCOME_ADJUSTMENT_RESPONSE = "loanCapitalizedIncomeAdjustmentResponse";
|
||||
public static final String LOAN_INTEREST_REFUND_RESPONSE = "loanInterestRefundResponse";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_CONTRACT_TERMINATION = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationContractTermination";
|
||||
public static final String LOAN_CONTRACT_TERMINATION_RESPONSE = "loanContractTerminationResponse";
|
||||
public static final String LOAN_UNDO_CONTRACT_TERMINATION_RESPONSE = "loanUndoContractTerminationResponse";
|
||||
|
||||
+199
-1
@@ -333,4 +333,202 @@ Feature: MerchantIssuedRefund
|
||||
| 01 August 2024 | Accrual | 8.33 | 0.0 | 8.33 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 01 August 2024 | Accrual Activity | 8.33 | 0.0 | 8.33 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
| 05 August 2024 | Merchant Issued Refund | 10.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
|
||||
Then Loan status will be "OVERPAID"
|
||||
Then Loan status will be "OVERPAID"
|
||||
|
||||
@TestRailId:C3873
|
||||
Scenario: Manual Interest Refund creation for Merchant Issued Refund with interestRefundCalculation = false
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation false
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.36 | 0.0 | 0.0 | 335.78 | 50.0 | 50.0 | 0.0 | 285.78 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 13.58 | 0.0 | 0.0 | 1013.58 | 388.9 | 388.9 | 0.0 | 624.68 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin manually adds Interest Refund for "MERCHANT_ISSUED_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 0.19 | 0.19 | 0.0 | 338.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.36 | 0.0 | 0.0 | 335.78 | 50.0 | 50.0 | 0.0 | 285.78 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 13.58 | 0.0 | 0.0 | 1013.58 | 389.09 | 389.09 | 0.0 | 624.49 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
Then Loan Transactions tab has a "MERCHANT_ISSUED_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
|
||||
@TestRailId:C3874
|
||||
Scenario: Undo Merchant Issued Refund with manual Interest Refund, both transactions are reversed
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation false
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.36 | 0.0 | 0.0 | 335.78 | 50.0 | 50.0 | 0.0 | 285.78 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 13.58 | 0.0 | 0.0 | 1013.58 | 388.9 | 388.9 | 0.0 | 624.68 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin manually adds Interest Refund for "MERCHANT_ISSUED_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 0.19 | 0.19 | 0.0 | 338.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.36 | 0.0 | 0.0 | 335.78 | 50.0 | 50.0 | 0.0 | 285.78 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 13.58 | 0.0 | 0.0 | 1013.58 | 389.09 | 389.09 | 0.0 | 624.49 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
Then Loan Transactions tab has a "MERCHANT_ISSUED_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
When Customer undo "1"th transaction made on "15 July 2024"
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 334.07 | 329.45 | 9.45 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 334.07 | 2.78 | 0.0 | 0.0 | 336.85 | 0.0 | 0.0 | 0.0 | 336.85 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.65 | 0.0 | 0.0 | 1014.65 | 338.9 | 338.9 | 0.0 | 675.75 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | true | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | true | false |
|
||||
Then Loan Transactions tab has a "MERCHANT_ISSUED_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
| ASSET | 112601 | Loans Receivable | 50.0 | |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 50.0 |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | 0.19 | |
|
||||
| INCOME | 404000 | Interest Income | | 0.19 |
|
||||
|
||||
@TestRailId:C3875
|
||||
Scenario: Prevent manual Interest Refund creation if interestRefundCalculation = true and Interest Refund already exists
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation true
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 0.19 | 0.19 | 0.0 | 338.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.36 | 0.0 | 0.0 | 335.78 | 50.0 | 50.0 | 0.0 | 285.78 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 13.58 | 0.0 | 0.0 | 1013.58 | 389.09 | 389.09 | 0.0 | 624.49 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Merchant Issued Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin fails to add duplicate Interest Refund for "MERCHANT_ISSUED_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
@@ -192,4 +192,202 @@ Feature: PayoutRefund
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 950.0 | true | false |
|
||||
| 10 July 2024 | Interest Refund | 0.12 | 0.0 | 0.12 | 0.0 | 0.0 | 950.0 | true | false |
|
||||
| 15 July 2024 | Repayment | 100.0 | 96.24 | 3.76 | 0.0 | 0.0 | 903.76 | false | true |
|
||||
| 15 July 2024 | Repayment | 100.0 | 96.24 | 3.76 | 0.0 | 0.0 | 903.76 | false | true |
|
||||
|
||||
@TestRailId:C3870
|
||||
Scenario: Manual Interest Refund creation for Payout Refund with interestRefundCalculation = false
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation false
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 50.0 | 50.0 | 0.0 | 288.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.78 | 0.0 | 0.0 | 336.2 | 0.0 | 0.0 | 0.0 | 336.2 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.0 | 0.0 | 0.0 | 1014.0 | 388.9 | 388.9 | 0.0 | 625.1 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin manually adds Interest Refund for "PAYOUT_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 50.19 | 50.19 | 0.0 | 288.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.78 | 0.0 | 0.0 | 336.2 | 0.0 | 0.0 | 0.0 | 336.2 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.0 | 0.0 | 0.0 | 1014.0 | 389.09 | 389.09 | 0.0 | 624.91 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
Then Loan Transactions tab has a "PAYOUT_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
|
||||
@TestRailId:C3871
|
||||
Scenario: Undo Payout Refund with manual Interest Refund, both transactions are reversed
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation false
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 50.0 | 50.0 | 0.0 | 288.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.78 | 0.0 | 0.0 | 336.2 | 0.0 | 0.0 | 0.0 | 336.2 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.0 | 0.0 | 0.0 | 1014.0 | 388.9 | 388.9 | 0.0 | 625.1 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin manually adds Interest Refund for "PAYOUT_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 50.19 | 50.19 | 0.0 | 288.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.78 | 0.0 | 0.0 | 336.2 | 0.0 | 0.0 | 0.0 | 336.2 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.0 | 0.0 | 0.0 | 1014.0 | 389.09 | 389.09 | 0.0 | 624.91 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
Then Loan Transactions tab has a "PAYOUT_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
When Customer undo "1"th transaction made on "15 July 2024"
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 334.07 | 329.45 | 9.45 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 334.07 | 2.78 | 0.0 | 0.0 | 336.85 | 0.0 | 0.0 | 0.0 | 336.85 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.65 | 0.0 | 0.0 | 1014.65 | 338.9 | 338.9 | 0.0 | 675.75 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | true | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | true | false |
|
||||
Then Loan Transactions tab has a "PAYOUT_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112601 | Loans Receivable | | 50.0 |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | 50.0 | |
|
||||
| ASSET | 112601 | Loans Receivable | 50.0 | |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 50.0 |
|
||||
Then Loan Transactions tab has a "INTEREST_REFUND" transaction with date "15 July 2024" which has the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | | 0.19 |
|
||||
| INCOME | 404000 | Interest Income | 0.19 | |
|
||||
| ASSET | 112603 | Interest/Fee Receivable | 0.19 | |
|
||||
| INCOME | 404000 | Interest Income | | 0.19 |
|
||||
|
||||
@TestRailId:C3872
|
||||
Scenario: Prevent manual Interest Refund creation if interestRefundCalculation = true and Interest Refund already exists
|
||||
When Admin sets the business date to "01 July 2024"
|
||||
And Admin creates a client with random data
|
||||
And 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_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 July 2024 | 1000 | 10 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 July 2024" with "1000" amount and expected disbursement date on "01 July 2024"
|
||||
And Admin successfully disburse the loan on "01 July 2024" with "1000" EUR transaction amount
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | | 669.43 | 330.57 | 8.33 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 2 | 31 | 01 September 2024 | | 336.11 | 333.32 | 5.58 | 0.0 | 0.0 | 338.9 | 0.0 | 0.0 | 0.0 | 338.9 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 336.11 | 2.8 | 0.0 | 0.0 | 338.91 | 0.0 | 0.0 | 0.0 | 338.91 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 16.71 | 0.0 | 0.0 | 1016.71 | 0.0 | 0.0 | 0.0 | 1016.71 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
When Admin sets the business date to "10 July 2024"
|
||||
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "10 July 2024" with 338.9 EUR transaction amount and system-generated Idempotency key
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
And Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type on "15 July 2024" with 50 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation true
|
||||
Then Loan Repayment schedule has 3 periods, with the following data for periods:
|
||||
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| | | 01 July 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||
| 1 | 31 | 01 August 2024 | 10 July 2024 | 663.52 | 336.48 | 2.42 | 0.0 | 0.0 | 338.9 | 338.9 | 338.9 | 0.0 | 0.0 |
|
||||
| 2 | 31 | 01 September 2024 | | 333.42 | 330.1 | 8.8 | 0.0 | 0.0 | 338.9 | 50.19 | 50.19 | 0.0 | 288.71 |
|
||||
| 3 | 30 | 01 October 2024 | | 0.0 | 333.42 | 2.78 | 0.0 | 0.0 | 336.2 | 0.0 | 0.0 | 0.0 | 336.2 |
|
||||
And Loan Repayment schedule has the following data in Total row:
|
||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||
| 1000.0 | 14.0 | 0.0 | 0.0 | 1014.0 | 389.09 | 389.09 | 0.0 | 624.91 |
|
||||
And Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
|
||||
| 01 July 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
|
||||
| 10 July 2024 | Repayment | 338.9 | 336.48 | 2.42 | 0.0 | 0.0 | 663.52 | false | false |
|
||||
| 15 July 2024 | Payout Refund | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
| 15 July 2024 | Interest Refund | 0.19 | 0.0 | 0.19 | 0.0 | 0.0 | 613.52 | false | false |
|
||||
When Admin fails to add duplicate Interest Refund for "PAYOUT_REFUND" transaction made on "15 July 2024" with 0.19 EUR interest refund amount
|
||||
+3
@@ -97,4 +97,7 @@ public interface LoanAccountDomainService {
|
||||
LoanTransaction applyInterestRefund(Loan loan, LoanRefundRequestData loanRefundRequest);
|
||||
|
||||
void updateAndSaveLoanCollateralTransactionsForIndividualAccounts(Loan loan, LoanTransaction transaction);
|
||||
|
||||
LoanTransaction createManualInterestRefundWithAmount(Loan loan, LoanTransaction targetTransaction, BigDecimal amount,
|
||||
PaymentDetail paymentDetail, ExternalId txnExternalId);
|
||||
}
|
||||
|
||||
+5
@@ -195,6 +195,11 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.INTEREST_REFUND, null, amount, date, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction interestRefund(final Loan loan, final BigDecimal amount, final LocalDate date,
|
||||
final PaymentDetail paymentDetail, final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.INTEREST_REFUND, paymentDetail, amount, date, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction chargeAdjustment(final Loan loan, final BigDecimal amount, final LocalDate transactionDate,
|
||||
final ExternalId externalId, PaymentDetail paymentDetail) {
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_ADJUSTMENT, paymentDetail, amount, transactionDate,
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "LOAN_TRANSACTION", action = "MANUAL_INTEREST_REFUND")
|
||||
public class ManualInterestRefundCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final LoanWritePlatformService loanWritePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return loanWritePlatformService.makeManualInterestRefund(command.getLoanId(), command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+2
@@ -94,4 +94,6 @@ public interface LoanTransactionValidator {
|
||||
void validateExternalId(DataValidatorBuilder baseDataValidator, JsonElement element);
|
||||
|
||||
void validateReversalExternalId(DataValidatorBuilder baseDataValidator, JsonElement element);
|
||||
|
||||
void validateManualInterestRefundTransaction(String json);
|
||||
}
|
||||
|
||||
+2
@@ -155,4 +155,6 @@ public interface LoanReadPlatformService {
|
||||
List<Long> retrieveLoanIdsByExternalIds(List<ExternalId> externalIds);
|
||||
|
||||
boolean existsByLoanId(Long loanId);
|
||||
|
||||
LoanTransactionData retrieveManualInterestRefundTemplate(Long loanId, Long targetTransactionId);
|
||||
}
|
||||
|
||||
+2
@@ -125,4 +125,6 @@ public interface LoanWritePlatformService {
|
||||
CommandProcessingResult undoChargeOff(JsonCommand command);
|
||||
|
||||
CommandProcessingResult makeRefund(Long loanId, LoanTransactionType loanTransactionType, JsonCommand command);
|
||||
|
||||
CommandProcessingResult makeManualInterestRefund(Long loanId, Long transactionId, JsonCommand command);
|
||||
}
|
||||
|
||||
+5
@@ -572,6 +572,11 @@ public class ProgressiveLoanTransactionValidatorImpl implements ProgressiveLoanT
|
||||
loanTransactionValidator.validateReversalExternalId(baseDataValidator, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateManualInterestRefundTransaction(final String json) {
|
||||
loanTransactionValidator.validateManualInterestRefundTransaction(json);
|
||||
}
|
||||
|
||||
private Set<String> getCapitalizedIncomeParameters() {
|
||||
return new HashSet<>(
|
||||
Arrays.asList("transactionDate", "dateFormat", "locale", "transactionAmount", "paymentTypeId", "note", "externalId"));
|
||||
|
||||
+9
-2
@@ -93,6 +93,7 @@ public class LoanTransactionsApiResource {
|
||||
public static final String CAPITALIZED_INCOME = "capitalizedIncome";
|
||||
public static final String CAPITALIZED_INCOME_ADJUSTMENT = "capitalizedIncomeAdjustment";
|
||||
public static final String CONTRACT_TERMINATION = "contractTermination";
|
||||
public static final String INTEREST_REFUND_COMMAND_VALUE = "interest-refund";
|
||||
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));
|
||||
|
||||
@@ -121,7 +122,8 @@ 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=interestPaymentWaiver"
|
||||
+ "\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=downPayment" + "\n")
|
||||
+ "\n" + "loans/1/transactions/template?command=charge-off" + "\n" + "loans/1/transactions/template?command=downPayment" + "\n"
|
||||
+ "loans/1/transactions/template?command=interest-refund")
|
||||
@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,
|
||||
@@ -151,7 +153,8 @@ 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=interestPaymentWaiver"
|
||||
+ "\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=downPayment" + "\n")
|
||||
+ "\n" + "loans/1/transactions/template?command=charge-off" + "\n" + "loans/1/transactions/template?command=downPayment" + "\n"
|
||||
+ "loans/1/transactions/template?command=interest-refund")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTemplateResponse.class))) })
|
||||
public String retrieveTransactionTemplate(
|
||||
@@ -694,6 +697,8 @@ public class LoanTransactionsApiResource {
|
||||
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.BUY_DOWN_FEE_ADJUSTMENT_COMMAND)) {
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId,
|
||||
LoanTransactionType.BUY_DOWN_FEE_ADJUSTMENT, transactionId);
|
||||
} else if (CommandParameterUtil.is(commandParam, INTEREST_REFUND_COMMAND_VALUE)) {
|
||||
transactionData = this.loanReadPlatformService.retrieveManualInterestRefundTemplate(resolvedLoanId, transactionId);
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
@@ -718,6 +723,8 @@ public class LoanTransactionsApiResource {
|
||||
commandRequest = builder.capitalizedIncomeAdjustment(resolvedLoanId, resolvedTransactionId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.BUY_DOWN_FEE_ADJUSTMENT_COMMAND)) {
|
||||
commandRequest = builder.buyDownFeeAdjustment(resolvedLoanId, resolvedTransactionId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, INTEREST_REFUND_COMMAND_VALUE)) {
|
||||
commandRequest = builder.manualInterestRefund(resolvedLoanId, resolvedTransactionId).build();
|
||||
} else { // Default to adjust the Loan Transaction
|
||||
commandRequest = builder.adjustTransaction(resolvedLoanId, resolvedTransactionId).build();
|
||||
}
|
||||
|
||||
+6
@@ -206,7 +206,13 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final ExternalId txnExternalId = externalIdFactory.create();
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionInterestRefundPreBusinessEvent(loan));
|
||||
return LoanTransaction.interestRefund(loan, interestRefundAmount, refundTransaction.getDateOf(), txnExternalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanTransaction createManualInterestRefundWithAmount(final Loan loan, final LoanTransaction targetTransaction,
|
||||
final BigDecimal interestRefundAmount, final PaymentDetail paymentDetail, final ExternalId txnExternalId) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionInterestRefundPreBusinessEvent(loan));
|
||||
return LoanTransaction.interestRefund(loan, interestRefundAmount, targetTransaction.getDateOf(), paymentDetail, txnExternalId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
+31
@@ -1089,4 +1089,35 @@ public final class LoanTransactionValidatorImpl implements LoanTransactionValida
|
||||
baseDataValidator.reset().parameter("reversalExternalId").value(reversalExternalId).notExceedingLengthOf(100);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateManualInterestRefundTransaction(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Set<String> transactionParameters = new HashSet<>(
|
||||
Arrays.asList("transactionAmount", "externalId", "note", "locale", "dateFormat", "paymentTypeId", "accountNumber",
|
||||
"checkNumber", "routingCode", "receiptNumber", "bankNumber", "loanId", "numberOfRepayments"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, transactionParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("transactionAmount", element);
|
||||
baseDataValidator.reset().parameter("transactionAmount").value(transactionAmount).notNull().positiveAmount();
|
||||
|
||||
final String note = this.fromApiJsonHelper.extractStringNamed("note", element);
|
||||
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
validatePaymentDetails(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -46,8 +46,10 @@ import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDoma
|
||||
import org.apache.fineract.infrastructure.core.api.ApiFacingEnum;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.data.StringEnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
@@ -192,6 +194,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
private final LoanBalanceService loanBalanceService;
|
||||
private final LoanCapitalizedIncomeBalanceRepository loanCapitalizedIncomeBalanceRepository;
|
||||
private final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository;
|
||||
private final InterestRefundServiceDelegate interestRefundServiceDelegate;
|
||||
|
||||
@Override
|
||||
public LoanAccountData retrieveOne(final Long loanId) {
|
||||
@@ -2448,6 +2451,39 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
return loanRepositoryWrapper.existsByLoanId(loanId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanTransactionData retrieveManualInterestRefundTemplate(final Long loanId, final Long targetTransactionId) {
|
||||
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||
final LoanTransaction targetTxn = loan.getLoanTransaction(txn -> txn.getId() != null && txn.getId().equals(targetTransactionId));
|
||||
if (targetTxn == null) {
|
||||
throw new LoanTransactionNotFoundException(targetTransactionId);
|
||||
}
|
||||
if (!(targetTxn.isMerchantIssuedRefund() || targetTxn.isPayoutRefund())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.not.refund.type", "Only for refund transactions");
|
||||
}
|
||||
if (targetTxn.isReversed()) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.reversed", "Refund transaction is reversed");
|
||||
}
|
||||
final boolean alreadyExists = loan.getLoanTransactions().stream().anyMatch(txn -> txn.isInterestRefund() && !txn
|
||||
.getLoanTransactionRelations(rel -> rel.getToTransaction() != null && rel.getToTransaction().equals(targetTxn)).isEmpty());
|
||||
if (alreadyExists) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.interest.refund.already.exists",
|
||||
"Interest Refund already exists for this refund");
|
||||
}
|
||||
|
||||
final InterestRefundService interestRefundService = interestRefundServiceDelegate.lookupInterestRefundService(loan);
|
||||
final Money totalInterest = interestRefundService.totalInterestByTransactions(null, loan.getId(), targetTxn.getTransactionDate(),
|
||||
List.of(), loan.getLoanTransactions().stream().map(AbstractPersistableCustom::getId).toList());
|
||||
final Money newTotalInterest = interestRefundService.totalInterestByTransactions(null, loan.getId(), targetTxn.getTransactionDate(),
|
||||
List.of(targetTxn), loan.getLoanTransactions().stream().map(AbstractPersistableCustom::getId).toList());
|
||||
final BigDecimal interestRefundAmount = totalInterest.minus(newTotalInterest).getAmount();
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = paymentTypeReadPlatformService.retrieveAllPaymentTypes();
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.INTEREST_REFUND);
|
||||
|
||||
return LoanTransactionData.loanTransactionDataForCreditTemplate(transactionType, targetTxn.getTransactionDate(),
|
||||
interestRefundAmount, paymentTypeOptions, loan.getCurrency().toData());
|
||||
}
|
||||
|
||||
private LoanTransaction deriveDefaultInterestWaiverTransaction(final Loan loan) {
|
||||
final Money totalInterestOutstanding = loan.getTotalInterestOutstandingOnLoan();
|
||||
Money possibleInterestToWaive = totalInterestOutstanding.copy();
|
||||
|
||||
+133
-1
@@ -98,6 +98,7 @@ import org.apache.fineract.infrastructure.event.business.domain.loan.transaction
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionInterestPaymentWaiverPostBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionInterestPaymentWaiverPreBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionInterestRefundPostBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoChargeOffBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanUndoWrittenOffBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanWaiveInterestBusinessEvent;
|
||||
@@ -188,6 +189,7 @@ import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactio
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanMultiDisbursementException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
@@ -210,6 +212,7 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanUpdateCommand
|
||||
import org.apache.fineract.portfolio.loanaccount.service.adjustment.LoanAdjustmentParameter;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.adjustment.LoanAdjustmentService;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.portfolio.note.domain.Note;
|
||||
@@ -3010,6 +3013,136 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult makeManualInterestRefund(final Long loanId, final Long transactionId, final JsonCommand command) {
|
||||
loanTransactionValidator.validateManualInterestRefundTransaction(command.json());
|
||||
Loan loan = loanAssembler.assembleFrom(loanId);
|
||||
if (loan == null) {
|
||||
throw new LoanNotFoundException(loanId);
|
||||
}
|
||||
final LoanTransaction targetTransaction = this.loanTransactionRepository.findByIdAndLoanId(transactionId, loanId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(transactionId, loanId));
|
||||
|
||||
final LocalDate transactionDate = targetTransaction.getDateOf();
|
||||
if (!(targetTransaction.isMerchantIssuedRefund() || targetTransaction.isPayoutRefund())) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.not.refund.type",
|
||||
"Target transaction must be Merchant Issued Refund or Payout Refund");
|
||||
}
|
||||
if (targetTransaction.isReversed()) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.reversed", "Target transaction is already reversed");
|
||||
}
|
||||
boolean alreadyHasInterestRefund = loan.getLoanTransactions().stream()
|
||||
.anyMatch(txn -> txn.isInterestRefund()
|
||||
&& !txn.getLoanTransactionRelations(rel -> rel.getToTransaction().equals(targetTransaction)).isEmpty()
|
||||
&& !txn.isReversed());
|
||||
if (alreadyHasInterestRefund) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.interest.refund.already.exists",
|
||||
"Interest Refund already exists for this transaction");
|
||||
}
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.interest.refund.amount.invalid",
|
||||
"Amount must be provided and positive");
|
||||
}
|
||||
|
||||
final boolean shouldCreateInterestRefundTransaction = loan.getLoanProductRelatedDetail().getSupportedInterestRefundTypes().stream()
|
||||
.map(LoanSupportedInterestRefundTypes::getTransactionType)
|
||||
.anyMatch(transactionType -> transactionType.equals(targetTransaction.getTypeOf()));
|
||||
if (!shouldCreateInterestRefundTransaction) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.transaction.interest.refund.not.supported",
|
||||
"Interest Refund calculation is not supported for this loan");
|
||||
}
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount"));
|
||||
changes.put("locale", command.locale());
|
||||
changes.put("dateFormat", command.dateFormat());
|
||||
changes.put(LoanApiConstants.externalIdParameterName, txnExternalId);
|
||||
|
||||
final LocalDate recalculateFrom = loan.isInterestBearingAndInterestRecalculationEnabled() ? transactionDate : null;
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom, null);
|
||||
|
||||
this.loanTransactionValidator.validateRefund(loan, LoanTransactionType.INTEREST_REFUND, transactionDate, scheduleGeneratorDTO);
|
||||
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
|
||||
createNote(loan, command, changes);
|
||||
|
||||
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
|
||||
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);
|
||||
|
||||
final LoanTransaction interestRefundTxn = loanAccountDomainService.createManualInterestRefundWithAmount(loan, targetTransaction,
|
||||
amount, paymentDetail, txnExternalId);
|
||||
|
||||
interestRefundTxn.getLoanTransactionRelations().add(
|
||||
LoanTransactionRelation.linkToTransaction(interestRefundTxn, targetTransaction, LoanTransactionRelationTypeEnum.RELATED));
|
||||
|
||||
final boolean isTransactionChronologicallyLatest = loanTransactionService.isChronologicallyLatestRepaymentOrWaiver(loan,
|
||||
interestRefundTxn);
|
||||
final LoanRepaymentScheduleInstallment currentInstallment = loan.fetchLoanRepaymentScheduleInstallmentByDueDate(transactionDate);
|
||||
|
||||
final boolean processLatest = isTransactionChronologicallyLatest //
|
||||
&& !loan.isForeclosure() //
|
||||
&& !loan.hasChargesAffectedByBackdatedRepaymentLikeTransaction(interestRefundTxn) //
|
||||
&& loanTransactionProcessingService.canProcessLatestTransactionOnly(loan, interestRefundTxn, currentInstallment); //
|
||||
if (processLatest) {
|
||||
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), interestRefundTxn,
|
||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||
loan.addLoanTransaction(interestRefundTxn);
|
||||
} else {
|
||||
if (loan.isCumulativeSchedule() && loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||
} else if (loan.isProgressiveSchedule() && ((loan.hasChargeOffTransaction() && loan.hasAccelerateChargeOffStrategy())
|
||||
|| loan.hasContractTerminationTransaction())) {
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan, scheduleGeneratorDTO);
|
||||
}
|
||||
loan.addLoanTransaction(interestRefundTxn);
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
}
|
||||
|
||||
// Update outstanding loan balances
|
||||
loanBalanceService.updateLoanOutstandingBalances(loan);
|
||||
|
||||
loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(interestRefundTxn);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanTransactionInterestRefundPostBusinessEvent(interestRefundTxn));
|
||||
|
||||
// Accrual reprocessing
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||
loanAccrualsProcessingService.reprocessExistingAccruals(loan);
|
||||
loanAccrualsProcessingService.processIncomePostingAndAccruals(loan);
|
||||
}
|
||||
|
||||
loan = saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, transactionDate);
|
||||
loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
|
||||
|
||||
loanAccountDomainService.updateAndSavePostDatedChecksForIndividualAccount(loan, interestRefundTxn);
|
||||
loanAccountDomainService.updateAndSaveLoanCollateralTransactionsForIndividualAccounts(loan, interestRefundTxn);
|
||||
|
||||
loanAccrualsProcessingService.processAccrualsOnInterestRecalculation(loan, loan.isInterestBearingAndInterestRecalculationEnabled(),
|
||||
false);
|
||||
|
||||
journalEntryPoster.postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||
loanAccrualTransactionBusinessEventService.raiseBusinessEventForAccrualTransactions(loan, existingTransactionIds);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withLoanId(loan.getId()) //
|
||||
.withEntityId(targetTransaction.getId()) //
|
||||
.withEntityExternalId(targetTransaction.getExternalId()) //
|
||||
.withSubEntityId(interestRefundTxn.getId()) //
|
||||
.withSubEntityExternalId(interestRefundTxn.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
public void handleChargebackTransaction(final Loan loan, LoanTransaction chargebackTransaction) {
|
||||
loanTransactionValidator.validateIfTransactionIsChargeback(chargebackTransaction);
|
||||
|
||||
@@ -3626,5 +3759,4 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loan.setExpectedMaturityDate(latestRepaymentDate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-2
@@ -110,6 +110,7 @@ import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlat
|
||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.InterestRefundServiceDelegate;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccountServiceImpl;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualActivityProcessingService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualEventService;
|
||||
@@ -177,6 +178,7 @@ import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
@@ -344,7 +346,8 @@ public class LoanAccountConfiguration {
|
||||
LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper,
|
||||
LoanTransactionProcessingService loanTransactionProcessingService, LoanBalanceService loanBalanceService,
|
||||
LoanCapitalizedIncomeBalanceRepository loanCapitalizedIncomeBalanceRepository,
|
||||
LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository) {
|
||||
LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository,
|
||||
@Lazy InterestRefundServiceDelegate interestRefundServiceDelegate) {
|
||||
return new LoanReadPlatformServiceImpl(jdbcTemplate, context, loanRepositoryWrapper, applicationCurrencyRepository,
|
||||
loanProductReadPlatformService, clientReadPlatformService, groupReadPlatformService, loanDropdownReadPlatformService,
|
||||
fundReadPlatformService, chargeReadPlatformService, codeValueReadPlatformService, calendarReadPlatformService,
|
||||
@@ -352,7 +355,7 @@ public class LoanAccountConfiguration {
|
||||
loanUtilService, configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator,
|
||||
delinquencyReadPlatformService, loanTransactionRepository, loanChargePaidByReadService, loanTransactionRelationReadService,
|
||||
loanForeclosureValidator, loanTransactionMapper, loanTransactionProcessingService, loanBalanceService,
|
||||
loanCapitalizedIncomeBalanceRepository, loanBuyDownFeeBalanceRepository);
|
||||
loanCapitalizedIncomeBalanceRepository, loanBuyDownFeeBalanceRepository, interestRefundServiceDelegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user