From 85e3c4dcb21675bd68e2d219f76e6c205a20cef5 Mon Sep 17 00:00:00 2001 From: rrpawar96 Date: Thu, 9 Jul 2020 22:04:36 +0530 Subject: [PATCH] Credit_Bureau_Phase3 (FINERACT-734) --- .../service/CommandWrapperBuilder.java | 41 ++ .../infrastructure/core/api/JsonCommand.java | 6 + .../core/data/CommandProcessingResult.java | 23 +- .../data/CommandProcessingResultBuilder.java | 11 +- .../api/CreditBureauConfigurationAPI.java | 46 ++ .../api/CreditBureauIntegrationAPI.java | 157 ++++++ .../data/CreditBureauConfigurations.java | 25 + .../data/CreditBureauReportData.java | 57 +++ .../creditbureau/data/CreditReportData.java | 41 ++ .../CreditReportReadPlatformServiceImpl.java | 74 +++ .../domain/CreditBureauConfiguration.java | 34 +- .../CreditBureauConfigurationRepository.java | 39 ++ ...tBureauConfigurationRepositoryWrapper.java | 39 ++ ...ditBureauLoanProductMappingRepository.java | 5 + .../domain/CreditBureauToken.java | 116 +++++ .../creditbureau/domain/CreditReport.java | 59 +++ .../domain/CreditReportRepository.java | 31 ++ .../creditbureau/domain/TokenRepository.java | 31 ++ .../domain/TokenRepositoryWrapper.java | 50 ++ .../CreditReportNotFoundException.java | 30 ++ ...BureauConfigurationDataCommandHandler.java | 48 ++ .../DeleteCreditReportCommandHandler.java | 46 ++ .../GetCreditReportCommandHandler.java | 47 ++ .../SaveCreditReportCommandHandler.java | 45 ++ ...BureauConfigurationDataCommandHandler.java | 48 ++ ...urationCommandFromApiJsonDeserializer.java | 113 +++++ ...auTokenCommandFromApiJsonDeserializer.java | 128 +++++ ...reauConfigurationWritePlatformService.java | 30 ++ ...ConfigurationWritePlatformServiceImpl.java | 110 +++++ .../CreditReportReadPlatformService.java | 28 ++ .../CreditReportWritePlatformService.java | 35 ++ .../CreditReportWritePlatformServiceImpl.java | 214 ++++++++ ...BureauIntegrationWritePlatformService.java | 37 ++ ...auIntegrationWritePlatformServiceImpl.java | 465 ++++++++++++++++++ .../V327_1__creditbureau_integration.sql | 80 +++ .../ThitsaworksCreditBureauTest.java | 128 +++++ .../CreditBureauConfigurationTest.java | 70 +++ .../CreditBureauConfigurationHelper.java | 102 ++++ 38 files changed, 2679 insertions(+), 10 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauConfigurations.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauReportData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepositoryWrapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauToken.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReport.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReportRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepositoryWrapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/exception/CreditReportNotFoundException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/AddCreditBureauConfigurationDataCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/DeleteCreditReportCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/GetCreditReportCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/SaveCreditReportCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/UpdateCreditBureauConfigurationDataCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauConfigurationCommandFromApiJsonDeserializer.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauTokenCommandFromApiJsonDeserializer.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/resources/sql/migrations/core_db/V327_1__creditbureau_integration.sql create mode 100644 fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/ThitsaworksCreditBureauTest.java create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/CreditBureauConfigurationTest.java create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CreditBureauConfigurationHelper.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 6226c265e..58e4acc50 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -76,6 +76,31 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder getCreditReport() { + this.actionName = "GET"; + this.entityName = "CREDITREPORT"; + this.entityId = null; + this.href = "/getCreditReport/template"; + return this; + } + + public CommandWrapperBuilder saveCreditReport(final long creditBureauId, final String nationalId) { + this.actionName = "SAVE"; + this.entityName = "CREDITREPORT"; + this.entityId = creditBureauId; + this.transactionId = nationalId; + this.href = "/saveCreditReport/"; + return this; + } + + public CommandWrapperBuilder deleteCreditReport(final Long creditBureauId) { + this.actionName = "DELETE"; + this.entityName = "CREDITREPORT"; + this.entityId = creditBureauId; + this.href = "/deleteCreditReport/"; + return this; + } + public CommandWrapperBuilder createCreditBureauLoanProductMapping(final long creditBureauId) { this.actionName = "CREATE"; this.entityName = "CREDITBUREAU_LOANPRODUCT_MAPPING"; @@ -85,6 +110,22 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder addCreditBureauConfiguration(final long creditBureauId) { + this.actionName = "CREATE"; + this.entityName = "CREDITBUREAU_CONFIGURATION"; + this.entityId = creditBureauId; + this.href = "/creditBureauConfigurationData/"; + return this; + } + + public CommandWrapperBuilder updateCreditBureauConfiguration(final long configurationId) { + this.actionName = "UPDATE"; + this.entityName = "CREDITBUREAU_CONFIGURATION"; + this.entityId = configurationId; + this.href = "/creditBureauConfigurationData/"; + return this; + } + public CommandWrapperBuilder addClientAddress(final long clientId, final long addressTypeId) { this.actionName = "CREATE"; this.entityName = "ADDRESS"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java index ad0fb0271..c22ec9b0a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java @@ -444,6 +444,12 @@ public final class JsonCommand { return value; } + public Map mapObjectValueOfParameterNamed(final String json) { + final Type typeOfMap = new TypeToken>() {}.getType(); + final Map value = this.fromApiJsonHelper.extractObjectMap(typeOfMap, json); + return value; + } + public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) { boolean isChanged = false; if (parameterExists(parameterName)) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java index 707b8dbf7..d74131da8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java @@ -21,6 +21,7 @@ package org.apache.fineract.infrastructure.core.data; import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauReportData; /** * Represents the successful result of an REST API call that results in processing a command. @@ -37,6 +38,7 @@ public class CommandProcessingResult implements Serializable { private final Long subResourceId; private final String transactionId; private final Map changes; + private final CreditBureauReportData creditBureauReportData; @SuppressWarnings("unused") private final String resourceIdentifier; private final Long productId; @@ -48,15 +50,15 @@ public class CommandProcessingResult implements Serializable { return new CommandProcessingResult(commandResult.commandId, commandResult.officeId, commandResult.groupId, commandResult.clientId, commandResult.loanId, commandResult.savingsId, commandResult.resourceIdentifier, commandResult.resourceId, commandResult.transactionId, commandResult.changes, commandResult.productId, commandResult.gsimId, commandResult.glimId, - commandResult.rollbackTransaction, commandResult.subResourceId); + commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId); } public static CommandProcessingResult fromDetails(final Long commandId, final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String resourceIdentifier, final Long entityId, final Long gsimId, - final Long glimId, final String transactionId, final Map changes, final Long productId, - final Boolean rollbackTransaction, final Long subResourceId) { + final Long glimId, final CreditBureauReportData creditBureauReportData, final String transactionId, + final Map changes, final Long productId, final Boolean rollbackTransaction, final Long subResourceId) { return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, savingsId, resourceIdentifier, entityId, - transactionId, changes, productId, gsimId, glimId, rollbackTransaction, subResourceId); + transactionId, changes, productId, gsimId, glimId, creditBureauReportData, rollbackTransaction, subResourceId); } public static CommandProcessingResult commandOnlyResult(final Long commandId) { @@ -108,13 +110,14 @@ public class CommandProcessingResult implements Serializable { this.productId = null; this.gsimId = null; this.glimId = null; + this.creditBureauReportData = null; this.subResourceId = null; } private CommandProcessingResult(final Long commandId, final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String resourceIdentifier, final Long resourceId, final String transactionId, - final Map changesOnly, final Long productId, final Long gsimId, final Long glimId, Boolean rollbackTransaction, - final Long subResourceId) { + final Map changesOnly, final Long productId, final Long gsimId, final Long glimId, + final CreditBureauReportData creditBureauReportData, Boolean rollbackTransaction, final Long subResourceId) { this.commandId = commandId; this.officeId = officeId; this.groupId = groupId; @@ -128,6 +131,7 @@ public class CommandProcessingResult implements Serializable { this.productId = productId; this.gsimId = gsimId; this.glimId = glimId; + this.creditBureauReportData = creditBureauReportData; this.rollbackTransaction = rollbackTransaction; this.subResourceId = subResourceId; } @@ -151,12 +155,13 @@ public class CommandProcessingResult implements Serializable { this.productId = null; this.gsimId = null; this.glimId = null; + this.creditBureauReportData = null; this.subResourceId = null; } protected CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId, final Map changesOnly, long clientId) { - this(commandId, officeId, null, clientId, null, null, null, resourceId, null, changesOnly, null, null, null, null, null); + this(commandId, officeId, null, clientId, null, null, null, resourceId, null, changesOnly, null, null, null, null, null, null); } public Long commandId() { @@ -195,6 +200,10 @@ public class CommandProcessingResult implements Serializable { return this.transactionId; } + public CreditBureauReportData getCreditReport() { + return this.creditBureauReportData; + } + public Map getChanges() { Map checkIfEmpty = null; if (this.changes != null && !this.changes.isEmpty()) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java index 1fdd91f00..9b340f8b0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java @@ -19,6 +19,7 @@ package org.apache.fineract.infrastructure.core.data; import java.util.Map; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauReportData; /** * Represents the successful result of an REST API call that results in processing a command. @@ -38,13 +39,14 @@ public class CommandProcessingResultBuilder { private Long glimId; private String transactionId; private Map changes; + private CreditBureauReportData creditBureauReportData; private Long productId; private boolean rollbackTransaction = false; public CommandProcessingResult build() { return CommandProcessingResult.fromDetails(this.commandId, this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, - this.resourceIdentifier, this.entityId, this.gsimId, this.glimId, this.transactionId, this.changes, this.productId, - this.rollbackTransaction, this.subEntityId); + this.resourceIdentifier, this.entityId, this.gsimId, this.glimId, this.creditBureauReportData, this.transactionId, + this.changes, this.productId, this.rollbackTransaction, this.subEntityId); } public CommandProcessingResultBuilder withCommandId(final Long withCommandId) { @@ -117,6 +119,11 @@ public class CommandProcessingResultBuilder { return this; } + public CommandProcessingResultBuilder withCreditReport(final CreditBureauReportData withCreditReport) { + this.creditBureauReportData = withCreditReport; + return this; + } + public CommandProcessingResultBuilder setRollbackTransaction(final boolean rollbackTransaction) { this.rollbackTransaction = this.rollbackTransaction || rollbackTransaction; return this; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauConfigurationAPI.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauConfigurationAPI.java index a533de9e5..822ac513e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauConfigurationAPI.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauConfigurationAPI.java @@ -77,6 +77,7 @@ public class CreditBureauConfigurationAPI { public CreditBureauConfigurationAPI(final PlatformSecurityContext context, final CreditBureauReadPlatformService readPlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, final CreditBureauLoanProductMappingReadPlatformService readPlatformServiceCreditBureauLoanProduct, + final CreditBureauReadConfigurationService readPlatformServiceCreditBureauConfiguration, final DefaultToApiJsonSerializer toApiJsonSerializerCreditBureauLoanProduct, final OrganisationCreditBureauReadPlatformService readPlatformServiceOrganisationCreditBureau, final DefaultToApiJsonSerializer toApiJsonSerializerOrganisationCreditBureau, @@ -172,6 +173,21 @@ public class CreditBureauConfigurationAPI { this.responseDataParameters); } + @GET + @Path("/loanProduct/{loanProductId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String fetchMappingByLoanProductId(@Context final UriInfo uriInfo, @PathParam("loanProductId") final Long loanProductId) { + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); + + final CreditBureauLoanProductMappingData creditBureauLoanProductMapping = this.readPlatformServiceCreditBureauLoanProduct + .readMappingByLoanId(loanProductId); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializerCreditBureauLoanProduct.serialize(settings, creditBureauLoanProductMapping, + this.responseDataParameters); + } + @PUT @Path("/organisationCreditBureau") @Consumes({ MediaType.APPLICATION_JSON }) @@ -229,4 +245,34 @@ public class CreditBureauConfigurationAPI { return this.toApiJsonSerializer.serialize(result); } + @POST + @Path("/configuration/{creditBureauId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String createCreditBureauConfiguration(@PathParam("creditBureauId") final Long creditBureauId, + final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().addCreditBureauConfiguration(creditBureauId) + .withJson(apiRequestBodyAsJson).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + + @PUT + @Path("/configuration/{configurationId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateCreditBureauConfiguration(@PathParam("configurationId") final Long configurationId, + final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCreditBureauConfiguration(configurationId) + .withJson(apiRequestBodyAsJson).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java new file mode 100644 index 000000000..db62c9745 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java @@ -0,0 +1,157 @@ +/** + * 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.infrastructure.creditbureau.api; + +import com.google.gson.Gson; +import io.swagger.v3.oas.annotations.Parameter; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.creditbureau.data.CreditReportData; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportReadPlatformService; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportWritePlatformService; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestParam; + +@Path("/creditBureauIntegration") +@Component +@Scope("singleton") +public class CreditBureauIntegrationAPI { + + private static final Set RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "creditBureauId", "nrc", "creditReport")); + + private final PlatformSecurityContext context; + private final DefaultToApiJsonSerializer toCreditReportApiJsonSerializer; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final CreditReportReadPlatformService creditReportReadPlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private static final Logger LOG = LoggerFactory.getLogger(CreditBureauIntegrationAPI.class); + + @Autowired + public CreditBureauIntegrationAPI(final PlatformSecurityContext context, + final DefaultToApiJsonSerializer toCreditReportApiJsonSerializer, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, + final ApiRequestParameterHelper apiRequestParameterHelper, + final CreditReportWritePlatformService creditReportWritePlatformService, + final CreditReportReadPlatformService creditReportReadPlatformService, + final DefaultToApiJsonSerializer toApiJsonSerializer) { + this.context = context; + this.toCreditReportApiJsonSerializer = toCreditReportApiJsonSerializer; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.creditReportReadPlatformService = creditReportReadPlatformService; + this.toApiJsonSerializer = toApiJsonSerializer; + + } + + @POST + @Path("creditReport") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String fetchCreditReport(@Context final UriInfo uriInfo, @RequestParam("params") final Map params) { + + Gson gson = new Gson(); + final String json = gson.toJson(params); + final CommandWrapper commandRequest = new CommandWrapperBuilder().getCreditReport().withJson(json).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toCreditReportApiJsonSerializer.serialize(result); + + } + + // saves fetched-creditreport into database + @POST + @Path("saveCreditReport") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String saveCreditReport(@Parameter(hidden = true) final String apiRequestBodyAsJson, + @QueryParam("creditBureauId") @Parameter(description = "creditBureauId") final Long creditBureauId, + @QueryParam("nationalId") @Parameter(description = "nationalId") final String nationalId) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .saveCreditReport(creditBureauId, nationalId).withJson(apiRequestBodyAsJson) // apiRequestBodyAsJson is + // a creditReport + .build(); // + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toCreditReportApiJsonSerializer.serialize(result); + + } + + // fetch saved creditReports(NRC) from DB by creditBureauId, to select for downloading and deleting the reports + @GET + @Path("creditReport/{creditBureauId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getSavedCreditReport(@PathParam("creditBureauId") @Parameter(description = "creditBureauId") final Long creditBureauId, + @Context final UriInfo uriInfo) { + + this.context.authenticatedUser(); + + final Collection creditReport = this.creditReportReadPlatformService.retrieveCreditReportDetails(creditBureauId); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, creditReport, RESPONSE_DATA_PARAMETERS); + + } + + // deletes saved creditReports from database + @DELETE + @Path("deleteCreditReport/{creditBureauId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String deleteCreditReport(@PathParam("creditBureauId") @Parameter(description = "creditBureauId") final Long creditBureauId, + @Parameter(hidden = true) final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCreditReport(creditBureauId).withJson(apiRequestBodyAsJson) + .build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toCreditReportApiJsonSerializer.serialize(result); + + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauConfigurations.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauConfigurations.java new file mode 100644 index 000000000..9255fe970 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauConfigurations.java @@ -0,0 +1,25 @@ +/** + * 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.infrastructure.creditbureau.data; + +public enum CreditBureauConfigurations { + + THITSAWORKS, SUBSCRIPTIONID, SUBSCRIPTIONKEY, USERNAME, PASSWORD, TOKENURL, SEARCHURL, CREDITREPORTURL; + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauReportData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauReportData.java new file mode 100644 index 000000000..0ab3493da --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditBureauReportData.java @@ -0,0 +1,57 @@ +/** + * 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.infrastructure.creditbureau.data; + +import java.io.Serializable; + +public final class CreditBureauReportData implements Serializable { + + @SuppressWarnings("unused") + private final String name; + + private final String gender; + + private final String address; + + private final String creditScore; + + private final String borrowerInfo; + + private final String[] openAccounts; + + private final String[] closedAccounts; + + public static CreditBureauReportData instance(final String name, final String gender, final String address, final String creditScore, + final String borrowerInfo, final String[] openAccounts, final String[] closedAccounts) { + return new CreditBureauReportData(name, gender, address, creditScore, borrowerInfo, openAccounts, closedAccounts); + } + + public CreditBureauReportData(final String name, final String gender, final String address, final String creditScore, + final String borrowerInfo, final String[] openAccounts, final String[] closedAccounts) { + this.name = name; + this.gender = gender; + this.address = address; + this.creditScore = creditScore; + this.borrowerInfo = borrowerInfo; + this.openAccounts = openAccounts; + this.closedAccounts = closedAccounts; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportData.java new file mode 100644 index 000000000..9a688673b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportData.java @@ -0,0 +1,41 @@ +/** + * 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.infrastructure.creditbureau.data; + +import java.io.Serializable; + +public final class CreditReportData implements Serializable { + + private final Long id; + @SuppressWarnings("unused") + private final Long creditBureauId; + @SuppressWarnings("unused") + private final String nationalId; + + public static CreditReportData instance(final Long id, final Long creditBureauId, final String nationalId) { + return new CreditReportData(id, creditBureauId, nationalId); + } + + private CreditReportData(final Long id, final Long creditBureauId, final String nationalId) { + this.id = id; + this.creditBureauId = creditBureauId; + this.nationalId = nationalId; + + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportReadPlatformServiceImpl.java new file mode 100644 index 000000000..9209336cc --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/data/CreditReportReadPlatformServiceImpl.java @@ -0,0 +1,74 @@ +/** + * 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.infrastructure.creditbureau.data; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportReadPlatformService; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class CreditReportReadPlatformServiceImpl implements CreditReportReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + + @Autowired + public CreditReportReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class CreditReportDataMapper implements RowMapper { + + public String schema() { + return " c.id as id, c.creditBureauId as creditBureauId , c.nationalId as nationalId from m_creditreport c "; + } + + @Override + public CreditReportData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { + + final Long id = rs.getLong("id"); + final Long creditBureauId = rs.getLong("creditBureauId"); + final String nationalId = rs.getString("nationalId"); + // final byte[] creditReports = rs.getBytes("creditReports"); + + return CreditReportData.instance(id, creditBureauId, nationalId);// , creditReports); + } + } + + @Override + public Collection retrieveCreditReportDetails(Long creditBureauId) { + + this.context.authenticatedUser(); + + final CreditReportDataMapper rm = new CreditReportDataMapper(); + final String sql = " select " + rm.schema() + " where c.creditBureauId = ? "; + + return this.jdbcTemplate.query(sql, rm, new Object[] { creditBureauId }); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfiguration.java index a4982b794..a04d97296 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfiguration.java @@ -18,11 +18,14 @@ */ package org.apache.fineract.infrastructure.creditbureau.domain; +import java.util.LinkedHashMap; +import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; +import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; @@ -56,7 +59,7 @@ public class CreditBureauConfiguration extends AbstractPersistableCustom { } - public CreditBureauConfiguration fromJson(JsonCommand command, OrganisationCreditBureau organisation_creditbureau) { + public static CreditBureauConfiguration fromJson(JsonCommand command, OrganisationCreditBureau organisation_creditbureau) { final String configkey = command.stringValueOfParameterNamed("configkey"); final String value = command.stringValueOfParameterNamed("value"); final String description = command.stringValueOfParameterNamed("description"); @@ -97,4 +100,33 @@ public class CreditBureauConfiguration extends AbstractPersistableCustom { this.organisationCreditbureau = organisation_creditbureau; } + public Map update(final JsonCommand command) { + + final Map actualChanges = new LinkedHashMap<>(1); + + final String configurationKey = "configurationKey"; + + if (command.isChangeInStringParameterNamed(configurationKey, this.configurationKey)) { + final String newValue = command.stringValueOfParameterNamed(configurationKey); + actualChanges.put(configurationKey, newValue); + this.configurationKey = StringUtils.defaultIfEmpty(newValue, null); + } + + final String value = "value"; + if (command.isChangeInStringParameterNamed(value, this.value)) { + final String newValue = command.stringValueOfParameterNamed(value); + actualChanges.put(value, newValue); + this.value = StringUtils.defaultIfEmpty(newValue, null); + } + + final String description = "description"; + if (command.isChangeInStringParameterNamed(description, this.configurationKey)) { + final String newValue = command.stringValueOfParameterNamed(description); + actualChanges.put(description, newValue); + this.description = StringUtils.defaultIfEmpty(newValue, null); + } + + return actualChanges; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepository.java new file mode 100644 index 000000000..8227ada57 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepository.java @@ -0,0 +1,39 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface CreditBureauConfigurationRepository + extends JpaRepository, JpaSpecificationExecutor { + + @Query("SELECT creditBureauConfig from CreditBureauConfiguration creditBureauConfig where creditBureauConfig.organisationCreditbureau.id = :creditBureauID and creditBureauConfig.configurationKey = :configurationKey ") + CreditBureauConfiguration getCreditBureauConfigData(@Param("creditBureauID") Integer creditBureauID, + @Param("configurationKey") String parameterName); + + @Query("SELECT creditBureauConfig from CreditBureauConfiguration creditBureauConfig where creditBureauConfig.organisationCreditbureau.id = :creditBureauID") + CreditBureauConfiguration getCreditBureauConfigurationData(@Param("creditBureauID") Integer creditBureauID); + + @Query("SELECT creditBureauConfig from CreditBureauConfiguration creditBureauConfig where creditBureauConfig.configurationKey = :configurationKey") + CreditBureauConfiguration getCreditBureauConfigurationValueData(@Param("configurationKey") String parameterName); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepositoryWrapper.java new file mode 100644 index 000000000..80d974962 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauConfigurationRepositoryWrapper.java @@ -0,0 +1,39 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CreditBureauConfigurationRepositoryWrapper { + + private final CreditBureauConfigurationRepository creditBureauConfigurationRepository; + + @Autowired + public CreditBureauConfigurationRepositoryWrapper(final CreditBureauConfigurationRepository creditBureauConfigurationRepository) { + + this.creditBureauConfigurationRepository = creditBureauConfigurationRepository; + } + + public CreditBureauConfiguration getCreditBureauConfigData(final Integer creditBureauID, final String parameterName) { + return this.creditBureauConfigurationRepository.getCreditBureauConfigData(creditBureauID, parameterName); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauLoanProductMappingRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauLoanProductMappingRepository.java index 4ac6f801f..6f5e14961 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauLoanProductMappingRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauLoanProductMappingRepository.java @@ -18,10 +18,15 @@ */ package org.apache.fineract.infrastructure.creditbureau.domain; +import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface CreditBureauLoanProductMappingRepository extends JpaRepository, JpaSpecificationExecutor { + CreditBureauLoanProductMapping findOneByLoanProduct(LoanProduct loanProduct); + + CreditBureauLoanProductMapping findOneByLoanProductId(Long loanProductID); + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauToken.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauToken.java new file mode 100644 index 000000000..34843af50 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditBureauToken.java @@ -0,0 +1,116 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Entity +@Table(name = "m_creditbureau_token") +public class CreditBureauToken extends AbstractPersistableCustom { + + private static final Logger LOG = LoggerFactory.getLogger(CreditBureauToken.class); + + @Column(name = "username") + private String userName; + + @Column(name = "token") + private String accessToken; + + @Column(name = "tokenType") + private String tokenType; + + @Column(name = "expiresIn") + private String expiresIn; + + @Column(name = "issued") + private String issued; + + @Column(name = "expiryDate") + private Date expires; + + public static CreditBureauToken fromJson(final JsonCommand command) { + final String userName = command.stringValueOfParameterNamed("userName"); + final String accessToken = command.stringValueOfParameterNamed("access_token"); + final String tokenType = command.stringValueOfParameterNamed("token_type"); + final String expiresIn = command.stringValueOfParameterNamed("expires_in"); + final String issued = command.stringValueOfParameterNamed(".issued"); + final String expiry = command.stringValueOfParameterNamed(".expires"); + + SimpleDateFormat dateformat = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss zzz", Locale.ENGLISH); + + Date expires = null; + try { + expires = dateformat.parse(expiry); + } catch (ParseException Ex) { + LOG.error("Error occured while converting Date(String) to SimpleDateFormat", Ex); + } + + return new CreditBureauToken(userName, accessToken, tokenType, expiresIn, issued, expires); + } + + public CreditBureauToken(String userName, String accessToken, String tokenType, String expiresIn, String issued, Date expires) { + this.userName = userName; + this.accessToken = accessToken; + this.tokenType = tokenType; + this.expiresIn = expiresIn; + this.issued = issued; + this.expires = expires; + } + + public CreditBureauToken() { + this.userName = null; + this.accessToken = null; + this.tokenType = null; + this.expiresIn = null; + this.issued = null; + this.expires = null; + } + + public String getUserName() { + return this.userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getCurrentToken() { + return this.accessToken; + } + + public void setTokens(String tokens) { + this.accessToken = tokens; + } + + public Date getTokenExpiryDate() { + return this.expires; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReport.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReport.java new file mode 100644 index 000000000..c0172889e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReport.java @@ -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.infrastructure.creditbureau.domain; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Table; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; + +@Entity +@Table(name = "m_creditreport") +public final class CreditReport extends AbstractPersistableCustom { + + @Column(name = "creditBureauId") + private Long creditBureauId; + + @Column(name = "nationalId") + private String nationalId; + + @Basic(fetch = FetchType.LAZY) + @Column(name = "creditReports") + private byte[] creditReports; + + private CreditReport() {} + + public static CreditReport instance(final Long creditBureauId, final String nationalId, final byte[] creditReports) { + return new CreditReport(creditBureauId, nationalId, creditReports); + } + + private CreditReport(final Long creditBureauId, final String nationalId, final byte[] creditReports) { + this.creditBureauId = creditBureauId; + this.nationalId = nationalId; + this.creditReports = creditReports; + + } + + public byte[] getCreditReport() { + return this.creditReports; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReportRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReportRepository.java new file mode 100644 index 000000000..c6ae0c407 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/CreditReportRepository.java @@ -0,0 +1,31 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface CreditReportRepository extends JpaRepository, JpaSpecificationExecutor { + + @Query("SELECT creditBureauReport from CreditReport creditBureauReport where creditBureauReport.nationalId = :nationalId and creditBureauReport.creditBureauId = :creditBureauId ") + CreditReport getThitsaWorksCreditReport(@Param("creditBureauId") Long creditBureauId, @Param("nationalId") String nationalId); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepository.java new file mode 100644 index 000000000..491ec81f8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepository.java @@ -0,0 +1,31 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +public interface TokenRepository extends JpaRepository, JpaSpecificationExecutor { + + @Query("select creditbureautoken from CreditBureauToken creditbureautoken") + CreditBureauToken getToken(); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepositoryWrapper.java new file mode 100644 index 000000000..28f437fa4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/domain/TokenRepositoryWrapper.java @@ -0,0 +1,50 @@ +/** + * 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.infrastructure.creditbureau.domain; + +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TokenRepositoryWrapper { + + private final TokenRepository repository; + private final PlatformSecurityContext context; + + @Autowired + public TokenRepositoryWrapper(final TokenRepository repository, final PlatformSecurityContext context) { + this.repository = repository; + this.context = context; + } + + public void save(final CreditBureauToken token) { + this.repository.save(token); + } + + public void delete(final CreditBureauToken token) { + this.repository.delete(token); + } + + public CreditBureauToken getToken() { + return this.repository.getToken(); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/exception/CreditReportNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/exception/CreditReportNotFoundException.java new file mode 100644 index 000000000..9db8ce42d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/exception/CreditReportNotFoundException.java @@ -0,0 +1,30 @@ +/** + * 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.infrastructure.creditbureau.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class CreditReportNotFoundException extends AbstractPlatformResourceNotFoundException { + + public CreditReportNotFoundException(final Long searchId) { + super("error.msg.creditreport.identifier.not.found", "CreditReport with identifier `" + searchId + "` does not exist", searchId); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/AddCreditBureauConfigurationDataCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/AddCreditBureauConfigurationDataCommandHandler.java new file mode 100644 index 000000000..7efafa10c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/AddCreditBureauConfigurationDataCommandHandler.java @@ -0,0 +1,48 @@ +/** + * 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.infrastructure.creditbureau.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.creditbureau.service.CreditBureauConfigurationWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "CREDITBUREAU_CONFIGURATION", action = "CREATE") +public class AddCreditBureauConfigurationDataCommandHandler implements NewCommandSourceHandler { + + private final CreditBureauConfigurationWritePlatformService writePlatformService; + + @Autowired + public AddCreditBureauConfigurationDataCommandHandler(final CreditBureauConfigurationWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.addCreditBureauConfiguration(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/DeleteCreditReportCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/DeleteCreditReportCommandHandler.java new file mode 100644 index 000000000..7f552d28b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/DeleteCreditReportCommandHandler.java @@ -0,0 +1,46 @@ +/** + * 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.infrastructure.creditbureau.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "CREDITREPORT", action = "DELETE") +public class DeleteCreditReportCommandHandler implements NewCommandSourceHandler { + + private final CreditReportWritePlatformService writePlatformService; + + @Autowired + public DeleteCreditReportCommandHandler(final CreditReportWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Override + public CommandProcessingResult processCommand(JsonCommand command) { + + return this.writePlatformService.deleteCreditReport(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/GetCreditReportCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/GetCreditReportCommandHandler.java new file mode 100644 index 000000000..f117c6620 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/GetCreditReportCommandHandler.java @@ -0,0 +1,47 @@ +/** + * 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.infrastructure.creditbureau.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "CREDITREPORT", action = "GET") +public class GetCreditReportCommandHandler implements NewCommandSourceHandler { + + private final CreditReportWritePlatformService writePlatformService; + + @Autowired + public GetCreditReportCommandHandler(final CreditReportWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.getCreditReport(command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/SaveCreditReportCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/SaveCreditReportCommandHandler.java new file mode 100644 index 000000000..69164fe04 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/SaveCreditReportCommandHandler.java @@ -0,0 +1,45 @@ +/** + * 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.infrastructure.creditbureau.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "CREDITREPORT", action = "SAVE") +public class SaveCreditReportCommandHandler implements NewCommandSourceHandler { + + private final CreditReportWritePlatformService writePlatformService; + + @Autowired + public SaveCreditReportCommandHandler(final CreditReportWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Override + public CommandProcessingResult processCommand(JsonCommand command) { + + return this.writePlatformService.saveCreditReport(command.entityId(), command.getTransactionId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/UpdateCreditBureauConfigurationDataCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/UpdateCreditBureauConfigurationDataCommandHandler.java new file mode 100644 index 000000000..5db001cbf --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/handler/UpdateCreditBureauConfigurationDataCommandHandler.java @@ -0,0 +1,48 @@ +/** + * 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.infrastructure.creditbureau.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.creditbureau.service.CreditBureauConfigurationWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "CREDITBUREAU_CONFIGURATION", action = "UPDATE") +public class UpdateCreditBureauConfigurationDataCommandHandler implements NewCommandSourceHandler { + + private final CreditBureauConfigurationWritePlatformService writePlatformService; + + @Autowired + public UpdateCreditBureauConfigurationDataCommandHandler(final CreditBureauConfigurationWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.updateCreditBureauConfiguration(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauConfigurationCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauConfigurationCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..715cc28e3 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauConfigurationCommandFromApiJsonDeserializer.java @@ -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.infrastructure.creditbureau.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public final class CreditBureauConfigurationCommandFromApiJsonDeserializer { + + private final Set supportedParameters = new HashSet<>(Arrays.asList("configkey", "value", "description")); + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CreditBureauConfigurationCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + public void validateForCreate(final String json, final Long creditBureauId) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource("CREDITBUREAU_CONFIGURATION"); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + baseDataValidator.reset().value(creditBureauId).notBlank().integerGreaterThanZero(); + + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + + final String configkey = this.fromApiJsonHelper.extractStringNamed("configkey", element); + baseDataValidator.reset().parameter("configkey").value(configkey).notBlank().notExceedingLengthOf(100); + + final String value = this.fromApiJsonHelper.extractStringNamed("value", element); + baseDataValidator.reset().parameter("value").value(value).notBlank().notExceedingLengthOf(100); + + final String description = this.fromApiJsonHelper.extractStringNamed("description", element); + baseDataValidator.reset().parameter("description").value(description).notBlank().notExceedingLengthOf(100); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + public void validateForUpdate(final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("config"); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + if (this.fromApiJsonHelper.parameterExists("value", element)) { + final String value = this.fromApiJsonHelper.extractStringNamed("value", element); + baseDataValidator.reset().parameter("value").value(value).notBlank().notExceedingLengthOf(100); + } + + if (this.fromApiJsonHelper.parameterExists("description", element)) { + final String description = this.fromApiJsonHelper.extractStringNamed("description", element); + baseDataValidator.reset().parameter("description").value(description).notBlank().notExceedingLengthOf(100); + } + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", + dataValidationErrors); + } + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauTokenCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauTokenCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..b07de91d7 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/serialization/CreditBureauTokenCommandFromApiJsonDeserializer.java @@ -0,0 +1,128 @@ +/** + * 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.infrastructure.creditbureau.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CreditBureauTokenCommandFromApiJsonDeserializer { + + private static final Logger LOG = LoggerFactory.getLogger(CreditBureauTokenCommandFromApiJsonDeserializer.class); + + private final Set supportedParameters = new HashSet<>( + Arrays.asList("access_token", "token_type", "expires_in", "userName", ".issued", ".expires")); + + private final Set supportedTokenConfigParameters = new HashSet<>( + Arrays.asList("userName", "password", "subscriptionId", "subscriptionKey")); + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CreditBureauTokenCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + public void validateForCreate(final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("tokens"); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final String access_token = this.fromApiJsonHelper.extractStringNamed("access_token", element); + baseDataValidator.reset().parameter("access_token").value(access_token).notBlank().notExceedingLengthOf(1000); + + final String token_type = this.fromApiJsonHelper.extractStringNamed("token_type", element); + baseDataValidator.reset().parameter("token_type").value(token_type).notBlank().notExceedingLengthOf(100); + + final String expires_in = this.fromApiJsonHelper.extractStringNamed("expires_in", element); + baseDataValidator.reset().parameter("expires_in").value(expires_in).notBlank().notExceedingLengthOf(100); + + final String userName = this.fromApiJsonHelper.extractStringNamed("userName", element); + baseDataValidator.reset().parameter("userName").value(userName).notBlank().notExceedingLengthOf(100); + + final String issued = this.fromApiJsonHelper.extractStringNamed(".issued", element); + baseDataValidator.reset().parameter(".issued").value(issued).notBlank().notExceedingLengthOf(100); + + final String expires = this.fromApiJsonHelper.extractStringNamed(".expires", element); + baseDataValidator.reset().parameter(".expires").value(expires).notBlank().notExceedingLengthOf(100); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + public void validateForUsingTokenConfig(final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedTokenConfigParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("configdata"); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final String userName = this.fromApiJsonHelper.extractStringNamed("userName", element); + baseDataValidator.reset().parameter("userName").value(userName).notBlank().notExceedingLengthOf(1000); + + final String password = this.fromApiJsonHelper.extractStringNamed("password", element); + baseDataValidator.reset().parameter("password").value(password).notBlank().notExceedingLengthOf(100); + + final String subscriptionId = this.fromApiJsonHelper.extractStringNamed("subscriptionId", element); + baseDataValidator.reset().parameter("subscriptionId").value(subscriptionId).notBlank().notExceedingLengthOf(100); + + final String subscriptionKey = this.fromApiJsonHelper.extractStringNamed("subscriptionKey", element); + baseDataValidator.reset().parameter("subscriptionKey").value(subscriptionKey).notBlank().notExceedingLengthOf(100); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", + dataValidationErrors); + } + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformService.java new file mode 100644 index 000000000..a41a82207 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformService.java @@ -0,0 +1,30 @@ +/** + * 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.infrastructure.creditbureau.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface CreditBureauConfigurationWritePlatformService { + + CommandProcessingResult addCreditBureauConfiguration(Long creditBureauId, JsonCommand command); + + CommandProcessingResult updateCreditBureauConfiguration(Long configurationId, JsonCommand command); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java new file mode 100644 index 000000000..81bfa9cc8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditBureauConfigurationWritePlatformServiceImpl.java @@ -0,0 +1,110 @@ +/** + * 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.infrastructure.creditbureau.service; + +import java.util.Map; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfiguration; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfigurationRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.OrganisationCreditBureau; +import org.apache.fineract.infrastructure.creditbureau.domain.OrganisationCreditBureauRepository; +import org.apache.fineract.infrastructure.creditbureau.exception.CreditReportNotFoundException; +import org.apache.fineract.infrastructure.creditbureau.serialization.CreditBureauConfigurationCommandFromApiJsonDeserializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CreditBureauConfigurationWritePlatformServiceImpl implements CreditBureauConfigurationWritePlatformService { + + private final PlatformSecurityContext context; + + private final CreditBureauConfigurationCommandFromApiJsonDeserializer fromApiJsonDeserializer; + + private final CreditBureauConfigurationRepository creditBureauConfigurationRepository; + + private final OrganisationCreditBureauRepository organisationCreditBureauRepository; + + @Autowired + public CreditBureauConfigurationWritePlatformServiceImpl(final PlatformSecurityContext context, + final CreditBureauConfigurationCommandFromApiJsonDeserializer fromApiJsonDeserializer, + final CreditBureauConfigurationRepository creditBureauConfigurationRepository, + OrganisationCreditBureauRepository organisationCreditBureauRepository) { + this.context = context; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; + this.creditBureauConfigurationRepository = creditBureauConfigurationRepository; + this.organisationCreditBureauRepository = organisationCreditBureauRepository; + } + + @Transactional + @Override + public CommandProcessingResult addCreditBureauConfiguration(Long creditBureauId, JsonCommand command) { + this.context.authenticatedUser(); + + this.fromApiJsonDeserializer.validateForCreate(command.json(), creditBureauId); + + final OrganisationCreditBureau orgcb = this.organisationCreditBureauRepository.getOne(creditBureauId); + + final CreditBureauConfiguration cb_config = CreditBureauConfiguration.fromJson(command, orgcb); + + this.creditBureauConfigurationRepository.save(cb_config); + + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(cb_config.getId()).build(); + + } + + @Transactional + @Override + public CommandProcessingResult updateCreditBureauConfiguration(Long configurationId, JsonCommand command) { + try { + this.context.authenticatedUser(); + + this.fromApiJsonDeserializer.validateForUpdate(command.json()); + + final CreditBureauConfiguration config = retrieveConfigBy(configurationId); + final Map changes = config.update(command); + + if (!changes.isEmpty()) { + this.creditBureauConfigurationRepository.save(config); + } + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(configurationId) // + .with(changes) // + .build(); + + } catch (final JpaSystemException | DataIntegrityViolationException dve) { + throw new PlatformDataIntegrityException("error.msg.cund.unknown.data.integrity.issue", + "Unknown data integrity issue with resource: " + dve.getMostSpecificCause(), dve); + } + + } + + private CreditBureauConfiguration retrieveConfigBy(final Long creditBureauId) { + return this.creditBureauConfigurationRepository.findById(creditBureauId) + .orElseThrow(() -> new CreditReportNotFoundException(creditBureauId)); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportReadPlatformService.java new file mode 100644 index 000000000..c5233120c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportReadPlatformService.java @@ -0,0 +1,28 @@ +/** + * 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.infrastructure.creditbureau.service; + +import java.util.Collection; +import org.apache.fineract.infrastructure.creditbureau.data.CreditReportData; + +public interface CreditReportReadPlatformService { + + Collection retrieveCreditReportDetails(Long creditBureauId); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformService.java new file mode 100644 index 000000000..72aca7303 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformService.java @@ -0,0 +1,35 @@ +/** + * 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.infrastructure.creditbureau.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface CreditReportWritePlatformService { + + // gets CreditReport from CreditBureau + CommandProcessingResult getCreditReport(JsonCommand command); + + // saves fetched-CreditReport to database + CommandProcessingResult saveCreditReport(Long organisationCreditBureauId, String nationalId, JsonCommand command); + + // deletes creditReports which are saved in database + CommandProcessingResult deleteCreditReport(Long creditBureauId, JsonCommand command); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java new file mode 100644 index 000000000..67be89276 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/CreditReportWritePlatformServiceImpl.java @@ -0,0 +1,214 @@ +/** + * 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.infrastructure.creditbureau.service; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import javax.persistence.PersistenceException; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauConfigurations; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauReportData; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureau; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfigurationRepositoryWrapper; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauLoanProductMappingRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditReport; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditReportRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.TokenRepositoryWrapper; +import org.apache.fineract.infrastructure.creditbureau.serialization.CreditBureauTokenCommandFromApiJsonDeserializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CreditReportWritePlatformServiceImpl implements CreditReportWritePlatformService { + + private final PlatformSecurityContext context; + private final CreditBureauConfigurationRepositoryWrapper configDataRepository; + private final CreditBureauRepository creditBureauRepository; + private final CreditReportRepository creditReportRepository; + private final ThitsaWorksCreditBureauIntegrationWritePlatformService thitsaWorksCreditBureauIntegrationWritePlatformService; + private final ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl; + private final List dataValidationErrors = new ArrayList<>(); + private final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource("creditBureauIntegration"); + + @Autowired + public CreditReportWritePlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, + final FromJsonHelper fromApiJsonHelper, final TokenRepositoryWrapper tokenRepository, + final CreditBureauConfigurationRepositoryWrapper configDataRepository, + final CreditBureauTokenCommandFromApiJsonDeserializer fromApiJsonDeserializer, + final CreditBureauLoanProductMappingRepository loanProductMappingRepository, + final CreditBureauRepository creditBureauRepository, final CreditReportRepository creditReportRepository, + final ThitsaWorksCreditBureauIntegrationWritePlatformService thitsaWorksCreditBureauIntegrationWritePlatformService, + final ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl) { + this.context = context; + this.configDataRepository = configDataRepository; + this.creditBureauRepository = creditBureauRepository; + this.creditReportRepository = creditReportRepository; + this.thitsaWorksCreditBureauIntegrationWritePlatformService = thitsaWorksCreditBureauIntegrationWritePlatformService; + this.thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl = thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl; + } + + @Override + @Transactional + public CommandProcessingResult getCreditReport(JsonCommand command) { + + try { + Long creditBureauID = command.longValueOfParameterNamed("creditBureauID"); + + Optional creditBureauName = getCreditBureau(creditBureauID); + + if (creditBureauName.isEmpty()) { + baseDataValidator.reset().failWithCode("creditBureau.has.not.been.Integrated"); + throw new PlatformApiDataValidationException("creditBureau.has.not.been.Integrated", "creditBureau.has.not.been.Integrated", + dataValidationErrors); + } + + if (Objects.equals(creditBureauName.get(), CreditBureauConfigurations.THITSAWORKS.toString())) { + + // CreditBureauToken creditBureauToken = this.thitsaWorksCreditBureauIntegrationWritePlatformService + // .createToken(creditBureauID); + + CreditBureauReportData reportobj = this.thitsaWorksCreditBureauIntegrationWritePlatformService + .getCreditReportFromThitsaWorks(command); + + // return new + // CommandProcessingResultBuilder().withCreditReport(reportobj).withCreditBureauToken(creditBureauToken).build(); + return new CommandProcessingResultBuilder().withCreditReport(reportobj).build(); + } + + baseDataValidator.reset().failWithCode("creditBureau.has.not.been.Integrated"); + throw new PlatformApiDataValidationException("creditBureau.has.not.been.Integrated", "creditBureau.has.not.been.Integrated", + dataValidationErrors); + + } catch (final DataIntegrityViolationException dve) { + handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); + return CommandProcessingResult.empty(); + } catch (final PersistenceException ee) { + Throwable throwable = ExceptionUtils.getRootCause(ee.getCause()); + handleTokenDataIntegrityIssues(command, throwable, ee); + return CommandProcessingResult.empty(); + } + + } + + private Optional getCreditBureau(Long creditBureauID) { + + if (creditBureauID != null) { + Optional creditBureau = this.creditBureauRepository.findById(creditBureauID); + + if (creditBureau.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(creditBureau.get().getName()); + + } + + return Optional.empty(); + } + + // saving the fetched creditreport in database + @Override + @Transactional + public CommandProcessingResult saveCreditReport(Long creditBureauId, String nationalId, JsonCommand command) { + + try { + this.context.authenticatedUser(); + + Optional creditBureauName = getCreditBureau(creditBureauId); + CreditReport creditReport = null; + + if (Objects.equals(creditBureauName.get(), CreditBureauConfigurations.THITSAWORKS.toString())) { + + // checks whether creditReport for same nationalId was saved before. if yes, then deletes it & replaces + // with new one. + creditReport = creditReportRepository.getThitsaWorksCreditReport(creditBureauId, nationalId); + + if (creditReport != null) { + this.creditReportRepository.delete(creditReport); + } + + String reportData = command.stringValueOfParameterNamed("apiRequestBodyAsJson"); + + byte[] creditReportArray = reportData.getBytes(StandardCharsets.UTF_8); + creditReport = CreditReport.instance(creditBureauId, nationalId, creditReportArray); + this.creditReportRepository.saveAndFlush(creditReport); + + } + + return new CommandProcessingResultBuilder().withEntityId(creditReport.getId()).build(); + } catch (final DataIntegrityViolationException dve) { + handleTokenDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); + return CommandProcessingResult.empty(); + } catch (final PersistenceException ee) { + Throwable throwable = ExceptionUtils.getRootCause(ee.getCause()); + handleTokenDataIntegrityIssues(command, throwable, ee); + return CommandProcessingResult.empty(); + } + } + + @Transactional + @Override + public CommandProcessingResult deleteCreditReport(Long creditBureauId, JsonCommand command) { + + this.context.authenticatedUser(); + + Optional creditBureauName = getCreditBureau(creditBureauId); + CreditReport creditReport = null; + + if (Objects.equals(creditBureauName.get(), CreditBureauConfigurations.THITSAWORKS.toString())) { + + String nationalId = command.stringValueOfParameterNamed("nationalId"); + + creditReport = creditReportRepository.getThitsaWorksCreditReport(creditBureauId, nationalId); + try { + this.creditReportRepository.delete(creditReport); + } catch (final JpaSystemException | DataIntegrityViolationException dve) { + throw new PlatformDataIntegrityException("error.msg.cund.unknown.data.integrity.issue", + "Unknown data integrity issue with resource: " + dve.getMostSpecificCause(), dve); + } + } + return new CommandProcessingResultBuilder().withEntityId(creditReport.getId()).build(); + } + + private void handleTokenDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve) { + + throw new PlatformDataIntegrityException("error.msg.cund.unknown.data.integrity.issue", + "Unknown data integrity issue with resource: " + realCause.getMessage()); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformService.java new file mode 100644 index 000000000..2df21f481 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformService.java @@ -0,0 +1,37 @@ +/** + * 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.infrastructure.creditbureau.service; + +import java.io.File; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauReportData; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauToken; + +public interface ThitsaWorksCreditBureauIntegrationWritePlatformService { + + CreditBureauToken createToken(Long creditBureauID); + + Long extractUniqueId(String jsonResult); + + String okHttpConnectionMethod(String userName, String password, String subscriptionKey, String subscriptionId, String url, String token, + File report, Long uniqueId, String nrcId, String process); + + CreditBureauReportData getCreditReportFromThitsaWorks(JsonCommand command); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java new file mode 100644 index 000000000..b14156a01 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/service/ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.java @@ -0,0 +1,465 @@ +/** + * 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.infrastructure.creditbureau.service; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauConfigurations; +import org.apache.fineract.infrastructure.creditbureau.data.CreditBureauReportData; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfiguration; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfigurationRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauConfigurationRepositoryWrapper; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditBureauToken; +import org.apache.fineract.infrastructure.creditbureau.domain.CreditReportRepository; +import org.apache.fineract.infrastructure.creditbureau.domain.TokenRepositoryWrapper; +import org.apache.fineract.infrastructure.creditbureau.serialization.CreditBureauTokenCommandFromApiJsonDeserializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Service +public class ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl implements ThitsaWorksCreditBureauIntegrationWritePlatformService { + + private final PlatformSecurityContext context; + private final FromJsonHelper fromApiJsonHelper; + private final TokenRepositoryWrapper tokenRepositoryWrapper; + private final CreditBureauConfigurationRepositoryWrapper configDataRepository; + private final CreditBureauTokenCommandFromApiJsonDeserializer fromApiJsonDeserializer; + private final List dataValidationErrors = new ArrayList<>(); + private final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource("ThitsaWorksCreditBureauIntegration"); + + @Autowired + public ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl(final PlatformSecurityContext context, + final FromJsonHelper fromApiJsonHelper, final TokenRepositoryWrapper tokenRepositoryWrapper, + final CreditBureauConfigurationRepositoryWrapper configDataRepository, + final CreditBureauConfigurationRepository configurationDataRepository, + final CreditBureauTokenCommandFromApiJsonDeserializer fromApiJsonDeserializer, + final CreditReportRepository creditReportRepository) { + this.context = context; + this.tokenRepositoryWrapper = tokenRepositoryWrapper; + this.configDataRepository = configDataRepository; + this.fromApiJsonHelper = fromApiJsonHelper; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; + } + + private static final Logger LOG = LoggerFactory.getLogger(ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.class); + + @Transactional + @Override + @SuppressWarnings("deprecation") + public String okHttpConnectionMethod(String userName, String password, String subscriptionKey, String subscriptionId, String url, + String token, File file, Long uniqueId, String nrcId, String process) { + + String reponseMessage = null; + RequestBody requestBody = null; + OkHttpClient client = new OkHttpClient(); + + if (process.equals("token")) { + + final MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); + String jsonBody = "" + "BODY=x-www-form-urlencoded&\r" + "grant_type=password&\r" + "userName=" + userName + "&\r" + "password=" + + password + "&\r"; + requestBody = RequestBody.create(jsonBody, mediaType); + + } else if (process.equals("NRC")) { + + final MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); + String jsonBody = "BODY=x-www-form-urlencoded&nrc=" + nrcId + "&"; + requestBody = RequestBody.create(jsonBody, mediaType); + + } + + HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder(); + String urlokhttp = urlBuilder.build().toString(); + Request request = null; + if (token == null) { + + request = new Request.Builder().header("mcix-subscription-key", subscriptionKey).header("mcix-subscription-id", subscriptionId) + .header("Content-Type", "application/x-www-form-urlencoded").url(urlokhttp).post(requestBody).build(); + } + + if (token != null) { + + if (process.equals("CreditReport")) { // GET method for fetching credit report + request = new Request.Builder().header("mcix-subscription-key", subscriptionKey) + .header("mcix-subscription-id", subscriptionId).header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer " + token).url(urlokhttp).get().build(); + } else { // POST method for application/x-www-form-urlencoded + + request = new Request.Builder().header("mcix-subscription-key", subscriptionKey) + .header("mcix-subscription-id", subscriptionId).header("Content-Type", "application/x-www-form-urlencoded") + .header("Authorization", "Bearer " + token).url(urlokhttp).post(requestBody).build(); + } + } + + Response response; + Integer responseCode = 0; + try { + response = client.newCall(request).execute(); + responseCode = response.code(); + reponseMessage = response.body().string(); + } catch (IOException e) { + + LOG.error("error occured in HTTP request-response method.", e); + } + + if (responseCode != HttpURLConnection.HTTP_OK) { + this.httpResponse(responseCode, reponseMessage); + } + + return reponseMessage; + + } + + private void httpResponse(Integer responseCode, String responseMessage) { + + if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { + + String httpResponse = "HTTP_UNAUTHORIZED"; + this.handleAPIIntegrityIssues(httpResponse); + + } else if (responseCode == HttpURLConnection.HTTP_FORBIDDEN) { + + String httpResponse = "HTTP_FORBIDDEN"; + this.handleAPIIntegrityIssues(httpResponse); + + } else { + String responseResult = "HTTP Response Code: " + responseCode + "/" + "Response Message: " + responseMessage; + this.handleAPIIntegrityIssues(responseResult); + } + + } + + @Transactional + @Override + public CreditBureauReportData getCreditReportFromThitsaWorks(final JsonCommand command) { + + this.context.authenticatedUser(); + String nrcId = command.stringValueOfParameterNamed("NRC"); + String bureauID = command.stringValueOfParameterNamed("creditBureauID"); + Integer creditBureauId = Integer.parseInt(bureauID); + + String token = null; + + String userName = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.USERNAME.toString()); + String password = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.PASSWORD.toString()); + String subscriptionId = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.SUBSCRIPTIONID.toString()); + String subscriptionKey = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.SUBSCRIPTIONKEY.toString()); + + CreditBureauToken creditbureautoken = createToken(creditBureauId.longValue()); + token = creditbureautoken.getCurrentToken(); + + // will use only "NRC" part of code from common http method to get data based on nrc + String process = "NRC"; + String url = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.SEARCHURL.toString()); + + String nrcUrl = url + nrcId; + + String searchResult = this.okHttpConnectionMethod(userName, password, subscriptionKey, subscriptionId, nrcUrl, token, null, 0L, + nrcId, process); + + if (process.equals("NRC")) { + Long uniqueID = this.extractUniqueId(searchResult); + + process = "CreditReport"; + url = getCreditBureauConfiguration(creditBureauId, CreditBureauConfigurations.CREDITREPORTURL.toString()); + + String creditReportUrl = url + uniqueID; + + searchResult = this.okHttpConnectionMethod(userName, password, subscriptionKey, subscriptionId, creditReportUrl, token, null, + uniqueID, null, process); + + } + + // after getting the result(creditreport) from httpconnection-response it will assign creditreport to generic + // creditreportdata object + + JsonObject reportObject = JsonParser.parseString(searchResult).getAsJsonObject(); + + // Credit Reports Stored into Generic CreditReportData + JsonObject jsonData = null; + JsonElement element = reportObject.get("Data"); + + if (!(element instanceof JsonNull)) { // NOTE : "element instanceof JsonNull" is for handling empty values (and + // assigning null) while fetching data from results + jsonData = (JsonObject) element; + + } + + JsonObject borrowerInfos = null; + String borrowerInfo = null; + + element = jsonData.get("BorrowerInfo"); + + if (!(element instanceof JsonNull)) { + borrowerInfos = (JsonObject) element; + Gson gson = new Gson(); + borrowerInfo = gson.toJson(borrowerInfos); + } + + String Name = borrowerInfos.get("Name").toString(); + String Gender = borrowerInfos.get("Gender").toString(); + String Address = borrowerInfos.get("Address").toString(); + + String creditScore = "CreditScore"; + creditScore = getJsonObjectToString(creditScore, element, jsonData); + + String activeLoans = "ActiveLoans"; + JsonArray activeLoansArray = getJsonObjectToArray(activeLoans, element, jsonData); + + String[] activeLoanStringArray = null; + if (activeLoansArray != null) { + activeLoanStringArray = convertArrayintoStringArray(activeLoansArray); + } + + String writeOffLoans = "WriteOffLoans"; + JsonArray writeOffLoansArray = getJsonObjectToArray(writeOffLoans, element, jsonData); + + String[] writeoffLoanStringArray = null; + if (writeOffLoansArray != null) { + writeoffLoanStringArray = convertArrayintoStringArray(writeOffLoansArray); + } + + return CreditBureauReportData.instance(Name, Gender, Address, creditScore, borrowerInfo, activeLoanStringArray, + writeoffLoanStringArray); + } + + private String[] convertArrayintoStringArray(JsonArray jsonResult) { + + String[] loanAccounts = new String[jsonResult.size()]; + + Integer i = 0; + for (JsonElement ele : jsonResult) { + loanAccounts[i++] = ele.toString(); + } + + return loanAccounts; + } + + @Override + @Transactional + public Long extractUniqueId(String jsonResult) { + + JsonObject reportObject = JsonParser.parseString(jsonResult).getAsJsonObject(); + + JsonElement element = reportObject.get("Data"); + + if (element.isJsonNull()) { + String ResponseMessage = reportObject.get("ResponseMessage").getAsString(); + handleAPIIntegrityIssues(ResponseMessage); + } + + // to fetch the Unique ID from Result + JsonObject jsonObject = JsonParser.parseString(jsonResult).getAsJsonObject(); + + Long uniqueID = 0L; + try { + JsonArray dataArray = jsonObject.getAsJsonArray("Data"); + + if (dataArray.size() == 1) { + + JsonObject jobject = dataArray.get(0).getAsJsonObject(); + + String uniqueIdString = jobject.get("UniqueID").toString(); + String TrimUniqueId = uniqueIdString.substring(1, uniqueIdString.length() - 1); + + uniqueID = Long.parseLong(TrimUniqueId); + + } else if (dataArray.size() == 0) { + String ResponseMessage = reportObject.get("ResponseMessage").getAsString(); + handleAPIIntegrityIssues(ResponseMessage); + } else { + String nrc = null; + List arrlist = new ArrayList(); + + for (int i = 0; i < dataArray.size(); ++i) { + JsonObject data = dataArray.get(i).getAsJsonObject(); + nrc = data.get("NRC").toString(); + arrlist.add(nrc); + } + + String listString = String.join(", ", arrlist); + + this.handleMultipleNRC(listString); + } + + } catch (IndexOutOfBoundsException e) { + String ResponseMessage = jsonObject.get("ResponseMessage").getAsString(); + handleAPIIntegrityIssues(ResponseMessage); + } + return uniqueID; + } + + private String getJsonObjectToString(String fetchData, JsonElement element, JsonObject jsonData) { + + String jsonString = null; + element = jsonData.get(fetchData); + if (!(element instanceof JsonNull)) { + JsonObject fetchJson = (JsonObject) element; + Gson gson = new Gson(); + jsonString = gson.toJson(fetchJson); + } + return jsonString; + } + + private JsonArray getJsonObjectToArray(String fetchData, JsonElement element, JsonObject jsonData) { + + JsonArray fetchJson = null; + element = jsonData.get(fetchData); + if (!(element instanceof JsonNull)) { + fetchJson = (JsonArray) element; + } + return fetchJson; + } + + @Transactional + @Override + public CreditBureauToken createToken(Long bureauID) { + + CreditBureauToken creditBureauToken = this.tokenRepositoryWrapper.getToken(); + + // check the expiry date of the previous token. + if (creditBureauToken != null) { + Date current = new Date(); + Date getExpiryDate = creditBureauToken.getTokenExpiryDate(); + + if (getExpiryDate.before(current)) { + this.tokenRepositoryWrapper.delete(creditBureauToken); + creditBureauToken = null; + } + } + // storing token if it is valid token(not expired) + + if (creditBureauToken != null) { + creditBureauToken = this.tokenRepositoryWrapper.getToken(); + } + + String userName = getCreditBureauConfiguration(bureauID.intValue(), CreditBureauConfigurations.USERNAME.toString()); + String password = getCreditBureauConfiguration(bureauID.intValue(), CreditBureauConfigurations.PASSWORD.toString()); + String subscriptionId = getCreditBureauConfiguration(bureauID.intValue(), CreditBureauConfigurations.SUBSCRIPTIONID.toString()); + String subscriptionKey = getCreditBureauConfiguration(bureauID.intValue(), CreditBureauConfigurations.SUBSCRIPTIONKEY.toString()); + + if (creditBureauToken == null) { + String url = getCreditBureauConfiguration(bureauID.intValue(), CreditBureauConfigurations.TOKENURL.toString()); + + String process = "token"; + String nrcId = null; + Long uniqueID = 0L; + String result = this.okHttpConnectionMethod(userName, password, subscriptionKey, subscriptionId, url, null, null, uniqueID, + nrcId, process); + // created token will be storing it into database + final CommandWrapper wrapper = new CommandWrapperBuilder().withJson(result).build(); + final String json = wrapper.getJson(); + + JsonCommand apicommand = null; + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(json); + + apicommand = JsonCommand.from(json, parsedCommand, this.fromApiJsonHelper, wrapper.getEntityName(), wrapper.getEntityId(), + wrapper.getSubentityId(), wrapper.getGroupId(), wrapper.getClientId(), wrapper.getLoanId(), wrapper.getSavingsId(), + wrapper.getTransactionId(), wrapper.getHref(), wrapper.getProductId(), wrapper.getCreditBureauId(), + wrapper.getOrganisationCreditBureauId()); + + this.fromApiJsonDeserializer.validateForCreate(apicommand.json()); + + final CreditBureauToken generatedtoken = CreditBureauToken.fromJson(apicommand); + + final CreditBureauToken credittoken = this.tokenRepositoryWrapper.getToken(); + if (credittoken != null) { + this.tokenRepositoryWrapper.delete(credittoken); + } + + this.tokenRepositoryWrapper.save(generatedtoken); + + creditBureauToken = this.tokenRepositoryWrapper.getToken(); + + } + + return creditBureauToken; + } + + public String getCreditBureauConfiguration(Integer creditBureauId, String configurationParameterName) { + + String creditBureauConfigurationValue = null; + + try { + + CreditBureauConfiguration configurationParameterValue = this.configDataRepository.getCreditBureauConfigData(creditBureauId, + configurationParameterName); + + creditBureauConfigurationValue = configurationParameterValue.getValue(); + if (creditBureauConfigurationValue.isEmpty()) { + baseDataValidator.reset().failWithCode("creditBureau.configuration." + configurationParameterName + ".is.not.available"); + throw new PlatformApiDataValidationException( + "creditBureau.Configuration." + configurationParameterName + ".is.not.available", + "creditBureau.Configuration.is.not.available", dataValidationErrors); + + } + } catch (NullPointerException ex) { + baseDataValidator.reset().failWithCode("creditBureau.configuration.is.not.available"); + throw new PlatformApiDataValidationException("creditBureau.Configuration.is.not.available" + ex, + "creditBureau.Configuration.is.not.available", dataValidationErrors); + + } + + return creditBureauConfigurationValue; + } + + private void handleAPIIntegrityIssues(String httpResponse) { + + throw new PlatformDataIntegrityException(httpResponse, httpResponse); + + } + + private void handleMultipleNRC(String nrc) { + String showMessageForMultipleNRC = "Found Multiple NRC's, Enter one from the given:" + nrc + "." + ""; + + throw new PlatformDataIntegrityException(showMessageForMultipleNRC, showMessageForMultipleNRC); + + } +} diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V327_1__creditbureau_integration.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V327_1__creditbureau_integration.sql new file mode 100644 index 000000000..dbd86b2ea --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V327_1__creditbureau_integration.sql @@ -0,0 +1,80 @@ +-- +-- 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. +-- + + +CREATE TABLE `m_creditbureau_token` ( + `id` INT(128) NOT NULL AUTO_INCREMENT, + `username` varchar(128) DEFAULT NULL, + `token` MEDIUMTEXT DEFAULT NULL, + `tokenType` varchar(128) DEFAULT NULL, + `expiresIn` varchar(128) DEFAULT NULL, + `issued` varchar(128) DEFAULT NULL, + `expiryDate` DATE DEFAULT NULL, + PRIMARY KEY (`id`) +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB; + +CREATE TABLE `m_creditreport` ( + `id` INT(128) NOT NULL AUTO_INCREMENT, + `creditBureauId` BIGINT(128) DEFAULT NULL, + `nationalId` varchar(128) DEFAULT NULL, + `creditReports` BLOB DEFAULT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `cbId` FOREIGN KEY (`creditBureauId`) REFERENCES `m_creditbureau` (`id`) +) +COLLATE='utf8mb4_general_ci' +ENGINE=InnoDB; + + +ALTER TABLE m_creditbureau_configuration +DROP FOREIGN KEY cbConfigfk1; + +ALTER TABLE m_creditbureau_configuration +ADD CONSTRAINT cbConfigfk1 +FOREIGN KEY (organisation_creditbureau_id) REFERENCES `m_creditbureau` (`id`); + +ALTER TABLE m_creditbureau_configuration MODIFY COLUMN value longtext; + +ALTER TABLE m_organisation_creditbureau CHANGE is_active isActive TINYINT(4) NOT NULL; +ALTER TABLE m_creditbureau_loanproduct_mapping CHANGE is_active isActive TINYINT(4) NULL; + +-- Integrated credit bureau added + +INSERT INTO `m_creditbureau` (`id`, `name`, `product`, `country`, `implementationKey`) VALUES ('1', 'THITSAWORKS', '1', 'Myanmar', '1'); + + +-- permissions added + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('configuration', 'GET_CREDITREPORT', 'CREDITREPORT', 'GET', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('configuration', 'CREATE_CREDITBUREAU_CONFIGURATION', 'CREDITBUREAU_CONFIGURATION', 'CREATE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('configuration', 'UPDATE_CREDITBUREAU_CONFIGURATION', 'CREDITBUREAU_CONFIGURATION', 'UPDATE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('configuration', 'SAVE_CREDITREPORT', 'CREDITREPORT', 'SAVE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('configuration', 'DELETE_CREDITREPORT', 'CREDITREPORT', 'DELETE', 0); + +-- configkeys added + +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('1', 'Password', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('2', 'SubscriptionId', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('3', 'SubscriptionKey', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('4', 'Username', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('5', 'tokenurl', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('6', 'searchurl', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('7', 'creditReporturl', '', '1', ''); +INSERT INTO `m_creditbureau_configuration` (`id`, `configkey`, `value`, `organisation_creditbureau_id`, `description`) VALUES ('8', 'addCreditReporturl', '', '1', ''); diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/ThitsaworksCreditBureauTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/ThitsaworksCreditBureauTest.java new file mode 100644 index 000000000..c14c08b42 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/ThitsaworksCreditBureauTest.java @@ -0,0 +1,128 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.File; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.infrastructure.creditbureau.service.CreditReportWritePlatformServiceImpl; +import org.apache.fineract.infrastructure.creditbureau.service.ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class ThitsaworksCreditBureauTest { + + private FromJsonHelper fromApiJsonHelper = new FromJsonHelper(); + + @Mock + private ThitsaWorksCreditBureauIntegrationWritePlatformServiceImpl thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl; + + @InjectMocks + private final CreditReportWritePlatformServiceImpl creditReportWritePlatformServiceImpl = null; + + /* + * @Autowired CreditBureauIntegrationTest(final FromJsonHelper fromApiJsonHelper) { this.fromApiJsonHelper = + * fromApiJsonHelper; } + */ + + static String process = "process"; + static String nrcID = "13/MiFoS(N)163525"; + + static String userName = "demomfi1@mifos.com"; + static String password = "password"; + static String subscriptionKey = "15c15ff17493acb44cb223f2feab2fe4"; + + static String subscriptionId = "4A7C-317A41BA-1FF8-8A64-F8EDBE0F625D"; + static String url = "url"; + static String token = "token"; + static Long uniqueId = 8113399260L; + static File file; + + static String testresult = "{ 'Data': {'BorrowerInfo': {'MainIdentifier': '2113439293', 'Name': 'Aung Khant Min'," + + " 'NRC': '13/MiFoS(N)163525', 'Gender': '', 'DOB': '1990-01-20', 'FatherName': '', 'Address': ''," + + " 'LastUpdatedDtm': 'Jul 8 2020 9:27AM', 'PrintedDtm': 'Aug 2 2020 2:54AM' }, " + + " 'ActiveLoanStatus': 'Record found', 'ActiveLoans': [{'ReportingDate': '2020-03-01'," + + " 'LoanGUID': 'BC309AD3-0444-4EFD-807E-79ECB99EE999'," + + " 'Institution': 'Demo 1', 'Division': 'YANGON '," + + " 'Township': 'YANKIN ', 'DisbursedDate': 'xxxx'," + + " 'DisbursedAmount': '500000', 'PrincipalOutstandingAmount': '300000'," + + " 'TotalOutstandingAmount': 'xxxx', 'PrincipalOverdueAmount': '100000'," + + " 'TotalOverdueAmount': '', 'DaysInDelay': '10'," + + " 'UpdatedDtm': 'Apr 27 2020 9:41AM', 'SortColumn': '2020-03-01T00:00:00'}], " + + " 'WriteOffLoanStatus': 'No record found', 'WriteOffLoans': null," + + " 'CreditScore': { 'Score': 'N/A','Class': 'N/A', 'Note': ''}," + + " 'InquiryStatus': 'Record found', 'Inquiries': [{ 'InquiryDate': '', 'Institution': '','NoOfInquiry': ''} ] }," + + " 'MessageDtm': '8/1/2020 8:24:20 PM UTC','SubscriptionID': '4A7C-317A41BA-1FF8-8A64-F8EDBE0F625D'," + + " 'CallerIP': '207.46.228.155'," + + " 'URI': 'https://qa-mmcix-api.azurewebsites.net/20200324/api/Dashboard/GetCreditReport?uniqueId=2113439292'," + + " 'ResponseMessage': 'Record found'}"; + + @Test + public void getUniqueIdFromSearchMethodTest() { + String searchResult = "{\"Data\":[{\"UniqueID\":\"8113399260\",\"NRC\":\"12/KaMaRa(N)253426\",\"FullName\":\"Aye Aye\",\"DOB\":\"1990-05-22,1991-05-22\",\"FatherFullName\":\"U Aye Myint Maung\",\"Location\":\"Yangon-Thongwa,Twantay,Yankin\",\"Flag\":\"[{\\\"WriteOff\\\":1}]\",\"Active\":\"Y\"}],\"MessageDtm\":\"8/1/2020 6:39:00 PM UTC\",\"SubscriptionID\":\"317A1FF8-625D-41BA-BE0F-F8ED8A644A7C\",\"CallerIP\":\"207.46.228.155\",\"URI\":\"https://qa-mmcix-api.azurewebsites.net/20200324/api/Search/SimpleSearch?nrc=253426\",\"ResponseMessage\":\"Record found\"}"; + + when(this.thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.okHttpConnectionMethod(userName, password, subscriptionKey, + subscriptionId, url, token, file, uniqueId, nrcID, process)).thenReturn(searchResult); + + final String search = thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.okHttpConnectionMethod(userName, password, + subscriptionKey, subscriptionId, url, token, file, uniqueId, nrcID, process); + + when(thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.extractUniqueId(search)).thenCallRealMethod(); + + Long uniqueId = thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.extractUniqueId(searchResult); + + Long expectedUniqueId = 8113399260L; + assertEquals(expectedUniqueId, uniqueId); + + } + + @Test + public void getCreditReportTest() { + String curentNrc = "13/MiFoS(N)163525"; + + when(this.thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.okHttpConnectionMethod(userName, password, subscriptionKey, + subscriptionId, url, token, file, uniqueId, nrcID, process)).thenReturn(testresult); + + String creditReport = thitsaWorksCreditBureauIntegrationWritePlatformServiceImpl.okHttpConnectionMethod(userName, password, + subscriptionKey, subscriptionId, url, token, file, uniqueId, nrcID, process); + + JsonObject resultObject = JsonParser.parseString(creditReport).getAsJsonObject(); + String data = resultObject.get("Data").toString(); + + JsonObject dataObject = JsonParser.parseString(data).getAsJsonObject(); + String borrowerInfo = dataObject.get("BorrowerInfo").toString(); + + JsonObject borrowerObject = JsonParser.parseString(borrowerInfo).getAsJsonObject(); + String nrc = borrowerObject.get("NRC").toString(); + + nrc = nrc.substring(1, nrc.length() - 1); + + assertEquals(nrc, curentNrc); + + } + +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/CreditBureauConfigurationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/CreditBureauConfigurationTest.java new file mode 100644 index 000000000..9d49224d8 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/CreditBureauConfigurationTest.java @@ -0,0 +1,70 @@ +/** + * 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.integrationtests; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.http.ContentType; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import org.apache.fineract.integrationtests.common.CreditBureauConfigurationHelper; +import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CreditBureauConfigurationTest { + + private static final Logger LOG = LoggerFactory.getLogger(CreditBureauConfigurationTest.class); + private ResponseSpecification responseSpec; + private RequestSpecification requestSpec; + private LoanTransactionHelper loanTransactionHelper; + + private static final String NO_ACCOUNTING = "1"; + + static final int MYTHREADS = 30; + + @BeforeEach + public void setup() { + Utils.initializeRESTAssured(); + this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); + this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + } + + @Test + public void creditBureauConfigurationTest() { + + // create creditBureauConfiguration + final Integer configurationId = CreditBureauConfigurationHelper.createCreditBureauConfiguration(this.requestSpec, + this.responseSpec); + Assertions.assertNotNull(configurationId); + + // update creditBureauConfiguration + final String updateconfiguration = CreditBureauConfigurationHelper.updateCreditBureauConfiguration(this.requestSpec, + this.responseSpec, configurationId); + + Assertions.assertEquals("updateConfigKeyValue", updateconfiguration); + } + +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CreditBureauConfigurationHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CreditBureauConfigurationHelper.java new file mode 100644 index 000000000..41dda394e --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CreditBureauConfigurationHelper.java @@ -0,0 +1,102 @@ +/** + * 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.integrationtests.common; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import java.util.HashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CreditBureauConfigurationHelper { + + private static final String CREATE_CREDITBUREAUCONFIGURATION_URL = "/fineract-provider/api/v1/CreditBureauConfiguration/configuration?" + + Utils.TENANT_IDENTIFIER; + private static final Logger LOG = LoggerFactory.getLogger(CreditBureauConfigurationHelper.class); + private final RequestSpecification requestSpec; + private final ResponseSpecification responseSpec; + + public CreditBureauConfigurationHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + this.requestSpec = requestSpec; + this.responseSpec = responseSpec; + } + + public static Integer createCreditBureauConfiguration(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec) { + return createCreditBureauConfiguration(requestSpec, responseSpec, "1"); + } + + public static Integer createCreditBureauConfiguration(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String creditBureauId) { + LOG.info("---------------------------------CREATING A CREDIT_BUREAU_CONFIGURATION---------------------------------------------"); + final String CREDITBUREAU_CONFIGURATION_URL = " /fineract-provider/api/v1/CreditBureauConfiguration/configuration/" + creditBureauId + + "?" + Utils.TENANT_IDENTIFIER; + return Utils.performServerPost(requestSpec, responseSpec, CREDITBUREAU_CONFIGURATION_URL, + creditBureauConfigurationAsJson("testConfigKey", "testConfigKeyValue", "description"), "resourceId"); + } + + /* + * public static Object updateCreditBureauConfiguration(final RequestSpecification requestSpec, final + * ResponseSpecification responseSpec, final Integer ConfigurationId) { return + * updateCreditBureauConfiguration(requestSpec, responseSpec, ConfigurationId); } + */ + + public static String updateCreditBureauConfiguration(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer ConfigurationId) { + + Object configurationObject = updateCreditBureauConfiguration(requestSpec, responseSpec, ConfigurationId, "updateConfigKeyValue"); + // Convert the Object to String and fetch updated value + Gson gson = new Gson(); + String result = gson.toJson(configurationObject); + JsonObject reportObject = JsonParser.parseString(result).getAsJsonObject(); + String value = reportObject.get("value").getAsString(); + + return value; + } + + public static Object updateCreditBureauConfiguration(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer ConfigurationId, final String updateConfigKeyValue) { + LOG.info("---------------------------------UPDATING A CREDIT_BUREAU_CONFIGURATION---------------------------------------------"); + final String CREDITBUREAU_CONFIGURATION_URL = " /fineract-provider/api/v1/CreditBureauConfiguration/configuration/" + + ConfigurationId + "?" + Utils.TENANT_IDENTIFIER; + return Utils.performServerPut(requestSpec, responseSpec, CREDITBUREAU_CONFIGURATION_URL, + updateCreditBureauConfigurationAsJson("updateConfigKeyValue", "description"), "changes"); + } + + public static String creditBureauConfigurationAsJson(final String configkey, final String value, final String description) { + final HashMap map = new HashMap<>(); + map.put("configkey", configkey); + map.put("value", value); + map.put("description", description); + LOG.info("map : {}", map); + return new Gson().toJson(map); + } + + public static String updateCreditBureauConfigurationAsJson(final String value, final String description) { + final HashMap map = new HashMap<>(); + map.put("value", value); + map.put("description", description); + LOG.info("map : {}", map); + return new Gson().toJson(map); + } + +}