FINERACT-2070: Further test cases
This commit is contained in:
committed by
Arnold Gálovics
parent
7c618a69d5
commit
ed5098b5a5
@@ -33,6 +33,8 @@ dependencies {
|
|||||||
implementation 'org.springframework:spring-test'
|
implementation 'org.springframework:spring-test'
|
||||||
testImplementation 'org.springframework:spring-jms'
|
testImplementation 'org.springframework:spring-jms'
|
||||||
|
|
||||||
|
testImplementation 'com.github.spotbugs:spotbugs-annotations'
|
||||||
|
|
||||||
testImplementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
testImplementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
testImplementation 'commons-httpclient:commons-httpclient:3.1'
|
testImplementation 'commons-httpclient:commons-httpclient:3.1'
|
||||||
testImplementation 'org.apache.commons:commons-lang3:3.14.0'
|
testImplementation 'org.apache.commons:commons-lang3:3.14.0'
|
||||||
|
|||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
|
import static org.awaitility.Awaitility.await;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.fineract.client.models.ExecuteJobRequest;
|
||||||
|
import org.apache.fineract.client.models.GetJobsResponse;
|
||||||
|
import org.apache.fineract.client.services.SchedulerJobApi;
|
||||||
|
import org.apache.fineract.test.data.job.Job;
|
||||||
|
import org.apache.fineract.test.data.job.JobResolver;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class JobService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SchedulerJobApi schedulerJobApi;
|
||||||
|
|
||||||
|
private final JobResolver jobResolver;
|
||||||
|
|
||||||
|
public void execute(Job job) {
|
||||||
|
try {
|
||||||
|
Long jobId = jobResolver.resolve(job);
|
||||||
|
Response<Void> response = schedulerJobApi.executeJob(jobId, "executeJob", new ExecuteJobRequest()).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Exception while executing job %s".formatted(job.getName()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeAndWait(Job job) {
|
||||||
|
execute(job);
|
||||||
|
waitUntilJobIsFinished(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitUntilJobIsFinished(Job job) {
|
||||||
|
String jobName = job.getName();
|
||||||
|
await().atMost(Duration.ofMinutes(2)).alias("%s didn't finish on time".formatted(jobName)).pollInterval(Duration.ofSeconds(10))
|
||||||
|
.until(() -> {
|
||||||
|
log.info("Waiting for job {} to finish", jobName);
|
||||||
|
Long jobId = jobResolver.resolve(job);
|
||||||
|
Response<GetJobsResponse> getJobsResponse = schedulerJobApi.retrieveOne5(jobId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(getJobsResponse);
|
||||||
|
Boolean currentlyRunning = getJobsResponse.body().getCurrentlyRunning();
|
||||||
|
return BooleanUtils.isFalse(currentlyRunning);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+771
@@ -0,0 +1,771 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 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.stepdef.assetexternalization;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import io.cucumber.datatable.DataTable;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.ExternalOwnerJournalEntryData;
|
||||||
|
import org.apache.fineract.client.models.ExternalOwnerTransferJournalEntryData;
|
||||||
|
import org.apache.fineract.client.models.ExternalTransferData;
|
||||||
|
import org.apache.fineract.client.models.JournalEntryData;
|
||||||
|
import org.apache.fineract.client.models.PageExternalTransferData;
|
||||||
|
import org.apache.fineract.client.models.PostInitiateTransferRequest;
|
||||||
|
import org.apache.fineract.client.models.PostInitiateTransferResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.ExternalAssetOwnersApi;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.test.data.AssetExternalizationErrorMessage;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.helper.Utils;
|
||||||
|
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String OWNER_EXTERNAL_ID_PREFIX = "TestOwner-";
|
||||||
|
public static final String DATE_FORMAT_ASSET_EXT = "yyyy-MM-dd";
|
||||||
|
public static final String DEFAULT_LOCALE = "en";
|
||||||
|
public static final String TRANSACTION_TYPE_SALE = "sale";
|
||||||
|
public static final String TRANSACTION_TYPE_BUYBACK = "buyback";
|
||||||
|
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_ASSET_EXT);
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExternalAssetOwnersApi externalAssetOwnersApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventCheckHelper eventCheckHelper;
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request by Loan ID with unique ownerExternalId, user-generated transferExternalId and the following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanIdUserGeneratedExtId(DataTable table) throws IOException {
|
||||||
|
// if user created transferExternalId previously, it will use that, otherwise create a new one
|
||||||
|
String transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED);
|
||||||
|
if (transferExternalId == null) {
|
||||||
|
transferExternalId = Utils.randomNameGenerator("TestTransferExtId_", 3);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAssetExternalizationRequestByLoanId(table, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request by Loan ID with unique ownerExternalId, system-generated transferExternalId and the following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanIdSystemGeneratedExtId(DataTable table) throws IOException {
|
||||||
|
createAssetExternalizationRequestByLoanId(table, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAssetExternalizationRequestByLoanId(DataTable table, String transferExternalId) throws IOException {
|
||||||
|
createAssetExternalizationRequestByLoanId(table, transferExternalId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAssetExternalizationRequestByLoanId(DataTable table, String transferExternalId, boolean regenerateOwner)
|
||||||
|
throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> transferData = data.get(1);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest();
|
||||||
|
if (transferData.get(0).equals(TRANSACTION_TYPE_BUYBACK)) {
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.transferExternalId(transferExternalId)//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, transferData.get(0)).execute();
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||||
|
response.body().getResourceExternalId());
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
} else if (transferData.get(0).equals(TRANSACTION_TYPE_SALE)) {
|
||||||
|
String ownerExternalId;
|
||||||
|
if (regenerateOwner) {
|
||||||
|
ownerExternalId = Utils.randomNameGenerator(OWNER_EXTERNAL_ID_PREFIX, 3);
|
||||||
|
} else {
|
||||||
|
ownerExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.ownerExternalId(ownerExternalId)//
|
||||||
|
.transferExternalId(transferExternalId)//
|
||||||
|
.purchasePriceRatio(transferData.get(2))//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, transferData.get(0)).execute();
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||||
|
response.body().getResourceExternalId());
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID, ownerExternalId);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException(String.format("%s is not supported Asset externalization transaction", transferData.get(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization BUYBACK request with ownerExternalId = null and settlement date {string} by Loan ID with system-generated transferExternalId")
|
||||||
|
public void createAssetExternalizationBuybackRequestOwnerNullByLoanIdSystemGeneratedExtId(String settlementDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest()//
|
||||||
|
.settlementDate(settlementDate)//
|
||||||
|
.ownerExternalId(null)//
|
||||||
|
.transferExternalId(testContext().get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_FROM_RESPONSE))//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, TRANSACTION_TYPE_BUYBACK).execute();
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||||
|
response.body().getResourceExternalId());
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request by Loan external ID with unique ownerExternalId, user-generated transferExternalId and the following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanExternalIdUserGeneratedExtId(DataTable table) throws IOException {
|
||||||
|
// if user created transferExternalId previously, it will use that, otherwise create a new one
|
||||||
|
String transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED);
|
||||||
|
if (transferExternalId == null) {
|
||||||
|
transferExternalId = Utils.randomNameGenerator("TestTransferExtId_", 3);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAssetExternalizationRequestByLoanExternalId(table, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request by Loan external ID with unique ownerExternalId, system-generated transferExternalId and the following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanExternalIdSystemGeneratedExtId(DataTable table) throws IOException {
|
||||||
|
createAssetExternalizationRequestByLoanExternalId(table, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAssetExternalizationRequestByLoanExternalId(DataTable table, String transferExternalId) throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> transferData = data.get(1);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest();
|
||||||
|
if (transferData.get(0).equals(TRANSACTION_TYPE_BUYBACK)) {
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.transferExternalId(transferExternalId)//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanExternalId(loanExternalId, request, transferData.get(0)).execute();
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||||
|
response.body().getResourceExternalId());
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
} else if (transferData.get(0).equals(TRANSACTION_TYPE_SALE)) {
|
||||||
|
String ownerExternalId = Utils.randomNameGenerator(OWNER_EXTERNAL_ID_PREFIX, 3);
|
||||||
|
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.ownerExternalId(ownerExternalId)//
|
||||||
|
.transferExternalId(transferExternalId)//
|
||||||
|
.purchasePriceRatio(transferData.get(2))//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanExternalId(loanExternalId, request, transferData.get(0)).execute();
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||||
|
response.body().getResourceExternalId());
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID, ownerExternalId);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException(String.format("%s is not supported Asset externalization transaction", transferData.get(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Asset externalization response has the correct Loan ID, transferExternalId")
|
||||||
|
public void checkAssetExternalizationResponse() {
|
||||||
|
String ownerExternalIdStored = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
|
||||||
|
String transferExternalIdExpected = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE);
|
||||||
|
PostInitiateTransferResponse body = response.body();
|
||||||
|
Long loanIdActual = body.getSubResourceId();
|
||||||
|
String transferExternalIdActual = body.getResourceExternalId();
|
||||||
|
|
||||||
|
log.info("loanId: {}", loanId);
|
||||||
|
log.info("ownerExternalIdStored: {}", ownerExternalIdStored);
|
||||||
|
log.info("transferExternalId generated by user: {}", transferExternalIdExpected);
|
||||||
|
log.info("transferExternalIdActual: {}", transferExternalIdActual);
|
||||||
|
|
||||||
|
assertThat(loanIdActual).as(ErrorMessageHelper.wrongDataInAssetExternalizationResponse(loanIdActual, loanId)).isEqualTo(loanId);
|
||||||
|
assertThat(body.getResourceId()).isNotNull();
|
||||||
|
if (transferExternalIdExpected != null) {
|
||||||
|
assertThat(transferExternalIdActual)
|
||||||
|
.as(ErrorMessageHelper.wrongDataInAssetExternalizationResponse(transferExternalIdActual, transferExternalIdExpected))
|
||||||
|
.isEqualTo(transferExternalIdExpected);
|
||||||
|
} else {
|
||||||
|
assertThat(transferExternalIdActual).isNotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Fetching Asset externalization details by loan id gives numberOfElements: {int} with correct ownerExternalId and the following data:")
|
||||||
|
public void checkAssetExternalizationDetailsByLoanId(int numberOfElements, DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
checkExternalAssetDetails(loanId, null, response, numberOfElements, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Fetching Asset externalization details by loan external id gives numberOfElements: {int} with correct ownerExternalId and the following data:")
|
||||||
|
public void checkAssetExternalizationDetailsByLoanExternalId(int numberOfElements, DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
Response<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, null, loanExternalId, null, null).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
checkExternalAssetDetails(null, loanExternalId, response, numberOfElements, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Fetching Asset externalization details by transfer external id gives numberOfElements: {int} with correct ownerExternalId and the following data:")
|
||||||
|
public void checkAssetExternalizationDetailsByTransferExternalId(int numberOfElements, DataTable table) throws IOException {
|
||||||
|
String transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
|
||||||
|
Response<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(transferExternalId, null, null, null, null)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
checkExternalAssetDetails(null, null, response, numberOfElements, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Asset externalization details has the generated transferExternalId")
|
||||||
|
public void checkGeneratedTransferExternalId() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> assetExtResponse = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE);
|
||||||
|
String transferExternalIdExpected = assetExtResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
Response<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
List<ExternalTransferData> content = response.body().getContent();
|
||||||
|
|
||||||
|
content.forEach(e -> {
|
||||||
|
assertThat(e.getTransferExternalId()).as(ErrorMessageHelper
|
||||||
|
.wrongDataInAssetExternalizationTransferExternalId(e.getTransferExternalId(), transferExternalIdExpected))
|
||||||
|
.isEqualTo(transferExternalIdExpected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExternalAssetDetails(Long loanId, String loanExternalId, Response<PageExternalTransferData> response,
|
||||||
|
int numberOfElements, DataTable table) {
|
||||||
|
PageExternalTransferData body = response.body();
|
||||||
|
Integer numberOfElementsActual = body.getNumberOfElements();
|
||||||
|
List<ExternalTransferData> content = body.getContent();
|
||||||
|
|
||||||
|
String ownerExternalIdStored = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
String transferExternalId;
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
List<String> expectedValues = data.get(i);
|
||||||
|
|
||||||
|
String transactionType = expectedValues.get(5);
|
||||||
|
if (transactionType.equals(ExternalTransferData.StatusEnum.BUYBACK.getValue())) {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
} else {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedValues.add(ownerExternalIdStored);
|
||||||
|
expectedValues.add(loanId == null ? null : String.valueOf(loanId));
|
||||||
|
expectedValues.add(loanExternalId);
|
||||||
|
expectedValues.add(transferExternalId);
|
||||||
|
|
||||||
|
List<List<String>> actualValuesList = content.stream().map(t -> {
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
actualValues.add(t.getSettlementDate() == null ? null : FORMATTER.format(t.getSettlementDate()));
|
||||||
|
actualValues.add(t.getPurchasePriceRatio() == null ? null : t.getPurchasePriceRatio());
|
||||||
|
actualValues.add(t.getStatus() == null ? null : String.valueOf(t.getStatus()));
|
||||||
|
actualValues.add(t.getEffectiveFrom() == null ? null : FORMATTER.format(t.getEffectiveFrom()));
|
||||||
|
actualValues.add(t.getEffectiveTo() == null ? null : FORMATTER.format(t.getEffectiveTo()));
|
||||||
|
actualValues.add(transactionType);
|
||||||
|
actualValues.add(t.getOwner().getExternalId() == null ? null : t.getOwner().getExternalId());
|
||||||
|
actualValues.add(loanId == null ? null : String.valueOf(t.getLoan().getLoanId()));
|
||||||
|
actualValues.add(loanExternalId == null ? null : t.getLoan().getExternalId());
|
||||||
|
actualValues.add(t.getTransferExternalId());
|
||||||
|
return actualValues;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
|
||||||
|
|
||||||
|
assertThat(numberOfElementsActual)
|
||||||
|
.as(ErrorMessageHelper.wrongTotalFilteredRecordsInAssetExternalizationDetails(numberOfElementsActual, numberOfElements))
|
||||||
|
.isEqualTo(numberOfElements);
|
||||||
|
assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInExternalAssetDetails(i, actualValuesList, expectedValues))
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("BUYBACK transaction results a {int} error and proper error message when its settlementDate is earlier than the original settlementDate")
|
||||||
|
public void buybackDateError(int errorCodeExpected, DataTable table) throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> transferData = data.get(1);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
String transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest()//
|
||||||
|
.settlementDate(transferData.get(1))//
|
||||||
|
.transferExternalId(transferExternalId)//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, transferData.get(0)).execute();
|
||||||
|
|
||||||
|
PageExternalTransferData transfers = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute().body();
|
||||||
|
String settlementDateOriginal = FORMATTER.format(transfers.getContent().get(0).getSettlementDate());
|
||||||
|
String errorMessageExpected = String.format(
|
||||||
|
"This loan cannot be bought back, settlement date is earlier than effective transfer settlement date: %s",
|
||||||
|
settlementDateOriginal);
|
||||||
|
|
||||||
|
String errorToString = response.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getDeveloperMessage();
|
||||||
|
int errorCodeActual = response.code();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Asset externalization transaction with the following data results a {int} error and {string} error message")
|
||||||
|
public void transactionError(int errorCodeExpected, String errorMessageType, DataTable table) throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> transferData = data.get(1);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest();
|
||||||
|
if (transferData.get(0).equals(TRANSACTION_TYPE_BUYBACK)) {
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.transferExternalId(null)//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
} else if (transferData.get(0).equals(TRANSACTION_TYPE_SALE)) {
|
||||||
|
String ownerExternalId = Utils.randomNameGenerator(OWNER_EXTERNAL_ID_PREFIX, 3);
|
||||||
|
|
||||||
|
request.settlementDate(transferData.get(1))//
|
||||||
|
.ownerExternalId(ownerExternalId)//
|
||||||
|
.transferExternalId(null)//
|
||||||
|
.purchasePriceRatio(transferData.get(2))//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID, ownerExternalId);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException(String.format("%s is not supported Asset externalization transaction", transferData.get(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, transferData.get(0)).execute();
|
||||||
|
|
||||||
|
AssetExternalizationErrorMessage errorMsgType = AssetExternalizationErrorMessage.valueOf(errorMessageType);
|
||||||
|
String errorMessageExpected = errorMsgType.getValue();
|
||||||
|
|
||||||
|
String errorToString = response.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getDeveloperMessage();
|
||||||
|
int errorCodeActual = response.code();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Asset externalization SALES transaction with ownerExternalId = null and the following data results a {int} error and {string} error message")
|
||||||
|
public void transactionErrorSalesOwnerNull(int errorCodeExpected, String errorMessageType, DataTable table) throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> transferData = data.get(1);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostInitiateTransferRequest request = new PostInitiateTransferRequest()//
|
||||||
|
.settlementDate(transferData.get(0))//
|
||||||
|
.ownerExternalId(null)//
|
||||||
|
.transferExternalId(null)//
|
||||||
|
.purchasePriceRatio(transferData.get(1))//
|
||||||
|
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi
|
||||||
|
.transferRequestWithLoanId(loanId, request, TRANSACTION_TYPE_SALE).execute();
|
||||||
|
|
||||||
|
AssetExternalizationErrorMessage errorMsgType = AssetExternalizationErrorMessage.valueOf(errorMessageType);
|
||||||
|
String errorMessageExpected = errorMsgType.getValue();
|
||||||
|
|
||||||
|
String errorToString = response.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getDeveloperMessage();
|
||||||
|
int errorCodeActual = response.code();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("The latest asset externalization transaction with {string} status has the following TRANSFER Journal entries:")
|
||||||
|
public void checkJournalEntriesTransaction(String status, DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Long lastTransferIdByStatus = getLastTransferIdByStatus(loanId, status);
|
||||||
|
|
||||||
|
Response<ExternalOwnerTransferJournalEntryData> journalEntriesOfTransfer = externalAssetOwnersApi
|
||||||
|
.getJournalEntriesOfTransfer(lastTransferIdByStatus, null, null).execute();
|
||||||
|
List<JournalEntryData> content = journalEntriesOfTransfer.body().getJournalEntryData().getContent();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
int linesExpected = data.size() - 1;
|
||||||
|
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
List<String> expectedValues = data.get(i);
|
||||||
|
List<List<String>> actualValuesList = content.stream().map(t -> {
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
actualValues.add(t.getGlAccountType().getValue());
|
||||||
|
actualValues.add(t.getGlAccountCode());
|
||||||
|
actualValues.add(t.getGlAccountName());
|
||||||
|
actualValues.add(t.getEntryType().getValue());
|
||||||
|
actualValues.add(t.getAmount().setScale(2, RoundingMode.HALF_DOWN).toString());
|
||||||
|
return actualValues;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
|
||||||
|
assertThat(containsExpectedValues)
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLineInAssetExternalizationJournalEntry(i, actualValuesList, expectedValues))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
|
int linesActual = journalEntriesOfTransfer.body().getJournalEntryData().getNumberOfElements();
|
||||||
|
assertThat(linesActual).as(ErrorMessageHelper.wrongNumberOfLinesInAssetExternalizationJournalEntry(linesActual, linesExpected))
|
||||||
|
.isEqualTo(linesExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("loanId: {}", journalEntriesOfTransfer.body().getTransferData().getLoan().getLoanId());
|
||||||
|
log.info("ownerExternalId: {}", journalEntriesOfTransfer.body().getTransferData().getOwner().getExternalId());
|
||||||
|
log.info("transferId: {}", lastTransferIdByStatus);
|
||||||
|
log.info("transferExternalId: {}", journalEntriesOfTransfer.body().getTransferData().getTransferExternalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getLastTransferIdByStatus(Long loanId, String status) throws IOException {
|
||||||
|
Response<PageExternalTransferData> transfersResponse = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null)
|
||||||
|
.execute();
|
||||||
|
List<ExternalTransferData> content = transfersResponse.body().getContent();
|
||||||
|
|
||||||
|
ExternalTransferData result = content.stream().filter(t -> status.equals(t.getStatus().getValue()))
|
||||||
|
.reduce((first, second) -> second)
|
||||||
|
.orElseThrow(() -> new IllegalStateException(String.format("No Journal entry found with status: %s", status)));
|
||||||
|
|
||||||
|
return result.getTransferId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getLastTransferId(Long loanId) throws IOException {
|
||||||
|
Response<PageExternalTransferData> transfersResponse = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null)
|
||||||
|
.execute();
|
||||||
|
List<ExternalTransferData> content = transfersResponse.body().getContent();
|
||||||
|
ExternalTransferData result = content.stream().reduce((first, second) -> second)
|
||||||
|
.orElseThrow(() -> new IllegalStateException("transfersResponse.body().getContent() is empty"));
|
||||||
|
|
||||||
|
return result.getTransferId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("The asset external owner has the following OWNER Journal entries:")
|
||||||
|
public void checkJournalEntriesOwner(DataTable table) throws IOException {
|
||||||
|
String ownerExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
|
||||||
|
Response<ExternalOwnerJournalEntryData> journalEntriesOfOwner = externalAssetOwnersApi
|
||||||
|
.getJournalEntriesOfOwner(ownerExternalId, null, null).execute();
|
||||||
|
List<JournalEntryData> content = journalEntriesOfOwner.body().getJournalEntryData().getContent();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
int linesExpected = data.size() - 1;
|
||||||
|
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
List<String> expectedValues = data.get(i);
|
||||||
|
List<List<String>> actualValuesList = content.stream().map(t -> {
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
actualValues.add(t.getGlAccountType().getValue());
|
||||||
|
actualValues.add(t.getGlAccountCode());
|
||||||
|
actualValues.add(t.getGlAccountName());
|
||||||
|
actualValues.add(t.getEntryType().getValue());
|
||||||
|
actualValues.add(t.getAmount().setScale(2, RoundingMode.HALF_DOWN).toString());
|
||||||
|
return actualValues;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
|
||||||
|
assertThat(containsExpectedValues)
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLineInAssetExternalizationJournalEntry(i, actualValuesList, expectedValues))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
|
int linesActual = journalEntriesOfOwner.body().getJournalEntryData().getNumberOfElements();
|
||||||
|
assertThat(linesActual).as(ErrorMessageHelper.wrongNumberOfLinesInAssetExternalizationJournalEntry(linesActual, linesExpected))
|
||||||
|
.isEqualTo(linesExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("ownerExternalId: {}", journalEntriesOfOwner.body().getOwnerData().getExternalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanOwnershipTransferBusinessEvent is created")
|
||||||
|
public void loanOwnershipTransferBusinessEventCheck() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Long transferId = getLastTransferId(loanId);
|
||||||
|
|
||||||
|
eventCheckHelper.loanOwnershipTransferBusinessEventCheck(loanId, transferId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanOwnershipTransferBusinessEvent with transfer status: {string} and transfer status reason {string} is created")
|
||||||
|
public void loanOwnershipTransferBusinessEventCheck(String transferStatus, String transferStatusReason) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Long transferId = getLastTransferId(loanId);
|
||||||
|
|
||||||
|
eventCheckHelper.loanOwnershipTransferBusinessEventWithStatusCheck(loanId, transferId, transferStatus, transferStatusReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanAccountSnapshotBusinessEvent is created")
|
||||||
|
public void loanAccountSnapshotBusinessEventCheck() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Long transferId = getLastTransferId(loanId);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountSnapshotBusinessEventCheck(loanId, transferId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Asset externalization response {string} has the correct Loan ID, transferExternalId")
|
||||||
|
public void checkAssetExternalizationResponse(String type) {
|
||||||
|
String ownerExternalIdStored = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
|
||||||
|
String transferExternalIdExpected = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_PREFIX + "_" + type);
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE);
|
||||||
|
PostInitiateTransferResponse body = response.body();
|
||||||
|
Long loanIdActual = body.getSubResourceId();
|
||||||
|
String transferExternalIdActual = body.getResourceExternalId();
|
||||||
|
|
||||||
|
log.info("loanId: {}", loanId);
|
||||||
|
log.info("ownerExternalIdStored: {}", ownerExternalIdStored);
|
||||||
|
log.info("transferExternalId generated by user: {}", transferExternalIdExpected);
|
||||||
|
log.info("transferExternalIdActual: {}", transferExternalIdActual);
|
||||||
|
|
||||||
|
assertThat(loanIdActual).as(ErrorMessageHelper.wrongDataInAssetExternalizationResponse(loanIdActual, loanId)).isEqualTo(loanId);
|
||||||
|
assertThat(body.getResourceId()).isNotNull();
|
||||||
|
if (transferExternalIdExpected != null) {
|
||||||
|
assertThat(transferExternalIdActual)
|
||||||
|
.as(ErrorMessageHelper.wrongDataInAssetExternalizationResponse(transferExternalIdActual, transferExternalIdExpected))
|
||||||
|
.isEqualTo(transferExternalIdExpected);
|
||||||
|
} else {
|
||||||
|
assertThat(transferExternalIdActual).isNotEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request for type {string} by Loan ID with unique ownerExternalId, user-generated transferExternalId and the following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanIdUserGeneratedExtId(String type, DataTable table) throws IOException {
|
||||||
|
// if user created transferExternalId previously, it will use that, otherwise create a new one
|
||||||
|
String transferExternalId = testContext()
|
||||||
|
.get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type);
|
||||||
|
if (transferExternalId == null) {
|
||||||
|
transferExternalId = Utils.randomNameGenerator("TestTransferExtId_", 3);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAssetExternalizationRequestByLoanId(table, transferExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin send {string} command to the transaction type {string}")
|
||||||
|
public void adminTransactionCommandTheWithType(String command, String type) throws IOException {
|
||||||
|
String transferExternalId = testContext()
|
||||||
|
.get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type);
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi.transferRequestWithId1(transferExternalId, command)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin send {string} command to the transaction type {string} will throw error")
|
||||||
|
public void adminTransactionCommandTheWithTypeThrowError(String command, String type) throws IOException {
|
||||||
|
String transferExternalId = testContext()
|
||||||
|
.get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type);
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi.transferRequestWithId1(transferExternalId, command)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkFailedApiCall(response, 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Fetching Asset externalization details by loan id gives numberOfElements: {int} with correct ownerExternalId, ignore transactionExternalId and contain the following data:")
|
||||||
|
public void checkAssetExternalizationDetailsByLoanIdIgnoreTransactionExternalId(int numberOfElements, DataTable table)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
checkExternalAssetDetailsIgnoreTransferExternalId(loanId, null, response, numberOfElements, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExternalAssetDetailsIgnoreTransferExternalId(Long loanId, String loanExternalId,
|
||||||
|
Response<PageExternalTransferData> response, int numberOfElements, DataTable table) {
|
||||||
|
PageExternalTransferData body = response.body();
|
||||||
|
Integer numberOfElementsActual = body.getNumberOfElements();
|
||||||
|
List<ExternalTransferData> content = body.getContent();
|
||||||
|
|
||||||
|
String ownerExternalIdStored = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
List<String> expectedValues = data.get(i);
|
||||||
|
expectedValues.add(ownerExternalIdStored);
|
||||||
|
expectedValues.add(loanId == null ? null : String.valueOf(loanId));
|
||||||
|
expectedValues.add(loanExternalId);
|
||||||
|
|
||||||
|
List<List<String>> actualValuesList = content.stream().map(t -> {
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
actualValues.add(t.getSettlementDate() == null ? null : FORMATTER.format(t.getSettlementDate()));
|
||||||
|
actualValues.add(t.getPurchasePriceRatio() == null ? null : t.getPurchasePriceRatio());
|
||||||
|
actualValues.add(t.getStatus() == null ? null : String.valueOf(t.getStatus()));
|
||||||
|
actualValues.add(t.getEffectiveFrom() == null ? null : FORMATTER.format(t.getEffectiveFrom()));
|
||||||
|
actualValues.add(t.getEffectiveTo() == null ? null : FORMATTER.format(t.getEffectiveTo()));
|
||||||
|
actualValues.add(t.getOwner().getExternalId() == null ? null : t.getOwner().getExternalId());
|
||||||
|
actualValues.add(loanId == null ? null : String.valueOf(t.getLoan().getLoanId()));
|
||||||
|
actualValues.add(loanExternalId == null ? null : t.getLoan().getExternalId());
|
||||||
|
return actualValues;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
|
||||||
|
|
||||||
|
assertThat(numberOfElementsActual)
|
||||||
|
.as(ErrorMessageHelper.wrongTotalFilteredRecordsInAssetExternalizationDetails(numberOfElementsActual, numberOfElements))
|
||||||
|
.isEqualTo(numberOfElements);
|
||||||
|
assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInExternalAssetDetails(i, actualValuesList, expectedValues))
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin send {string} command on {string} transaction it will throw an error")
|
||||||
|
public void adminSendCommandAndItWillThrowError(String command, String transactionType) throws IOException {
|
||||||
|
String transferExternalId;
|
||||||
|
if (transactionType.equals(ExternalTransferData.StatusEnum.BUYBACK.getValue())) {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
} else {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi.transferRequestWithId1(transferExternalId, command)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkFailedApiCall(response, 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin send {string} command on {string} transaction")
|
||||||
|
public void adminSendCommand(String command, String transactionType) throws IOException {
|
||||||
|
String transferExternalId;
|
||||||
|
if (transactionType.equals(ExternalTransferData.StatusEnum.BUYBACK.getValue())) {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
} else {
|
||||||
|
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Response<PostInitiateTransferResponse> response = externalAssetOwnersApi.transferRequestWithId1(transferExternalId, command)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes asset externalization request for type {string} by Loan ID with unique ownerExternalId, force generated transferExternalId and without change test owner with following data:")
|
||||||
|
public void createAssetExternalizationRequestByLoanIdUserGeneratedExtIdForceTransferIdNoTestOwner(String type, DataTable table)
|
||||||
|
throws IOException {
|
||||||
|
// if user created transferExternalId previously, it will use that, otherwise create a new one
|
||||||
|
String transferExternalId = Utils.randomNameGenerator("TestTransferExtId_", 3);
|
||||||
|
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type, transferExternalId);
|
||||||
|
|
||||||
|
createAssetExternalizationRequestByLoanId(table, transferExternalId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import org.apache.fineract.client.models.BusinessDateResponse;
|
||||||
|
import org.apache.fineract.client.services.BusinessDateManagementApi;
|
||||||
|
import org.apache.fineract.test.helper.BusinessDateHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class BusinessDateStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDateHelper businessDateHelper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessDateManagementApi businessDateManagementApi;
|
||||||
|
|
||||||
|
@When("Admin sets the business date to {string}")
|
||||||
|
public void setBusinessDate(String businessDate) throws IOException {
|
||||||
|
businessDateHelper.setBusinessDate(businessDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin sets the business date to the actual date")
|
||||||
|
public void setBusinessDateToday() throws IOException {
|
||||||
|
businessDateHelper.setBusinessDateToday();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Admin checks that the business date is correctly set to {string}")
|
||||||
|
public void checkBusinessDate(String businessDate) throws IOException {
|
||||||
|
Response<BusinessDateResponse> businessDateResponse = businessDateManagementApi.getBusinessDate(BusinessDateHelper.BUSINESS_DATE)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(businessDateResponse);
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy");
|
||||||
|
LocalDate localDate = LocalDate.parse(businessDate, formatter);
|
||||||
|
|
||||||
|
assertThat(businessDateResponse.body().getDate()).isEqualTo(localDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Given;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.fineract.client.models.BusinessStep;
|
||||||
|
import org.apache.fineract.client.models.UpdateBusinessStepConfigRequest;
|
||||||
|
import org.apache.fineract.client.services.BusinessStepConfigurationApi;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class BusinessStepStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
private static final String WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS = "LOAN_CLOSE_OF_BUSINESS";
|
||||||
|
private static final String BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS = "APPLY_CHARGE_TO_OVERDUE_LOANS";
|
||||||
|
private static final String BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION = "LOAN_DELINQUENCY_CLASSIFICATION";
|
||||||
|
private static final String BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE = "CHECK_LOAN_REPAYMENT_DUE";
|
||||||
|
private static final String BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE = "CHECK_LOAN_REPAYMENT_OVERDUE";
|
||||||
|
private static final String BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING = "UPDATE_LOAN_ARREARS_AGING";
|
||||||
|
private static final String BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES = "ADD_PERIODIC_ACCRUAL_ENTRIES";
|
||||||
|
private static final String BUSINESS_STEP_NAME_EXTERNAL_ASSET_OWNER_TRANSFER = "EXTERNAL_ASSET_OWNER_TRANSFER";
|
||||||
|
private static final String BUSINESS_STEP_NAME_CHECK_DUE_INSTALLMENTS = "CHECK_DUE_INSTALLMENTS";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BusinessStepConfigurationApi businessStepConfigurationApi;
|
||||||
|
|
||||||
|
@Given("Admin puts EXTERNAL_ASSET_OWNER_TRANSFER job into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||||
|
public void putExternalAssetOwnerTransferJobInCOB() throws IOException {
|
||||||
|
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||||
|
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||||
|
.order(2L);
|
||||||
|
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||||
|
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||||
|
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||||
|
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||||
|
BusinessStep externalAssetOwnerTransfer = new BusinessStep().stepName(BUSINESS_STEP_NAME_EXTERNAL_ASSET_OWNER_TRANSFER).order(7L);
|
||||||
|
|
||||||
|
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||||
|
businessSteps.add(applyChargeToOverdueLoans);
|
||||||
|
businessSteps.add(loanDelinquencyClassification);
|
||||||
|
businessSteps.add(checkLoanRepaymentDue);
|
||||||
|
businessSteps.add(checkLoanRepaymentOverdue);
|
||||||
|
businessSteps.add(updateLoanArrearsAging);
|
||||||
|
businessSteps.add(addPeriodicAccrualEntries);
|
||||||
|
businessSteps.add(externalAssetOwnerTransfer);
|
||||||
|
|
||||||
|
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||||
|
|
||||||
|
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Admin removes EXTERNAL_ASSET_OWNER_TRANSFER job from LOAN_CLOSE_OF_BUSINESS workflow")
|
||||||
|
public void removeExternalAssetOwnerTransferJobInCOB() throws IOException {
|
||||||
|
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||||
|
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||||
|
.order(2L);
|
||||||
|
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||||
|
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||||
|
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||||
|
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||||
|
|
||||||
|
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||||
|
businessSteps.add(applyChargeToOverdueLoans);
|
||||||
|
businessSteps.add(loanDelinquencyClassification);
|
||||||
|
businessSteps.add(checkLoanRepaymentDue);
|
||||||
|
businessSteps.add(checkLoanRepaymentOverdue);
|
||||||
|
businessSteps.add(updateLoanArrearsAging);
|
||||||
|
businessSteps.add(addPeriodicAccrualEntries);
|
||||||
|
|
||||||
|
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||||
|
|
||||||
|
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Given("Admin puts CHECK_DUE_INSTALLMENTS job into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||||
|
public void putCheckDueInstallmentsJobInCOB() throws IOException {
|
||||||
|
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||||
|
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||||
|
.order(2L);
|
||||||
|
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||||
|
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||||
|
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||||
|
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||||
|
BusinessStep checkDueInstallments = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_DUE_INSTALLMENTS).order(7L);
|
||||||
|
|
||||||
|
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||||
|
businessSteps.add(applyChargeToOverdueLoans);
|
||||||
|
businessSteps.add(loanDelinquencyClassification);
|
||||||
|
businessSteps.add(checkLoanRepaymentDue);
|
||||||
|
businessSteps.add(checkLoanRepaymentOverdue);
|
||||||
|
businessSteps.add(updateLoanArrearsAging);
|
||||||
|
businessSteps.add(addPeriodicAccrualEntries);
|
||||||
|
businessSteps.add(checkDueInstallments);
|
||||||
|
|
||||||
|
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||||
|
|
||||||
|
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Admin removes CHECK_DUE_INSTALLMENTS job from LOAN_CLOSE_OF_BUSINESS workflow")
|
||||||
|
public void removeCheckDueInstallmentsJobInCOB() throws IOException {
|
||||||
|
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||||
|
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||||
|
.order(2L);
|
||||||
|
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||||
|
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||||
|
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||||
|
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||||
|
|
||||||
|
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||||
|
businessSteps.add(applyChargeToOverdueLoans);
|
||||||
|
businessSteps.add(loanDelinquencyClassification);
|
||||||
|
businessSteps.add(checkLoanRepaymentDue);
|
||||||
|
businessSteps.add(checkLoanRepaymentOverdue);
|
||||||
|
businessSteps.add(updateLoanArrearsAging);
|
||||||
|
businessSteps.add(addPeriodicAccrualEntries);
|
||||||
|
|
||||||
|
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||||
|
|
||||||
|
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -33,6 +33,7 @@ import org.apache.fineract.test.helper.CodeHelper;
|
|||||||
import org.apache.fineract.test.helper.ErrorHelper;
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
import org.apache.fineract.test.helper.Utils;
|
import org.apache.fineract.test.helper.Utils;
|
||||||
|
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
import org.apache.fineract.test.support.TestContextKey;
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -49,6 +50,9 @@ public class ClientStepDef extends AbstractStepDef {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ClientRequestFactory clientRequestFactory;
|
private ClientRequestFactory clientRequestFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventCheckHelper eventCheckHelper;
|
||||||
|
|
||||||
@When("Admin creates a client with random data")
|
@When("Admin creates a client with random data")
|
||||||
public void createClientRandomFirstNameLastName() throws IOException {
|
public void createClientRandomFirstNameLastName() throws IOException {
|
||||||
PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest();
|
PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest();
|
||||||
@@ -56,6 +60,8 @@ public class ClientStepDef extends AbstractStepDef {
|
|||||||
Response<PostClientsResponse> response = clientApi.create6(clientsRequest).execute();
|
Response<PostClientsResponse> response = clientApi.create6(clientsRequest).execute();
|
||||||
ErrorHelper.checkSuccessfulApiCall(response);
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
|
testContext().set(TestContextKey.CLIENT_CREATE_RESPONSE, response);
|
||||||
|
|
||||||
|
eventCheckHelper.clientEventCheck(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@When("Admin creates a second client with random data")
|
@When("Admin creates a second client with random data")
|
||||||
@@ -65,6 +71,8 @@ public class ClientStepDef extends AbstractStepDef {
|
|||||||
Response<PostClientsResponse> response = clientApi.create6(clientsRequest).execute();
|
Response<PostClientsResponse> response = clientApi.create6(clientsRequest).execute();
|
||||||
ErrorHelper.checkSuccessfulApiCall(response);
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
testContext().set(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE, response);
|
testContext().set(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE, response);
|
||||||
|
|
||||||
|
eventCheckHelper.clientEventCheck(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@When("Admin creates a client with Firstname {string} and Lastname {string}")
|
@When("Admin creates a client with Firstname {string} and Lastname {string}")
|
||||||
@@ -114,5 +122,7 @@ public class ClientStepDef extends AbstractStepDef {
|
|||||||
Response<PostClientsResponse> response = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
Response<PostClientsResponse> response = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||||
|
|
||||||
assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue();
|
assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue();
|
||||||
|
|
||||||
|
eventCheckHelper.clientEventCheck(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.github.classgraph.ClassGraph;
|
||||||
|
import io.github.classgraph.ClassInfoList;
|
||||||
|
import io.github.classgraph.ScanResult;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.Event;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
public class EventStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@Then("{string} event has been raised for the loan")
|
||||||
|
public void assertEventRaisedForLoan(String eventType) {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Class<? extends Event> eventTypeClazz = resolveEventType(eventType);
|
||||||
|
eventAssertion.assertEventRaised(eventTypeClazz, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("No new event with type {string} has been raised for the loan")
|
||||||
|
public void assertEventNotRaisedForLoan(String eventType) {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Class<? extends Event> eventTypeClazz = resolveEventType(eventType);
|
||||||
|
eventAssertion.assertEventNotRaised(eventTypeClazz, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class<? extends Event> resolveEventType(String eventType) {
|
||||||
|
String fullyQualifiedEventClassName = null;
|
||||||
|
try (ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages("org.apache.fineract.test").scan()) {
|
||||||
|
ClassInfoList matchingClasses = scanResult.getAllClasses().filter(i -> i.getSimpleName().equalsIgnoreCase(eventType));
|
||||||
|
if (matchingClasses.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Cannot find event with type name: " + eventType);
|
||||||
|
}
|
||||||
|
fullyQualifiedEventClassName = matchingClasses.get(0).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends Event> eventTypeClazz = null;
|
||||||
|
try {
|
||||||
|
eventTypeClazz = (Class<? extends Event>) Class.forName(fullyQualifiedEventClassName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot find event with type name: " + eventType, e);
|
||||||
|
}
|
||||||
|
return eventTypeClazz;
|
||||||
|
}
|
||||||
|
}
|
||||||
+225
@@ -0,0 +1,225 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
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.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
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.JournalEntryTransactionItem;
|
||||||
|
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.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class JournalEntriesStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JournalEntriesApi journalEntriesApi;
|
||||||
|
|
||||||
|
@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);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||||
|
|
||||||
|
TransactionType transactionType1 = TransactionType.valueOf(transactionType);
|
||||||
|
String transactionTypeExpected = transactionType1.getValue();
|
||||||
|
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||||
|
|
||||||
|
List<GetLoansLoanIdTransactions> transactionsMatch = transactions.stream()
|
||||||
|
.filter(t -> transactionDate.equals(formatter.format(t.getDate()))
|
||||||
|
&& transactionTypeExpected.equals(t.getType().getCode().substring(20)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<List<JournalEntryTransactionItem>> journalLinesActualList = transactionsMatch.stream().map(t -> {
|
||||||
|
String transactionId = "L" + t.getId();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return journalEntryDataResponse.body().getPageItems();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
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);
|
||||||
|
boolean containsAnyExpected = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < journalLinesActualList.size(); j++) {
|
||||||
|
List<JournalEntryTransactionItem> journalLinesActual = journalLinesActualList.get(j);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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(i, possibleActualValuesList, expectedValues)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("In Loan transactions the replayed {string} transaction with date {string} has a reverted transaction pair with the following Journal entries:")
|
||||||
|
public void revertedJournalEntryDataCheck(String transactionType, String transactionDate, DataTable table) throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||||
|
|
||||||
|
TransactionType transactionType1 = TransactionType.valueOf(transactionType);
|
||||||
|
String transactionTypeExpected = transactionType1.getValue();
|
||||||
|
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||||
|
|
||||||
|
List<GetLoansLoanIdTransactions> transactionsMatch = transactions.stream()
|
||||||
|
.filter(t -> transactionDate.equals(formatter.format(t.getDate()))
|
||||||
|
&& transactionTypeExpected.equals(t.getType().getCode().substring(20)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<String> transactionIdList = transactionsMatch.stream().flatMap(t -> t.getTransactionRelations().stream()
|
||||||
|
.filter(e -> "REPLAYED".equals(e.getRelationType())).map(c -> "L" + c.getToLoanTransaction().toString()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<List<JournalEntryTransactionItem>> journalLinesActualList = transactionIdList.stream().map(t -> {
|
||||||
|
Response<GetJournalEntriesTransactionIdResponse> journalEntryDataResponse = null;
|
||||||
|
try {
|
||||||
|
journalEntryDataResponse = journalEntriesApi.retrieveAll1(//
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
t, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
null, //
|
||||||
|
true//
|
||||||
|
).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(journalEntryDataResponse);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Exception", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return journalEntryDataResponse.body().getPageItems();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
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);
|
||||||
|
boolean containsAnyExpected = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < journalLinesActualList.size(); j++) {
|
||||||
|
List<JournalEntryTransactionItem> journalLinesActual = journalLinesActualList.get(j);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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(i, possibleActualValuesList, expectedValues)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.And;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.test.data.job.DefaultJob;
|
||||||
|
import org.apache.fineract.test.service.JobService;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SchedulerStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JobService jobService;
|
||||||
|
|
||||||
|
@And("Admin runs the Add Accrual Transactions job")
|
||||||
|
public void runAccrualTransaction() {
|
||||||
|
jobService.executeAndWait(DefaultJob.ADD_ACCRUAL_TRANSACTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin runs the Add Periodic Accrual Transactions job")
|
||||||
|
public void runPeriodicAccrualTransaction() {
|
||||||
|
jobService.executeAndWait(DefaultJob.ADD_PERIODIC_ACCRUAL_TRANSACTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin runs the Increase Business Date by 1 day job")
|
||||||
|
public void runIncreaseBusinessDate() {
|
||||||
|
jobService.executeAndWait(DefaultJob.INCREASE_BUSINESS_DAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin runs the Loan Delinquency Classification job")
|
||||||
|
public void runLoanDelinquencyClassification() {
|
||||||
|
jobService.executeAndWait(DefaultJob.LOAN_DELINQUENCY_CLASSIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin runs COB job")
|
||||||
|
public void runCOB() {
|
||||||
|
jobService.executeAndWait(DefaultJob.LOAN_COB);
|
||||||
|
}
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.common;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.fineract.client.models.GetRolesResponse;
|
||||||
|
import org.apache.fineract.client.models.PostRolesRequest;
|
||||||
|
import org.apache.fineract.client.models.PostRolesResponse;
|
||||||
|
import org.apache.fineract.client.models.PostUsersRequest;
|
||||||
|
import org.apache.fineract.client.models.PostUsersResponse;
|
||||||
|
import org.apache.fineract.client.models.PutRolesRoleIdPermissionsRequest;
|
||||||
|
import org.apache.fineract.client.models.PutRolesRoleIdPermissionsResponse;
|
||||||
|
import org.apache.fineract.client.services.RolesApi;
|
||||||
|
import org.apache.fineract.client.services.UsersApi;
|
||||||
|
import org.apache.fineract.test.api.ApiProperties;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.Utils;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class UserStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
private static final String EMAIL = "test@test.com";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RolesApi rolesApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UsersApi usersApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApiProperties apiProperties;
|
||||||
|
|
||||||
|
@When("Admin creates new user with {string} username, {string} role name and given permissions:")
|
||||||
|
public void createUserWithUsernameAndRoles(String username, String roleName, List<String> permissions) throws IOException {
|
||||||
|
Response<List<GetRolesResponse>> retrieveAllRolesResponse = rolesApi.retrieveAllRoles().execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(retrieveAllRolesResponse);
|
||||||
|
PostRolesRequest newRoleRequest = new PostRolesRequest().name(Utils.randomNameGenerator(roleName, 8)).description(roleName);
|
||||||
|
Response<PostRolesResponse> createNewRole = rolesApi.createRole(newRoleRequest).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(createNewRole);
|
||||||
|
Long roleId = createNewRole.body().getResourceId();
|
||||||
|
Map<String, Boolean> permissionMap = new HashMap<>();
|
||||||
|
permissions.forEach(role -> permissionMap.put(role, true));
|
||||||
|
PutRolesRoleIdPermissionsRequest putRolesRoleIdPermissionsRequest = new PutRolesRoleIdPermissionsRequest()
|
||||||
|
.permissions(permissionMap);
|
||||||
|
Response<PutRolesRoleIdPermissionsResponse> updateRolePermissionResponse = rolesApi
|
||||||
|
.updateRolePermissions(roleId, putRolesRoleIdPermissionsRequest).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(updateRolePermissionResponse);
|
||||||
|
|
||||||
|
PostUsersRequest postUsersRequest = new PostUsersRequest() //
|
||||||
|
.username(Utils.randomNameGenerator(username, 8)) //
|
||||||
|
.email(EMAIL) //
|
||||||
|
.firstname(username) //
|
||||||
|
.lastname(username) //
|
||||||
|
.sendPasswordToEmail(Boolean.FALSE) //
|
||||||
|
.officeId(1L) //
|
||||||
|
.password(apiProperties.getPassword()) //
|
||||||
|
.repeatPassword(apiProperties.getPassword()) //
|
||||||
|
.roles(List.of(roleId));
|
||||||
|
|
||||||
|
Response<PostUsersResponse> createUserResponse = usersApi.create15(postUsersRequest).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(createUserResponse);
|
||||||
|
testContext().set(TestContextKey.CREATED_SIMPLE_USER_RESPONSE, createUserResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import org.apache.fineract.client.models.InlineJobRequest;
|
||||||
|
import org.apache.fineract.client.models.InlineJobResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.ExternalEventConfigurationApi;
|
||||||
|
import org.apache.fineract.client.services.InlineJobApi;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.assetexternalization.LoanAccountCustomSnapshotEvent;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.repayment.LoanRepaymentDueEvent;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.repayment.LoanRepaymentOverdueEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class InlineCOBStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd MMMM yyyy");
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InlineJobApi inlineJobApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ExternalEventConfigurationApi eventConfigurationApi;
|
||||||
|
|
||||||
|
@When("Admin runs inline COB job for Loan")
|
||||||
|
public void runInlineCOB() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
InlineJobRequest inlineJobRequest = new InlineJobRequest().addLoanIdsItem(loanId);
|
||||||
|
|
||||||
|
Response<InlineJobResponse> inlineJobResponse = inlineJobApi.executeInlineJob("LOAN_COB", inlineJobRequest).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(inlineJobResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan Repayment Due Business Event is created")
|
||||||
|
public void checkLoanRepaymentDueBusinessEventCreated() {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEventRaised(LoanRepaymentDueEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan Repayment Overdue Business Event is created")
|
||||||
|
public void checkLoanRepaymentOverdueBusinessEventCreated() {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEventRaised(LoanRepaymentOverdueEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanAccountCustomSnapshotBusinessEvent is created with business date {string}")
|
||||||
|
public void checkLoanRepaymentDueBusinessEventCreatedWithBusinessDate(String expectedBusinessDate) {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
LocalDate expectedBusinessDateParsed = LocalDate.parse(expectedBusinessDate, FORMATTER);
|
||||||
|
eventAssertion.assertEvent(LoanAccountCustomSnapshotEvent.class, loanId).isRaisedOnBusinessDate(expectedBusinessDateParsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.GetLoanAccountLockResponse;
|
||||||
|
import org.apache.fineract.client.models.GetOldestCOBProcessedLoanResponse;
|
||||||
|
import org.apache.fineract.client.models.LoanAccountLock;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.DefaultApi;
|
||||||
|
import org.apache.fineract.client.services.LoanAccountLockApi;
|
||||||
|
import org.apache.fineract.client.services.LoanCobCatchUpApi;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LoanCOBStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanCobCatchUpApi loanCobCatchUpApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanAccountLockApi loanAccountLockApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DefaultApi defaultApi;
|
||||||
|
|
||||||
|
@Then("The cobProcessedDate of the oldest loan processed by COB is more than 1 day earlier than cobBusinessDate")
|
||||||
|
public void checkOldestCOBProcessed() throws IOException {
|
||||||
|
Response<GetOldestCOBProcessedLoanResponse> response = loanCobCatchUpApi.getOldestCOBProcessedLoan().execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
LocalDate cobDate = response.body().getCobBusinessDate();
|
||||||
|
LocalDate cobDateMinusOne = cobDate.minusDays(1);
|
||||||
|
LocalDate cobProcessedDate = response.body().getCobProcessedDate();
|
||||||
|
log.info("cobDateMinusOne: {}", cobDateMinusOne);
|
||||||
|
log.info("cobProcessedDate: {}", cobProcessedDate);
|
||||||
|
|
||||||
|
boolean result = cobDateMinusOne.isAfter(cobProcessedDate);
|
||||||
|
assertThat(result).as(ErrorMessageHelper.wrongLastCOBProcessedLoanDate(cobProcessedDate, cobDateMinusOne)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("There are no locked loan accounts")
|
||||||
|
public void listOfLockedLoansEmpty() throws IOException {
|
||||||
|
Response<GetLoanAccountLockResponse> response = loanAccountLockApi.retrieveLockedAccounts(0, 1000).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
int size = response.body().getContent().size();
|
||||||
|
assertThat(size).as(ErrorMessageHelper.listOfLockedLoansNotEmpty(response)).isEqualTo(0);
|
||||||
|
log.info("Size of List of the locked loans: {}", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("The loan account is not locked")
|
||||||
|
public void loanIsNotInListOfLockedLoans() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
Long targetLoanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoanAccountLockResponse> response = loanAccountLockApi.retrieveLockedAccounts(0, 1000).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
List<LoanAccountLock> content = response.body().getContent();
|
||||||
|
boolean contains = content.stream()//
|
||||||
|
.map(LoanAccountLock::getLoanId)//
|
||||||
|
.anyMatch(targetLoanId::equals);//
|
||||||
|
|
||||||
|
assertThat(contains).as(ErrorMessageHelper.listOfLockedLoansContainsLoan(targetLoanId, response)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin places a lock on loan account with an error message")
|
||||||
|
public void placeLockOnLoanAccountWithErrorMessage() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<Void> response = defaultApi.placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING", "TestError").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin places a lock on loan account WITHOUT an error message")
|
||||||
|
public void placeLockOnLoanAccountNoErrorMessage() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<Void> response = defaultApi.placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
+188
@@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.fineract.client.models.BusinessDateResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.BusinessDateManagementApi;
|
||||||
|
import org.apache.fineract.client.services.LoanChargesApi;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.client.services.LoansApi;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.test.data.ChargeProductType;
|
||||||
|
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.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||||
|
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanChargesApi loanChargesApi;
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
@Autowired
|
||||||
|
private BusinessDateManagementApi businessDateManagementApi;
|
||||||
|
|
||||||
|
@When("Admin makes a charge adjustment for the last {string} type charge which is due on {string} with {double} EUR transaction amount and externalId {string}")
|
||||||
|
public void makeLoanChargeAdjustment(String chargeTypeEnum, String date, Double transactionAmount, String externalId)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "charges", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||||
|
|
||||||
|
Long transactionId = getTransactionIdForLastChargeMetConditions(chargeTypeEnum, date, loanDetailsResponse);
|
||||||
|
makeChargeAdjustmentCall(loanId, transactionId, externalId, transactionAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes a charge adjustment for the last {string} type charge which is due on {string} with transaction amount higher than the available charge amount")
|
||||||
|
public void loanChargeAdjustmentFailedOnWrongAmount(String chargeTypeEnum, String date) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "charges", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||||
|
|
||||||
|
Long transactionId = getTransactionIdForLastChargeMetConditions(chargeTypeEnum, date, loanDetailsResponse);
|
||||||
|
PostLoansLoanIdChargesChargeIdRequest chargeAdjustmentRequest = LoanRequestFactory.defaultChargeAdjustmentRequest().amount(8.0)
|
||||||
|
.externalId("");
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesChargeIdResponse> chargeAdjustmentResponseFail = loanChargesApi
|
||||||
|
.executeLoanCharge2(loanId, transactionId, chargeAdjustmentRequest, "adjustment").execute();
|
||||||
|
|
||||||
|
String string = chargeAdjustmentResponseFail.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(string, ErrorResponse.class);
|
||||||
|
Integer httpStatusCodeActual = errorResponse.getHttpStatusCode();
|
||||||
|
String developerMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||||
|
|
||||||
|
Integer httpStatusCodeExpected = 403;
|
||||||
|
String developerMessageExpected = "Transaction amount cannot be higher than the available charge amount for adjustment: 7.000000";
|
||||||
|
|
||||||
|
assertThat(httpStatusCodeActual)
|
||||||
|
.as(ErrorMessageHelper.wrongErrorCodeInFailedChargeAdjustment(httpStatusCodeActual, httpStatusCodeExpected))
|
||||||
|
.isEqualTo(httpStatusCodeExpected);
|
||||||
|
assertThat(developerMessageActual)
|
||||||
|
.as(ErrorMessageHelper.wrongErrorMessageInFailedChargeAdjustment(developerMessageActual, developerMessageExpected))
|
||||||
|
.isEqualTo(developerMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin reverts the charge adjustment which was raised on {string} with {double} EUR transaction amount")
|
||||||
|
public void loanChargeAdjustmentUndo(String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||||
|
|
||||||
|
Long transactionId = getTransactionIdForTransactionMetConditions(transactionDate, transactionAmount, loanDetailsResponse);
|
||||||
|
|
||||||
|
Response<List<BusinessDateResponse>> businessDateResponse = businessDateManagementApi.getBusinessDates().execute();
|
||||||
|
LocalDate businessDate = businessDateResponse.body().get(0).getDate();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
String businessDateActual = formatter.format(businessDate);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest chargeAdjustmentUndoRequest = LoanRequestFactory
|
||||||
|
.defaultChargeAdjustmentTransactionUndoRequest().transactionDate(businessDateActual);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> chargeAdjustmentUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, transactionId, chargeAdjustmentUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(chargeAdjustmentUndoResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getTransactionIdForTransactionMetConditions(String transactionDate, double transactionAmount,
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse) {
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||||
|
GetLoansLoanIdTransactions transactionMetConditions = new GetLoansLoanIdTransactions();
|
||||||
|
for (int i = 0; i < transactions.size(); i++) {
|
||||||
|
LocalDate date = transactions.get(i).getDate();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
String dateActual = formatter.format(date);
|
||||||
|
|
||||||
|
Double amountActual = transactions.get(i).getAmount();
|
||||||
|
|
||||||
|
if (dateActual.equals(transactionDate) && amountActual.equals(transactionAmount)) {
|
||||||
|
transactionMetConditions = transactions.get(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transactionMetConditions.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeChargeAdjustmentCall(Long loanId, Long transactionId, String externalId, double transactionAmount) throws IOException {
|
||||||
|
PostLoansLoanIdChargesChargeIdRequest chargeAdjustmentRequest = LoanRequestFactory.defaultChargeAdjustmentRequest()
|
||||||
|
.amount(transactionAmount).externalId(externalId);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesChargeIdResponse> chargeAdjustmentResponse = loanChargesApi
|
||||||
|
.executeLoanCharge2(loanId, transactionId, chargeAdjustmentRequest, "adjustment").execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_CHARGE_ADJUSTMENT_RESPONSE, chargeAdjustmentResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(chargeAdjustmentResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getTransactionIdForLastChargeMetConditions(String chargeTypeEnum, String date,
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetailsResponse) {
|
||||||
|
List<GetLoansLoanIdLoanChargeData> charges = loanDetailsResponse.body().getCharges();
|
||||||
|
|
||||||
|
ChargeProductType chargeType = ChargeProductType.valueOf(chargeTypeEnum);
|
||||||
|
Long chargeProductId = chargeType.getValue();
|
||||||
|
|
||||||
|
List<GetLoansLoanIdLoanChargeData> resultList = new ArrayList<>();
|
||||||
|
charges.forEach(charge -> {
|
||||||
|
Long chargeId = charge.getChargeId();
|
||||||
|
LocalDate dueDate = charge.getDueDate();
|
||||||
|
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
String chargeDueDate = formatter.format(dueDate);
|
||||||
|
|
||||||
|
if (chargeId.equals(chargeProductId) && chargeDueDate.equals(date)) {
|
||||||
|
resultList.add(charge);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
GetLoansLoanIdLoanChargeData lastChargeResult = resultList.get(resultList.size() - 1);
|
||||||
|
return lastChargeResult.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
+174
@@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanTransactionEnumDataV1;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansType;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.client.services.LoansApi;
|
||||||
|
import org.apache.fineract.test.data.paymenttype.DefaultPaymentType;
|
||||||
|
import org.apache.fineract.test.data.paymenttype.PaymentTypeResolver;
|
||||||
|
import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargebackTransactionEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class LoanChargeBackStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PaymentTypeResolver paymentTypeResolver;
|
||||||
|
|
||||||
|
@When("Admin makes {string} chargeback with {double} EUR transaction amount")
|
||||||
|
public void makeLoanChargeback(String repaymentType, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
Long transactionId = Long.valueOf(repaymentResponse.body().getResourceId());
|
||||||
|
|
||||||
|
makeChargebackCall(loanId, transactionId, repaymentType, transactionAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes {string} chargeback with {double} EUR transaction amount for Payment nr. {double}")
|
||||||
|
public void makeLoanChargebackForPayment(String repaymentType, double transactionAmount, double paymentNr) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetails.body().getTransactions();
|
||||||
|
|
||||||
|
List<Long> transactionIdList = new ArrayList<>();
|
||||||
|
for (GetLoansLoanIdTransactions f : transactions) {
|
||||||
|
String code = f.getType().getCode();
|
||||||
|
if (code.equals("loanTransactionType.repayment")) {
|
||||||
|
transactionIdList.add(f.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(transactionIdList);
|
||||||
|
Long transactionId = transactionIdList.get((int) paymentNr - 1);
|
||||||
|
|
||||||
|
makeChargebackCall(loanId, transactionId, repaymentType, transactionAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin makes {string} chargeback with {double} EUR transaction amount for Downpayment nr. {double}")
|
||||||
|
public void makeLoanChargebackForDownpaymentayment(String repaymentType, double transactionAmount, double paymentNr)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetails.body().getTransactions();
|
||||||
|
|
||||||
|
List<Long> transactionIdList = new ArrayList<>();
|
||||||
|
for (GetLoansLoanIdTransactions f : transactions) {
|
||||||
|
String code = f.getType().getCode();
|
||||||
|
if (code.equals("loanTransactionType.downPayment")) {
|
||||||
|
transactionIdList.add(f.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(transactionIdList);
|
||||||
|
Long transactionId = transactionIdList.get((int) paymentNr - 1);
|
||||||
|
|
||||||
|
makeChargebackCall(loanId, transactionId, repaymentType, transactionAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeChargebackCall(Long loanId, Long transactionId, String repaymentType, double transactionAmount) throws IOException {
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest chargebackRequest = LoanRequestFactory.defaultChargebackRequest()
|
||||||
|
.paymentTypeId(paymentTypeValue).transactionAmount(transactionAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> chargebackResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, transactionId, chargebackRequest, "chargeback").execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_CHARGEBACK_RESPONSE, chargebackResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(chargebackResponse);
|
||||||
|
|
||||||
|
checkEvents(chargebackResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEvents(Response<PostLoansLoanIdTransactionsResponse> chargebackResponse) throws IOException {
|
||||||
|
PostLoansLoanIdTransactionsResponse responseBody = chargebackResponse.body();
|
||||||
|
Long loanId = responseBody.getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEvent(LoanBalanceChangedEvent.class, loanId).extractingData(data -> data.getId()).isEqualTo(loanId);
|
||||||
|
|
||||||
|
checkLoanChargebackTransactionEvent(responseBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkLoanChargebackTransactionEvent(PostLoansLoanIdTransactionsResponse chargebackResponse) throws IOException {
|
||||||
|
|
||||||
|
// get loanId and transactionId
|
||||||
|
Long loanId = chargebackResponse.getLoanId();
|
||||||
|
long transactionId = Long.valueOf(chargebackResponse.getResourceId());
|
||||||
|
|
||||||
|
// retrieve transaction details
|
||||||
|
Response<GetLoansLoanIdTransactionsTransactionIdResponse> transactionResponse = loanTransactionsApi
|
||||||
|
.retrieveTransaction(loanId, transactionId, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(transactionResponse);
|
||||||
|
|
||||||
|
GetLoansLoanIdTransactionsTransactionIdResponse transactionResponseBody = transactionResponse.body();
|
||||||
|
|
||||||
|
// Get transaction type from response
|
||||||
|
GetLoansType transactionType = transactionResponseBody.getType();
|
||||||
|
// Build expected avro transaction type from api response type
|
||||||
|
LoanTransactionEnumDataV1 expectedEventTransactionType = LoanTransactionEnumDataV1.newBuilder()
|
||||||
|
.setId(transactionType.getId().intValue()).setCode(transactionType.getCode()).setValue("Chargeback")
|
||||||
|
.setDisbursement(transactionType.getDisbursement()).setRepaymentAtDisbursement(transactionType.getRepaymentAtDisbursement())
|
||||||
|
.setRepayment(transactionType.getRepayment()).setMerchantIssuedRefund(false).setPayoutRefund(false).setGoodwillCredit(false)
|
||||||
|
.setChargeRefund(false).setContra(transactionType.getContra()).setWaiveInterest(transactionType.getWaiveInterest())
|
||||||
|
.setWaiveCharges(transactionType.getWaiveCharges()).setAccrual(false).setWriteOff(transactionType.getWriteOff())
|
||||||
|
.setRecoveryRepayment(transactionType.getRecoveryRepayment()).setInitiateTransfer(false).setApproveTransfer(false)
|
||||||
|
.setWithdrawTransfer(false).setRejectTransfer(false).setChargePayment(false).setRefund(false).setRefundForActiveLoans(false)
|
||||||
|
.setCreditBalanceRefund(false).setChargeback(true).build();
|
||||||
|
|
||||||
|
// verify payload for loanId, transactionId, transactionType, amount
|
||||||
|
eventAssertion.assertEvent(LoanChargebackTransactionEvent.class, transactionId).extractingData(LoanTransactionDataV1::getLoanId)
|
||||||
|
.isEqualTo(loanId).extractingData(LoanTransactionDataV1::getType).isEqualTo(expectedEventTransactionType)
|
||||||
|
.extractingBigDecimal(LoanTransactionDataV1::getAmount).isEqualTo(BigDecimal.valueOf(transactionResponseBody.getAmount()));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+296
@@ -0,0 +1,296 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import io.cucumber.datatable.DataTable;
|
||||||
|
import io.cucumber.java.en.And;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanChargeDataV1;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdChargesChargeIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.models.PutChargeTransactionChangesRequest;
|
||||||
|
import org.apache.fineract.client.models.PutChargeTransactionChangesResponse;
|
||||||
|
import org.apache.fineract.client.services.LoanChargesApi;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.client.services.LoansApi;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.test.data.ChargeProductType;
|
||||||
|
import org.apache.fineract.test.data.ErrorMessageType;
|
||||||
|
import org.apache.fineract.test.factory.LoanChargeRequestFactory;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.charge.LoanAddChargeEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LoanChargeStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String DEFAULT_DATE_FORMAT = "dd MMMM yyyy";
|
||||||
|
public static final String DATE_FORMAT_EVENTS = "yyyy-MM-dd";
|
||||||
|
public static final Double DEFAULT_CHARGE_FEE_FLAT = 10D;
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanChargesApi loanChargesApi;
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@When("Admin adds {string} due date charge with {string} due date and {double} EUR transaction amount")
|
||||||
|
public void addChargeDueDate(String chargeType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
ChargeProductType chargeProductType = ChargeProductType.valueOf(chargeType);
|
||||||
|
Long chargeTypeId = chargeProductType.getValue();
|
||||||
|
if (chargeTypeId.equals(ChargeProductType.LOAN_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
|| chargeTypeId.equals(ChargeProductType.LOAN_TRANCHE_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
|| chargeTypeId.equals(ChargeProductType.LOAN_INSTALLMENT_PERCENTAGE_FEE.getValue())) {
|
||||||
|
throw new IllegalStateException(String.format("The requested %s charge is NOT due date type, cannot be used here", chargeType));
|
||||||
|
}
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest().chargeId(chargeTypeId)
|
||||||
|
.dueDate(transactionDate).amount(transactionAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||||
|
testContext().set(TestContextKey.ADD_DUE_DATE_CHARGE_RESPONSE, loanChargeResponse);
|
||||||
|
|
||||||
|
addChargeEventCheck(loanChargeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin adds {string} charge with {double} % of transaction amount")
|
||||||
|
public void addChargePercentage(String chargeType, double transactionPercentageAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
ChargeProductType chargeProductType = ChargeProductType.valueOf(chargeType);
|
||||||
|
Long chargeTypeId = chargeProductType.getValue();
|
||||||
|
if (!chargeTypeId.equals(ChargeProductType.LOAN_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
&& !chargeTypeId.equals(ChargeProductType.LOAN_TRANCHE_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
&& !chargeTypeId.equals(ChargeProductType.LOAN_INSTALLMENT_PERCENTAGE_FEE.getValue())) {
|
||||||
|
throw new IllegalStateException(String.format("The requested %s charge is due date type, cannot be used here", chargeType));
|
||||||
|
}
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest().chargeId(chargeTypeId)
|
||||||
|
.amount(transactionPercentageAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||||
|
testContext().set(TestContextKey.ADD_DUE_DATE_CHARGE_RESPONSE, loanChargeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Admin is not able to add {string} due date charge with {string} due date and {double} EUR transaction amount because the of charged-off account")
|
||||||
|
public void addChargeDueDateOnChargedOff(String chargeType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
ChargeProductType chargeProductType = ChargeProductType.valueOf(chargeType);
|
||||||
|
Long chargeTypeId = chargeProductType.getValue();
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest().chargeId(chargeTypeId)
|
||||||
|
.dueDate(transactionDate).amount(transactionAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
testContext().set(TestContextKey.ADD_DUE_DATE_CHARGE_RESPONSE, loanChargeResponse);
|
||||||
|
ErrorResponse errorDetails = ErrorResponse.from(loanChargeResponse);
|
||||||
|
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.addChargeForChargeOffLoanCodeMsg()).isEqualTo(403);
|
||||||
|
assertThat(errorDetails.getSingleError().getDeveloperMessage())
|
||||||
|
.isEqualTo(ErrorMessageHelper.addChargeForChargeOffLoanFailure(loanId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin adds a {double} % Processing charge to the loan with {string} locale on date: {string}")
|
||||||
|
public void addProcessingFee(double chargeAmount, String locale, String date) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest()
|
||||||
|
.chargeId(ChargeProductType.LOAN_PERCENTAGE_PROCESSING_FEE.value).amount(chargeAmount).dueDate(date)
|
||||||
|
.dateFormat(DEFAULT_DATE_FORMAT).locale(locale);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||||
|
testContext().set(TestContextKey.ADD_PROCESSING_FEE_RESPONSE, loanChargeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin adds an NSF fee because of payment bounce with {string} transaction date")
|
||||||
|
public void addNSFfee(String date) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest()
|
||||||
|
.chargeId(ChargeProductType.LOAN_NSF_FEE.value).amount(DEFAULT_CHARGE_FEE_FLAT).dueDate(date)
|
||||||
|
.dateFormat(DEFAULT_DATE_FORMAT);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||||
|
testContext().set(TestContextKey.ADD_NSF_FEE_RESPONSE, loanChargeResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin waives charge")
|
||||||
|
public void waiveCharge() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = testContext().get(TestContextKey.ADD_NSF_FEE_RESPONSE);
|
||||||
|
Long chargeId = Long.valueOf(loanChargeResponse.body().getResourceId());
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesChargeIdRequest waiveRequest = new PostLoansLoanIdChargesChargeIdRequest();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesChargeIdResponse> waiveResponse = loanChargesApi
|
||||||
|
.executeLoanCharge2(loanId, chargeId, waiveRequest, "waive").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(waiveResponse);
|
||||||
|
testContext().set(TestContextKey.WAIVE_CHARGE_RESPONSE, waiveResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin waives due date charge")
|
||||||
|
public void waiveDueDateCharge() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = testContext().get(TestContextKey.ADD_DUE_DATE_CHARGE_RESPONSE);
|
||||||
|
Long chargeId = Long.valueOf(loanChargeResponse.body().getResourceId());
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesChargeIdRequest waiveRequest = new PostLoansLoanIdChargesChargeIdRequest();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesChargeIdResponse> waiveResponse = loanChargesApi
|
||||||
|
.executeLoanCharge2(loanId, chargeId, waiveRequest, "waive").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(waiveResponse);
|
||||||
|
testContext().set(TestContextKey.WAIVE_CHARGE_RESPONSE, waiveResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Admin makes waive undone for charge")
|
||||||
|
public void undoWaiveForCharge() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loanDetails.body().getTransactions();
|
||||||
|
|
||||||
|
Long transactionId = 0L;
|
||||||
|
for (GetLoansLoanIdTransactions f : transactions) {
|
||||||
|
String code = f.getType().getCode();
|
||||||
|
if (code.equals("loanTransactionType.waiveCharges")) {
|
||||||
|
transactionId = f.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PutChargeTransactionChangesRequest undoWaiveRequest = new PutChargeTransactionChangesRequest();
|
||||||
|
Response<PutChargeTransactionChangesResponse> undoWaiveResponse = loanTransactionsApi
|
||||||
|
.undoWaiveCharge(loanId, transactionId, undoWaiveRequest).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(undoWaiveResponse);
|
||||||
|
testContext().set(TestContextKey.UNDO_WAIVE_RESPONSE, undoWaiveResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Charge is successfully added to the loan")
|
||||||
|
public void loanChargeStatus() throws IOException {
|
||||||
|
Response<PostLoansLoanIdChargesResponse> response = testContext().get(TestContextKey.ADD_NSF_FEE_RESPONSE);
|
||||||
|
|
||||||
|
assertThat(response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue();
|
||||||
|
assertThat(response.code()).as(ErrorMessageHelper.requestFailedWithCode(response)).isEqualTo(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Charge is successfully added to the loan with {float} EUR")
|
||||||
|
public void checkLoanChargeAmount(float chargeAmount) throws IOException {
|
||||||
|
Response<PostLoansLoanIdChargesResponse> response = testContext().get(TestContextKey.ADD_PROCESSING_FEE_RESPONSE);
|
||||||
|
Response<GetLoansLoanIdChargesChargeIdResponse> loanChargeAmount = loanChargesApi
|
||||||
|
.retrieveLoanCharge(response.body().getLoanId(), Long.valueOf(response.body().getResourceId())).execute();
|
||||||
|
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
assertThat(loanChargeAmount.body().getAmount()).as("Charge amount is wrong").isEqualTo(chargeAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addChargeEventCheck(Response<PostLoansLoanIdChargesResponse> loanChargeResponse) throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT_EVENTS);
|
||||||
|
Response<GetLoansLoanIdChargesChargeIdResponse> chargeDetails = loanChargesApi
|
||||||
|
.retrieveLoanCharge(loanChargeResponse.body().getLoanId(), loanChargeResponse.body().getResourceId()).execute();
|
||||||
|
GetLoansLoanIdChargesChargeIdResponse body = chargeDetails.body();
|
||||||
|
|
||||||
|
eventAssertion.assertEvent(LoanAddChargeEvent.class, loanChargeResponse.body().getResourceId())
|
||||||
|
.extractingData(LoanChargeDataV1::getName).isEqualTo(body.getName())
|
||||||
|
.extractingData(loanChargeDataV1 -> loanChargeDataV1.getAmount().longValue()).isEqualTo(body.getAmount().longValue())
|
||||||
|
.extractingData(LoanChargeDataV1::getDueDate).isEqualTo(formatter.format(body.getDueDate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan charge transaction with the following data results a {int} error and {string} error message")
|
||||||
|
public void chargeOffTransactionError(int errorCodeExpected, String errorMessageType, DataTable table) throws IOException {
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> chargeData = data.get(1);
|
||||||
|
String chargeType = chargeData.get(0);
|
||||||
|
String transactionDate = chargeData.get(1);
|
||||||
|
Double transactionAmount = Double.valueOf(chargeData.get(2));
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
ErrorMessageType errorMsgType = ErrorMessageType.valueOf(errorMessageType);
|
||||||
|
String errorMessageExpectedRaw = errorMsgType.getValue();
|
||||||
|
String errorMessageExpected = String.format(errorMessageExpectedRaw, loanId);
|
||||||
|
|
||||||
|
ChargeProductType chargeProductType = ChargeProductType.valueOf(chargeType);
|
||||||
|
Long chargeTypeId = chargeProductType.getValue();
|
||||||
|
if (chargeTypeId.equals(ChargeProductType.LOAN_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
|| chargeTypeId.equals(ChargeProductType.LOAN_TRANCHE_DISBURSEMENT_PERCENTAGE_FEE.getValue())
|
||||||
|
|| chargeTypeId.equals(ChargeProductType.LOAN_INSTALLMENT_PERCENTAGE_FEE.getValue())) {
|
||||||
|
throw new IllegalStateException(String.format("The requested %s charge is NOT due date type, cannot be used here", chargeType));
|
||||||
|
}
|
||||||
|
|
||||||
|
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest().chargeId(chargeTypeId)
|
||||||
|
.dueDate(transactionDate).amount(transactionAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdChargesResponse> loanChargeResponse = loanChargesApi.executeLoanCharge(loanId, loanIdChargesRequest, "")
|
||||||
|
.execute();
|
||||||
|
int errorCodeActual = loanChargeResponse.code();
|
||||||
|
String errorBody = loanChargeResponse.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorBody, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
}
|
||||||
+771
@@ -0,0 +1,771 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
import io.cucumber.datatable.DataTable;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanAccountDelinquencyRangeDataV1;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1;
|
||||||
|
import org.apache.fineract.client.models.GetDelinquencyActionsResponse;
|
||||||
|
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
|
||||||
|
import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencyPausePeriod;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencySummary;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdLoanInstallmentLevelDelinquency;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetUsersUserIdResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansDelinquencyActionRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansDelinquencyActionResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.models.PostUsersResponse;
|
||||||
|
import org.apache.fineract.client.services.LoansApi;
|
||||||
|
import org.apache.fineract.client.services.UsersApi;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.test.api.ApiProperties;
|
||||||
|
import org.apache.fineract.test.data.DelinquencyRange;
|
||||||
|
import org.apache.fineract.test.data.LoanStatus;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyRangeChangeEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LoanDelinquencyStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||||
|
public static final String DEFAULT_LOCALE = "en";
|
||||||
|
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventCheckHelper eventCheckHelper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApiProperties apiProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UsersApi usersApi;
|
||||||
|
|
||||||
|
@Then("Admin checks that delinquency range is: {string} and has delinquentDate {string}")
|
||||||
|
public void checkDelinquencyRange(String range, String delinquentDateExpected) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
Integer loanStatus = loanDetails.body().getStatus().getId();
|
||||||
|
|
||||||
|
if (!LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.value.equals(loanStatus) && !LoanStatus.APPROVED.value.equals(loanStatus)) {
|
||||||
|
String delinquentDateExpectedValue = "".equals(delinquentDateExpected) ? null : delinquentDateExpected;
|
||||||
|
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)//
|
||||||
|
.extractingData(LoanAccountDelinquencyRangeDataV1::getDelinquentDate)//
|
||||||
|
.isEqualTo(delinquentDateExpectedValue);//
|
||||||
|
}
|
||||||
|
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(range);
|
||||||
|
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||||
|
|
||||||
|
String actualDelinquencyRangeValue = DelinquencyRange.NO_DELINQUENCY.value;
|
||||||
|
GetDelinquencyRangesResponse actualDelinquencyRange = loanDetails.body().getDelinquencyRange();
|
||||||
|
if (actualDelinquencyRange != null) {
|
||||||
|
actualDelinquencyRangeValue = actualDelinquencyRange.getClassification();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(actualDelinquencyRangeValue)
|
||||||
|
.as(ErrorMessageHelper.delinquencyRangeError(actualDelinquencyRangeValue, expectedDelinquencyRangeValue))
|
||||||
|
.isEqualTo(expectedDelinquencyRangeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Admin checks that {string}th delinquency range is: {string} and added on: {string} and has delinquentDate {string}")
|
||||||
|
public void checkDelinquencyRange(String nthInList, String range, String addedOnDate, String delinquentDateExpected)
|
||||||
|
throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
String delinquentDateExpectedValue = "".equals(delinquentDateExpected) ? null : delinquentDateExpected;
|
||||||
|
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)
|
||||||
|
.extractingData(LoanAccountDelinquencyRangeDataV1::getDelinquentDate).isEqualTo(delinquentDateExpectedValue);
|
||||||
|
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(range);
|
||||||
|
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||||
|
|
||||||
|
Response<List<GetDelinquencyTagHistoryResponse>> delinquencyHistoryDetails = loansApi.getDelinquencyTagHistory(loanId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(delinquencyHistoryDetails);
|
||||||
|
|
||||||
|
String actualDelinquencyRangeValue = DelinquencyRange.NO_DELINQUENCY.value;
|
||||||
|
String actualDelinquencyAddedOnDate = "";
|
||||||
|
int i = Integer.parseInt(nthInList) - 1;
|
||||||
|
GetDelinquencyTagHistoryResponse delinquencyTag = delinquencyHistoryDetails.body().get(i);
|
||||||
|
if (delinquencyTag != null) {
|
||||||
|
actualDelinquencyRangeValue = delinquencyTag.getDelinquencyRange().getClassification();
|
||||||
|
actualDelinquencyAddedOnDate = formatter.format(delinquencyTag.getAddedOnDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(actualDelinquencyRangeValue)
|
||||||
|
.as(ErrorMessageHelper.delinquencyRangeError(actualDelinquencyRangeValue, expectedDelinquencyRangeValue))
|
||||||
|
.isEqualTo(expectedDelinquencyRangeValue);
|
||||||
|
assertThat(actualDelinquencyAddedOnDate).as(ErrorMessageHelper.delinquencyRangeError(actualDelinquencyAddedOnDate, addedOnDate))
|
||||||
|
.isEqualTo(addedOnDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan delinquency history has the following details:")
|
||||||
|
public void delinquencyHistoryCheck(DataTable table) throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
List<List<String>> dataExpected = table.asLists();
|
||||||
|
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<List<GetDelinquencyTagHistoryResponse>> delinquencyHistoryDetails = loansApi.getDelinquencyTagHistory(loanId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(delinquencyHistoryDetails);
|
||||||
|
List<GetDelinquencyTagHistoryResponse> body = delinquencyHistoryDetails.body();
|
||||||
|
|
||||||
|
for (int i = 0; i < body.size(); i++) {
|
||||||
|
List<String> line = dataExpected.get(i + 1);
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(line.get(0));
|
||||||
|
String classificationExpected = expectedDelinquencyRange.getValue();
|
||||||
|
String addedOnDateExpected = line.get(1);
|
||||||
|
String liftedOnDateExpected = line.get(2);
|
||||||
|
|
||||||
|
String classificationActual = body.get(i).getDelinquencyRange().getClassification();
|
||||||
|
String addedOnDateActual = body.get(i).getAddedOnDate() == null ? null : formatter.format(body.get(i).getAddedOnDate());
|
||||||
|
String liftedOnDateActual = body.get(i).getLiftedOnDate() == null ? null : formatter.format(body.get(i).getLiftedOnDate());
|
||||||
|
|
||||||
|
assertThat(classificationActual)
|
||||||
|
.as(ErrorMessageHelper.wrongDataInDelinquencyHistoryClassification(classificationActual, classificationExpected))
|
||||||
|
.isEqualTo(classificationExpected);
|
||||||
|
assertThat(addedOnDateActual)
|
||||||
|
.as(ErrorMessageHelper.wrongDataInDelinquencyHistoryAddedOnDate(addedOnDateActual, addedOnDateExpected))
|
||||||
|
.isEqualTo(addedOnDateExpected);
|
||||||
|
assertThat(liftedOnDateActual)
|
||||||
|
.as(ErrorMessageHelper.wrongDataInDelinquencyHistoryLiftedOnDate(liftedOnDateActual, liftedOnDateExpected))
|
||||||
|
.isEqualTo(liftedOnDateExpected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}")
|
||||||
|
public void delinquencyPause(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountDelinquencyPauseChangedBusinessEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Created user with CREATE_DELINQUENCY_ACTION permission initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}")
|
||||||
|
public void delinquencyPauseWithCreatedUser(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
Response<PostUsersResponse> createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE);
|
||||||
|
Long createdUserId = createUserResponse.body().getResourceId();
|
||||||
|
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(user);
|
||||||
|
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword();
|
||||||
|
Base64 base64 = new Base64();
|
||||||
|
headerMap.put("Authorization",
|
||||||
|
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request, headerMap).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountDelinquencyPauseChangedBusinessEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Created user with no CREATE_DELINQUENCY_ACTION permission gets an error when initiate a DELINQUENCY PAUSE with startDate: {string} and endDate: {string}")
|
||||||
|
public void delinquencyPauseWithCreatedUserNOPermissionError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
int errorCodeExpected = 403;
|
||||||
|
String errorMessageExpected = "User has no authority to CREATE delinquency_actions";
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
Response<PostUsersResponse> createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE);
|
||||||
|
Long createdUserId = createUserResponse.body().getResourceId();
|
||||||
|
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(user);
|
||||||
|
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword();
|
||||||
|
Base64 base64 = new Base64();
|
||||||
|
headerMap.put("Authorization",
|
||||||
|
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request, headerMap).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
int errorCodeActual = response.code();
|
||||||
|
String errorBody = response.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorBody, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin initiate a DELINQUENCY RESUME with startDate: {string}")
|
||||||
|
public void delinquencyResume(String startDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountDelinquencyPauseChangedBusinessEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin initiate a DELINQUENCY PAUSE by loanExternalId with startDate: {string} and endDate: {string}")
|
||||||
|
public void delinquencyPauseByLoanExternalId(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction1(loanExternalId, request).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountDelinquencyPauseChangedBusinessEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin initiate a DELINQUENCY RESUME by loanExternalId with startDate: {string}")
|
||||||
|
public void delinquencyResumeByLoanExternalId(String startDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction1(loanExternalId, request).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_DELINQUENCY_ACTION_RESPONSE, response);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
|
||||||
|
eventCheckHelper.loanAccountDelinquencyPauseChangedBusinessEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Delinquency-actions have the following data:")
|
||||||
|
public void getDelinquencyActionData(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
int nrOfLinesExpected = data.size() - 1;
|
||||||
|
|
||||||
|
Response<List<GetDelinquencyActionsResponse>> response = loansApi.getLoanDelinquencyActions(loanId).execute();
|
||||||
|
int nrOfLinesActual = response.body().size();
|
||||||
|
|
||||||
|
assertThat(nrOfLinesActual)//
|
||||||
|
.as(ErrorMessageHelper.wrongNumberOfLinesInDelinquencyActions(nrOfLinesActual, nrOfLinesExpected))//
|
||||||
|
.isEqualTo(nrOfLinesExpected);//
|
||||||
|
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
List<String> expectedValues = data.get(i);
|
||||||
|
|
||||||
|
GetDelinquencyActionsResponse lineActual = response.body().get(i - 1);
|
||||||
|
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
actualValues.add(Objects.requireNonNull(lineActual.getAction()));
|
||||||
|
actualValues.add(FORMATTER.format(Objects.requireNonNull(lineActual.getStartDate())));
|
||||||
|
actualValues.add(lineActual.getEndDate() == null ? null : FORMATTER.format(lineActual.getEndDate()));
|
||||||
|
|
||||||
|
assertThat(actualValues)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLineDelinquencyActions(i, actualValues, expectedValues))//
|
||||||
|
.isEqualTo(expectedValues);//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a delinquency-action other than PAUSE or RESUME in action field results an error - startDate: {string}, endDate: {string}")
|
||||||
|
public void actionFieldError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("TEST")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Invalid Delinquency Action: TEST";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY PAUSE with startDate before the actual business date results an error - startDate: {string}, endDate: {string}")
|
||||||
|
public void delinquencyPauseStartDateError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Start date of pause period must be in the future";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY PAUSE on a non-active loan results an error - startDate: {string}, endDate: {string}")
|
||||||
|
public void delinquencyPauseNonActiveLoanError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Delinquency actions can be created only for active loans.";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY RESUME on a non-active loan results an error - startDate: {string}")
|
||||||
|
public void delinquencyResumeNonActiveLoanError(String startDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Delinquency actions can be created only for active loans.";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Overlapping PAUSE periods result an error - startDate: {string}, endDate: {string}")
|
||||||
|
public void delinquencyPauseOverlappingError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("pause")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Delinquency pause period cannot overlap with another pause period";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY RESUME without an active PAUSE period results an error - startDate: {string}")
|
||||||
|
public void delinquencyResumeWithoutPauseError(String startDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Resume Delinquency Action can only be created during an active pause";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY RESUME with start date other than actual business date results an error - startDate: {string}")
|
||||||
|
public void delinquencyResumeStartDateError(String startDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Start date of the Resume Delinquency action must be the current business date";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Initiating a DELINQUENCY RESUME with an endDate results an error - startDate: {string}, endDate: {string}")
|
||||||
|
public void delinquencyResumeWithEndDateError(String startDate, String endDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansDelinquencyActionRequest request = new PostLoansDelinquencyActionRequest()//
|
||||||
|
.action("resume")//
|
||||||
|
.startDate(startDate)//
|
||||||
|
.endDate(endDate)//
|
||||||
|
.dateFormat(DATE_FORMAT)//
|
||||||
|
.locale(DEFAULT_LOCALE);//
|
||||||
|
|
||||||
|
Response<PostLoansDelinquencyActionResponse> response = loansApi.createLoanDelinquencyAction(loanId, request).execute();
|
||||||
|
int errorCodeExpected = 400;
|
||||||
|
String errorMessageExpected = "Resume Delinquency action can not have end date";
|
||||||
|
errorMessageAssertation(response, errorCodeExpected, errorMessageExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Installment level delinquency event has correct data")
|
||||||
|
public void installmentLevelDelinquencyEventCheck() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventCheckHelper.installmentLevelDelinquencyRangeChangeEventCheck(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("INSTALLMENT level delinquency is null")
|
||||||
|
public void installmentLevelDelinquencyNull() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
List<GetLoansLoanIdLoanInstallmentLevelDelinquency> installmentLevelDelinquency = loanDetails.body().getDelinquent()
|
||||||
|
.getInstallmentLevelDelinquency() == null ? null : loanDetails.body().getDelinquent().getInstallmentLevelDelinquency();
|
||||||
|
assertThat(installmentLevelDelinquency).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan has the following LOAN level delinquency data:")
|
||||||
|
public void loanDelinquencyDataCheck(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<String> expectedValuesList = table.asLists().get(1);
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedValuesList.get(0));
|
||||||
|
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||||
|
expectedValuesList.set(0, expectedDelinquencyRangeValue);
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
String actualDelinquencyRangeValue = loanDetails.body().getDelinquencyRange() == null ? "NO_DELINQUENCY"
|
||||||
|
: loanDetails.body().getDelinquencyRange().getClassification();
|
||||||
|
GetLoansLoanIdDelinquencySummary delinquent = loanDetails.body().getDelinquent();
|
||||||
|
List<String> actualValuesList = List.of(actualDelinquencyRangeValue, delinquent.getDelinquentAmount().toString(),
|
||||||
|
delinquent.getDelinquentDate() == null ? "null" : FORMATTER.format(delinquent.getDelinquentDate()),
|
||||||
|
delinquent.getDelinquentDays().toString(), delinquent.getPastDueDays().toString());
|
||||||
|
|
||||||
|
assertThat(actualValuesList).as(ErrorMessageHelper.wrongValueInLoanLevelDelinquencyData(actualValuesList, expectedValuesList))
|
||||||
|
.isEqualTo(expectedValuesList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan has the following INSTALLMENT level delinquency data:")
|
||||||
|
public void loanDelinquencyInstallmentLevelDataCheck(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
List<GetLoansLoanIdLoanInstallmentLevelDelinquency> installmentLevelDelinquency = loanDetails.body().getDelinquent()
|
||||||
|
.getInstallmentLevelDelinquency();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
assertThat(installmentLevelDelinquency.size())
|
||||||
|
.as(ErrorMessageHelper.nrOfLinesWrongInInstallmentLevelDelinquencyData(installmentLevelDelinquency.size(), data.size() - 1))
|
||||||
|
.isEqualTo(data.size() - 1);
|
||||||
|
for (int i = 1; i < data.size(); i++) {
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(data.get(i).get(1));
|
||||||
|
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||||
|
|
||||||
|
List<String> expectedValuesList = data.get(i);
|
||||||
|
expectedValuesList.set(1, expectedDelinquencyRangeValue);
|
||||||
|
|
||||||
|
List<String> actualValuesList = List.of(String.valueOf(installmentLevelDelinquency.get(i - 1).getRangeId()),
|
||||||
|
installmentLevelDelinquency.get(i - 1).getClassification(),
|
||||||
|
installmentLevelDelinquency.get(i - 1).getDelinquentAmount().setScale(2, RoundingMode.HALF_DOWN).toString());
|
||||||
|
assertThat(actualValuesList)
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLineInInstallmentLevelDelinquencyData(i, actualValuesList, expectedValuesList))
|
||||||
|
.isEqualTo(expectedValuesList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan Delinquency pause periods has the following data:")
|
||||||
|
public void loanDelinquencyPauseDataCheck(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<List<String>> expectedData = table.asLists();
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
|
||||||
|
List<GetLoansLoanIdDelinquencyPausePeriod> delinquencyPausePeriods = loanDetails.body().getDelinquent()
|
||||||
|
.getDelinquencyPausePeriods();
|
||||||
|
|
||||||
|
assertThat(delinquencyPausePeriods.size())
|
||||||
|
.as(ErrorMessageHelper.nrOfLinesWrongInLoanDelinquencyPauseData(delinquencyPausePeriods.size(), expectedData.size() - 1))
|
||||||
|
.isEqualTo(expectedData.size() - 1);
|
||||||
|
|
||||||
|
for (int i = 1; i < expectedData.size(); i++) {
|
||||||
|
List<String> expectedValuesList = expectedData.get(i);
|
||||||
|
|
||||||
|
List<List<String>> actualValuesList = delinquencyPausePeriods.stream()
|
||||||
|
.map(t -> fetchValuesOfDelinquencyPausePeriods(table.row(0), t)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValuesList));
|
||||||
|
assertThat(containsExpectedValues)
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLineInDelinquencyPausePeriodData(i, actualValuesList, expectedValuesList)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan details delinquent.nextPaymentDueDate will be {string}")
|
||||||
|
public void nextPaymentDueDateCheck(String expectedDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
String actualDate = FORMATTER.format(loanDetails.body().getDelinquent().getNextPaymentDueDate());
|
||||||
|
|
||||||
|
assertThat(actualDate).as(ErrorMessageHelper.wrongDataInNextPaymentDueDate(actualDate, expectedDate)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanAccountDelinquencyRangeDataV1 has delinquencyRange field with value {string}")
|
||||||
|
public void checkDelinquencyRangeInEvent(String expectedRange) {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
DelinquencyRange expectedDelinquencyRange = DelinquencyRange.valueOf(expectedRange);
|
||||||
|
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||||
|
|
||||||
|
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)//
|
||||||
|
.extractingData(loanAccountDelinquencyRangeDataV1 -> { //
|
||||||
|
String actualDelinquencyRangeValue = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getClassification();//
|
||||||
|
assertThat(actualDelinquencyRangeValue)//
|
||||||
|
.as(ErrorMessageHelper.delinquencyRangeError(actualDelinquencyRangeValue, expectedDelinquencyRangeValue))//
|
||||||
|
.isEqualTo(expectedDelinquencyRangeValue);//
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanDelinquencyRangeChangeBusinessEvent has the same Delinquency range, date and amount as in LoanDetails on both loan- and installment-level")
|
||||||
|
public void checkDelinquencyRangeInEvent() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
GetDelinquencyRangesResponse delinquencyRange = loanDetails.body().getDelinquencyRange();
|
||||||
|
GetLoansLoanIdDelinquencySummary delinquent = loanDetails.body().getDelinquent();
|
||||||
|
|
||||||
|
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)//
|
||||||
|
.extractingData(loanAccountDelinquencyRangeDataV1 -> { //
|
||||||
|
Long loanLevelDelinquencyRangeId = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getId();
|
||||||
|
String loanLevelDelinquencyRange = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getClassification();
|
||||||
|
String loanLevelDelinquentDate = loanAccountDelinquencyRangeDataV1.getDelinquentDate();
|
||||||
|
BigDecimal loanLevelTotalAmount = loanAccountDelinquencyRangeDataV1.getAmount().getTotalAmount();
|
||||||
|
|
||||||
|
Long loanLevelDelinquencyRangeIdExpected = delinquencyRange.getId();
|
||||||
|
String loanLevelDelinquencyRangeExpected = delinquencyRange.getClassification();
|
||||||
|
String loanLevelDelinquentDateExpected = FORMATTER.format(delinquent.getDelinquentDate());
|
||||||
|
BigDecimal loanLevelTotalAmountExpected = new BigDecimal(delinquent.getDelinquentAmount());
|
||||||
|
|
||||||
|
assertThat(loanLevelDelinquencyRangeId)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent4(loanLevelDelinquencyRangeId,
|
||||||
|
loanLevelDelinquencyRangeIdExpected))//
|
||||||
|
.isEqualTo(loanLevelDelinquencyRangeIdExpected);//
|
||||||
|
assertThat(loanLevelDelinquencyRange)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent5(loanLevelDelinquencyRange,
|
||||||
|
loanLevelDelinquencyRangeExpected))//
|
||||||
|
.isEqualTo(loanLevelDelinquencyRangeExpected);//
|
||||||
|
assertThat(loanLevelDelinquentDate)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent7(loanLevelDelinquentDate,
|
||||||
|
loanLevelDelinquentDateExpected))//
|
||||||
|
.isEqualTo(loanLevelDelinquentDateExpected);//
|
||||||
|
assertThat(loanLevelTotalAmount)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent6(loanLevelTotalAmount,
|
||||||
|
loanLevelTotalAmountExpected))//
|
||||||
|
.isEqualTo(loanLevelTotalAmountExpected);//
|
||||||
|
|
||||||
|
List<GetLoansLoanIdLoanInstallmentLevelDelinquency> installmentLevelDelinquencyBucketsExpected = delinquent
|
||||||
|
.getInstallmentLevelDelinquency();
|
||||||
|
List<LoanInstallmentDelinquencyBucketDataV1> installmentDelinquencyBuckets = loanAccountDelinquencyRangeDataV1
|
||||||
|
.getInstallmentDelinquencyBuckets();
|
||||||
|
for (int i = 0; i < installmentDelinquencyBuckets.size(); i++) {
|
||||||
|
Long installmentLevelDelinquencyRangeId = installmentDelinquencyBuckets.get(i).getDelinquencyRange().getId();
|
||||||
|
String installmentLevelDelinquencyRange = installmentDelinquencyBuckets.get(i).getDelinquencyRange()
|
||||||
|
.getClassification();
|
||||||
|
BigDecimal installmentLevelTotalAmount = installmentDelinquencyBuckets.get(i).getAmount().getTotalAmount();
|
||||||
|
|
||||||
|
Long installmentLevelDelinquencyRangeIdExpected = installmentLevelDelinquencyBucketsExpected.get(i).getRangeId();
|
||||||
|
String installmentLevelDelinquencyRangeExpected = installmentLevelDelinquencyBucketsExpected.get(i)
|
||||||
|
.getClassification();
|
||||||
|
BigDecimal installmentLevelTotalAmountExpected = installmentLevelDelinquencyBucketsExpected.get(i)
|
||||||
|
.getDelinquentAmount();
|
||||||
|
|
||||||
|
assertThat(installmentLevelDelinquencyRangeId)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent1(
|
||||||
|
installmentLevelDelinquencyRangeId, installmentLevelDelinquencyRangeIdExpected))//
|
||||||
|
.isEqualTo(installmentLevelDelinquencyRangeIdExpected);//
|
||||||
|
assertThat(installmentLevelDelinquencyRange)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent2(
|
||||||
|
installmentLevelDelinquencyRange, installmentLevelDelinquencyRangeExpected))//
|
||||||
|
.isEqualTo(installmentLevelDelinquencyRangeExpected);//
|
||||||
|
assertThat(installmentLevelTotalAmount)//
|
||||||
|
.as(ErrorMessageHelper.wrongValueInLoanDelinquencyRangeChangeBusinessEvent3(installmentLevelTotalAmount,
|
||||||
|
installmentLevelTotalAmountExpected))//
|
||||||
|
.isEqualTo(installmentLevelTotalAmountExpected);//
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("In Loan details delinquent.lastRepaymentAmount is {int} EUR with lastRepaymentDate {string}")
|
||||||
|
public void delinquentLastRepaymentAmountCheck(int expectedLastRepaymentAmount, String expectedLastRepaymentDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(loanDetails);
|
||||||
|
|
||||||
|
Double expectedLastRepaymentAmount1 = Double.valueOf(expectedLastRepaymentAmount);
|
||||||
|
Double actualLastRepaymentAmount = loanDetails.body().getDelinquent().getLastRepaymentAmount();
|
||||||
|
String actualLastRepaymentDate = FORMATTER.format(loanDetails.body().getDelinquent().getLastRepaymentDate());
|
||||||
|
|
||||||
|
assertThat(actualLastRepaymentAmount)//
|
||||||
|
.as(ErrorMessageHelper.wrongDataInDelinquentLastRepaymentAmount(actualLastRepaymentAmount, expectedLastRepaymentAmount1))//
|
||||||
|
.isEqualTo(expectedLastRepaymentAmount);//
|
||||||
|
assertThat(actualLastRepaymentDate)//
|
||||||
|
.as(ErrorMessageHelper.wrongDataInDelinquentLastRepaymentDate(actualLastRepaymentDate, expectedLastRepaymentDate))//
|
||||||
|
.isEqualTo(expectedLastRepaymentDate);//
|
||||||
|
|
||||||
|
log.info("loanDetails.delinquent.lastRepaymentAmount: {}", actualLastRepaymentAmount);
|
||||||
|
log.info("loanDetails.delinquent.lastRepaymentDate: {}", actualLastRepaymentDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
|
||||||
|
private List<String> fetchValuesOfDelinquencyPausePeriods(List<String> header, GetLoansLoanIdDelinquencyPausePeriod t) {
|
||||||
|
List<String> actualValues = new ArrayList<>();
|
||||||
|
for (String headerName : header) {
|
||||||
|
switch (headerName) {
|
||||||
|
case "active" -> actualValues.add(t.getActive() == null ? null : t.getActive().toString());
|
||||||
|
case "pausePeriodStart" ->
|
||||||
|
actualValues.add(t.getPausePeriodStart() == null ? null : FORMATTER.format(t.getPausePeriodStart()));
|
||||||
|
case "pausePeriodEnd" -> actualValues.add(t.getPausePeriodEnd() == null ? null : FORMATTER.format(t.getPausePeriodEnd()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actualValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void errorMessageAssertation(Response<PostLoansDelinquencyActionResponse> response, int errorCodeExpected,
|
||||||
|
String errorMessageExpected) throws IOException {
|
||||||
|
String errorToString = response.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||||
|
int errorCodeActual = response.code();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanDelinquencyRangeChangeBusinessEvent is created")
|
||||||
|
public void checkLoanDelinquencyRangeChangeBusinessEventCreated() {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEventRaised(LoanDelinquencyRangeChangeEvent.class, loanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+107
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import io.cucumber.datatable.DataTable;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.LoanReAgeEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LoanReAgingStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@When("Admin creates a Loan re-aging transaction with the following data:")
|
||||||
|
public void createReAgingTransaction(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<String> data = table.asLists().get(1);
|
||||||
|
int frequencyNumber = Integer.parseInt(data.get(0));
|
||||||
|
String frequencyType = data.get(1);
|
||||||
|
String startDate = data.get(2);
|
||||||
|
int numberOfInstallments = Integer.parseInt(data.get(3));
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory.defaultReAgingRequest().frequencyNumber(frequencyNumber)
|
||||||
|
.frequencyType(frequencyType).startDate(startDate).numberOfInstallments(numberOfInstallments);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi.executeLoanTransaction(loanId, reAgingRequest, "reAge")
|
||||||
|
.execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAGING_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin creates a Loan re-aging transaction by Loan external ID with the following data:")
|
||||||
|
public void createReAgingTransactionByLoanExternalId(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
List<String> data = table.asLists().get(1);
|
||||||
|
int frequencyNumber = Integer.parseInt(data.get(0));
|
||||||
|
String frequencyType = data.get(1);
|
||||||
|
String startDate = data.get(2);
|
||||||
|
int numberOfInstallments = Integer.parseInt(data.get(3));
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory.defaultReAgingRequest().frequencyNumber(frequencyNumber)
|
||||||
|
.frequencyType(frequencyType).startDate(startDate).numberOfInstallments(numberOfInstallments);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||||
|
.executeLoanTransaction1(loanExternalId, reAgingRequest, "reAge").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAGING_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Admin successfully undo Loan re-aging transaction")
|
||||||
|
public void undoReAgingTransaction() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, new PostLoansLoanIdTransactionsRequest(), "undoReAge").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAGING_UNDO_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanReAgeBusinessEvent is created")
|
||||||
|
public void checkLoanReAmortizeBusinessEventCreated() {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEventRaised(LoanReAgeEvent.class, loanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.LoanReAmortizeEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class LoanReAmortizationStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@When("When Admin creates a Loan re-amortization transaction on current business date")
|
||||||
|
public void createLoanReAmortization() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest reAmortizationRequest = LoanRequestFactory.defaultLoanReAmortizationRequest();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, reAmortizationRequest, "reAmortize").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAMORTIZATION_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("When Admin creates a Loan re-amortization transaction on current business date by loan external ID")
|
||||||
|
public void createLoanReAmortizationByLoanExternalId() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
String loanExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest reAmortizationRequest = LoanRequestFactory.defaultLoanReAmortizationRequest();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||||
|
.executeLoanTransaction1(loanExternalId, reAmortizationRequest, "reAmortize").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAMORTIZATION_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("When Admin undo Loan re-amortization transaction on current business date")
|
||||||
|
public void undoLoanReAmortization() throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, new PostLoansLoanIdTransactionsRequest(), "undoReAmortize").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(response);
|
||||||
|
testContext().set(TestContextKey.LOAN_REAMORTIZATION_UNDO_RESPONSE, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("LoanReAmortizeBusinessEvent is created")
|
||||||
|
public void checkLoanReAmortizeBusinessEventCreated() {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
eventAssertion.assertEventRaised(LoanReAmortizeEvent.class, loanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+564
@@ -0,0 +1,564 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.apache.fineract.test.data.paymenttype.DefaultPaymentType.AUTOPAY;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.And;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanTransactionAdjustmentDataV1;
|
||||||
|
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||||
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
|
||||||
|
import org.apache.fineract.client.models.GetUsersUserIdResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.models.PostUsersResponse;
|
||||||
|
import org.apache.fineract.client.services.LoanTransactionsApi;
|
||||||
|
import org.apache.fineract.client.services.LoansApi;
|
||||||
|
import org.apache.fineract.client.services.UsersApi;
|
||||||
|
import org.apache.fineract.test.api.ApiProperties;
|
||||||
|
import org.apache.fineract.test.data.TransactionType;
|
||||||
|
import org.apache.fineract.test.data.paymenttype.DefaultPaymentType;
|
||||||
|
import org.apache.fineract.test.data.paymenttype.PaymentTypeResolver;
|
||||||
|
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.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.messaging.EventAssertion;
|
||||||
|
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent;
|
||||||
|
import org.apache.fineract.test.messaging.event.loan.transaction.LoanAdjustTransactionBusinessEvent;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||||
|
public static final String DEFAULT_LOCALE = "en";
|
||||||
|
public static final String DEFAULT_ACCOUNT_NB = "1234567890";
|
||||||
|
public static final String DEFAULT_CHECK_NB = "1234567890";
|
||||||
|
public static final String DEFAULT_RECEIPT_NB = "1234567890";
|
||||||
|
public static final String DEFAULT_BANK_NB = "1234567890";
|
||||||
|
@Autowired
|
||||||
|
private LoanTransactionsApi loanTransactionsApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LoansApi loansApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventAssertion eventAssertion;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApiProperties apiProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UsersApi usersApi;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PaymentTypeResolver paymentTypeResolver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventCheckHelper eventCheckHelper;
|
||||||
|
|
||||||
|
@And("Customer makes {string} repayment on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeLoanRepayment(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
makeRepayment(repaymentType, transactionDate, transactionAmount, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Customer makes {string} repayment on {string} with {double} EUR transaction amount and check external owner")
|
||||||
|
public void makeLoanRepaymentAndCheckOwner(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
String transferExternalOwnerId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
makeRepayment(repaymentType, transactionDate, transactionAmount, transferExternalOwnerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeRepayment(String repaymentType, String transactionDate, double transactionAmount, String transferExternalOwnerId)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
String idempotencyKey = UUID.randomUUID().toString();
|
||||||
|
testContext().set(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY, idempotencyKey);
|
||||||
|
headerMap.put("Idempotency-Key", idempotencyKey);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, repaymentRequest, "repayment", headerMap).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionDataV1> transactionEvent = eventCheckHelper
|
||||||
|
.transactionEventCheck(repaymentResponse, TransactionType.REPAYMENT, transferExternalOwnerId);
|
||||||
|
testContext().set(TestContextKey.TRANSACTION_EVENT, transactionEvent);
|
||||||
|
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Created user makes {string} repayment on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeRepaymentWithGivenUser(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
String idempotencyKey = UUID.randomUUID().toString();
|
||||||
|
testContext().set(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY, idempotencyKey);
|
||||||
|
headerMap.put("Idempotency-Key", idempotencyKey);
|
||||||
|
|
||||||
|
Response<PostUsersResponse> createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE);
|
||||||
|
Long createdUserId = createUserResponse.body().getResourceId();
|
||||||
|
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(user);
|
||||||
|
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword();
|
||||||
|
Base64 base64 = new Base64();
|
||||||
|
headerMap.put("Authorization",
|
||||||
|
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, repaymentRequest, "repayment", headerMap).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||||
|
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Customer makes externalID controlled {string} repayment on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeRepaymentByExternalId(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
String resourceExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
String idempotencyKey = UUID.randomUUID().toString();
|
||||||
|
testContext().set(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY, idempotencyKey);
|
||||||
|
headerMap.put("Idempotency-Key", idempotencyKey);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction1(resourceExternalId, repaymentRequest, "repayment", headerMap).execute();
|
||||||
|
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||||
|
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Created user makes externalID controlled {string} repayment on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeRepaymentWithGivenUserByExternalId(String repaymentType, String transactionDate, double transactionAmount)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
String resourceExternalId = loanResponse.body().getResourceExternalId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Map<String, String> headerMap = new HashMap<>();
|
||||||
|
String idempotencyKey = UUID.randomUUID().toString();
|
||||||
|
testContext().set(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY, idempotencyKey);
|
||||||
|
headerMap.put("Idempotency-Key", idempotencyKey);
|
||||||
|
|
||||||
|
Response<PostUsersResponse> createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE);
|
||||||
|
Long createdUserId = createUserResponse.body().getResourceId();
|
||||||
|
Response<GetUsersUserIdResponse> user = usersApi.retrieveOne31(createdUserId).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(user);
|
||||||
|
String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword();
|
||||||
|
Base64 base64 = new Base64();
|
||||||
|
headerMap.put("Authorization",
|
||||||
|
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction1(resourceExternalId, repaymentRequest, "repayment", headerMap).execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||||
|
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Customer not able to make {string} repayment on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeLoanRepaymentFails(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, repaymentRequest, "repayment").execute();
|
||||||
|
ErrorResponse errorDetails = ErrorResponse.from(repaymentResponse);
|
||||||
|
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(400);
|
||||||
|
assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.loanRepaymentOnClosedLoanFailureMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Customer not able to make a repayment undo on {string} due to charge off")
|
||||||
|
public void makeLoanRepaymentUndoAfterChargeOff(String transactionDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> transactionResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
Long loanId = loanResponse.body().getLoanId();
|
||||||
|
Long transactionId = transactionResponse.body().getResourceId();
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest repaymentUndoRequest = LoanRequestFactory.defaultRepaymentUndoRequest()
|
||||||
|
.transactionDate(transactionDate).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, repaymentResponse.body().getResourceId(), repaymentUndoRequest, "").execute();
|
||||||
|
ErrorResponse errorDetails = ErrorResponse.from(repaymentUndoResponse);
|
||||||
|
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.repaymentUndoFailureDueToChargeOffCodeMsg()).isEqualTo(403);
|
||||||
|
assertThat(errorDetails.getSingleError().getDeveloperMessage())
|
||||||
|
.isEqualTo(ErrorMessageHelper.repaymentUndoFailureDueToChargeOff(transactionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@And("Customer makes {string} repayment on {string} with {double} EUR transaction amount \\(and transaction fails because of wrong date)")
|
||||||
|
public void makeLoanRepaymentWithWrongDate(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||||
|
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, repaymentRequest, "repayment").execute();
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Refund happens on {string} with {double} EUR transaction amount")
|
||||||
|
public void makeRefund(String transactionDate, double transactionAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
PostLoansLoanIdTransactionsRequest refundRequest = LoanRequestFactory.defaultRefundRequest().transactionDate(transactionDate)
|
||||||
|
.transactionAmount(transactionAmount).paymentTypeId(paymentTypeResolver.resolve(AUTOPAY)).dateFormat(DATE_FORMAT)
|
||||||
|
.locale(DEFAULT_LOCALE).accountNumber(DEFAULT_ACCOUNT_NB).checkNumber(DEFAULT_CHECK_NB).receiptNumber(DEFAULT_RECEIPT_NB)
|
||||||
|
.bankNumber(DEFAULT_BANK_NB);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> refundResponse = loanTransactionsApi
|
||||||
|
.executeLoanTransaction(loanId, refundRequest, "payoutRefund").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(refundResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_REFUND_RESPONSE, refundResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Refund undo happens on {string}")
|
||||||
|
public void makeRefundUndo(String transactionDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> refundResponse = testContext().get(TestContextKey.LOAN_REFUND_RESPONSE);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest refundUndoRequest = LoanRequestFactory.defaultRefundUndoRequest()
|
||||||
|
.transactionDate(transactionDate).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> refundUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, refundResponse.body().getResourceId(), refundUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(refundUndoResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_UNDO_RESPONSE, refundUndoResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, refundResponse.body().getResourceId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(refundResponse.body().getResourceId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer makes a repayment undo on {string}")
|
||||||
|
public void makeLoanRepaymentUndo(String transactionDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest repaymentUndoRequest = LoanRequestFactory.defaultRepaymentUndoRequest()
|
||||||
|
.transactionDate(transactionDate).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, repaymentResponse.body().getResourceId(), repaymentUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentUndoResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_UNDO_RESPONSE, repaymentUndoResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, repaymentResponse.body().getResourceId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(repaymentResponse.body().getResourceId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan {string} transaction adjust amount {double} must return {int} code")
|
||||||
|
public void makeLoanRepaymentAdjustFail(String transactionType, double transactionAmount, int codeExpected) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(transactionType);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest repaymentUndoRequest = LoanRequestFactory.defaultRepaymentUndoRequest()
|
||||||
|
.transactionAmount(transactionAmount);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, repaymentResponse.body().getResourceId(), repaymentUndoRequest, "").execute();
|
||||||
|
assertThat(repaymentUndoResponse.code()).isEqualTo(codeExpected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer undo {string}th repayment on {string}")
|
||||||
|
public void undoNthRepayment(String nthItemStr, String transactionDate) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
|
||||||
|
.getTransactions();
|
||||||
|
|
||||||
|
int nthItem = Integer.parseInt(nthItemStr) - 1;
|
||||||
|
GetLoansLoanIdTransactions targetTransaction = transactions.stream().filter(t -> Boolean.TRUE.equals(t.getType().getRepayment()))
|
||||||
|
.toList().get(nthItem);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest repaymentUndoRequest = LoanRequestFactory.defaultRepaymentUndoRequest()
|
||||||
|
.transactionDate(transactionDate).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, targetTransaction.getId(), repaymentUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentUndoResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_UNDO_RESPONSE, repaymentUndoResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer undo {string}th transaction made on {string}")
|
||||||
|
public void undoNthTransaction(String nthItemStr, String transactionDate) throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
|
||||||
|
.getTransactions();
|
||||||
|
|
||||||
|
int nthItem = Integer.parseInt(nthItemStr) - 1;
|
||||||
|
GetLoansLoanIdTransactions targetTransaction = transactions.stream()
|
||||||
|
.filter(t -> transactionDate.equals(formatter.format(t.getDate()))).toList().get(nthItem);
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest transactionUndoRequest = LoanRequestFactory.defaultTransactionUndoRequest()
|
||||||
|
.transactionDate(transactionDate);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> transactionUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(transactionUndoResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_TRANSACTION_UNDO_RESPONSE, transactionUndoResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer undo {string}th {string} transaction made on {string}")
|
||||||
|
public void undoNthTransactionType(String nthItemStr, String transactionType, String transactionDate) throws IOException {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
|
||||||
|
.getTransactions();
|
||||||
|
|
||||||
|
int nthItem = Integer.parseInt(nthItemStr) - 1;
|
||||||
|
GetLoansLoanIdTransactions targetTransaction = transactions//
|
||||||
|
.stream()//
|
||||||
|
.filter(t -> transactionDate.equals(formatter.format(t.getDate())) && transactionType.equals(t.getType().getValue()))//
|
||||||
|
.toList()//
|
||||||
|
.get(nthItem);//
|
||||||
|
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest transactionUndoRequest = LoanRequestFactory.defaultTransactionUndoRequest()
|
||||||
|
.transactionDate(transactionDate);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> transactionUndoResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(transactionUndoResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_TRANSACTION_UNDO_RESPONSE, transactionUndoResponse);
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Repayment transaction is created with {double} amount and {string} type")
|
||||||
|
public void loanRepaymentStatus(double repaymentAmount, String paymentType) throws IOException {
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
Response<GetLoansLoanIdTransactionsTransactionIdResponse> transactionResponse = loanTransactionsApi
|
||||||
|
.retrieveTransaction(loanId, repaymentResponse.body().getResourceId(), "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(transactionResponse);
|
||||||
|
assertThat(transactionResponse.body().getAmount()).isEqualTo(repaymentAmount);
|
||||||
|
assertThat(transactionResponse.body().getPaymentDetailData().getPaymentType().getName()).isEqualTo(paymentType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Repayment failed because the repayment date is after the business date")
|
||||||
|
public void repaymentDateFailure() {
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> response = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||||
|
|
||||||
|
ErrorResponse errorDetails = ErrorResponse.from(response);
|
||||||
|
|
||||||
|
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
|
||||||
|
assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.transactionDateInFutureFailureMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Amounts are distributed equally in loan repayment schedule in case of total amount {double}")
|
||||||
|
public void amountsEquallyDistributedInSchedule(double totalAmount) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId1 = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
Response<GetLoansLoanIdResponse> getLoansLoanIdResponseCall = loansApi
|
||||||
|
.retrieveLoan(loanId1, false, "all", "guarantors,futureSchedule", "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(getLoansLoanIdResponseCall);
|
||||||
|
|
||||||
|
List<GetLoansLoanIdRepaymentPeriod> periods = getLoansLoanIdResponseCall.body().getRepaymentSchedule().getPeriods();
|
||||||
|
|
||||||
|
BigDecimal expectedAmount = new BigDecimal(totalAmount / (periods.size() - 1)).setScale(0, RoundingMode.HALF_DOWN);
|
||||||
|
BigDecimal lastExpectedAmount = new BigDecimal(totalAmount).setScale(0, RoundingMode.HALF_DOWN);
|
||||||
|
|
||||||
|
for (int i = 1; i < periods.size(); i++) {
|
||||||
|
BigDecimal actualAmount = new BigDecimal(periods.get(i).getPrincipalOriginalDue()).setScale(0, RoundingMode.HALF_DOWN);
|
||||||
|
|
||||||
|
if (i == periods.size() - 1) {
|
||||||
|
assertThat(actualAmount.compareTo(lastExpectedAmount))
|
||||||
|
.as(ErrorMessageHelper.wrongAmountInRepaymentSchedule(i, actualAmount, lastExpectedAmount)).isEqualTo(0);
|
||||||
|
} else {
|
||||||
|
assertThat(actualAmount.compareTo(expectedAmount))
|
||||||
|
.as(ErrorMessageHelper.wrongAmountInRepaymentSchedule(i, actualAmount, expectedAmount)).isEqualTo(0);
|
||||||
|
lastExpectedAmount = lastExpectedAmount.subtract(actualAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer adjust {string}th repayment on {string} with amount {string} and check external owner")
|
||||||
|
public void adjustNthRepaymentWithExternalOwner(String nthItemStr, String transactionDate, String amount) throws IOException {
|
||||||
|
String transferExternalOwnerId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
|
||||||
|
adjustNthRepaymentWithExternalOwnerCheck(nthItemStr, transactionDate, amount, transferExternalOwnerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@When("Customer adjust {string}th repayment on {string} with amount {string}")
|
||||||
|
public void adjustNthRepayment(String nthItemStr, String transactionDate, String amount) throws IOException {
|
||||||
|
adjustNthRepaymentWithExternalOwnerCheck(nthItemStr, transactionDate, amount, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adjustNthRepaymentWithExternalOwnerCheck(String nthItemStr, String transactionDate, String amount, String externalOwnerId)
|
||||||
|
throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
|
||||||
|
.getTransactions();
|
||||||
|
|
||||||
|
int nthItem = Integer.parseInt(nthItemStr) - 1;
|
||||||
|
GetLoansLoanIdTransactions targetTransaction = transactions.stream().filter(t -> Boolean.TRUE.equals(t.getType().getRepayment()))
|
||||||
|
.toList().get(nthItem);
|
||||||
|
double amountValue = Double.parseDouble(amount);
|
||||||
|
PostLoansLoanIdTransactionsTransactionIdRequest repaymentUndoRequest = LoanRequestFactory.defaultRepaymentAdjustRequest(amountValue)
|
||||||
|
.transactionDate(transactionDate).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);
|
||||||
|
|
||||||
|
Response<PostLoansLoanIdTransactionsResponse> repaymentAdjustmentResponse = loanTransactionsApi
|
||||||
|
.adjustLoanTransaction(loanId, targetTransaction.getId(), repaymentUndoRequest, "").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(repaymentAdjustmentResponse);
|
||||||
|
testContext().set(TestContextKey.LOAN_REPAYMENT_UNDO_RESPONSE, repaymentAdjustmentResponse);
|
||||||
|
|
||||||
|
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
|
||||||
|
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
|
||||||
|
.isEqualTo(targetTransaction.getId());
|
||||||
|
eventAssertionBuilder.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getAmount().doubleValue())
|
||||||
|
.isEqualTo(targetTransaction.getAmount());
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||||
|
.isEqualTo(Boolean.TRUE);
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getExternalOwnerId())
|
||||||
|
.isEqualTo(externalOwnerId);
|
||||||
|
if (amountValue > 0) {
|
||||||
|
eventAssertionBuilder
|
||||||
|
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getNewTransactionDetail().getId())
|
||||||
|
.isEqualTo(repaymentAdjustmentResponse.body().getResourceId());
|
||||||
|
eventAssertionBuilder.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getNewTransactionDetail().getAmount().doubleValue())
|
||||||
|
.isEqualTo(amountValue);
|
||||||
|
eventAssertionBuilder.extractingData(
|
||||||
|
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getNewTransactionDetail().getExternalOwnerId())
|
||||||
|
.isEqualTo(externalOwnerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
* 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.stepdef.loan;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import io.cucumber.datatable.DataTable;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
|
||||||
|
import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
|
||||||
|
import org.apache.fineract.client.models.PostLoansResponse;
|
||||||
|
import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
|
||||||
|
import org.apache.fineract.client.models.PostUpdateRescheduleLoansResponse;
|
||||||
|
import org.apache.fineract.client.services.RescheduleLoansApi;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.test.data.LoanRescheduleErrorMessage;
|
||||||
|
import org.apache.fineract.test.helper.ErrorHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||||
|
import org.apache.fineract.test.helper.ErrorResponse;
|
||||||
|
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||||
|
import org.apache.fineract.test.support.TestContextKey;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class LoanRescheduleStepDef extends AbstractStepDef {
|
||||||
|
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RescheduleLoansApi rescheduleLoansApi;
|
||||||
|
|
||||||
|
@When("Admin creates and approves Loan reschedule with the following data:")
|
||||||
|
public void createAndApproveLoanReschedule(DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> rescheduleData = data.get(1);
|
||||||
|
String rescheduleFromDate = rescheduleData.get(0);
|
||||||
|
String submittedOnDate = rescheduleData.get(1);
|
||||||
|
String adjustedDueDate = rescheduleData.get(2);
|
||||||
|
Integer graceOfPrincipal = Integer.parseInt(rescheduleData.get(3)) == 0 ? null : Integer.valueOf(rescheduleData.get(3));
|
||||||
|
Integer graceOnInterest = Integer.parseInt(rescheduleData.get(4)) == 0 ? null : Integer.valueOf(rescheduleData.get(4));
|
||||||
|
Integer extraTerms = Integer.parseInt(rescheduleData.get(5)) == 0 ? null : Integer.valueOf(rescheduleData.get(5));
|
||||||
|
BigDecimal newInterestRate = new BigDecimal(rescheduleData.get(6));
|
||||||
|
|
||||||
|
PostCreateRescheduleLoansRequest request = new PostCreateRescheduleLoansRequest()//
|
||||||
|
.loanId(loanId)//
|
||||||
|
.rescheduleFromDate(rescheduleFromDate)//
|
||||||
|
.submittedOnDate(submittedOnDate)//
|
||||||
|
.adjustedDueDate(adjustedDueDate)//
|
||||||
|
.graceOnPrincipal(graceOfPrincipal)//
|
||||||
|
.graceOnInterest(graceOnInterest)//
|
||||||
|
.extraTerms(extraTerms)//
|
||||||
|
.newInterestRate(newInterestRate)//
|
||||||
|
.rescheduleReasonId(54L)//
|
||||||
|
.rescheduleReasonComment("")//
|
||||||
|
.dateFormat("dd MMMM yyyy")//
|
||||||
|
.locale("en");//
|
||||||
|
|
||||||
|
Response<PostCreateRescheduleLoansResponse> createResponse = rescheduleLoansApi.createLoanRescheduleRequest(request).execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(createResponse);
|
||||||
|
|
||||||
|
Long scheduleId = createResponse.body().getResourceId();
|
||||||
|
PostUpdateRescheduleLoansRequest approveRequest = new PostUpdateRescheduleLoansRequest()//
|
||||||
|
.approvedOnDate(submittedOnDate)//
|
||||||
|
.dateFormat("dd MMMM yyyy")//
|
||||||
|
.locale("en");//
|
||||||
|
|
||||||
|
Response<PostUpdateRescheduleLoansResponse> approveResponse = rescheduleLoansApi
|
||||||
|
.updateLoanRescheduleRequest(scheduleId, approveRequest, "approve").execute();
|
||||||
|
ErrorHelper.checkSuccessfulApiCall(approveResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Then("Loan reschedule with the following data results a {int} error and {string} error message")
|
||||||
|
public void createLoanRescheduleError(int errorCodeExpected, String errorMessageType, DataTable table) throws IOException {
|
||||||
|
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||||
|
long loanId = loanResponse.body().getLoanId();
|
||||||
|
|
||||||
|
List<List<String>> data = table.asLists();
|
||||||
|
List<String> rescheduleData = data.get(1);
|
||||||
|
String rescheduleFromDate = rescheduleData.get(0);
|
||||||
|
String submittedOnDate = rescheduleData.get(1);
|
||||||
|
String adjustedDueDate = rescheduleData.get(2);
|
||||||
|
Integer graceOfPrincipal = Integer.parseInt(rescheduleData.get(3)) == 0 ? null : Integer.valueOf(rescheduleData.get(3));
|
||||||
|
Integer graceOnInterest = Integer.parseInt(rescheduleData.get(4)) == 0 ? null : Integer.valueOf(rescheduleData.get(4));
|
||||||
|
Integer extraTerms = Integer.parseInt(rescheduleData.get(5)) == 0 ? null : Integer.valueOf(rescheduleData.get(5));
|
||||||
|
BigDecimal newInterestRate = new BigDecimal(rescheduleData.get(6));
|
||||||
|
|
||||||
|
PostCreateRescheduleLoansRequest request = new PostCreateRescheduleLoansRequest()//
|
||||||
|
.loanId(loanId)//
|
||||||
|
.rescheduleFromDate(rescheduleFromDate)//
|
||||||
|
.submittedOnDate(submittedOnDate)//
|
||||||
|
.adjustedDueDate(adjustedDueDate)//
|
||||||
|
.graceOnPrincipal(graceOfPrincipal)//
|
||||||
|
.graceOnInterest(graceOnInterest)//
|
||||||
|
.extraTerms(extraTerms)//
|
||||||
|
.newInterestRate(newInterestRate)//
|
||||||
|
.rescheduleReasonId(54L)//
|
||||||
|
.rescheduleReasonComment("")//
|
||||||
|
.dateFormat("dd MMMM yyyy")//
|
||||||
|
.locale("en");//
|
||||||
|
|
||||||
|
Response<PostCreateRescheduleLoansResponse> createResponse = rescheduleLoansApi.createLoanRescheduleRequest(request).execute();
|
||||||
|
|
||||||
|
LoanRescheduleErrorMessage loanRescheduleErrorMessage = LoanRescheduleErrorMessage.valueOf(errorMessageType);
|
||||||
|
String errorMessageExpected = loanRescheduleErrorMessage.getValue(loanId);
|
||||||
|
|
||||||
|
String errorToString = createResponse.errorBody().string();
|
||||||
|
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||||
|
String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||||
|
int errorCodeActual = createResponse.code();
|
||||||
|
|
||||||
|
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||||
|
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
|
||||||
|
.isEqualTo(errorMessageExpected);
|
||||||
|
|
||||||
|
log.info("ERROR CODE: {}", errorCodeActual);
|
||||||
|
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2093
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
|||||||
|
@BusinessDateFeature
|
||||||
|
Feature: BusinessDate
|
||||||
|
|
||||||
|
@TestRailId:C38
|
||||||
|
Scenario: As a user I would like to enable the Business date configuration
|
||||||
|
Given Global configuration "enable_business_date" is enabled
|
||||||
|
|
||||||
|
@TestRailId:C39
|
||||||
|
Scenario: As a user I would like to disable the Business date configuration
|
||||||
|
Given Global configuration "enable_business_date" is disabled
|
||||||
|
|
||||||
|
@TestRailId:C40
|
||||||
|
Scenario: As a user I would like to set the business date
|
||||||
|
When Admin sets the business date to "10 July 2022"
|
||||||
|
Then Admin checks that the business date is correctly set to "10 July 2022"
|
||||||
|
|
||||||
|
@TestRailId:C41
|
||||||
|
Scenario: As a user I would like to change the business date manually
|
||||||
|
When Admin sets the business date to "10 July 2022"
|
||||||
|
Then Admin checks that the business date is correctly set to "10 July 2022"
|
||||||
|
When Admin sets the business date to "11 July 2022"
|
||||||
|
Then Admin checks that the business date is correctly set to "11 July 2022"
|
||||||
|
|
||||||
|
@TestRailId:C27
|
||||||
|
Scenario: As a user I would like to change the business date with scheduled job
|
||||||
|
When Admin sets the business date to "10 July 2022"
|
||||||
|
When Admin runs the Increase Business Date by 1 day job
|
||||||
|
Then Admin checks that the business date is correctly set to "11 July 2022"
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
@COBFeature
|
||||||
|
Feature: COBFeature
|
||||||
|
|
||||||
|
@TestRailId:C2501 @Skip
|
||||||
|
Scenario: As an admin I would like to see that last closed business date got updated after COB catch up job finished
|
||||||
|
When Admin sets the business date to "01 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2022"
|
||||||
|
And Admin successfully approves the loan on "01 January 2022" with "1000" amount and expected disbursement date on "01 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2022" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 January 2022"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin sets the business date to "05 January 2022"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin runs COB catch up
|
||||||
|
When Admin checks that Loan COB is running until the current business date
|
||||||
|
Then Admin checks that last closed business date of loan is "04 January 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "05 January 2022" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
|
||||||
|
|
||||||
|
@TestRailId:C2681 @Skip
|
||||||
|
Scenario: As an admin I would like to check that the Delinquency bucket set on the loan correctly when the arrears setting is 3 on the product
|
||||||
|
When Admin sets the business date to "1 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "1 January 2022"
|
||||||
|
And Admin successfully approves the loan on "1 January 2022" with "1000" amount and expected disbursement date on "1 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "1 January 2022" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "4 February 2022"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_1" and has delinquentDate "2022-02-03"
|
||||||
|
|
||||||
|
@TestRailId:C2791 @Skip
|
||||||
|
Scenario: Verify that COB processes loans which are not closed/overpaid and has a last_closed_business_date exactly 1 day behind COB date
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 July 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 July 2023"
|
||||||
|
When Admin sets the business date to "03 July 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "02 July 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2792
|
||||||
|
Scenario: Verify that COB doesn’t touch loans with last closed business date behind COB date
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "10 August 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2023-08-03"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
When Admin sets the business date to "12 August 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
|
||||||
|
@TestRailId:C2793
|
||||||
|
Scenario: Verify that COB doesn’t touch CLOSED loans
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "10 August 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2023-08-03"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
And Customer makes "AUTOPAY" repayment on "10 August 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | 10 August 2023 |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
When Admin sets the business date to "11 August 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | 10 August 2023 |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
|
||||||
|
@TestRailId:C2794
|
||||||
|
Scenario: Verify that COB doesn’t touch OVERPAID loans
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "10 August 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2023-08-03"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
And Customer makes "AUTOPAY" repayment on "10 August 2023" with 1200 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | 10 August 2023 |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
When Admin sets the business date to "11 August 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "09 August 2023"
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_3 | 09 August 2023 | 10 August 2023 |
|
||||||
|
| RANGE_1 | 04 August 2023 | 09 August 2023 |
|
||||||
|
|
||||||
|
@TestRailId:C2795 @Skip
|
||||||
|
Scenario: Verify that COB catch up runs properly on loan which is behind date because of locked with error
|
||||||
|
When Admin sets the business date to "01 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2022"
|
||||||
|
And Admin successfully approves the loan on "01 January 2022" with "1000" amount and expected disbursement date on "01 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 January 2022"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin sets the business date to "03 January 2022"
|
||||||
|
Then Admin places a lock on loan account with an error message
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin sets the business date to "05 January 2022"
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin runs COB catch up
|
||||||
|
When Admin checks that Loan COB is running until the current business date
|
||||||
|
Then Admin checks that last closed business date of loan is "04 January 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "05 January 2022" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
|
||||||
|
@TestRailId:C2796
|
||||||
|
Scenario: Verify that after COB runs there are no unreleased loan locks
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 July 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then The loan account is not locked
|
||||||
|
|
||||||
|
@TestRailId:C2797 @Skip
|
||||||
|
Scenario: Verify that Inline COB is executed for stuck loans - when payment happened on a loan with last closed business date in the past, COB got executed before the repayment
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 July 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 July 2023"
|
||||||
|
When Admin sets the business date to "04 July 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
When Created user makes externalID controlled "AUTOPAY" repayment on "04 July 2023" with 500 EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "03 July 2023"
|
||||||
|
|
||||||
|
# On a hard locked loan, in case of the lock has an error message, payment by a non-bypass user should trigger inlineCob and it should be executed
|
||||||
|
# this functionality is not implemented yet
|
||||||
|
@Skip @TestRailId:C2798
|
||||||
|
Scenario: Verify that Inline COB is executed for stuck loans - when payment happened on a locked loan COB got executed before the repayment
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "02 July 2023"
|
||||||
|
When Admin runs COB job
|
||||||
|
Then Admin checks that last closed business date of loan is "01 July 2023"
|
||||||
|
When Admin places a lock on loan account with an error message
|
||||||
|
When Admin sets the business date to "04 July 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
When Created user makes externalID controlled "AUTOPAY" repayment on "04 July 2023" with 500 EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "03 July 2023"
|
||||||
|
|
||||||
|
@TestRailId:C3044 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that LoanAccountCustomSnapshotBusinessEvent is created with proper business date when installment is due date and COB runs
|
||||||
|
Given Admin puts CHECK_DUE_INSTALLMENTS job into LOAN_CLOSE_OF_BUSINESS workflow
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "17 January 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then LoanAccountCustomSnapshotBusinessEvent is created with business date "17 January 2024"
|
||||||
|
Then Admin removes CHECK_DUE_INSTALLMENTS job from LOAN_CLOSE_OF_BUSINESS workflow
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
@InlineCOBFeature
|
||||||
|
Feature: InlineCOBFeature
|
||||||
|
|
||||||
|
@TestRailId:C2457
|
||||||
|
Scenario: As an admin I would like to see that inline COB Happy Path scenario is working properly
|
||||||
|
When Admin sets the business date to "1 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "1 January 2022"
|
||||||
|
And Admin successfully approves the loan on "1 January 2022" with "1000" amount and expected disbursement date on "1 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "1 January 2022" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "1 March 2022"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2022-02-03"
|
||||||
|
|
||||||
|
@TestRailId:C2473
|
||||||
|
Scenario: As an admin I would like to see that loan was catching up with inline COB
|
||||||
|
When Admin sets the business date to "1 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "1 January 2022"
|
||||||
|
And Admin successfully approves the loan on "1 January 2022" with "1000" amount and expected disbursement date on "1 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "1 January 2022" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "2 January 2022"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin sets the business date to "5 January 2022"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "04 January 2022"
|
||||||
|
|
||||||
|
@TestRailId:C2554
|
||||||
|
Scenario: As an admin I would like to see that loan was catching up with inline COB on a repayment
|
||||||
|
When Admin sets the business date to "1 January 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "1 January 2022"
|
||||||
|
And Admin successfully approves the loan on "1 January 2022" with "1000" amount and expected disbursement date on "1 January 2022"
|
||||||
|
When Admin successfully disburse the loan on "1 January 2022" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "2 January 2022"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2022"
|
||||||
|
When Admin sets the business date to "5 January 2022"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
And Created user makes "AUTOPAY" repayment on "5 January 2022" with 100 EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "04 January 2022"
|
||||||
|
|
||||||
|
@TestRailId:C2602
|
||||||
|
Scenario: Verify that LoanCOBApiFilter works fine in the background and loanId controlled transaction does not trigger inlineCOB if COB had not been applied on loan before
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new Loan with date: "01 January 2023" and with 1 day loan term and repayment
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "07 January 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
And Created user makes "AUTOPAY" repayment on "07 January 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
Then Loan Transactions tab has a "REPAYMENT" transaction with date "07 January 2023" which has the following Journal entries:
|
||||||
|
| Type | Account code | Account name | Debit | Credit |
|
||||||
|
| ASSET | 112601 | Loans Receivable | | 1000.0 |
|
||||||
|
| LIABILITY | 145023 | Suspense/Clearing account | 1000.0 | |
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_1 | 06 January 2023 | 07 January 2023 |
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
|
||||||
|
@TestRailId:C2603
|
||||||
|
Scenario: Verify that LoanCOBApiFilter works fine in the background and externalId controlled transaction does not trigger inlineCOB if COB had not been applied on loan before
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new Loan with date: "01 January 2023" and with 1 day loan term and repayment
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "07 January 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
When Created user makes externalID controlled "AUTOPAY" repayment on "07 January 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
Then Loan Transactions tab has a "REPAYMENT" transaction with date "07 January 2023" which has the following Journal entries:
|
||||||
|
| Type | Account code | Account name | Debit | Credit |
|
||||||
|
| ASSET | 112601 | Loans Receivable | | 1000.0 |
|
||||||
|
| LIABILITY | 145023 | Suspense/Clearing account | 1000.0 | |
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_1 | 06 January 2023 | 07 January 2023 |
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
|
||||||
|
@TestRailId:C2604
|
||||||
|
Scenario: Verify that LoanCOBApiFilter works fine in the background and loanId controlled transaction triggers inlineCOB if COB had been applied on loan before
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new Loan with date: "01 January 2023" and with 1 day loan term and repayment
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "2 January 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2023"
|
||||||
|
When Admin sets the business date to "07 January 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
And Created user makes "AUTOPAY" repayment on "07 January 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
Then Loan Transactions tab has a "REPAYMENT" transaction with date "07 January 2023" which has the following Journal entries:
|
||||||
|
| Type | Account code | Account name | Debit | Credit |
|
||||||
|
| ASSET | 112601 | Loans Receivable | | 1000.0 |
|
||||||
|
| LIABILITY | 145023 | Suspense/Clearing account | 1000.0 | |
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_1 | 06 January 2023 | 07 January 2023 |
|
||||||
|
Then Admin checks that last closed business date of loan is "06 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2605
|
||||||
|
Scenario: Verify that LoanCOBApiFilter works fine in the background and externalId controlled transaction triggers inlineCOB if COB had been applied on loan before
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new Loan with date: "01 January 2023" and with 1 day loan term and repayment
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
Then Admin checks that last closed business date of loan is "null"
|
||||||
|
When Admin sets the business date to "2 January 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that last closed business date of loan is "01 January 2023"
|
||||||
|
When Admin sets the business date to "07 January 2023"
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| REPAYMENT_LOAN |
|
||||||
|
When Created user makes externalID controlled "AUTOPAY" repayment on "07 January 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
Then Loan Transactions tab has a "REPAYMENT" transaction with date "07 January 2023" which has the following Journal entries:
|
||||||
|
| Type | Account code | Account name | Debit | Credit |
|
||||||
|
| ASSET | 112601 | Loans Receivable | | 1000.0 |
|
||||||
|
| LIABILITY | 145023 | Suspense/Clearing account | 1000.0 | |
|
||||||
|
Then Loan delinquency history has the following details:
|
||||||
|
| Range (Classification) | Added on date | Lifted on date |
|
||||||
|
| RANGE_1 | 06 January 2023 | 07 January 2023 |
|
||||||
|
Then Admin checks that last closed business date of loan is "06 January 2023"
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,844 @@
|
|||||||
|
@LoanAccrualFeature
|
||||||
|
Feature: LoanAccrualTransaction
|
||||||
|
|
||||||
|
@TestRailId:C2647
|
||||||
|
Scenario: Verify that after COB job Accrual event is raised when loan has a fee-charge on disbursal date
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2023"
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "01 January 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Transactions tab has a transaction with date: "01 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "01 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2648
|
||||||
|
Scenario: Verify that after COB job Accrual event is raised when loan has a fee-charge on disbursal date with partial repayment
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2023"
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "01 January 2023" due date and 10 EUR transaction amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 January 2023" with 500 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Transactions tab has a transaction with date: "01 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "01 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2649
|
||||||
|
Scenario: Verify that after COB job Accrual event is raised when loan has a fee-charge on disbursal date with full repayment and loan is closed
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2023"
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "01 January 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "02 January 2023" with 1010 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan Transactions tab has a transaction with date: "02 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "02 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2650
|
||||||
|
Scenario: Verify that after COB job Accrual event is raised when loan has a fee-charge added with chargeback
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2023"
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "02 January 2023" with 250 EUR transaction amount
|
||||||
|
When Admin sets the business date to "03 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "03 January 2023" with 250 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "04 January 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "04 January 2023"
|
||||||
|
And Admin runs COB job
|
||||||
|
When Admin sets the business date to "05 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "05 January 2023" with 510 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
And Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 250 EUR transaction amount for Payment nr. 2
|
||||||
|
Then Loan has 250 outstanding amount
|
||||||
|
Then Loan Transactions tab has a transaction with date: "05 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "05 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2651
|
||||||
|
Scenario: Verify that after periodic accrual transaction job accrual event is raised when loan has a fee-charge added with waive charge and undo waive charge
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "01 January 2023", with Principal: "750", a loanTermFrequency: 3 months, and numberOfRepayments: 3
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "750" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "750" EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 February 2023" with 250 EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 March 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 March 2023" with 250 EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 April 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 April 2023" with 250 EUR transaction amount
|
||||||
|
When Customer makes a repayment undo on "01 April 2023"
|
||||||
|
When Admin sets the business date to "05 April 2023"
|
||||||
|
And Admin adds an NSF fee because of payment bounce with "05 April 2023" transaction date
|
||||||
|
When Admin sets the business date to "07 April 2023"
|
||||||
|
And Admin waives charge
|
||||||
|
When Admin sets the business date to "08 April 2023"
|
||||||
|
And Admin makes waive undone for charge
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
Then Loan has 260 outstanding amount
|
||||||
|
And Admin runs the Add Periodic Accrual Transactions job
|
||||||
|
Then Loan Transactions tab has a transaction with date: "05 April 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "05 April 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2652
|
||||||
|
Scenario: Verify that after periodic accrual transaction job accrual event is raised when loan has a fee-charge added when loan is closed
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 January 2023"
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "02 January 2023" with 1000 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "02 January 2023" due date and 10 EUR transaction amount
|
||||||
|
And Admin runs the Add Periodic Accrual Transactions job
|
||||||
|
Then Loan Transactions tab has a transaction with date: "02 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "02 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2653
|
||||||
|
Scenario: Verify that after disbursement and COB job Accrual event is raised when loan has a interest recalculation
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE | 01 January 2023 | 5000 | 12 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "5000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "5000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
When Admin runs the Add Periodic Accrual Transactions job
|
||||||
|
Then Loan Transactions tab has a transaction with date: "02 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 1.64 | 0.0 | 1.64 | 0.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "02 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2654
|
||||||
|
Scenario: Verify that after loan is closed accrual event is raised when loan has a interest recalculation
|
||||||
|
When Admin sets the business date to "01 January 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE | 01 January 2023 | 1000 | 12 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 1 | MONTHS | 1 | MONTHS | 1 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 January 2023" with "1000" amount and expected disbursement date on "01 January 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "02 January 2023" with 1010.19 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan Transactions tab has a transaction with date: "02 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.19 | 0.0 | 10.19 | 0.0 | 0.0 | 0.0 |
|
||||||
|
Then LoanAccrualTransactionCreatedBusinessEvent is raised on "02 January 2023"
|
||||||
|
|
||||||
|
@TestRailId:C2683
|
||||||
|
Scenario: Verify that the final accrual is created when the loan goes to overpaid state
|
||||||
|
When Admin sets the business date to "1 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 July 2023", with Principal: "5000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 July 2023" with "5000" amount and expected disbursement date on "1 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 July 2023" with "5000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "10 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "6 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "6 July 2023" with 5011 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 06 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Repayment | 5011.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2684
|
||||||
|
Scenario: Verify that the accrual transaction correctly created in case a CBR is applied on the loan
|
||||||
|
When Admin sets the business date to "1 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 July 2023", with Principal: "5000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 July 2023" with "5000" amount and expected disbursement date on "1 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 July 2023" with "5000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "10 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "6 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "6 July 2023" with 5011 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 06 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Repayment | 5011.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
When Admin makes Credit Balance Refund transaction on "06 July 2023" with 1 EUR transaction amount
|
||||||
|
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 06 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Repayment | 5011.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Credit Balance Refund | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2685
|
||||||
|
Scenario: Verify that the accrual transaction correctly created (overpay, undo repayment, overpay)
|
||||||
|
When Admin sets the business date to "1 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 July 2023", with Principal: "5000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 July 2023" with "5000" amount and expected disbursement date on "1 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 July 2023" with "5000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "10 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "5 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "5 July 2023" with 1000 EUR transaction amount
|
||||||
|
When Admin sets the business date to "6 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "6 July 2023" with 4011 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 06 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 05 July 2023 | Repayment | 1000.0 | 990.0 | 0.0 | 10.0 | 0.0 | 4010.0 |
|
||||||
|
| 06 July 2023 | Repayment | 4011.0 | 4010.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
And Customer makes a repayment undo on "6 July 2023"
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
When Admin sets the business date to "7 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "7 July 2023" with 4011 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 07 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 05 July 2023 | Repayment | 1000.0 | 990.0 | 0.0 | 10.0 | 0.0 | 4010.0 |
|
||||||
|
| 06 July 2023 | Repayment | 4011.0 | 4010.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 07 July 2023 | Repayment | 4011.0 | 4010.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2686
|
||||||
|
Scenario: Verify that the accrual transaction correctly created (overpay, undo repayment, add charge, overpay)
|
||||||
|
When Admin sets the business date to "1 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 July 2023", with Principal: "5000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 July 2023" with "5000" amount and expected disbursement date on "1 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 July 2023" with "5000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "10 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "5 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "5 July 2023" with 1000 EUR transaction amount
|
||||||
|
When Admin sets the business date to "6 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "6 July 2023" with 4011 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 06 July 2023 | 0.0 | 5000.0 | 0.0 | 10.0 | 0.0 | 5010.0 | 5010.0 | 5010.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 10 | 0 | 5010 | 5010 | 5010 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 05 July 2023 | Repayment | 1000.0 | 990.0 | 0.0 | 10.0 | 0.0 | 4010.0 |
|
||||||
|
| 06 July 2023 | Repayment | 4011.0 | 4010.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
And Customer makes a repayment undo on "6 July 2023"
|
||||||
|
Then Loan status will be "ACTIVE"
|
||||||
|
When Admin sets the business date to "7 July 2023"
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "20 July 2023" due date and 50 EUR transaction amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "7 July 2023" with 4061 EUR transaction amount
|
||||||
|
Then Loan status will be "OVERPAID"
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | 07 July 2023 | 0.0 | 5000.0 | 0.0 | 60.0 | 0.0 | 5060.0 | 5060.0 | 5060.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 5000 | 0 | 60 | 0 | 5060 | 5060 | 5060 | 0 | 0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 July 2023 | Disbursement | 5000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
| 05 July 2023 | Repayment | 1000.0 | 940.0 | 0.0 | 60.0 | 0.0 | 4060.0 |
|
||||||
|
| 06 July 2023 | Repayment | 4011.0 | 4010.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 06 July 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 07 July 2023 | Repayment | 4061.0 | 4060.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 07 July 2023 | Accrual | 50.0 | 0.0 | 0.0 | 50.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2707 @Skip
|
||||||
|
Scenario: Verify that the accrual transaction is not reversed when multi disbursement happens
|
||||||
|
When Admin sets the business date to "26 April 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "26 April 2023", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "26 April 2023" with "1000" amount and expected disbursement date on "1 May 2023"
|
||||||
|
And Admin successfully disburse the loan on "26 April 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "27 April 2023"
|
||||||
|
And Admin successfully disburse the loan on "27 April 2023" with "30" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "27 April 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "28 April 2023"
|
||||||
|
And Admin runs COB job
|
||||||
|
And Admin successfully disburse the loan on "28 April 2023" with "20" EUR transaction amount
|
||||||
|
When Admin sets the business date to "29 April 2023"
|
||||||
|
And Admin runs COB job
|
||||||
|
Then Loan Repayment schedule has 1 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 |
|
||||||
|
| | | 26 April 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 27 April 2023 | | 30.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 28 April 2023 | | 20.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 26 May 2023 | | 0.0 | 1050.0 | 0.0 | 10.0 | 0.0 | 1060.0 | 0.0 | 0.0 | 0.0 | 1060.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1050 | 0 | 10 | 0 | 1060 | 0 | 0 | 0 | 1060 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 26 April 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 27 April 2023 | Disbursement | 30.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
| 27 April 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 28 April 2023 | Disbursement | 20.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1050.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2708 @Skip
|
||||||
|
Scenario: Verify that the accrual is correct when it is on the installment start date
|
||||||
|
When Admin sets the business date to "1 May 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 May 2023", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 May 2023" with "1000" amount and expected disbursement date on "1 May 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 May 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "1 May 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "2 May 2023"
|
||||||
|
And Admin runs COB job
|
||||||
|
When Admin sets the business date to "8 May 2023"
|
||||||
|
And Admin successfully disburse the loan on "8 May 2023" with "20" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 May 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 08 May 2023 | | 20.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 June 2023 | | 0.0 | 1020.0 | 0.0 | 10.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1020 | 0 | 10 | 0 | 1030 | 0 | 0 | 0 | 1030 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 May 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 May 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 08 May 2023 | Disbursement | 20.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2709
|
||||||
|
Scenario:Verify that the accrual transaction is created for disbursement fee
|
||||||
|
When Admin sets the business date to "1 May 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 May 2023", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 May 2023" with "1000" amount and expected disbursement date on "1 May 2023"
|
||||||
|
When Admin adds "LOAN_DISBURSEMENT_PERCENTAGE_FEE" charge with 1 % of transaction amount
|
||||||
|
And Admin successfully disburse the loan on "1 May 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 May 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 May 2023 | Repayment (at time of disbursement) | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 May 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2710 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: single installment loan, charge-accrual-date = submitted-date, multiple charges with different submitted date
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 February 2023"
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "1000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "16 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 16 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 20.0 | 0.0 | 0.0 | 20.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has 1 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 February 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 03 March 2023 | | 0.0 | 1000.0 | 0.0 | 20.0 | 0.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 20 | 0 | 1020 | 0 | 0 | 0 | 1020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2711
|
||||||
|
Scenario: Verify global config charge-accrual-date function: single installment loan, charge-accrual-date = due-date, multiple charges with different submitted date
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 February 2023"
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "1000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "16 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "07 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "17 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 16 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 06 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 16 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has 1 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 February 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 03 March 2023 | | 0.0 | 1000.0 | 0.0 | 20.0 | 0.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 20 | 0 | 1020 | 0 | 0 | 0 | 1020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2712 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = submitted-date, multiple charges with different submitted date, due dates in same repayment period
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "16 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 16 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 20.0 | 0.0 | 0.0 | 20.0 | 0.0 | 0.0 |
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 20.0 | 0.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 20 | 0 | 3020 | 0 | 0 | 0 | 3020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2713
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = due-date, multiple charges with different submitted date, due dates in same repayment period
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "16 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "07 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "17 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 16 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 06 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 16 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 20.0 | 0.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 20 | 0 | 3020 | 0 | 0 | 0 | 3020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2714 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = submitted-date, multiple charges with different submitted date, due dates in different repayment periods
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 March 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 06 March 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 20 | 0 | 3020 | 0 | 0 | 0 | 3020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2715
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = due-date, multiple charges with different submitted date, due dates in different repayment periods
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 March 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "07 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "07 March 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| Snooze fee | false | Specified due date | 06 March 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 06 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 06 March 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 20 | 0 | 3020 | 0 | 0 | 0 | 3020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2716 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: single installment loan, charge-accrual-date = submitted-date, multi disbursement
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 February 2023"
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "1000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "500" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "04 February 2023" with "500" EUR transaction amount
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has 1 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 |
|
||||||
|
| | | 04 February 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 01 February 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 03 March 2023 | | 0.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 10 | 0 | 1010 | 0 | 0 | 0 | 1010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2717 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: single installment loan, charge-accrual-date = submitted-date, repayment reversal
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 February 2023"
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "1000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "04 February 2023" with 500 EUR transaction amount
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "05 February 2023"
|
||||||
|
When Customer undo "1"th "Repayment" transaction made on "04 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "06 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Repayment | 500.0 | 490.0 | 0.0 | 10.0 | 0.0 | 510.0 |
|
||||||
|
Then On Loan Transactions tab the "Repayment" Transaction with date "04 February 2023" is reverted
|
||||||
|
Then Loan Repayment schedule has 1 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 February 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 03 March 2023 | | 0.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 10 | 0 | 1010 | 0 | 0 | 0 | 1010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2718 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: single installment loan, charge-accrual-date = submitted-date, waive charge, undo waive
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 February 2023"
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "1000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 February 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
And Admin waives due date charge
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "05 February 2023"
|
||||||
|
And Admin makes waive undone for charge
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "06 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 February 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Waive loan charges | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 1000.0 |
|
||||||
|
Then On Loan Transactions tab the "Waive loan charges" Transaction with date "04 February 2023" is reverted
|
||||||
|
Then Loan Repayment schedule has 1 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 February 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 03 March 2023 | | 0.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 10 | 0 | 1010 | 0 | 0 | 0 | 1010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2719 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = submitted-date, multi disbursement
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "2000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 March 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "04 February 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 March 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 2000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 2000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
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 February 2023 | | 2000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 04 February 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 10 | 0 | 3010 | 0 | 0 | 0 | 3010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2720 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = submitted-date, repayment reversal
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 March 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "04 February 2023" with 500 EUR transaction amount
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "05 February 2023"
|
||||||
|
When Customer undo "1"th "Repayment" transaction made on "04 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "06 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 March 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Repayment | 500.0 | 500.0 | 0.0 | 0.0 | 0.0 | 2500.0 |
|
||||||
|
Then On Loan Transactions tab the "Repayment" Transaction with date "04 February 2023" is reverted
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 10 | 0 | 3010 | 0 | 0 | 0 | 3010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
@TestRailId:C2721 @Specific
|
||||||
|
Scenario: Verify global config charge-accrual-date function: multiple installment loan, charge-accrual-date = submitted-date, waive charge, undo waive
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "01 February 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 1 February 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 February 2023" with "3000" amount and expected disbursement date on "1 February 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 February 2023" with "3000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 March 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "04 February 2023"
|
||||||
|
And Admin waives due date charge
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "05 February 2023"
|
||||||
|
And Admin makes waive undone for charge
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "06 February 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Charges tab has the following data:
|
||||||
|
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
|
||||||
|
| Snooze fee | false | Specified due date | 06 March 2023 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 February 2023 | Disbursement | 3000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3000.0 |
|
||||||
|
| 01 February 2023 | Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
| 04 February 2023 | Waive loan charges | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 3000.0 |
|
||||||
|
Then On Loan Transactions tab the "Waive loan charges" Transaction with date "04 February 2023" is reverted
|
||||||
|
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 February 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 28 | 01 March 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 April 2023 | | 1000.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 3 | 30 | 01 May 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 10 | 0 | 3010 | 0 | 0 | 0 | 3010 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
|
|
||||||
|
|
||||||
|
@TestRailId:C2789 @Specific
|
||||||
|
Scenario: Verify accrual transaction for new fee for loan with accrued snooze fee and schedule adjustment
|
||||||
|
When Global config "charge-accrual-date" value set to "submitted-date"
|
||||||
|
When Admin sets the business date to "19 May 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 19 May 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 30 | DAYS | 30 | DAYS | 1 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "19 May 2023" with "1000" amount and expected disbursement date on "19 May 2023"
|
||||||
|
When Admin successfully disburse the loan on "19 May 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "12 June 2023"
|
||||||
|
When Admin adds "LOAN_SNOOZE_FEE" due date charge with "18 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Batch API call with steps: rescheduleLoan from "18 June 2023" to "18 July 2023" submitted on date: "19 May 2023", approveReschedule on date: "19 May 2023" runs with enclosingTransaction: "true"
|
||||||
|
When Admin sets the business date to "13 June 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Transactions tab has a transaction with date: "12 June 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 10.0 | 0.0 | 0.0 |
|
||||||
|
When Admin sets the business date to "18 July 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "18 July 2023" with 1010 EUR transaction amount
|
||||||
|
When Admin sets the business date to "19 July 2023"
|
||||||
|
When Customer makes a repayment undo on "19 July 2023"
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "19 July 2023" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "20 July 2023"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Loan Transactions tab has a transaction with date: "19 July 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Accrual | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 | 0.0 |
|
||||||
|
Then Loan Repayment schedule has 2 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 |
|
||||||
|
| | | 19 May 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 60 | 18 July 2023 | | 0.0 | 1000.0 | 0.0 | 10.0 | 0.0 | 1010.0 | 0.0 | 0.0 | 0.0 | 1010.0 |
|
||||||
|
| 2 | 1 | 19 July 2023 | | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 10 | 10 | 1020 | 0 | 0 | 0 | 1020 |
|
||||||
|
When Global config "charge-accrual-date" value set to "due-date"
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,183 @@
|
|||||||
|
@Product
|
||||||
|
Feature: LoanProduct
|
||||||
|
|
||||||
|
@Scenario1 @TestRailId:C52
|
||||||
|
Scenario: As a user I would like to fully repay the loan in time
|
||||||
|
When Admin sets the business date to "12 December 2021"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "12 December 2021", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "12 December 2021" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "12 December 2021" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "30 December 2021"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "30 December 2021" with 1000 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 1000 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario2 @TestRailId:C53
|
||||||
|
Scenario: As a user I would like to fully repay a loan which was disbursed 2 times
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "5 June 2022"
|
||||||
|
And Admin successfully disburse the loan on "5 June 2022" with "500" EUR transaction amount
|
||||||
|
Then Loan has 1500 outstanding amount
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "1 July 2022" with 1500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 1500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario3 @TestRailId:C54
|
||||||
|
Scenario: As a user I would like to fully repay a multi disbursed loan with 2 repayments
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "15 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 June 2022" with 500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Admin runs the Increase Business Date by 1 day job
|
||||||
|
And Admin successfully disburse the loan on "16 June 2022" with "500" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "15 July 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 July 2022" with 1000 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario4 @TestRailId:C55
|
||||||
|
Scenario: As a user I would like to multi disburse a loan which was previously fully paid
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "15 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 June 2022" with 1000 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 1000 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
When Admin runs the Increase Business Date by 1 day job
|
||||||
|
And Admin successfully disburse the loan on "16 June 2022" with "500" EUR transaction amount
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Admin sets the business date to "15 July 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 July 2022" with 500 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario5 @TestRailId:C57
|
||||||
|
Scenario: As a user I would like to fully repay a loan and check a repayment reversal with NSF fee
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "15 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 June 2022" with 1000 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 1000 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
When Customer makes a repayment undo on "15 June 2022"
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "18 June 2022"
|
||||||
|
And Admin adds an NSF fee because of payment bounce with "18 June 2022" transaction date
|
||||||
|
Then Loan has 1010 outstanding amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "18 June 2022" with 1010 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario6 @TestRailId:C58
|
||||||
|
Scenario: As a user I would like to repay the half amount of the loan and check a repayment reversal with NSF fee
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "15 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 June 2022" with 500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Customer makes a repayment undo on "15 June 2022"
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "18 June 2022"
|
||||||
|
And Admin adds an NSF fee because of payment bounce with "18 June 2022" transaction date
|
||||||
|
Then Loan has 1010 outstanding amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "18 June 2022" with 1010 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario7 @TestRailId:C59
|
||||||
|
Scenario: As a user I would like to fully repay a loan then reverse the repayment + add an NSF fee after the 1 month period
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "1 July 2022" with 1000 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 1000 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
When Customer makes a repayment undo on "1 July 2022"
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "5 July 2022"
|
||||||
|
And Admin adds an NSF fee because of payment bounce with "5 July 2022" transaction date
|
||||||
|
Then Loan has 1010 outstanding amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "5 July 2022" with 1010 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario8 @TestRailId:C60
|
||||||
|
Scenario: As a user I would like to repay the half amount of the loan and do a refund
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "25 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "25 June 2022" with 500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
When Refund happens on "1 July 2022" with 500 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
|
||||||
|
@Scenario9 @TestRailId:C61
|
||||||
|
Scenario: As a user I would like to repay the half amount of the loan and do a refund + repayment reversal on the repayment
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
And Admin sets the business date to "25 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "25 June 2022" with 500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
When Refund happens on "1 July 2022" with 500 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
When Customer makes a repayment undo on "25 June 2022"
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
|
||||||
|
@Scenario10 @TestRailId:C62
|
||||||
|
Scenario: As a user I would like to repay the half amount of the loan and do a refund + repayment reversal + refund reversal
|
||||||
|
When Admin sets the business date to "1 June 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 June 2022", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 June 2022" with "1000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
And Admin successfully disburse the loan on "1 June 2022" with "1000" EUR transaction amount
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
|
When Admin sets the business date to "25 June 2022"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "25 June 2022" with 500 EUR transaction amount
|
||||||
|
Then Repayment transaction is created with 500 amount and "AUTOPAY" type
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
When Refund happens on "1 July 2022" with 500 EUR transaction amount
|
||||||
|
Then Loan has 0 outstanding amount
|
||||||
|
When Customer makes a repayment undo on "25 June 2022"
|
||||||
|
Then Loan has 500 outstanding amount
|
||||||
|
When Refund undo happens on "1 July 2022"
|
||||||
|
Then Loan has 1000 outstanding amount
|
||||||
@@ -0,0 +1,572 @@
|
|||||||
|
@LoanReAgingFeature
|
||||||
|
Feature: LoanReAging
|
||||||
|
|
||||||
|
@TestRailId:C3050 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction happy path works properly
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "20 February 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_30" and has delinquentDate "2024-01-19"
|
||||||
|
When Admin creates a Loan re-aging transaction with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 1 | MONTHS | 01 March 2024 | 6 |
|
||||||
|
Then Loan Repayment schedule has 10 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 15 | 01 March 2024 | | 625.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 6 | 31 | 01 April 2024 | | 500.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 7 | 30 | 01 May 2024 | | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 8 | 31 | 01 June 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 9 | 30 | 01 July 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 10 | 31 | 01 August 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0| 0.0 | 0.0 | 750.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
|
||||||
|
|
||||||
|
@TestRailId:C3051 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction made by Loan external ID happy path works properly
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "20 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 30 | DAYS | 10 March 2024 | 2 |
|
||||||
|
Then Loan Repayment schedule has 6 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 24 | 10 March 2024 | | 375.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 6 | 30 | 09 April 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
|
||||||
|
@TestRailId:C3052 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction undo works properly
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "20 February 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_30" and has delinquentDate "2024-01-19"
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 1 | DAYS | 10 March 2024 | 1 |
|
||||||
|
When Admin sets the business date to "25 February 2024"
|
||||||
|
Then Loan Repayment schedule has 5 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 20 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 24 | 10 March 2024 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
|
||||||
|
When Admin successfully undo Loan re-aging transaction
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | true |
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_30" and has delinquentDate "2024-01-19"
|
||||||
|
|
||||||
|
|
||||||
|
@TestRailId:C3053 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction works properly when chargeback happens after re-aging
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "20 February 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_30" and has delinquentDate "2024-01-04"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 January 2024" with 250 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
When Admin sets the business date to "21 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 2 | MONTHS | 10 March 2024 | 3 |
|
||||||
|
Then Loan Repayment schedule has 7 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 24 | 10 March 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 6 | 61 | 10 May 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 7 | 61 | 10 July 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 21 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
When Admin sets the business date to "25 February 2024"
|
||||||
|
When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 250 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 7 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 24 | 10 March 2024 | | 500.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 6 | 61 | 10 May 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 7 | 61 | 10 July 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1250.0 | 0.0 | 0.0 | 0.0 | 1250.0 | 250.0| 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 21 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
| 25 February 2024 | Chargeback | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
|
||||||
|
@Skip @TestRailId:C3054 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-aging transaction - reverse-replay scenario 1
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "27 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction with the following data:
|
||||||
|
| frequencyType | startDate | numberOfInstallments |
|
||||||
|
| MONTHS | 01 March 2024 | 6 |
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 February 2024" with 125 EUR transaction amount
|
||||||
|
When Admin successfully undo Loan re-aging transaction
|
||||||
|
# TODO fill with proper expected data
|
||||||
|
# Then Loan Repayment schedule has 10 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
# | 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
# | 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
# | 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
# | 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
# | 5 | 15 | 01 March 2024 | | 750.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# | 6 | 15 | 01 April 2024 | | 625.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# | 7 | 15 | 01 May 2024 | | 500.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# | 8 | 15 | 01 June 2024 | | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# | 9 | 15 | 01 July 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# | 10 | 15 | 01 August 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
# Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
# | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
# | 1000.0 | 0.0 | 0.0 | 20.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
# Then Loan Transactions tab has the following data:
|
||||||
|
# | Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
# | 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
# | 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
# | 01 February 2024 | Repayment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 250.0 | false |
|
||||||
|
# | 27 February 2024 | Re-age | 375.0 | 375.0 | 0.0 | 0.0 | 0.0 | 125.0 | true |
|
||||||
|
# Then Admin checks that delinquency range is: "RANGE_30" and has delinquentDate "2024-01-19"
|
||||||
|
|
||||||
|
@Skip @TestRailId:C3055 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-aging transaction - reverse-replay scenario 2
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "27 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction with the following data:
|
||||||
|
| frequencyType | startDate | numberOfInstallments |
|
||||||
|
| MONTHS | 01 March 2024 | 6 |
|
||||||
|
When Customer undo "1"th "Down Payment" transaction made on "01 January 2024"
|
||||||
|
When Admin successfully undo Loan re-aging transaction
|
||||||
|
# TODO fill with proper expected data and checks
|
||||||
|
|
||||||
|
@TestRailId:C3056 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction - chargeback before maturity and prior to re-aging
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 January 2024" with 250 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
When Admin sets the business date to "02 February 2024"
|
||||||
|
When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 125 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 02 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1125.0 | 0.0 | 0.0 | 0.0 | 1125.0 | 250.0| 0.0 | 0.0 | 875.0 |
|
||||||
|
When Admin sets the business date to "21 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 2 | MONTHS | 10 March 2024 | 3 |
|
||||||
|
Then Loan Repayment schedule has 7 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 21 February 2024| 875.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 24 | 10 March 2024 | | 583.33 | 291.67 | 0.0 | 0.0 | 0.0 | 291.67| 0.0 | 0.0 | 0.0 | 291.67 |
|
||||||
|
| 6 | 61 | 10 May 2024 | | 291.66 | 291.67 | 0.0 | 0.0 | 0.0 | 291.67| 0.0 | 0.0 | 0.0 | 291.67 |
|
||||||
|
| 7 | 61 | 10 July 2024 | | 0.0 | 291.66 | 0.0 | 0.0 | 0.0 | 291.66| 0.0 | 0.0 | 0.0 | 291.66 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 02 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
| 21 February 2024 | Re-age | 875.0 | 875.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
|
||||||
|
@TestRailId:C3057 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction - chargeback after maturity date and prior to re-aging
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 January 2024" with 250 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
When Admin sets the business date to "20 February 2024"
|
||||||
|
When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 125 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 5 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 5 | 5 | 20 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1125.0 | 0.0 | 0.0 | 0.0 | 1125.0 | 250.0| 0.0 | 0.0 | 875.0 |
|
||||||
|
When Admin sets the business date to "21 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 2 | MONTHS | 10 March 2024 | 3 |
|
||||||
|
Then Loan Repayment schedule has 8 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 21 February 2024| 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 5 | 20 February 2024 | 21 February 2024| 875.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 6 | 19 | 10 March 2024 | | 583.33 | 291.67 | 0.0 | 0.0 | 0.0 | 291.67| 0.0 | 0.0 | 0.0 | 291.67 |
|
||||||
|
| 7 | 61 | 10 May 2024 | | 291.66 | 291.67 | 0.0 | 0.0 | 0.0 | 291.67| 0.0 | 0.0 | 0.0 | 291.67 |
|
||||||
|
| 8 | 61 | 10 July 2024 | | 0.0 | 291.66 | 0.0 | 0.0 | 0.0 | 291.66| 0.0 | 0.0 | 0.0 | 291.66 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 20 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
| 21 February 2024 | Re-age | 875.0 | 875.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
|
||||||
|
@TestRailId:C3058 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that Loan re-aging transaction - chargeback after maturity date and prior to re-aging with charge N+1 installment
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 January 2024" with 250 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
When Admin sets the business date to "26 February 2024"
|
||||||
|
When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 125 EUR transaction amount
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "26 February 2024" due date and 20 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 5 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 5 | 11 | 26 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 20.0 | 145.0 | 0.0 | 0.0 | 0.0 | 145.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 26 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1125.0 | 0.0 | 0.0 | 20.0 | 1145.0 | 250.0| 0.0 | 0.0 | 895.0 |
|
||||||
|
When Admin sets the business date to "27 February 2024"
|
||||||
|
When Admin makes a charge adjustment for the last "LOAN_NSF_FEE" type charge which is due on "26 February 2024" with 20 EUR transaction amount and externalId ""
|
||||||
|
When Admin creates a Loan re-aging transaction by Loan external ID with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 2 | MONTHS | 10 March 2024 | 3 |
|
||||||
|
Then Loan Repayment schedule has 8 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 January 2024 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 27 February 2024| 730.0 | 20.0 | 0.0 | 0.0 | 0.0 | 20.0 | 20.0 | 0.0 | 20.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 27 February 2024| 730.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 27 February 2024| 730.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 11 | 26 February 2024 | | 855.0 | 0.0 | 0.0 | 0.0 | 20.0 | 20.0 | 0.0 | 0.0 | 0.0 | 20.0 |
|
||||||
|
| 6 | 13 | 10 March 2024 | | 570.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 |
|
||||||
|
| 7 | 61 | 10 May 2024 | | 285.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 |
|
||||||
|
| 8 | 61 | 10 July 2024 | | 0.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 | 0.0 | 0.0 | 0.0 | 285.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
| 26 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 875.0 | false |
|
||||||
|
| 27 February 2024 | Charge Adjustment| 20.0 | 20.0 | 0.0 | 0.0 | 0.0 | 855.0 | false |
|
||||||
|
| 27 February 2024 | Re-age | 855.0 | 855.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1125.0 | 0.0 | 0.0 | 20.0 | 1145.0 | 270.0| 0.0 | 20.0 | 875.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3059 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-aging transaction - partial principal payment scenario + undo re-ageing
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
When Admin sets the business date to "16 January 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "16 January 2024" with 50 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 50.0 | 0.0 | 0.0 | 75.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
| 16 January 2024 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 325.0 | false |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 175.0 | 0.0 | 0.0 | 325.0 |
|
||||||
|
When Admin sets the business date to "27 February 2024"
|
||||||
|
When Admin creates a Loan re-aging transaction with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 1 | MONTHS | 01 March 2024 | 6 |
|
||||||
|
Then Loan Repayment schedule has 10 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 27 February 2024| 325.0 | 50.0 | 0.0 | 0.0 | 0.0 | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 27 February 2024| 325.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | 27 February 2024| 325.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 5 | 15 | 01 March 2024 | | 271.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 |
|
||||||
|
| 6 | 31 | 01 April 2024 | | 217.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 |
|
||||||
|
| 7 | 30 | 01 May 2024 | | 163.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 |
|
||||||
|
| 8 | 31 | 01 June 2024 | | 109.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 |
|
||||||
|
| 9 | 30 | 01 July 2024 | | 55.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 | 0.0 | 0.0 | 0.0 | 54.0 |
|
||||||
|
| 10 | 31 | 01 August 2024 | | 0.0 | 55.0 | 0.0 | 0.0 | 0.0 | 55.0 | 0.0 | 0.0 | 0.0 | 55.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
| 16 January 2024 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 325.0 | false |
|
||||||
|
| 27 February 2024 | Re-age | 325.0 | 325.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
When Admin sets the business date to "29 February 2024"
|
||||||
|
When Admin successfully undo Loan re-aging transaction
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 50.0 | 0.0 | 0.0 | 75.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
| 16 January 2024 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 325.0 | false |
|
||||||
|
| 27 February 2024 | Re-age | 325.0 | 325.0 | 0.0 | 0.0 | 0.0 | 0.0 | true |
|
||||||
|
|
||||||
|
@TestRailId:C3091 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-age transaction - Event check
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "27 February 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then LoanDelinquencyRangeChangeBusinessEvent is created
|
||||||
|
When Admin creates a Loan re-aging transaction with the following data:
|
||||||
|
| frequencyNumber | frequencyType | startDate | numberOfInstallments |
|
||||||
|
| 1 | MONTHS | 01 March 2024 | 6 |
|
||||||
|
Then LoanDelinquencyRangeChangeBusinessEvent is created
|
||||||
|
Then LoanReAgeBusinessEvent is created
|
||||||
@@ -0,0 +1,377 @@
|
|||||||
|
@LoanReAmortizationFeature
|
||||||
|
Feature: LoanReAmortization
|
||||||
|
|
||||||
|
@TestRailId:C3069 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - re-amortization happy path
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "25 January 2024"
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 25 January 2024 | Re-amortize | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3070 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - re-amortization happy path with loan externalId
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "25 January 2024"
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date by loan external ID
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 25 January 2024 | Re-amortize | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3071 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - re-amortization undo happy path
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "25 January 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 25 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
| 25 January 2024 | Re-amortize | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
|
||||||
|
When Admin sets the business date to "26 January 2024"
|
||||||
|
When When Admin undo Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 | false |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 | false |
|
||||||
|
| 25 January 2024 | Re-amortize | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 0.0 | true |
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2024-01-19"
|
||||||
|
|
||||||
|
@TestRailId:C3072 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - delinquency calculation triggered upon re-amortization transaction
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "24 January 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then Admin checks that delinquency range is: "RANGE_3" and has delinquentDate "2024-01-19"
|
||||||
|
When Admin sets the business date to "25 January 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
|
||||||
|
|
||||||
|
@TestRailId:C3073 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC1: re-amortization after charge applied on loan
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "16 January 2024"
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "16 January 2024" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "25 January 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 375.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 187.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 | 0.0 | 0.0 | 0.0 | 188.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 | 0.0 | 0.0 | 0.0 | 187.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 10.0 | 510.0 | 125.0 | 0.0 | 0.0 | 385.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 25 January 2024 | Re-amortize | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3074 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC2: complete past due principal amount reamortization scenario
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 February 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 01 February 2024 | Re-amortize | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3075 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC3: reverse replay scenario
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 February 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 125.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 01 February 2024 | Re-amortize | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
When Admin sets the business date to "02 February 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "15 January 2024" with 125 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 15 January 2024 | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 125.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 01 February 2024 | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 250.0 | 125.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 15 January 2024 | Repayment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 01 February 2024 | Re-amortize | 375.0 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3076 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC4: N+1 Installment scenario
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "01 February 2024"
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "27 February 2024" due date and 10 EUR transaction amount
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 5 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 01 February 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 5 | 12 | 27 February 2024 | | 0.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 10.0 | 510.0 | 125.0 | 0.0 | 0.0 | 385.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 01 February 2024 | Re-amortize | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3077 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC5: re-amortization on same day of installment
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "16 January 2024"
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "16 January 2024" due date and 10 EUR transaction amount
|
||||||
|
When Admin sets the business date to "31 January 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 375.0 | 0.0 | 0.0 | 0.0 | 10.0 | 10.0 | 0.0 | 0.0 | 0.0 | 10.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | 31 January 2024 | 375.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 10.0 | 510.0 | 125.0 | 0.0 | 0.0 | 385.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 31 January 2024 | Re-amortize | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3078 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - UC6: Parital Paid Scenario
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "17 January 2024"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "17 January 2024" with 50 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | | 250.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 50.0 | 0.0 | 50.0 | 75.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 175.0 | 0.0 | 50.0 | 325.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 17 January 2024 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 325.0 |
|
||||||
|
When Admin sets the business date to "30 January 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date by loan external ID
|
||||||
|
Then Loan Repayment schedule has 4 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 January 2024 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 January 2024 | 01 January 2024 | 375.0 | 125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 January 2024 | 30 January 2024 | 325.0 | 50.0 | 0.0 | 0.0 | 0.0 | 50.0 | 50.0 | 0.0 | 50.0 | 0.0 |
|
||||||
|
| 3 | 15 | 31 January 2024 | | 162.0 | 163.0 | 0.0 | 0.0 | 0.0 | 163.0 | 0.0 | 0.0 | 0.0 | 163.0 |
|
||||||
|
| 4 | 15 | 15 February 2024 | | 0.0 | 162.0 | 0.0 | 0.0 | 0.0 | 162.0 | 0.0 | 0.0 | 0.0 | 162.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 175.0 | 0.0 | 50.0 | 325.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| 01 January 2024 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 01 January 2024 | Down Payment | 125.0 | 125.0 | 0.0 | 0.0 | 0.0 | 375.0 |
|
||||||
|
| 17 January 2024 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | 0.0 | 325.0 |
|
||||||
|
| 30 January 2024 | Re-amortize | 75.0 | 75.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3089 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify Loan re-amortization transaction - Event check
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 500 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "500" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "500" EUR transaction amount
|
||||||
|
When Admin sets the business date to "31 January 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
Then LoanDelinquencyRangeChangeBusinessEvent is created
|
||||||
|
When Admin sets the business date to "01 February 2024"
|
||||||
|
When When Admin creates a Loan re-amortization transaction on current business date
|
||||||
|
Then LoanDelinquencyRangeChangeBusinessEvent is created
|
||||||
|
Then LoanReAmortizeBusinessEvent is created
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,681 @@
|
|||||||
|
@LoanRescheduleFeature
|
||||||
|
Feature: LoanReschedule
|
||||||
|
|
||||||
|
@TestRailId:C2680
|
||||||
|
Scenario: As a user I would like to see a loan changed event was triggered when the loan got rescheduled
|
||||||
|
When Admin sets the business date to "1 July 2022"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
And Admin successfully creates a new customised Loan submitted on date: "1 July 2022", with Principal: "5000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
|
||||||
|
And Admin successfully approves the loan on "1 July 2022" with "5000" amount and expected disbursement date on "1 July 2022"
|
||||||
|
When Admin successfully disburse the loan on "1 July 2022" with "5000" EUR transaction amount
|
||||||
|
When Batch API call with steps: rescheduleLoan from "1 August 2022" to "31 August 2022" submitted on date: "1 July 2022", approveReschedule on date: "1 July 2022" runs with enclosingTransaction: "true"
|
||||||
|
Then Loan Repayment schedule has 1 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 2022 | | 5000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 61 | 31 August 2022 | | 0.0 | 5000.0 | 0.0 | 0.0 | 0.0 | 5000.0 | 0.0 | 0.0 | 0.0 | 5000.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2801
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: undo disbursement
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
When Admin sets the business date to "02 July 2023"
|
||||||
|
When Admin successfully undo disbursal
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 1000.0 | | | 0.0 | | 0.0 | | | | 0.0 |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
|
||||||
|
@TestRailId:C2802
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple disbursement, second disbursement placed within payment period
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "500" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500 | 0 | 0 | 0 | 500 | 0 | 0 | 0 | 500 |
|
||||||
|
When Admin sets the business date to "10 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "10 July 2023" with "500" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| | | 10 July 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
|
||||||
|
@TestRailId:C2803
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple disbursement, second disbursement placed after payment period
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "500" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500 | 0 | 0 | 0 | 500 | 0 | 0 | 0 | 500 |
|
||||||
|
When Admin sets the business date to "10 August 2023"
|
||||||
|
And Admin successfully disburse the loan on "10 August 2023" with "500" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 2 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 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| | | 10 August 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 2 | 30 | 30 August 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
When Admin successfully undo last disbursal
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 500.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 500 | 0 | 0 | 0 | 500 | 0 | 0 | 0 | 500 |
|
||||||
|
|
||||||
|
@TestRailId:C2804
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: single installment, changing installment date
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a new default Loan with date: "01 July 2023"
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "1000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "1000" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 30 | 31 July 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 31 July 2023 | 05 July 2023 | 31 August 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 1 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 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 61 | 31 August 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000 | 0 | 0 | 0 | 1000 | 0 | 0 | 0 | 1000 |
|
||||||
|
|
||||||
|
@TestRailId:C2805
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple installments, changing installment date
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 01 July 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "3000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "3000" 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 01 September 2023 | 05 July 2023 | 15 September 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 45 | 15 September 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 15 October 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
|
||||||
|
@TestRailId:C2806
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple installments, extending repayment schedule
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 01 July 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "3000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "3000" 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 01 September 2023 | 05 July 2023 | | 0 | 0 | 2 | 0 |
|
||||||
|
Then Loan Repayment schedule has 5 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1500.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 1000.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 4 | 31 | 01 November 2023 | | 500.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
| 5 | 30 | 01 December 2023 | | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
|
||||||
|
@TestRailId:C2807
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple installments, mid-term grace period on principal
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30 | 01 July 2023 | 3000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "3000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "3000" 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 01 September 2023 | 05 July 2023 | | 1 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | 01 July 2023 | 2000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
| 4 | 31 | 01 November 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 0 | 0 | 0 | 3000 | 0 | 0 | 0 | 3000 |
|
||||||
|
|
||||||
|
# TODO check and fix after Loan reschedule with graceOnInterest deletes all future interest portions when called from API was fixed (periods back to 3 or 5)
|
||||||
|
@Skip @TestRailId:C2808
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple installments, mid-term grace period on interest
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30_INTEREST_FLAT | 01 July 2023 | 3000 | 12 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 10 | MONTHS | 1 | MONTHS | 10 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "3000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "3000" 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
# | 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
# | 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
# | 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
# Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
# | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
# | 3000 | 90 | 0 | 0 | 3090 | 0 | 0 | 0 | 3090 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 01 September 2023 | 05 July 2023 | | 0 | 2 | 0 | 0 |
|
||||||
|
# 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
# | 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
# | 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
# | 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
# Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
# | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
# | 3000 | 30 | 0 | 0 | 3030 | 0 | 0 | 0 | 3030 |
|
||||||
|
|
||||||
|
@TestRailId:C2809
|
||||||
|
Scenario: Verify that loan is rescheduled properly in case of: multiple installments, new interest rate
|
||||||
|
When Admin sets the business date to "01 July 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN30_INTEREST_FLAT | 01 July 2023 | 3000 | 12 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||||
|
And Admin successfully approves the loan on "01 July 2023" with "3000" amount and expected disbursement date on "01 July 2023"
|
||||||
|
And Admin successfully disburse the loan on "01 July 2023" with "3000" 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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 90 | 0 | 0 | 3090 | 0 | 0 | 0 | 3090 |
|
||||||
|
When Admin sets the business date to "05 July 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 01 September 2023 | 05 July 2023 | | 0 | 0 | 0 | 6 |
|
||||||
|
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 2023 | | 3000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 31 | 01 August 2023 | | 2000.0 | 1000.0 | 30.0 | 0.0 | 0.0 | 1030.0 | 0.0 | 0.0 | 0.0 | 1030.0 |
|
||||||
|
| 2 | 31 | 01 September 2023 | | 1000.0 | 1000.0 | 15.0 | 0.0 | 0.0 | 1015.0 | 0.0 | 0.0 | 0.0 | 1015.0 |
|
||||||
|
| 3 | 30 | 01 October 2023 | | 0.0 | 1000.0 | 15.0 | 0.0 | 0.0 | 1015.0 | 0.0 | 0.0 | 0.0 | 1015.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 3000 | 60 | 0 | 0 | 3060 | 0 | 0 | 0 | 3060 |
|
||||||
|
|
||||||
|
@TestRailId:C2996
|
||||||
|
Scenario: Verify that reschedule: add extra terms working properly with auto downpayment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 01 October 2023 | | 0 | 0 | 2 | 0 |
|
||||||
|
Then Loan Repayment schedule has 6 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 October 2023 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 3 | 15 | 31 October 2023 | | 450.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 4 | 15 | 15 November 2023 | | 300.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 5 | 15 | 30 November 2023 | | 150.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 6 | 15 | 15 December 2023 | | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C2997
|
||||||
|
Scenario: Verify that reschedule: add extra terms working properly with auto downpayment and 2nd disbursement before reschedule
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "10 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "10 October 2023" with "400" EUR transaction amount
|
||||||
|
When Admin sets the business date to "11 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 01 October 2023 | | 0 | 0 | 2 | 0 |
|
||||||
|
Then Loan Repayment schedule has 7 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| | | 10 October 2023 | | 400.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 2 | 0 | 10 October 2023 | 10 October 2023 | 1050.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 100.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 16 October 2023 | | 840.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 |
|
||||||
|
| 4 | 15 | 31 October 2023 | | 630.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 |
|
||||||
|
| 5 | 15 | 15 November 2023 | | 420.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 |
|
||||||
|
| 6 | 15 | 30 November 2023 | | 210.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 |
|
||||||
|
| 7 | 15 | 15 December 2023 | | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 | 0.0 | 0.0 | 0.0 | 210.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 0.0 | 1050.0 |
|
||||||
|
|
||||||
|
# TODO remove Skip when Reschedule does not work properly in case of PIN4_DOWNPAYMENT_AUTO and with 2nd disbursement after reschedule and first installment is fixed
|
||||||
|
@Skip
|
||||||
|
@TestRailId:C2998
|
||||||
|
Scenario: Verify that reschedule: add extra terms working properly with auto downpayment and 2nd disbursement after reschedule and first installment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "11 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 01 October 2023 | | 0 | 0 | 2 | 0 |
|
||||||
|
When Admin sets the business date to "20 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "20 October 2023" with "400" EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 7 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 15 | 16 October 2023 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 100.0 | 0.0 | 100.0 | 50.0 |
|
||||||
|
| | | 20 October 2023 | | 400.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 3 | 0 | 20 October 2023 | | 900.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
|
||||||
|
| 4 | 15 | 31 October 2023 | | 675.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
|
||||||
|
| 5 | 15 | 15 November 2023 | | 450.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
|
||||||
|
| 6 | 15 | 30 November 2023 | | 225.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
|
||||||
|
| 7 | 15 | 15 December 2023 | | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 100.0 | 1050.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3022
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 1 installment period after successful downpayment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3023
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 2 installment period after successful downpayment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 15 November 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 45 | 15 November 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 30 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 December 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3024
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 2 installment period while downpayment is still due
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 15 November 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 45 | 15 November 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 30 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 December 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3025
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 1 installment period after downpayment was reverted, fee added and downpayment paid by autopayment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
And Customer makes "AUTOPAY" repayment on "01 October 2023" with 250 EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 October 2023"
|
||||||
|
When Customer undo "1"th repayment on "01 October 2023"
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "16 October 2023" due date and 15 EUR transaction amount
|
||||||
|
When Admin sets the business date to "03 October 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "03 October 2023" with 250 EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 03 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 250.0 | 0.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 15.0 | 265.0 | 0.0 | 0.0 | 0.0 | 265.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 15.0 | 1015.0 | 250.0 | 0.0 | 250.0 | 765.0 |
|
||||||
|
Then Loan Transactions tab has the following data:
|
||||||
|
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted |
|
||||||
|
| 01 October 2023 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false |
|
||||||
|
| 01 October 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | true |
|
||||||
|
| 03 October 2023 | Repayment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
|
||||||
|
|
||||||
|
@TestRailId:C3026
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of auto downpayment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 01 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 4 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3027
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of auto downpayment and 2nd disbursement before reschedule
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "10 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "10 October 2023" with "400" EUR transaction amount
|
||||||
|
When Admin sets the business date to "11 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 01 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 5 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| | | 10 October 2023 | | 400.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 2 | 0 | 10 October 2023 | 10 October 2023 | 1050.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 100.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 30 | 31 October 2023 | | 700.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 |
|
||||||
|
| 4 | 15 | 15 November 2023 | | 350.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 |
|
||||||
|
| 5 | 15 | 30 November 2023 | | 0.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 | 0.0 | 0.0 | 0.0 | 350.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 0.0 | 1050.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3028
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 1 installment period and 2 extra terms
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 0 | 0 | 2 | 0 |
|
||||||
|
Then Loan Repayment schedule has 6 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 450.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 300.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 5 | 15 | 15 December 2023 | | 150.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
| 6 | 15 | 30 December 2023 | | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3029
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 1 installment period and 1 grace on principal
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 1 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 5 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | 01 October 2023 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 5 | 15 | 15 December 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3030
|
||||||
|
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) gives error in case of charged-off loan
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "03 October 2023"
|
||||||
|
And Admin does charge-off the loan on "03 October 2023"
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
Then Loan reschedule with the following data results a 403 error and "LOAN_CHARGED_OFF" error message
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
|
||||||
|
@TestRailId:C3033
|
||||||
|
Scenario: Verify that reschedule keeps the N+1 installment
|
||||||
|
When Admin sets the business date to "01 October 2023"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT | 01 October 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
|
||||||
|
And Admin successfully approves the loan on "01 October 2023" with "1000" amount and expected disbursement date on "01 October 2023"
|
||||||
|
When Admin successfully disburse the loan on "01 October 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin adds "LOAN_NSF_FEE" due date charge with "17 December 2023" due date and 20 EUR transaction amount
|
||||||
|
Then Loan Repayment schedule has 5 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 15 | 16 October 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 31 October 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 15 November 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 5 | 32 | 17 December 2023 | | 0.0 | 0.0 | 0.0 | 0.0 | 20.0 | 20.0 | 0.0 | 0.0 | 0.0 | 20.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 20.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
When Admin sets the business date to "05 October 2023"
|
||||||
|
When Admin creates and approves Loan reschedule with the following data:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | graceOnPrincipal | graceOnInterest | extraTerms | newInterestRate |
|
||||||
|
| 16 October 2023 | 05 October 2023 | 31 October 2023 | 0 | 0 | 0 | 0 |
|
||||||
|
Then Loan Repayment schedule has 5 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 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
|
||||||
|
| 1 | 0 | 01 October 2023 | | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 2 | 30 | 31 October 2023 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 3 | 15 | 15 November 2023 | | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 4 | 15 | 30 November 2023 | | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
|
||||||
|
| 5 | 17 | 17 December 2023 | | 0.0 | 0.0 | 0.0 | 0.0 | 20.0 | 20.0 | 0.0 | 0.0 | 0.0 | 20.0 |
|
||||||
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
|
| 1000.0 | 0.0 | 0.0 | 20.0 | 1020.0 | 0.0 | 0.0 | 0.0 | 1020.0 |
|
||||||
|
|
||||||
|
@TestRailId:C3045 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that inline COB execution is taking place in case of a BatchAPI request of Loan reschedule creation and approval
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| APPROVE_RESCHEDULELOAN |
|
||||||
|
| CREATE_RESCHEDULELOAN |
|
||||||
|
| READ_RESCHEDULELOAN |
|
||||||
|
| REJECT_RESCHEDULELOAN |
|
||||||
|
When Admin sets the business date to "10 January 2024"
|
||||||
|
When Batch API call with created user and with steps: rescheduleLoan from "16 January 2024" to "31 January 2024" submitted on date: "10 January 2024", approveReschedule on date: "10 January 2024" runs with enclosingTransaction: "true"
|
||||||
|
Then Admin checks that last closed business date of loan is "09 January 2024"
|
||||||
|
|
||||||
|
@TestRailId:C3048 @AdvancedPaymentAllocation
|
||||||
|
Scenario: Verify that in case of Loan is hard locked for COB execution, BatchAPI request of Loan reschedule creation and approval will result a 409 error and a LOAN_LOCKED_BY_COB error message
|
||||||
|
When Admin sets the business date to "01 January 2024"
|
||||||
|
When Admin creates a client with random data
|
||||||
|
When Admin set "PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2024 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
|
||||||
|
When Admin successfully disburse the loan on "01 January 2024" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "02 January 2024"
|
||||||
|
When Admin runs inline COB job for Loan
|
||||||
|
When Admin sets the business date to "10 January 2024"
|
||||||
|
When Admin places a lock on loan account with an error message
|
||||||
|
When Admin creates new user with "NO_BYPASS_AUTOTEST" username, "NO_BYPASS_AUTOTEST_ROLE" role name and given permissions:
|
||||||
|
| APPROVE_RESCHEDULELOAN |
|
||||||
|
| CREATE_RESCHEDULELOAN |
|
||||||
|
| READ_RESCHEDULELOAN |
|
||||||
|
| REJECT_RESCHEDULELOAN |
|
||||||
|
When Batch API call with created user and the following data results a 409 error and a "LOAN_LOCKED_BY_COB" error message:
|
||||||
|
| rescheduleFromDate | submittedOnDate | adjustedDueDate | approvedOnDate | enclosingTransaction |
|
||||||
|
| 16 January 2024 | 10 January 2024 | 31 January 2024 | 10 January 2024 | true |
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
@WriteOffFeature
|
||||||
|
Feature: Write-off
|
||||||
|
|
||||||
|
@TestRailId:C2934
|
||||||
|
Scenario: As a user I want to do Write-off a loan and verify that undo repayment post write-off results in error
|
||||||
|
When Admin sets the business date to "1 January 2023"
|
||||||
|
And Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "1 January 2023" with "1000" amount and expected disbursement date on "1 January 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "22 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "22 January 2023" with 100 EUR transaction amount
|
||||||
|
When Admin sets the business date to "29 January 2023"
|
||||||
|
And Admin does write-off the loan on "29 January 2023"
|
||||||
|
Then Loan status will be "CLOSED_WRITTEN_OFF"
|
||||||
|
Then Loan Transactions tab has a transaction with date: "29 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Close (as written-off) | 650.0 | 650.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
Then Admin fails to undo "1"th transaction made on "22 January 2023"
|
||||||
|
|
||||||
|
|
||||||
|
@TestRailId:C2935
|
||||||
|
Scenario: As a user I want to do Write-off a loan and verify that backdate repayment post write-off results in error
|
||||||
|
When Admin sets the business date to "1 January 2023"
|
||||||
|
And Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "1 January 2023" with "1000" amount and expected disbursement date on "1 January 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "22 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "22 January 2023" with 100 EUR transaction amount
|
||||||
|
When Admin sets the business date to "29 January 2023"
|
||||||
|
And Admin does write-off the loan on "29 January 2023"
|
||||||
|
Then Loan status will be "CLOSED_WRITTEN_OFF"
|
||||||
|
Then Loan Transactions tab has a transaction with date: "29 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Close (as written-off) | 650.0 | 650.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
Then Loan "AUTOPAY" repayment transaction on "26 January 2023" with 50 EUR transaction amount results in error
|
||||||
|
|
||||||
|
|
||||||
|
@TestRailId:C2936
|
||||||
|
Scenario: As a user I want to do Write-off a loan and verify that undo write-off results in error
|
||||||
|
When Admin sets the business date to "1 January 2023"
|
||||||
|
And Admin creates a client with random data
|
||||||
|
When Admin creates a fully customized loan with the following data:
|
||||||
|
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||||
|
| PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION | 01 January 2023 | 1000 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||||
|
And Admin successfully approves the loan on "1 January 2023" with "1000" amount and expected disbursement date on "1 January 2023"
|
||||||
|
And Admin successfully disburse the loan on "1 January 2023" with "1000" EUR transaction amount
|
||||||
|
When Admin sets the business date to "22 January 2023"
|
||||||
|
And Customer makes "AUTOPAY" repayment on "22 January 2023" with 100 EUR transaction amount
|
||||||
|
When Admin sets the business date to "29 January 2023"
|
||||||
|
And Admin does write-off the loan on "29 January 2023"
|
||||||
|
Then Loan status will be "CLOSED_WRITTEN_OFF"
|
||||||
|
Then Loan Transactions tab has a transaction with date: "29 January 2023", and with the following data:
|
||||||
|
| Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||||
|
| Close (as written-off) | 650.0 | 650.0 | 0.0 | 0.0 | 0.0 | 0.0 |
|
||||||
|
Then Admin fails to undo "1"th transaction made on "29 January 2023"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user