Skip to content

Commit f358c00

Browse files
Jose Alberto Hernandezalberto-art3ch
authored andcommitted
FINERACT-2421: Loan product basic detail endpoint
1 parent 1cdc97a commit f358c00

File tree

14 files changed

+279
-2
lines changed

14 files changed

+279
-2
lines changed

fineract-client/src/main/java/org/apache/fineract/client/util/FineractClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
import org.apache.fineract.client.services.LoanDisbursementDetailsApi;
9696
import org.apache.fineract.client.services.LoanInterestPauseApi;
9797
import org.apache.fineract.client.services.LoanProductsApi;
98+
import org.apache.fineract.client.services.LoanProductsDetailsApi;
9899
import org.apache.fineract.client.services.LoanReschedulingApi;
99100
import org.apache.fineract.client.services.LoanTransactionsApi;
100101
import org.apache.fineract.client.services.LoansApi;
@@ -238,6 +239,7 @@ public final class FineractClient {
238239
public final LoanCollateralApi loanCollaterals;
239240
public final LoanCapitalizedIncomeApi loanCapitalizedIncome;
240241
public final LoanProductsApi loanProducts;
242+
public final LoanProductsDetailsApi loanProductsDetails;
241243
public final LoanReschedulingApi loanSchedules;
242244
public final LoansPointInTimeApi loansPointInTimeApi;
243245
public final LoansApi loans;
@@ -371,6 +373,7 @@ private FineractClient(OkHttpClient okHttpClient, Retrofit retrofit) {
371373
loanCollaterals = retrofit.create(LoanCollateralApi.class);
372374
loanCapitalizedIncome = retrofit.create(LoanCapitalizedIncomeApi.class);
373375
loanProducts = retrofit.create(LoanProductsApi.class);
376+
loanProductsDetails = retrofit.create(LoanProductsDetailsApi.class);
374377
loanSchedules = retrofit.create(LoanReschedulingApi.class);
375378
loansPointInTimeApi = retrofit.create(LoansPointInTimeApi.class);
376379
loans = retrofit.create(LoansApi.class);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.loanproduct.data;
20+
21+
import lombok.Data;
22+
import lombok.RequiredArgsConstructor;
23+
import org.apache.fineract.organisation.monetary.data.CurrencyData;
24+
25+
@Data
26+
@RequiredArgsConstructor
27+
public class LoanProductBasicDetailsData {
28+
29+
private final String productType;
30+
private final Long id;
31+
private final String name;
32+
private final String shortName;
33+
private final String description;
34+
private final CurrencyData currency;
35+
36+
}

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.fineract.portfolio.loanproduct.domain;
2020

21+
import java.time.LocalDate;
2122
import java.util.List;
2223
import org.apache.fineract.infrastructure.core.domain.ExternalId;
2324
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
@@ -41,4 +42,7 @@ public interface LoanProductRepository extends JpaRepository<LoanProduct, Long>,
4142
@Override
4243
@Query("SELECT CASE WHEN COUNT(loanProduct)>0 THEN TRUE ELSE FALSE END FROM LoanProduct loanProduct WHERE loanProduct.id = :loanProductId")
4344
boolean existsById(@NonNull @Param("loanProductId") Long loanProductId);
45+
46+
@Query("select loanProduct from LoanProduct loanProduct where loanProduct.closeDate is null or loanProduct.closeDate >= :businessDate")
47+
List<LoanProduct> fetchActiveLoanProducts(LocalDate businessDate);
4448
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.loanproduct.mapper;
20+
21+
import java.util.List;
22+
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
23+
import org.apache.fineract.organisation.monetary.data.CurrencyData;
24+
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
25+
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBasicDetailsData;
26+
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
27+
import org.mapstruct.Mapper;
28+
import org.mapstruct.Mapping;
29+
import org.mapstruct.Named;
30+
31+
@Mapper(config = MapstructMapperConfig.class)
32+
public interface LoanProductBasicDetailsMapper {
33+
34+
@Mapping(target = "productType", constant = "loan")
35+
@Mapping(target = "currency", source = "loanProductRelatedDetail.currency", qualifiedByName = "currencyData")
36+
LoanProductBasicDetailsData map(LoanProduct source);
37+
38+
List<LoanProductBasicDetailsData> map(List<LoanProduct> source);
39+
40+
@Named("currencyData")
41+
default CurrencyData currencyData(final MonetaryCurrency currency) {
42+
return currency.toData();
43+
}
44+
45+
}

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.fineract.infrastructure.core.domain.ExternalId;
2323
import org.apache.fineract.portfolio.loanproduct.data.AdvancedPaymentData;
2424
import org.apache.fineract.portfolio.loanproduct.data.CreditAllocationData;
25+
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBasicDetailsData;
2526
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVariationData;
2627
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
2728
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
@@ -57,4 +58,6 @@ public interface LoanProductReadPlatformService {
5758
Collection<CreditAllocationData> retrieveCreditAllocationData(Long loanProductId);
5859

5960
LoanProductData retrieveLoanProductFloatingDetails(Long loanProductId);
61+
62+
Collection<LoanProductBasicDetailsData> retrieveProducts();
6063
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.loanproduct.api;
20+
21+
import io.swagger.v3.oas.annotations.Operation;
22+
import io.swagger.v3.oas.annotations.tags.Tag;
23+
import jakarta.ws.rs.Consumes;
24+
import jakarta.ws.rs.GET;
25+
import jakarta.ws.rs.Path;
26+
import jakarta.ws.rs.Produces;
27+
import jakarta.ws.rs.core.Context;
28+
import jakarta.ws.rs.core.MediaType;
29+
import jakarta.ws.rs.core.UriInfo;
30+
import java.util.ArrayList;
31+
import java.util.Collection;
32+
import lombok.RequiredArgsConstructor;
33+
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
34+
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBasicDetailsData;
35+
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
36+
import org.apache.fineract.portfolio.workingcapitalloanproduct.service.WorkingCapitalLoanProductReadPlatformService;
37+
import org.springframework.stereotype.Component;
38+
39+
@Path("/v1/loanproducts")
40+
@Component
41+
@Tag(name = "Loan Products Details", description = "Loan product basic details to be listed")
42+
@RequiredArgsConstructor
43+
public class LoanProductsDetailsApiResource {
44+
45+
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "LOANPRODUCT";
46+
private final PlatformSecurityContext context;
47+
private final LoanProductReadPlatformService loanProductReadPlatformService;
48+
private final WorkingCapitalLoanProductReadPlatformService workingCapitalLoanProductReadPlatformService;
49+
50+
@GET
51+
@Path("basic-details")
52+
@Consumes({ MediaType.APPLICATION_JSON })
53+
@Produces({ MediaType.APPLICATION_JSON })
54+
@Operation(summary = "List Loan Products with basic details", description = "Lists Loan Products with basic details to be listed")
55+
public Collection<LoanProductBasicDetailsData> fetchProducts(@Context final UriInfo uriInfo) {
56+
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
57+
58+
Collection<LoanProductBasicDetailsData> products = new ArrayList<>();
59+
products.addAll(loanProductReadPlatformService.retrieveProducts());
60+
products.addAll(workingCapitalLoanProductReadPlatformService.retrieveProducts());
61+
62+
return products;
63+
}
64+
65+
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.apache.fineract.portfolio.loanproduct.data.AdvancedPaymentData;
5959
import org.apache.fineract.portfolio.loanproduct.data.AdvancedPaymentData.PaymentAllocationOrder;
6060
import org.apache.fineract.portfolio.loanproduct.data.CreditAllocationData;
61+
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBasicDetailsData;
6162
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVariationData;
6263
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
6364
import org.apache.fineract.portfolio.loanproduct.data.LoanProductGuaranteeData;
@@ -68,6 +69,7 @@
6869
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
6970
import org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
7071
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
72+
import org.apache.fineract.portfolio.loanproduct.mapper.LoanProductBasicDetailsMapper;
7173
import org.apache.fineract.portfolio.rate.data.RateData;
7274
import org.apache.fineract.portfolio.rate.service.RateReadService;
7375
import org.springframework.dao.EmptyResultDataAccessException;
@@ -86,6 +88,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
8688
private final FineractEntityAccessUtil fineractEntityAccessUtil;
8789
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
8890
private final LoanProductRepository loanProductRepository;
91+
private final LoanProductBasicDetailsMapper loanProductBasicDetailsMapper;
8992

9093
@Override
9194
public LoanProductData retrieveLoanProduct(final Long loanProductId) {
@@ -831,6 +834,11 @@ public LoanProductData retrieveLoanProductFloatingDetails(final Long loanProduct
831834
}
832835
}
833836

837+
@Override
838+
public Collection<LoanProductBasicDetailsData> retrieveProducts() {
839+
return loanProductBasicDetailsMapper.map(loanProductRepository.fetchActiveLoanProducts(DateUtils.getBusinessLocalDate()));
840+
}
841+
834842
private static final class LoanProductFloatingRateMapper implements RowMapper<LoanProductData> {
835843

836844
LoanProductFloatingRateMapper() {}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/starter/LoanProductConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.fineract.portfolio.loanproduct.domain.AdvancedPaymentAllocationsJsonParser;
3838
import org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationsJsonParser;
3939
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
40+
import org.apache.fineract.portfolio.loanproduct.mapper.LoanProductBasicDetailsMapper;
4041
import org.apache.fineract.portfolio.loanproduct.serialization.LoanProductDataValidator;
4142
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
4243
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformServiceImpl;
@@ -66,9 +67,9 @@ public LoanDropdownReadPlatformService loanDropdownReadPlatformService(
6667
public LoanProductReadPlatformService loanProductReadPlatformService(PlatformSecurityContext context, JdbcTemplate jdbcTemplate,
6768
ChargeReadPlatformService chargeReadPlatformService, RateReadService rateReadService, DatabaseSpecificSQLGenerator sqlGenerator,
6869
FineractEntityAccessUtil fineractEntityAccessUtil, DelinquencyReadPlatformService delinquencyReadPlatformService,
69-
LoanProductRepository loanProductRepository) {
70+
LoanProductRepository loanProductRepository, final LoanProductBasicDetailsMapper loanProductBasicDetailsMapper) {
7071
return new LoanProductReadPlatformServiceImpl(context, jdbcTemplate, chargeReadPlatformService, rateReadService, sqlGenerator,
71-
fineractEntityAccessUtil, delinquencyReadPlatformService, loanProductRepository);
72+
fineractEntityAccessUtil, delinquencyReadPlatformService, loanProductRepository, loanProductBasicDetailsMapper);
7273
}
7374

7475
@Bean
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloanproduct.mapper;
20+
21+
import java.util.List;
22+
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
23+
import org.apache.fineract.organisation.monetary.data.CurrencyData;
24+
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
25+
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBasicDetailsData;
26+
import org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WorkingCapitalLoanProduct;
27+
import org.mapstruct.Mapper;
28+
import org.mapstruct.Mapping;
29+
import org.mapstruct.Named;
30+
31+
@Mapper(config = MapstructMapperConfig.class)
32+
public interface WorkingCapitalLoanProductBasicDetailsMapper {
33+
34+
@Mapping(target = "productType", constant = "working-capital")
35+
@Mapping(target = "currency", source = "currency", qualifiedByName = "currencyData")
36+
LoanProductBasicDetailsData map(WorkingCapitalLoanProduct source);
37+
38+
List<LoanProductBasicDetailsData> map(List<WorkingCapitalLoanProduct> source);
39+
40+
@Named("currencyData")
41+
default CurrencyData currencyData(final MonetaryCurrency currency) {
42+
return currency.toData();
43+
}
44+
45+
}

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloanproduct/repository/WorkingCapitalLoanProductRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.fineract.portfolio.workingcapitalloanproduct.repository;
2020

21+
import java.time.LocalDate;
2122
import java.util.List;
2223
import java.util.Optional;
2324
import org.apache.fineract.infrastructure.core.domain.ExternalId;
@@ -64,6 +65,9 @@ public interface WorkingCapitalLoanProductRepository
6465
""")
6566
Optional<WorkingCapitalLoanProduct> findByExternalIdWithDetails(@Param("externalId") ExternalId externalId);
6667

68+
@Query("select wclp FROM WorkingCapitalLoanProduct wclp where wclp.closeDate is null or wclp.closeDate >= :businessDate")
69+
List<WorkingCapitalLoanProduct> fetchActiveWorkingCapitalLoanProducts(LocalDate businessDate);
70+
6771
// TODO: Check if product is used in any loans (for deletion validation)
6872
// This will be implemented when Working Capital Loan entity is created
6973
// @Query("SELECT CASE WHEN COUNT(l)>0 THEN TRUE ELSE FALSE END FROM WorkingCapitalLoan l WHERE l.wcpProduct.id =

0 commit comments

Comments
 (0)