[FINERACT-1760] Loan product external id
This commit is contained in:
+11
@@ -35,6 +35,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.core.serialization.FromJsonHelper;
|
||||||
import org.apache.fineract.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
|
import org.apache.fineract.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
|
||||||
import org.apache.fineract.infrastructure.security.domain.PlatformUser;
|
import org.apache.fineract.infrastructure.security.domain.PlatformUser;
|
||||||
@@ -643,6 +644,16 @@ public final class JsonCommand {
|
|||||||
return isChanged;
|
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,
|
public String passwordValueOfParameterNamed(final String parameterName, final PlatformPasswordEncoder platformPasswordEncoder,
|
||||||
final Long saltValue) {
|
final Long saltValue) {
|
||||||
final String passwordPlainText = stringValueOfParameterNamed(parameterName);
|
final String passwordPlainText = stringValueOfParameterNamed(parameterName);
|
||||||
|
|||||||
+8
-6
@@ -48,6 +48,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
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.MonetaryCurrency;
|
||||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||||
@@ -130,7 +132,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
|||||||
private LocalDate closeDate;
|
private LocalDate closeDate;
|
||||||
|
|
||||||
@Column(name = "external_id", length = 100, unique = true)
|
@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)
|
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loanProduct", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||||
private Set<LoanProductBorrowerCycleVariations> borrowerCycleVariations = new HashSet<>();
|
private Set<LoanProductBorrowerCycleVariations> borrowerCycleVariations = new HashSet<>();
|
||||||
@@ -290,7 +292,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
|||||||
|
|
||||||
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
|
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
|
||||||
final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate");
|
final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate");
|
||||||
final String externalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
final ExternalId externalId = ExternalIdFactory.produce(command.stringValueOfParameterNamedAllowingNull("externalId"));
|
||||||
|
|
||||||
final boolean useBorrowerCycle = command
|
final boolean useBorrowerCycle = command
|
||||||
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME);
|
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME);
|
||||||
@@ -593,7 +595,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
|||||||
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
|
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
|
||||||
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final AmortizationMethod amortizationMethod,
|
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final AmortizationMethod amortizationMethod,
|
||||||
final BigDecimal inArrearsTolerance, final List<Charge> charges, final AccountingRuleType accountingRuleType,
|
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 useBorrowerCycle, final Set<LoanProductBorrowerCycleVariations> loanProductBorrowerCycleVariations,
|
||||||
final boolean multiDisburseLoan, final Integer maxTrancheCount, final BigDecimal outstandingLoanBalance,
|
final boolean multiDisburseLoan, final Integer maxTrancheCount, final BigDecimal outstandingLoanBalance,
|
||||||
final Integer graceOnArrearsAgeing, final Integer overdueDaysForNPA, final DaysInMonthType daysInMonthType,
|
final Integer graceOnArrearsAgeing, final Integer overdueDaysForNPA, final DaysInMonthType daysInMonthType,
|
||||||
@@ -964,8 +966,8 @@ public class LoanProduct extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String externalIdTypeParamName = "externalId";
|
final String externalIdTypeParamName = "externalId";
|
||||||
if (command.isChangeInStringParameterNamed(externalIdTypeParamName, this.externalId)) {
|
if (command.isChangeInExternalIdParameterNamed(externalIdTypeParamName, this.externalId)) {
|
||||||
final String newValue = command.stringValueOfParameterNamed(externalIdTypeParamName);
|
final ExternalId newValue = ExternalIdFactory.produce(command.stringValueOfParameterNamed(externalIdTypeParamName));
|
||||||
actualChanges.put(accountingTypeParamName, newValue);
|
actualChanges.put(accountingTypeParamName, newValue);
|
||||||
this.externalId = newValue;
|
this.externalId = newValue;
|
||||||
}
|
}
|
||||||
@@ -1315,7 +1317,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getExternalId() {
|
public ExternalId getExternalId() {
|
||||||
return this.externalId;
|
return this.externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+84
-19
@@ -43,6 +43,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
|
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.api.ApiRequestParameterHelper;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
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.ApiRequestJsonSerializationSettings;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
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.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||||
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
|
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.LoanProductConstants;
|
||||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
||||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
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.data.ProductMixData;
|
||||||
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixReadPlatformService;
|
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
|
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
|
||||||
@@ -230,6 +234,86 @@ public class LoanProductsApiResource {
|
|||||||
|
|
||||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
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());
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
|
||||||
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
|
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
|
||||||
@@ -256,25 +340,6 @@ public class LoanProductsApiResource {
|
|||||||
return this.toApiJsonSerializer.serialize(settings, loanProduct, LOAN_PRODUCT_DATA_PARAMETERS);
|
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) {
|
private LoanProductData handleTemplate(final LoanProductData productData) {
|
||||||
|
|
||||||
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableFees();
|
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableFees();
|
||||||
|
|||||||
+2
@@ -41,6 +41,8 @@ final class LoanProductsApiResourceSwagger {
|
|||||||
|
|
||||||
@Schema(example = "LP Accrual Accounting")
|
@Schema(example = "LP Accrual Accounting")
|
||||||
public String name;
|
public String name;
|
||||||
|
@Schema(example = "2075e308-d4a8-44d9-8203-f5a947b8c2f4")
|
||||||
|
public String externalId;
|
||||||
@Schema(example = "LPAA")
|
@Schema(example = "LPAA")
|
||||||
public String shortName;
|
public String shortName;
|
||||||
@Schema(example = "non-interest bearing product")
|
@Schema(example = "non-interest bearing product")
|
||||||
|
|||||||
+3
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
@@ -33,4 +34,6 @@ public interface LoanProductRepository extends JpaRepository<LoanProduct, Long>,
|
|||||||
Long countByDelinquencyBucket(DelinquencyBucket delinquencyBucket);
|
Long countByDelinquencyBucket(DelinquencyBucket delinquencyBucket);
|
||||||
|
|
||||||
List<LoanProduct> findByDelinquencyBucketNotNull();
|
List<LoanProduct> findByDelinquencyBucketNotNull();
|
||||||
|
|
||||||
|
LoanProduct findByExternalId(ExternalId externalId);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanproduct.exception;
|
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.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||||
import org.springframework.dao.EmptyResultDataAccessException;
|
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);
|
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) {
|
public LoanProductNotFoundException(Long id, EmptyResultDataAccessException e) {
|
||||||
super("error.msg.loanproduct.id.invalid", "Loan product with identifier " + id + " does not exist", id, e);
|
super("error.msg.loanproduct.id.invalid", "Loan product with identifier " + id + " does not exist", id, e);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -19,8 +19,10 @@
|
|||||||
package org.apache.fineract.portfolio.loanproduct.service;
|
package org.apache.fineract.portfolio.loanproduct.service;
|
||||||
|
|
||||||
import java.util.Collection;
|
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.LoanProductBorrowerCycleVariationData;
|
||||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
||||||
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
|
|
||||||
public interface LoanProductReadPlatformService {
|
public interface LoanProductReadPlatformService {
|
||||||
|
|
||||||
@@ -34,6 +36,8 @@ public interface LoanProductReadPlatformService {
|
|||||||
|
|
||||||
LoanProductData retrieveLoanProduct(Long productId);
|
LoanProductData retrieveLoanProduct(Long productId);
|
||||||
|
|
||||||
|
LoanProduct retrieveLoanProductByExternalId(ExternalId externalId);
|
||||||
|
|
||||||
LoanProductData retrieveNewLoanProductDetails();
|
LoanProductData retrieveNewLoanProductDetails();
|
||||||
|
|
||||||
Collection<LoanProductData> retrieveAllLoanProductsForCurrency(String currencyCode);
|
Collection<LoanProductData> retrieveAllLoanProductsForCurrency(String currencyCode);
|
||||||
|
|||||||
+11
-15
@@ -24,8 +24,10 @@ import java.sql.SQLException;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
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.domain.JdbcSupport;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
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.LoanProductData;
|
||||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductGuaranteeData;
|
import org.apache.fineract.portfolio.loanproduct.data.LoanProductGuaranteeData;
|
||||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductInterestRecalculationData;
|
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.LoanProductConfigurableAttributes;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductParamType;
|
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.loanproduct.exception.LoanProductNotFoundException;
|
||||||
import org.apache.fineract.portfolio.rate.data.RateData;
|
import org.apache.fineract.portfolio.rate.data.RateData;
|
||||||
import org.apache.fineract.portfolio.rate.service.RateReadService;
|
import org.apache.fineract.portfolio.rate.service.RateReadService;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.dao.EmptyResultDataAccessException;
|
import org.springframework.dao.EmptyResultDataAccessException;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatformService {
|
public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatformService {
|
||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
@@ -64,20 +68,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
|||||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||||
private final FineractEntityAccessUtil fineractEntityAccessUtil;
|
private final FineractEntityAccessUtil fineractEntityAccessUtil;
|
||||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||||
|
private final LoanProductRepository loanProductRepository;
|
||||||
@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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanProductData retrieveLoanProduct(final Long loanProductId) {
|
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
|
@Override
|
||||||
public Collection<LoanProductBorrowerCycleVariationData> retrieveLoanProductBorrowerCycleVariations(final Long loanProductId) {
|
public Collection<LoanProductBorrowerCycleVariationData> retrieveLoanProductBorrowerCycleVariations(final Long loanProductId) {
|
||||||
final LoanProductBorrowerCycleMapper rm = new LoanProductBorrowerCycleMapper();
|
final LoanProductBorrowerCycleMapper rm = new LoanProductBorrowerCycleMapper();
|
||||||
|
|||||||
+76
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -18,8 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.integrationtests.common.loans;
|
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.PostLoanProductsRequest;
|
||||||
import org.apache.fineract.client.models.PostLoanProductsResponse;
|
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;
|
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||||
|
|
||||||
public class LoanProductHelper extends IntegrationTest {
|
public class LoanProductHelper extends IntegrationTest {
|
||||||
@@ -29,4 +32,12 @@ public class LoanProductHelper extends IntegrationTest {
|
|||||||
public PostLoanProductsResponse createLoanProduct(PostLoanProductsRequest request) {
|
public PostLoanProductsResponse createLoanProduct(PostLoanProductsRequest request) {
|
||||||
return ok(fineract().loanProducts.createLoanProduct(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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -76,6 +76,7 @@ public class LoanProductTestBuilder {
|
|||||||
|
|
||||||
private String nameOfLoanProduct = Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6);
|
private String nameOfLoanProduct = Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6);
|
||||||
private String shortName = Utils.uniqueRandomStringGenerator("", 4);
|
private String shortName = Utils.uniqueRandomStringGenerator("", 4);
|
||||||
|
private String externalId = null;
|
||||||
private String principal = "10000.00";
|
private String principal = "10000.00";
|
||||||
private String numberOfRepayments = "5";
|
private String numberOfRepayments = "5";
|
||||||
private String repaymentFrequency = MONTHS;
|
private String repaymentFrequency = MONTHS;
|
||||||
@@ -160,6 +161,7 @@ public class LoanProductTestBuilder {
|
|||||||
}
|
}
|
||||||
map.put("name", this.nameOfLoanProduct);
|
map.put("name", this.nameOfLoanProduct);
|
||||||
map.put("shortName", this.shortName);
|
map.put("shortName", this.shortName);
|
||||||
|
map.put("externalId", this.externalId);
|
||||||
map.put("currencyCode", this.currencyCode);
|
map.put("currencyCode", this.currencyCode);
|
||||||
map.put("locale", LOCALE);
|
map.put("locale", LOCALE);
|
||||||
map.put("dateFormat", "dd MMMM yyyy");
|
map.put("dateFormat", "dd MMMM yyyy");
|
||||||
@@ -281,6 +283,11 @@ public class LoanProductTestBuilder {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoanProductTestBuilder withExternalId(String externalId) {
|
||||||
|
this.externalId = externalId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public LoanProductTestBuilder withInstallmentAmountInMultiplesOf(String installmentAmountInMultiplesOf) {
|
public LoanProductTestBuilder withInstallmentAmountInMultiplesOf(String installmentAmountInMultiplesOf) {
|
||||||
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
|
this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
Reference in New Issue
Block a user