FINERACT-2311: added e2e auto test scenarios for manual journal entries with asset externalization owner
This commit is contained in:
committed by
Adam Saghy
parent
0c1ca2baba
commit
c8b88c3664
+21
@@ -19,12 +19,14 @@
|
||||
package org.apache.fineract.test.factory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.client.models.DisbursementDetail;
|
||||
import org.apache.fineract.client.models.InterestPauseRequestDto;
|
||||
import org.apache.fineract.client.models.JournalEntryCommand;
|
||||
import org.apache.fineract.client.models.PostAddAndDeleteDisbursementDetailRequest;
|
||||
import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||
@@ -34,11 +36,14 @@ import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionI
|
||||
import org.apache.fineract.client.models.PostLoansRequest;
|
||||
import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.SingleDebitOrCreditEntryCommand;
|
||||
import org.apache.fineract.test.data.InterestCalculationPeriodTime;
|
||||
import org.apache.fineract.test.data.InterestType;
|
||||
import org.apache.fineract.test.data.LoanTermFrequencyType;
|
||||
import org.apache.fineract.test.data.RepaymentFrequencyType;
|
||||
import org.apache.fineract.test.data.TransactionProcessingStrategyCode;
|
||||
import org.apache.fineract.test.data.accounttype.AccountTypeResolver;
|
||||
import org.apache.fineract.test.data.accounttype.DefaultAccountType;
|
||||
import org.apache.fineract.test.data.loanproduct.DefaultLoanProduct;
|
||||
import org.apache.fineract.test.data.loanproduct.LoanProductResolver;
|
||||
import org.apache.fineract.test.helper.Utils;
|
||||
@@ -87,6 +92,8 @@ public class LoanRequestFactory {
|
||||
public static final String DATE_WITHDRAWN_STRING = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
public static final String DEFAULT_TRANSACTION_DATE = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
|
||||
private final AccountTypeResolver accountTypeResolver;
|
||||
|
||||
public PostLoansRequest defaultLoansRequest(Long clientId) {
|
||||
return new PostLoansRequest()//
|
||||
.clientId(clientId)//
|
||||
@@ -312,4 +319,18 @@ public class LoanRequestFactory {
|
||||
public static PostLoansLoanIdRequest defaultLoanContractTerminationRequest() {
|
||||
return new PostLoansLoanIdRequest().dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE).note("Contract Termination");
|
||||
}
|
||||
|
||||
public JournalEntryCommand defaultManualJournalEntryRequest(BigDecimal amount) {
|
||||
final Long glAccountDebit = accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE);
|
||||
final Long glAccountCredit = accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT);
|
||||
|
||||
return new JournalEntryCommand().amount(BigDecimal.TEN).officeId(1L).currencyCode("USD").locale(DEFAULT_LOCALE)
|
||||
.dateFormat("uuuu-MM-dd").transactionDate(LocalDate.of(2024, 1, 1))
|
||||
.addCreditsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountCredit).amount(amount))
|
||||
.addDebitsItem(new SingleDebitOrCreditEntryCommand().glAccountId(glAccountDebit).amount(amount));
|
||||
}
|
||||
|
||||
public JournalEntryCommand defaultManualJournalEntryRequest(BigDecimal amount, String externalAssetOwner) {
|
||||
return defaultManualJournalEntryRequest(amount).externalAssetOwner(externalAssetOwner);
|
||||
}
|
||||
}
|
||||
|
||||
+136
@@ -18,11 +18,14 @@
|
||||
*/
|
||||
package org.apache.fineract.test.stepdef.common;
|
||||
|
||||
import static org.apache.fineract.test.stepdef.loan.LoanRescheduleStepDef.FORMATTER_EN;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.cucumber.datatable.DataTable;
|
||||
import io.cucumber.java.en.Then;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -32,11 +35,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||
import org.apache.fineract.client.models.JournalEntryCommand;
|
||||
import org.apache.fineract.client.models.JournalEntryTransactionItem;
|
||||
import org.apache.fineract.client.models.PostJournalEntriesResponse;
|
||||
import org.apache.fineract.client.models.PostLoansResponse;
|
||||
import org.apache.fineract.client.services.JournalEntriesApi;
|
||||
import org.apache.fineract.client.services.LoansApi;
|
||||
import org.apache.fineract.test.data.TransactionType;
|
||||
import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
@@ -55,6 +61,9 @@ public class JournalEntriesStepDef extends AbstractStepDef {
|
||||
@Autowired
|
||||
private JournalEntriesApi journalEntriesApi;
|
||||
|
||||
@Autowired
|
||||
private LoanRequestFactory loanRequestFactory;
|
||||
|
||||
@Then("Loan Transactions tab has a {string} transaction with date {string} which has the following Journal entries:")
|
||||
public void journalEntryDataCheck(String transactionType, String transactionDate, DataTable table) throws IOException {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
@@ -360,4 +369,131 @@ public class JournalEntriesStepDef extends AbstractStepDef {
|
||||
|
||||
assertThat(journalLinesActualList.stream().findFirst().get().size()).isZero();
|
||||
}
|
||||
|
||||
public Response<PostJournalEntriesResponse> addManualJournalEntryWithoutExternalAssetOwner(String amount, String date)
|
||||
throws IOException {
|
||||
LocalDate transactionDate = LocalDate.parse(date, FORMATTER_EN);
|
||||
JournalEntryCommand journalEntriesRequest = loanRequestFactory.defaultManualJournalEntryRequest(new BigDecimal(amount))
|
||||
.transactionDate(transactionDate);
|
||||
Response<PostJournalEntriesResponse> journalEntriesResponse = journalEntriesApi.createGLJournalEntry("", journalEntriesRequest)
|
||||
.execute();
|
||||
testContext().set(TestContextKey.MANUAL_JOURNAL_ENTRIES_REQUEST, journalEntriesRequest);
|
||||
return journalEntriesResponse;
|
||||
}
|
||||
|
||||
public Response<PostJournalEntriesResponse> addManualJournalEntryWithExternalAssetOwner(String amount, String date,
|
||||
String externalAssetOwner) throws IOException {
|
||||
LocalDate transactionDate = LocalDate.parse(date, FORMATTER_EN);
|
||||
JournalEntryCommand journalEntriesRequest = loanRequestFactory
|
||||
.defaultManualJournalEntryRequest(new BigDecimal(amount), externalAssetOwner).transactionDate(transactionDate);
|
||||
Response<PostJournalEntriesResponse> journalEntriesResponse = journalEntriesApi.createGLJournalEntry("", journalEntriesRequest)
|
||||
.execute();
|
||||
testContext().set(TestContextKey.MANUAL_JOURNAL_ENTRIES_REQUEST, journalEntriesRequest);
|
||||
return journalEntriesResponse;
|
||||
}
|
||||
|
||||
@Then("Admin creates manual Journal entry with {string} amount and {string} date and unique External Asset Owner")
|
||||
public void createManualJournalEntryWithExternalAssetOwner(String amount, String date) throws IOException {
|
||||
String ownerExternalIdStored = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||
Response<PostJournalEntriesResponse> journalEntriesResponse = addManualJournalEntryWithExternalAssetOwner(amount, date,
|
||||
ownerExternalIdStored);
|
||||
|
||||
testContext().set(TestContextKey.MANUAL_JOURNAL_ENTRIES_RESPONSE, journalEntriesResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(journalEntriesResponse);
|
||||
}
|
||||
|
||||
@Then("Admin creates manual Journal entry with {string} amount and {string} date and empty External Asset Owner")
|
||||
public void createManualJournalEntryWithEmptyExternalAssetOwner(String amount, String date) throws IOException {
|
||||
Response<PostJournalEntriesResponse> journalEntriesResponse = addManualJournalEntryWithExternalAssetOwner(amount, date, "");
|
||||
|
||||
testContext().set(TestContextKey.MANUAL_JOURNAL_ENTRIES_RESPONSE, journalEntriesResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(journalEntriesResponse);
|
||||
}
|
||||
|
||||
@Then("Admin creates manual Journal entry with {string} amount and {string} date and without External Asset Owner")
|
||||
public void createManualJournalEntryWithoutExternalAssetOwner(String amount, String date) throws IOException {
|
||||
Response<PostJournalEntriesResponse> journalEntriesResponse = addManualJournalEntryWithoutExternalAssetOwner(amount, date);
|
||||
|
||||
testContext().set(TestContextKey.MANUAL_JOURNAL_ENTRIES_RESPONSE, journalEntriesResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(journalEntriesResponse);
|
||||
}
|
||||
|
||||
@Then("Verify manual Journal entry with External Asset Owner {string} and with the following Journal entries:")
|
||||
public void checkManualJournalEntry(String externalAssetOwnerEnabled, DataTable table) {
|
||||
Response<PostJournalEntriesResponse> journalEnriesResponse = testContext().get(TestContextKey.MANUAL_JOURNAL_ENTRIES_RESPONSE);
|
||||
PostJournalEntriesResponse journalEntriesResponseBody = journalEnriesResponse.body();
|
||||
String transactionId = journalEntriesResponseBody.getTransactionId();
|
||||
|
||||
JournalEntryCommand journalEntriesRequest = testContext().get(TestContextKey.MANUAL_JOURNAL_ENTRIES_REQUEST);
|
||||
|
||||
Response<GetJournalEntriesTransactionIdResponse> journalEntryDataResponse = null;
|
||||
try {
|
||||
journalEntryDataResponse = journalEntriesApi.retrieveAll1(//
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
transactionId, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
null, //
|
||||
true//
|
||||
).execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(journalEntryDataResponse);
|
||||
} catch (IOException e) {
|
||||
log.error("Exception", e);
|
||||
}
|
||||
|
||||
List<List<String>> data = table.asLists();
|
||||
for (int i = 1; i < data.size(); i++) {
|
||||
List<List<List<String>>> possibleActualValuesList = new ArrayList<>();
|
||||
List<String> expectedValues = data.get(i);
|
||||
if (Boolean.parseBoolean(externalAssetOwnerEnabled)) {
|
||||
expectedValues
|
||||
.add(journalEntriesRequest.getExternalAssetOwner() == null ? null : journalEntriesRequest.getExternalAssetOwner());
|
||||
}
|
||||
boolean containsAnyExpected = false;
|
||||
|
||||
GetJournalEntriesTransactionIdResponse journalEntryData = journalEntryDataResponse.body();
|
||||
|
||||
List<JournalEntryTransactionItem> journalLinesActual = journalEntryData.getPageItems();
|
||||
|
||||
List<List<String>> actualValuesList = journalLinesActual.stream().map(t -> {
|
||||
List<String> actualValues = new ArrayList<>();
|
||||
actualValues.add(t.getGlAccountType().getValue() == null ? null : t.getGlAccountType().getValue());
|
||||
actualValues.add(t.getGlAccountCode() == null ? null : t.getGlAccountCode());
|
||||
actualValues.add(t.getGlAccountName() == null ? null : t.getGlAccountName());
|
||||
actualValues.add("DEBIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
|
||||
actualValues.add("CREDIT".equals(t.getEntryType().getValue()) ? String.valueOf(t.getAmount()) : null);
|
||||
actualValues.add(String.valueOf(t.getManualEntry()).toLowerCase());
|
||||
if (Boolean.parseBoolean(externalAssetOwnerEnabled)) {
|
||||
actualValues.add(t.getExternalAssetOwner() == null ? null : t.getExternalAssetOwner());
|
||||
}
|
||||
|
||||
return actualValues;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
possibleActualValuesList.add(actualValuesList);
|
||||
|
||||
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
|
||||
if (containsExpectedValues) {
|
||||
containsAnyExpected = true;
|
||||
}
|
||||
|
||||
assertThat(containsAnyExpected)
|
||||
.as(ErrorMessageHelper.wrongValueInLineInJournalEntries(transactionId, i, possibleActualValuesList, expectedValues))
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -232,4 +232,6 @@ public abstract class TestContextKey {
|
||||
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";
|
||||
public static final String MANUAL_JOURNAL_ENTRIES_REQUEST = "manualJournalEntriesRequest";
|
||||
public static final String MANUAL_JOURNAL_ENTRIES_RESPONSE = "manualJournalEntriesResponse";
|
||||
}
|
||||
|
||||
@@ -1776,3 +1776,83 @@ Feature: Asset Externalization
|
||||
| ASSET | 112603 | Interest/Fee Receivable | DEBIT | 0.33 |
|
||||
| INCOME | 404000 | Interest Income | CREDIT | 0.33 |
|
||||
When Global config "outstanding-interest-calculation-strategy-for-external-asset-transfer" value set to "TOTAL_OUTSTANDING_INTEREST"
|
||||
|
||||
@TestRailId:C3799 @AssetExternalizationJournalEntry
|
||||
Scenario: Verify manual journal entry with External Asset Owner value if asset-externalization is enabled for existing loan - UC1
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
When Admin sets the business date to "1 June 2025"
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a new default Loan with date: "1 June 2025"
|
||||
And Admin successfully approves the loan on "1 June 2025" with "1000" amount and expected disbursement date on "1 June 2025"
|
||||
When Admin successfully disburse the loan on "1 June 2025" with "1000" EUR transaction amount
|
||||
Then Loan status will be "ACTIVE"
|
||||
When Admin makes asset externalization request by Loan ID with unique ownerExternalId, system-generated transferExternalId and the following data:
|
||||
| Transaction type | settlementDate | purchasePriceRatio |
|
||||
| sale | 2025-06-01 | 1 |
|
||||
Then Asset externalization response has the correct Loan ID, transferExternalId
|
||||
Then Fetching Asset externalization details by loan id gives numberOfElements: 1 with correct ownerExternalId and the following data:
|
||||
| settlementDate | purchasePriceRatio | status | effectiveFrom | effectiveTo | Transaction type |
|
||||
| 2025-06-01 | 1 | PENDING | 2025-06-01 | 9999-12-31 | SALE |
|
||||
|
||||
When Admin sets the business date to "26 June 2025"
|
||||
Then Admin creates manual Journal entry with "131" amount and "26 June 2025" date and unique External Asset Owner
|
||||
Then Verify manual Journal entry with External Asset Owner "true" and with the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit | Manual Entry |
|
||||
| ASSET | 112601 | Loans Receivable | 131.0 | | true |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 131.0 | true |
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
When Loan Pay-off is made on "26 June 2025"
|
||||
Then Loan's all installments have obligations met
|
||||
|
||||
@TestRailId:C3800 @AssetExternalizationJournalEntry
|
||||
Scenario: Verify manual journal entry with External Asset Owner empty value if asset-externalization is enabled - UC2
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
When Admin sets the business date to "25 June 2025"
|
||||
Then Admin creates manual Journal entry with "88" amount and "20 June 2025" date and without External Asset Owner
|
||||
Then Verify manual Journal entry with External Asset Owner "true" and with the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit | Manual Entry |
|
||||
| ASSET | 112601 | Loans Receivable | 88.0 | | true |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 88.0 | true |
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
@TestRailId:C38001 @AssetExternalizationJournalEntry
|
||||
Scenario: Verify manual journal entry with External Asset Owner empty value if asset-externalization is enabled for existing loan - UC3
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
When Admin sets the business date to "1 June 2025"
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a new default Loan with date: "1 June 2025"
|
||||
And Admin successfully approves the loan on "1 June 2025" with "1000" amount and expected disbursement date on "1 June 2025"
|
||||
When Admin successfully disburse the loan on "1 June 2025" with "1000" EUR transaction amount
|
||||
Then Loan status will be "ACTIVE"
|
||||
When Admin makes asset externalization request by Loan ID with unique ownerExternalId, system-generated transferExternalId and the following data:
|
||||
| Transaction type | settlementDate | purchasePriceRatio |
|
||||
| sale | 2025-06-01 | 1 |
|
||||
Then Asset externalization response has the correct Loan ID, transferExternalId
|
||||
Then Fetching Asset externalization details by loan id gives numberOfElements: 1 with correct ownerExternalId and the following data:
|
||||
| settlementDate | purchasePriceRatio | status | effectiveFrom | effectiveTo | Transaction type |
|
||||
| 2025-06-01 | 1 | PENDING | 2025-06-01 | 9999-12-31 | SALE |
|
||||
|
||||
When Admin sets the business date to "25 June 2025"
|
||||
Then Admin creates manual Journal entry with "99" amount and "20 June 2025" date and without External Asset Owner
|
||||
Then Verify manual Journal entry with External Asset Owner "true" and with the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit | Manual Entry |
|
||||
| ASSET | 112601 | Loans Receivable | 99.0 | | true |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 99.0 | true |
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
When Loan Pay-off is made on "25 June 2025"
|
||||
Then Loan's all installments have obligations met
|
||||
|
||||
@TestRailId:C3802 @AssetExternalizationJournalEntry
|
||||
Scenario: Verify manual journal entry with no External Asset Owner value if asset-externalization is disabled - UC4
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is disabled
|
||||
When Admin sets the business date to "25 June 2025"
|
||||
Then Admin creates manual Journal entry with "250.05" amount and "15 June 2025" date and without External Asset Owner
|
||||
Then Verify manual Journal entry with External Asset Owner "false" and with the following Journal entries:
|
||||
| Type | Account code | Account name | Debit | Credit | Manual Entry |
|
||||
| ASSET | 112601 | Loans Receivable | 250.05 | | true |
|
||||
| LIABILITY | 145023 | Suspense/Clearing account | | 250.05 | true |
|
||||
Given Global configuration "asset-externalization-of-non-active-loans" is enabled
|
||||
|
||||
Reference in New Issue
Block a user