[FINERACT-1760] Loan product external id

This commit is contained in:
taskain7
2023-07-13 19:57:28 +02:00
committed by Adam Saghy
parent d65de7a8e9
commit be935cd55b
11 changed files with 222 additions and 40 deletions
@@ -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();
@@ -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")
@@ -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);
}
@@ -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);
}
@@ -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);
@@ -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();