This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new be935cd55 [FINERACT-1760] Loan product external id
be935cd55 is described below
commit be935cd55b9f57c9e98f31fa876c64c8163892e7
Author: taskain7 <[email protected]>
AuthorDate: Thu Jul 13 12:31:37 2023 +0200
[FINERACT-1760] Loan product external id
---
.../infrastructure/core/api/JsonCommand.java | 11 +++
.../portfolio/loanproduct/domain/LoanProduct.java | 14 +--
.../loanproduct/api/LoanProductsApiResource.java | 103 +++++++++++++++++----
.../api/LoanProductsApiResourceSwagger.java | 2 +
.../loanproduct/domain/LoanProductRepository.java | 3 +
.../exception/LoanProductNotFoundException.java | 5 +
.../service/LoanProductReadPlatformService.java | 4 +
.../LoanProductReadPlatformServiceImpl.java | 26 +++---
.../LoanProductExternalIdTest.java | 76 +++++++++++++++
.../common/loans/LoanProductHelper.java | 11 +++
.../common/loans/LoanProductTestBuilder.java | 7 ++
11 files changed, 222 insertions(+), 40 deletions(-)
diff --git
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
index 49ebc937d..32175c5f7 100644
---
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
@@ -35,6 +35,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import
org.apache.fineract.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
import org.apache.fineract.infrastructure.security.domain.PlatformUser;
@@ -643,6 +644,16 @@ public final class JsonCommand {
return isChanged;
}
+ public boolean isChangeInExternalIdParameterNamed(final String
parameterName, final ExternalId externalId) {
+ boolean isChanged = false;
+ if (parameterExists(parameterName)) {
+ final String workingValue =
stringValueOfParameterNamed(parameterName);
+ String existingValue = externalId.getValue();
+ isChanged = differenceExists(existingValue, workingValue);
+ }
+ return isChanged;
+ }
+
public String passwordValueOfParameterNamed(final String parameterName,
final PlatformPasswordEncoder platformPasswordEncoder,
final Long saltValue) {
final String passwordPlainText =
stringValueOfParameterNamed(parameterName);
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
index 9ec2258d7..5218cba42 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
@@ -48,6 +48,8 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.accounting.common.AccountingRuleType;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import
org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
+import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.charge.domain.Charge;
@@ -130,7 +132,7 @@ public class LoanProduct extends AbstractPersistableCustom {
private LocalDate closeDate;
@Column(name = "external_id", length = 100, unique = true)
- private String externalId;
+ private ExternalId externalId;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loanProduct",
orphanRemoval = true, fetch = FetchType.EAGER)
private Set<LoanProductBorrowerCycleVariations> borrowerCycleVariations =
new HashSet<>();
@@ -290,7 +292,7 @@ public class LoanProduct extends AbstractPersistableCustom {
final LocalDate startDate =
command.localDateValueOfParameterNamed("startDate");
final LocalDate closeDate =
command.localDateValueOfParameterNamed("closeDate");
- final String externalId =
command.stringValueOfParameterNamedAllowingNull("externalId");
+ final ExternalId externalId =
ExternalIdFactory.produce(command.stringValueOfParameterNamedAllowingNull("externalId"));
final boolean useBorrowerCycle = command
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME);
@@ -593,7 +595,7 @@ public class LoanProduct extends AbstractPersistableCustom {
final Integer graceOnPrincipalPayment, final Integer
recurringMoratoriumOnPrincipalPeriods,
final Integer graceOnInterestPayment, final Integer
graceOnInterestCharged, final AmortizationMethod amortizationMethod,
final BigDecimal inArrearsTolerance, final List<Charge> charges,
final AccountingRuleType accountingRuleType,
- final boolean includeInBorrowerCycle, final LocalDate startDate,
final LocalDate closeDate, final String externalId,
+ final boolean includeInBorrowerCycle, final LocalDate startDate,
final LocalDate closeDate, final ExternalId externalId,
final boolean useBorrowerCycle, final
Set<LoanProductBorrowerCycleVariations> loanProductBorrowerCycleVariations,
final boolean multiDisburseLoan, final Integer maxTrancheCount,
final BigDecimal outstandingLoanBalance,
final Integer graceOnArrearsAgeing, final Integer
overdueDaysForNPA, final DaysInMonthType daysInMonthType,
@@ -964,8 +966,8 @@ public class LoanProduct extends AbstractPersistableCustom {
}
final String externalIdTypeParamName = "externalId";
- if (command.isChangeInStringParameterNamed(externalIdTypeParamName,
this.externalId)) {
- final String newValue =
command.stringValueOfParameterNamed(externalIdTypeParamName);
+ if
(command.isChangeInExternalIdParameterNamed(externalIdTypeParamName,
this.externalId)) {
+ final ExternalId newValue =
ExternalIdFactory.produce(command.stringValueOfParameterNamed(externalIdTypeParamName));
actualChanges.put(accountingTypeParamName, newValue);
this.externalId = newValue;
}
@@ -1315,7 +1317,7 @@ public class LoanProduct extends
AbstractPersistableCustom {
return this.name;
}
- public String getExternalId() {
+ public ExternalId getExternalId() {
return this.externalId;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
index c834a7aca..910b8069e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
@@ -43,6 +43,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import
org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
@@ -58,8 +59,10 @@ import
org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import
org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import
org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
@@ -76,6 +79,7 @@ import
org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
import
org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
+import
org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import
org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixData;
import
org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixReadPlatformService;
import
org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
@@ -230,6 +234,86 @@ public class LoanProductsApiResource {
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
+ return getLoanProductDetails(productId, uriInfo);
+ }
+
+ @PUT
+ @Path("{productId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Operation(summary = "Update a Loan Product", description = "Updates a
Loan Product")
+ @RequestBody(required = true, content = @Content(schema =
@Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdRequest.class)))
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "OK", content =
@Content(schema = @Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdResponse.class))) })
+ public String updateLoanProduct(@PathParam("productId")
@Parameter(description = "productId") final Long productId,
+ @Parameter(hidden = true) final String apiRequestBodyAsJson) {
+
+ return getUpdateLoanProductResult(apiRequestBodyAsJson, productId);
+ }
+
+ @GET
+ @Path("external-id/{externalProductId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Operation(summary = "Retrieve a Loan Product", description = "Retrieves a
Loan Product\n\n" + "Example Requests:\n" + "\n"
+ +
"loanproducts/external-id/2075e308-d4a8-44d9-8203-f5a947b8c2f4\n" + "\n" + "\n"
+ +
"loanproducts/external-id/2075e308-d4a8-44d9-8203-f5a947b8c2f4?template=true\n"
+ "\n" + "\n"
+ +
"loanproducts/external-id/2075e308-d4a8-44d9-8203-f5a947b8c2f4?fields=name,description,numberOfRepayments")
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "OK", content =
@Content(schema = @Schema(implementation =
LoanProductsApiResourceSwagger.GetLoanProductsProductIdResponse.class))) })
+ public String retrieveLoanProductDetails(
+ @PathParam("externalProductId") @Parameter(description =
"externalProductId") final String externalProductId,
+ @Context final UriInfo uriInfo) {
+
+
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
+
+ ExternalId externalId = ExternalIdFactory.produce(externalProductId);
+
+ Long productId = resolveProductId(externalId);
+ if (Objects.isNull(productId)) {
+ throw new LoanProductNotFoundException(externalId);
+ }
+
+ return getLoanProductDetails(productId, uriInfo);
+ }
+
+ @PUT
+ @Path("external-id/{externalProductId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Operation(summary = "Update a Loan Product", description = "Updates a
Loan Product")
+ @RequestBody(required = true, content = @Content(schema =
@Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdRequest.class)))
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "OK", content =
@Content(schema = @Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdResponse.class))) })
+ public String updateLoanProduct(
+ @PathParam("externalProductId") @Parameter(description =
"externalProductId") final String externalProductId,
+ @Parameter(hidden = true) final String apiRequestBodyAsJson) {
+
+ ExternalId externalId = ExternalIdFactory.produce(externalProductId);
+
+ Long productId = resolveProductId(externalId);
+
+ if (Objects.isNull(productId)) {
+ throw new LoanProductNotFoundException(externalId);
+ }
+
+ return getUpdateLoanProductResult(apiRequestBodyAsJson, productId);
+ }
+
+ private String getUpdateLoanProductResult(String apiRequestBodyAsJson,
Long productId) {
+ final CommandWrapper commandRequest = new
CommandWrapperBuilder().updateLoanProduct(productId).withJson(apiRequestBodyAsJson)
+ .build();
+
+ final CommandProcessingResult result =
this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+
+ return this.toApiJsonSerializer.serialize(result);
+ }
+
+ private Long resolveProductId(ExternalId externalProductId) {
+ return
loanProductReadPlatformService.retrieveLoanProductByExternalId(externalProductId).getId();
+ }
+
+ private String getLoanProductDetails(Long productId, UriInfo uriInfo) {
final ApiRequestJsonSerializationSettings settings =
this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
LoanProductData loanProduct =
this.loanProductReadPlatformService.retrieveLoanProduct(productId);
@@ -256,25 +340,6 @@ public class LoanProductsApiResource {
return this.toApiJsonSerializer.serialize(settings, loanProduct,
LOAN_PRODUCT_DATA_PARAMETERS);
}
- @PUT
- @Path("{productId}")
- @Consumes({ MediaType.APPLICATION_JSON })
- @Produces({ MediaType.APPLICATION_JSON })
- @Operation(summary = "Update a Loan Product", description = "Updates a
Loan Product")
- @RequestBody(required = true, content = @Content(schema =
@Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdRequest.class)))
- @ApiResponses({
- @ApiResponse(responseCode = "200", description = "OK", content =
@Content(schema = @Schema(implementation =
LoanProductsApiResourceSwagger.PutLoanProductsProductIdResponse.class))) })
- public String updateLoanProduct(@PathParam("productId")
@Parameter(description = "productId") final Long productId,
- @Parameter(hidden = true) final String apiRequestBodyAsJson) {
-
- final CommandWrapper commandRequest = new
CommandWrapperBuilder().updateLoanProduct(productId).withJson(apiRequestBodyAsJson)
- .build();
-
- final CommandProcessingResult result =
this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
-
- return this.toApiJsonSerializer.serialize(result);
- }
-
private LoanProductData handleTemplate(final LoanProductData productData) {
Collection<ChargeData> chargeOptions =
this.chargeReadPlatformService.retrieveLoanApplicableFees();
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index 2626ac977..26fad80e1 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -41,6 +41,8 @@ final class LoanProductsApiResourceSwagger {
@Schema(example = "LP Accrual Accounting")
public String name;
+ @Schema(example = "2075e308-d4a8-44d9-8203-f5a947b8c2f4")
+ public String externalId;
@Schema(example = "LPAA")
public String shortName;
@Schema(example = "non-interest bearing product")
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRepository.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRepository.java
index 64c93583d..68e912b04 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRepository.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRepository.java
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.loanproduct.domain;
import java.util.List;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -33,4 +34,6 @@ public interface LoanProductRepository extends
JpaRepository<LoanProduct, Long>,
Long countByDelinquencyBucket(DelinquencyBucket delinquencyBucket);
List<LoanProduct> findByDelinquencyBucketNotNull();
+
+ LoanProduct findByExternalId(ExternalId externalId);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/exception/LoanProductNotFoundException.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/exception/LoanProductNotFoundException.java
index 13b6ff69e..a4f1cbece 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/exception/LoanProductNotFoundException.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/exception/LoanProductNotFoundException.java
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.portfolio.loanproduct.exception;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import
org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -30,6 +31,10 @@ public class LoanProductNotFoundException extends
AbstractPlatformResourceNotFou
super("error.msg.loanproduct.id.invalid", "Loan product with
identifier " + id + " does not exist", id);
}
+ public LoanProductNotFoundException(final ExternalId externalId) {
+ super("error.msg.loanproduct.id.invalid", "Loan product with
identifier " + externalId + " does not exist", externalId);
+ }
+
public LoanProductNotFoundException(Long id,
EmptyResultDataAccessException e) {
super("error.msg.loanproduct.id.invalid", "Loan product with
identifier " + id + " does not exist", id, e);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
index 54df64fc7..27613d700 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
@@ -19,8 +19,10 @@
package org.apache.fineract.portfolio.loanproduct.service;
import java.util.Collection;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import
org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVariationData;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
public interface LoanProductReadPlatformService {
@@ -34,6 +36,8 @@ public interface LoanProductReadPlatformService {
LoanProductData retrieveLoanProduct(Long productId);
+ LoanProduct retrieveLoanProductByExternalId(ExternalId externalId);
+
LoanProductData retrieveNewLoanProductDetails();
Collection<LoanProductData> retrieveAllLoanProductsForCurrency(String
currencyCode);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
index 7122139c6..01cd94103 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
@@ -24,8 +24,10 @@ import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
+import lombok.RequiredArgsConstructor;
import org.apache.fineract.accounting.common.AccountingEnumerations;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
@@ -42,19 +44,21 @@ import
org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVa
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductGuaranteeData;
import
org.apache.fineract.portfolio.loanproduct.data.LoanProductInterestRecalculationData;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
import
org.apache.fineract.portfolio.loanproduct.domain.LoanProductConfigurableAttributes;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductParamType;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
import
org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.apache.fineract.portfolio.rate.data.RateData;
import org.apache.fineract.portfolio.rate.service.RateReadService;
import org.jetbrains.annotations.NotNull;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
+@RequiredArgsConstructor
public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatformService {
private final PlatformSecurityContext context;
@@ -64,20 +68,7 @@ public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatfo
private final DatabaseSpecificSQLGenerator sqlGenerator;
private final FineractEntityAccessUtil fineractEntityAccessUtil;
private final DelinquencyReadPlatformService
delinquencyReadPlatformService;
-
- @Autowired
- public LoanProductReadPlatformServiceImpl(final PlatformSecurityContext
context,
- final ChargeReadPlatformService chargeReadPlatformService, final
JdbcTemplate jdbcTemplate,
- final FineractEntityAccessUtil fineractEntityAccessUtil, final
RateReadService rateReadService,
- final DelinquencyReadPlatformService
delinquencyReadPlatformService, final DatabaseSpecificSQLGenerator
sqlGenerator) {
- this.context = context;
- this.chargeReadPlatformService = chargeReadPlatformService;
- this.jdbcTemplate = jdbcTemplate;
- this.fineractEntityAccessUtil = fineractEntityAccessUtil;
- this.rateReadService = rateReadService;
- this.sqlGenerator = sqlGenerator;
- this.delinquencyReadPlatformService = delinquencyReadPlatformService;
- }
+ private final LoanProductRepository loanProductRepository;
@Override
public LoanProductData retrieveLoanProduct(final Long loanProductId) {
@@ -99,6 +90,11 @@ public class LoanProductReadPlatformServiceImpl implements
LoanProductReadPlatfo
}
}
+ @Override
+ public LoanProduct retrieveLoanProductByExternalId(final ExternalId
externalId) {
+ return loanProductRepository.findByExternalId(externalId);
+ }
+
@Override
public Collection<LoanProductBorrowerCycleVariationData>
retrieveLoanProductBorrowerCycleVariations(final Long loanProductId) {
final LoanProductBorrowerCycleMapper rm = new
LoanProductBorrowerCycleMapper();
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java
new file mode 100644
index 000000000..03d327012
--- /dev/null
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java
@@ -0,0 +1,76 @@
+/**
+ * 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 static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+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 java.util.HashMap;
+import java.util.UUID;
+import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
+import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
+import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.loans.LoanProductHelper;
+import
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class LoanProductExternalIdTest {
+
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+ private LoanTransactionHelper loanTransactionHelper;
+ private LoanProductHelper loanProductHelper;
+
+ @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(requestSpec,
responseSpec);
+ this.loanProductHelper = new LoanProductHelper();
+ }
+
+ @Test
+ public void testLoanProductWithExternalId() {
+ String externalId = UUID.randomUUID().toString();
+ HashMap<String, Object> request = new
LoanProductTestBuilder().withExternalId(externalId).build(null, null);
+ Integer loanProductId =
loanTransactionHelper.getLoanProductId(Utils.convertToJson(request));
+ assertNotNull(loanProductId);
+
+ GetLoanProductsProductIdResponse getLoanProductsProductIdResponse =
loanProductHelper.retrieveLoanProductByExternalId(externalId);
+ assertNotNull(getLoanProductsProductIdResponse.getId());
+ assertEquals(loanProductId,
getLoanProductsProductIdResponse.getId().intValue());
+
+ final PutLoanProductsProductIdRequest requestModifyLoan = new
PutLoanProductsProductIdRequest()
+ .shortName(Utils.uniqueRandomStringGenerator("", 3));
+ PutLoanProductsProductIdResponse putLoanProductsProductIdResponse =
loanProductHelper.updateLoanProductByExternalId(externalId,
+ requestModifyLoan);
+ assertNotNull(putLoanProductsProductIdResponse.getResourceId());
+ assertEquals(loanProductId,
putLoanProductsProductIdResponse.getResourceId().intValue());
+ }
+}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
index d3f0a1be3..46c7aa1ff 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductHelper.java
@@ -18,8 +18,11 @@
*/
package org.apache.fineract.integrationtests.common.loans;
+import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
+import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
import org.apache.fineract.integrationtests.client.IntegrationTest;
public class LoanProductHelper extends IntegrationTest {
@@ -29,4 +32,12 @@ public class LoanProductHelper extends IntegrationTest {
public PostLoanProductsResponse createLoanProduct(PostLoanProductsRequest
request) {
return ok(fineract().loanProducts.createLoanProduct(request));
}
+
+ public GetLoanProductsProductIdResponse
retrieveLoanProductByExternalId(String externalId) {
+ return
ok(fineract().loanProducts.retrieveLoanProductDetails1(externalId));
+ }
+
+ public PutLoanProductsProductIdResponse
updateLoanProductByExternalId(String externalId,
PutLoanProductsProductIdRequest request) {
+ return ok(fineract().loanProducts.updateLoanProduct1(externalId,
request));
+ }
}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index a13b01e6c..49c6c9181 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -76,6 +76,7 @@ public class LoanProductTestBuilder {
private String nameOfLoanProduct =
Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6);
private String shortName = Utils.uniqueRandomStringGenerator("", 4);
+ private String externalId = null;
private String principal = "10000.00";
private String numberOfRepayments = "5";
private String repaymentFrequency = MONTHS;
@@ -160,6 +161,7 @@ public class LoanProductTestBuilder {
}
map.put("name", this.nameOfLoanProduct);
map.put("shortName", this.shortName);
+ map.put("externalId", this.externalId);
map.put("currencyCode", this.currencyCode);
map.put("locale", LOCALE);
map.put("dateFormat", "dd MMMM yyyy");
@@ -281,6 +283,11 @@ public class LoanProductTestBuilder {
return map;
}
+ public LoanProductTestBuilder withExternalId(String externalId) {
+ this.externalId = externalId;
+ return this;
+ }
+
public LoanProductTestBuilder withInstallmentAmountInMultiplesOf(String
installmentAmountInMultiplesOf) {
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
return this;