Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3871,6 +3871,15 @@ public CommandWrapperBuilder updateExternalAssetOwnerLoanProductAttribute(final
return this;
}

public CommandWrapperBuilder deleteExternalAssetOwnerLoanProductAttribute(final Long loanProductId, final Long attributeId) {
this.actionName = ACTION_DELETE;
this.entityName = ENTITY_EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE;
this.productId = loanProductId;
this.entityId = attributeId;
this.href = "/external-asset-owners/loan-product/" + loanProductId + "/attributes/" + attributeId;
return this;
}

public CommandWrapperBuilder intermediarySaleLoanToExternalAssetOwner(final Long loanId) {
this.actionName = ACTION_INTERMEDIARYSALE;
this.entityName = ENTITY_LOAN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public enum AssetExternalizationErrorMessage {
LOAN_SUBMITTED_AND_PENDING_APPROVAL_INVALID("Loan status SUBMITTED_AND_PENDING_APPROVAL is not valid for transfer."), //
LOAN_APPROVED_INVALID("Loan status APPROVED is not valid for transfer."), //
ALREADY_IN_PROGRESS("This loan cannot be sold, there is already an in progress transfer"), //
LOAN_PRODUCT_ATTRIBUTE_ALREADY_EXISTS("attributeKey already exists for the loanProductId"), //
LOAN_PRODUCT_ATTRIBUTE_INVALID("The given attribute key or attribute value is not valid."), //
LOAN_PRODUCT_NOT_FOUND("Loan product with identifier"), //
USER_HAS_NO_CREATE_ATTRIBUTE_AUTHORITY("User has no authority to: CREATE_EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE"), //
USER_HAS_NO_UPDATE_ATTRIBUTE_AUTHORITY("User has no authority to: UPDATE_EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE"), //
INVALID_REQUEST("The request was invalid. This typically will happen due to validation errors which are provided."); //

public final String value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.feign.FineractFeignClient;
import org.apache.fineract.client.feign.services.ExternalAssetOwnerLoanProductAttributesApi;
import org.apache.fineract.client.feign.services.ExternalAssetOwnersApi;
import org.apache.fineract.client.feign.services.LoanProductsApi;
import org.apache.fineract.client.feign.util.CallFailedRuntimeException;
import org.apache.fineract.client.models.CommandProcessingResult;
import org.apache.fineract.client.models.ExternalAssetOwnerRequest;
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.ExternalTransferLoanProductAttributesData;
import org.apache.fineract.client.models.ExternalTransferLoanProductAttributesTemplateData;
import org.apache.fineract.client.models.ExternalTransferOwnerData;
import org.apache.fineract.client.models.GetLoanProductsResponse;
import org.apache.fineract.client.models.JournalEntryData;
Expand All @@ -52,19 +55,22 @@
import org.apache.fineract.client.models.PostExternalAssetOwnerRequest;
import org.apache.fineract.client.models.PostExternalAssetOwnerResponse;
import org.apache.fineract.client.models.PostInitiateTransferResponse;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PutExternalAssetOwnerLoanProductAttributeRequest;
import org.apache.fineract.test.api.FineractClientConfiguration;
import org.apache.fineract.test.data.AssetExternalizationErrorMessage;
import org.apache.fineract.test.factory.LoanProductsRequestFactory;
import org.apache.fineract.test.helper.ErrorMessageHelper;
import org.apache.fineract.test.helper.Utils;
import org.apache.fineract.test.messaging.EventAssertion;
import org.apache.fineract.test.messaging.event.EventCheckHelper;
import org.apache.fineract.test.messaging.event.assetexternalization.LoanOwnershipTransferEvent;
import org.apache.fineract.test.stepdef.AbstractStepDef;
import org.apache.fineract.test.support.TestContextKey;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
@RequiredArgsConstructor
public class AssetExternalizationStepDef extends AbstractStepDef {

public static final String OWNER_EXTERNAL_ID_PREFIX = "TestOwner-";
Expand All @@ -75,15 +81,13 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
public static final String TRANSACTION_TYPE_INTERMEDIARY_SALE = "intermediarySale";
public static final String COMMAND = "command";
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_ASSET_EXT);
private static final long NON_EXISTING_LOAN_PRODUCT_ID = 999_999_999L;

@Autowired
private FineractFeignClient fineractFeignClient;

@Autowired
private EventCheckHelper eventCheckHelper;

@Autowired
private EventAssertion eventAssertion;
private final FineractFeignClient fineractFeignClient;
private final EventCheckHelper eventCheckHelper;
private final EventAssertion eventAssertion;
private final FineractClientConfiguration fineractClientConfiguration;
private final LoanProductsRequestFactory loanProductsRequestFactory;

private ExternalAssetOwnersApi externalAssetOwnersApi() {
return fineractFeignClient.externalAssetOwners();
Expand Down Expand Up @@ -1021,4 +1025,168 @@ public void retrieveAllExternalAssetOwners() {
assertThat(owners).as("Owners list should not be null").isNotNull();
}

@When("Admin creates a new loan product for external asset owner loan product attributes")
public void createLoanProductForExternalAssetOwnerLoanProductAttributes() {
final PostLoanProductsResponse response = ok(
() -> loanProductsApi().createLoanProduct(loanProductsRequestFactory.defaultLoanProductsRequestLP1()));
testContext().set(TestContextKey.EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE_LOAN_PRODUCT_ID, response.getResourceId());
}

@Then("External asset owner loan product attributes template contains the following attributes:")
public void checkExternalAssetOwnerLoanProductAttributesTemplate(final DataTable table) {
final List<ExternalTransferLoanProductAttributesTemplateData> template = ok(
() -> externalAssetOwnerLoanProductAttributesApi().retrieveTemplateExternalAssetOwnerLoanProductAttributes());

table.asMaps().forEach(expectedAttribute -> {
final String attributeKey = expectedAttribute.get("attributeKey");
final ExternalTransferLoanProductAttributesTemplateData actualAttribute = template.stream()
.filter(attribute -> attributeKey.equals(attribute.getAttributeKey())).findFirst()
.orElseThrow(() -> new IllegalStateException(String.format("No attribute %s is found in the template", attributeKey)));

assertThat(actualAttribute.getAttributeValues()).as("Values of attribute %s in the template", attributeKey)
.isEqualTo(List.of(expectedAttribute.get("attributeValues").split(",", -1)));
assertThat(actualAttribute.getMultiValue()).as("Multi value flag of attribute %s in the template", attributeKey)
.isEqualTo(Boolean.parseBoolean(expectedAttribute.get("multiValue")));
});
}

@When("Admin creates external asset owner loan product attribute {string} with value {string} for the new loan product")
public void createExternalAssetOwnerLoanProductAttribute(final String attributeKey, final String attributeValue) {
final Long loanProductId = newLoanProductId();

final CommandProcessingResult result = ok(() -> externalAssetOwnerLoanProductAttributesApi()
.createExternalAssetOwnerLoanProductAttribute(loanProductId, createAttributeRequest(attributeKey, attributeValue)));

assertThat(result.getResourceId()).as("Resource id of the created attribute %s", attributeKey).isEqualTo(loanProductId);
}

@When("Admin updates external asset owner loan product attribute {string} of the new loan product to value {string}")
public void updateExternalAssetOwnerLoanProductAttribute(final String attributeKey, final String attributeValue) {
final Long loanProductId = newLoanProductId();
final Long attributeId = retrieveAttributeOfNewLoanProduct(attributeKey).getAttributeId();

ok(() -> externalAssetOwnerLoanProductAttributesApi().updateExternalAssetOwnerLoanProductAttribute(loanProductId, attributeId,
updateAttributeRequest(attributeKey, attributeValue)));
}

@Then("External asset owner loan product attribute {string} of the new loan product has value {string}")
public void checkExternalAssetOwnerLoanProductAttributeValue(final String attributeKey, final String attributeValue) {
final Long loanProductId = newLoanProductId();
final PageExternalTransferLoanProductAttributesData attributes = retrieveAttributesOfNewLoanProduct(attributeKey);

assertThat(attributes.getTotalFilteredRecords()).as("Number of attributes %s of loan product %s", attributeKey, loanProductId)
.isOne();
final ExternalTransferLoanProductAttributesData attribute = attributes.getPageItems().stream().findFirst().orElseThrow();
assertThat(attribute.getAttributeId()).as("Id of attribute %s", attributeKey).isNotNull();
assertThat(attribute.getAttributeKey()).as("Key of attribute %s", attributeKey).isEqualTo(attributeKey);
assertThat(attribute.getAttributeValue()).as("Value of attribute %s", attributeKey).isEqualTo(attributeValue);
assertThat(attribute.getLoanProductId()).as("Loan product id of attribute %s", attributeKey).isEqualTo(loanProductId);
}

@Then("External asset owner loan product attribute {string} of the new loan product does not exist")
public void checkExternalAssetOwnerLoanProductAttributeDoesNotExist(final String attributeKey) {
assertThat(retrieveAttributesOfNewLoanProduct(attributeKey).getTotalFilteredRecords())
.as("Number of attributes %s of loan product %s", attributeKey, newLoanProductId()).isZero();
}

@Then("Creating external asset owner loan product attribute {string} with value {string} for the new loan product results a {int} error and {string} error message")
public void createExternalAssetOwnerLoanProductAttributeFails(final String attributeKey, final String attributeValue,
final int errorCodeExpected, final String errorMessageType) {
assertExternalAssetOwnerLoanProductAttributeCreationFails(externalAssetOwnerLoanProductAttributesApi(), newLoanProductId(),
attributeKey, attributeValue, errorCodeExpected, errorMessageType);
}

@Then("Created user creating external asset owner loan product attribute {string} with value {string} for the new loan product results a {int} error and {string} error message")
public void createExternalAssetOwnerLoanProductAttributeByCreatedUserFails(final String attributeKey, final String attributeValue,
final int errorCodeExpected, final String errorMessageType) {
assertExternalAssetOwnerLoanProductAttributeCreationFails(createdUserExternalAssetOwnerLoanProductAttributesApi(),
newLoanProductId(), attributeKey, attributeValue, errorCodeExpected, errorMessageType);
}

@Then("Creating external asset owner loan product attribute {string} with value {string} for non-existing loan product results a {int} error and {string} error message")
public void createExternalAssetOwnerLoanProductAttributeForNonExistingLoanProductFails(final String attributeKey,
final String attributeValue, final int errorCodeExpected, final String errorMessageType) {
assertExternalAssetOwnerLoanProductAttributeCreationFails(externalAssetOwnerLoanProductAttributesApi(),
NON_EXISTING_LOAN_PRODUCT_ID, attributeKey, attributeValue, errorCodeExpected, errorMessageType);
}

@Then("Updating external asset owner loan product attribute {string} of the new loan product to value {string} results a {int} error and {string} error message")
public void updateExternalAssetOwnerLoanProductAttributeFails(final String attributeKey, final String attributeValue,
final int errorCodeExpected, final String errorMessageType) {
assertExternalAssetOwnerLoanProductAttributeUpdateFails(externalAssetOwnerLoanProductAttributesApi(), attributeKey, attributeValue,
errorCodeExpected, errorMessageType);
}

@Then("Created user updating external asset owner loan product attribute {string} of the new loan product to value {string} results a {int} error and {string} error message")
public void updateExternalAssetOwnerLoanProductAttributeByCreatedUserFails(final String attributeKey, final String attributeValue,
final int errorCodeExpected, final String errorMessageType) {
assertExternalAssetOwnerLoanProductAttributeUpdateFails(createdUserExternalAssetOwnerLoanProductAttributesApi(), attributeKey,
attributeValue, errorCodeExpected, errorMessageType);
}

private void assertExternalAssetOwnerLoanProductAttributeCreationFails(final ExternalAssetOwnerLoanProductAttributesApi attributesApi,
final Long loanProductId, final String attributeKey, final String attributeValue, final int errorCodeExpected,
final String errorMessageType) {
final CallFailedRuntimeException exception = fail(() -> attributesApi.createExternalAssetOwnerLoanProductAttribute(loanProductId,
createAttributeRequest(attributeKey, attributeValue)));

assertExternalAssetOwnerLoanProductAttributeError(exception, errorCodeExpected, errorMessageType);
}

private void assertExternalAssetOwnerLoanProductAttributeUpdateFails(final ExternalAssetOwnerLoanProductAttributesApi attributesApi,
final String attributeKey, final String attributeValue, final int errorCodeExpected, final String errorMessageType) {
final Long loanProductId = newLoanProductId();
final Long attributeId = retrieveAttributeOfNewLoanProduct(attributeKey).getAttributeId();

final CallFailedRuntimeException exception = fail(() -> attributesApi.updateExternalAssetOwnerLoanProductAttribute(loanProductId,
attributeId, updateAttributeRequest(attributeKey, attributeValue)));

assertExternalAssetOwnerLoanProductAttributeError(exception, errorCodeExpected, errorMessageType);
}

private void assertExternalAssetOwnerLoanProductAttributeError(final CallFailedRuntimeException exception, final int errorCodeExpected,
final String errorMessageType) {
final String errorMessageExpected = AssetExternalizationErrorMessage.valueOf(errorMessageType).getValue();
final int errorCodeActual = exception.getStatus();
final String errorMessageActual = exception.getDeveloperMessage();

assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
.contains(errorMessageExpected);

logErrorDetails(errorCodeActual, errorMessageActual);
}

private Long newLoanProductId() {
return testContext().get(TestContextKey.EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE_LOAN_PRODUCT_ID);
}

private ExternalAssetOwnerLoanProductAttributesApi createdUserExternalAssetOwnerLoanProductAttributesApi() {
final String username = testContext().get(TestContextKey.CREATED_SIMPLE_USER_USERNAME);
final String password = testContext().get(TestContextKey.CREATED_SIMPLE_USER_PASSWORD);
return fineractClientConfiguration.fineractFeignClientForUser(username, password).externalAssetOwnerLoanProductAttributes();
}

private PageExternalTransferLoanProductAttributesData retrieveAttributesOfNewLoanProduct(final String attributeKey) {
final Long loanProductId = newLoanProductId();
return ok(() -> externalAssetOwnerLoanProductAttributesApi().retrieveAllExternalAssetOwnerLoanProductAttributes(loanProductId,
attributeKey));
}

private ExternalTransferLoanProductAttributesData retrieveAttributeOfNewLoanProduct(final String attributeKey) {
return retrieveAttributesOfNewLoanProduct(attributeKey).getPageItems().stream().findFirst()
.orElseThrow(() -> new IllegalStateException(
ErrorMessageHelper.wrongDataInExternalAssetOwnerLoanProductAttribute(attributeKey, newLoanProductId())));
}

private PostExternalAssetOwnerLoanProductAttributeRequest createAttributeRequest(final String attributeKey,
final String attributeValue) {
return new PostExternalAssetOwnerLoanProductAttributeRequest().attributeKey(attributeKey).attributeValue(attributeValue);
}

private PutExternalAssetOwnerLoanProductAttributeRequest updateAttributeRequest(final String attributeKey,
final String attributeValue) {
return new PutExternalAssetOwnerLoanProductAttributeRequest().attributeKey(attributeKey).attributeValue(attributeValue);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public abstract class TestContextKey {
public static final String ASSET_EXTERNALIZATION_PREVIOUS_OWNER_EXTERNAL_ID = "assetExternalizationPreviousOwnerExternalId";
public static final String EXTERNAL_ASSET_OWNER_CREATE_RESPONSE = "externalAssetOwnerCreateResponse";
public static final String EXTERNAL_ASSET_OWNER_EXTERNAL_ID = "externalAssetOwnerExternalId";
public static final String EXTERNAL_ASSET_OWNER_LOAN_PRODUCT_ATTRIBUTE_LOAN_PRODUCT_ID = "externalAssetOwnerLoanProductAttributeLoanProductId";
public static final String TRANSACTION_EVENT = "transactionEvent";
public static final String LOAN_WRITE_OFF_RESPONSE = "loanWriteOffResponse";
public static final String LOAN_DELINQUENCY_ACTION_RESPONSE = "loanDelinquencyActionResponse";
Expand Down
Loading
Loading