FINERACT-2311: Add GET API for buy down fees related information
This commit is contained in:
committed by
Adam Saghy
parent
54f055d9c7
commit
ca3f63badf
@@ -85,6 +85,7 @@ import org.apache.fineract.client.services.InterestRateSlabAKAInterestBandsApi;
|
|||||||
import org.apache.fineract.client.services.JournalEntriesApi;
|
import org.apache.fineract.client.services.JournalEntriesApi;
|
||||||
import org.apache.fineract.client.services.ListReportMailingJobHistoryApi;
|
import org.apache.fineract.client.services.ListReportMailingJobHistoryApi;
|
||||||
import org.apache.fineract.client.services.LoanAccountLockApi;
|
import org.apache.fineract.client.services.LoanAccountLockApi;
|
||||||
|
import org.apache.fineract.client.services.LoanBuyDownFeesApi;
|
||||||
import org.apache.fineract.client.services.LoanChargesApi;
|
import org.apache.fineract.client.services.LoanChargesApi;
|
||||||
import org.apache.fineract.client.services.LoanCobCatchUpApi;
|
import org.apache.fineract.client.services.LoanCobCatchUpApi;
|
||||||
import org.apache.fineract.client.services.LoanCollateralApi;
|
import org.apache.fineract.client.services.LoanCollateralApi;
|
||||||
@@ -304,6 +305,7 @@ public final class FineractClient {
|
|||||||
public final ExternalAssetOwnerLoanProductAttributesApi externalAssetOwnerLoanProductAttributes;
|
public final ExternalAssetOwnerLoanProductAttributesApi externalAssetOwnerLoanProductAttributes;
|
||||||
public final LoanAccountLockApi loanAccountLockApi;
|
public final LoanAccountLockApi loanAccountLockApi;
|
||||||
public final InlineJobApi inlineJobApi;
|
public final InlineJobApi inlineJobApi;
|
||||||
|
public final LoanBuyDownFeesApi loanBuyDownFeesApi;
|
||||||
|
|
||||||
private FineractClient(OkHttpClient okHttpClient, Retrofit retrofit) {
|
private FineractClient(OkHttpClient okHttpClient, Retrofit retrofit) {
|
||||||
this.okHttpClient = okHttpClient;
|
this.okHttpClient = okHttpClient;
|
||||||
@@ -430,6 +432,7 @@ public final class FineractClient {
|
|||||||
loanInterestPauseApi = retrofit.create(LoanInterestPauseApi.class);
|
loanInterestPauseApi = retrofit.create(LoanInterestPauseApi.class);
|
||||||
progressiveLoanApi = retrofit.create(ProgressiveLoanApi.class);
|
progressiveLoanApi = retrofit.create(ProgressiveLoanApi.class);
|
||||||
inlineJobApi = retrofit.create(InlineJobApi.class);
|
inlineJobApi = retrofit.create(InlineJobApi.class);
|
||||||
|
loanBuyDownFeesApi = retrofit.create(LoanBuyDownFeesApi.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
|
|||||||
+4
@@ -271,4 +271,8 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
|||||||
|
|
||||||
@Query("select loan.loanRepaymentScheduleDetail.enableIncomeCapitalization from Loan loan where loan.id = :loanId")
|
@Query("select loan.loanRepaymentScheduleDetail.enableIncomeCapitalization from Loan loan where loan.id = :loanId")
|
||||||
Boolean isEnabledCapitalizedIncome(Long loanId);
|
Boolean isEnabledCapitalizedIncome(Long loanId);
|
||||||
|
|
||||||
|
@Query("select loan.loanRepaymentScheduleDetail.enableBuyDownFee from Loan loan where loan.id = :loanId")
|
||||||
|
Boolean isEnabledBuyDownFee(@Param("loanId") Long loanId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -157,4 +157,7 @@ public interface LoanReadPlatformService {
|
|||||||
boolean existsByLoanId(Long loanId);
|
boolean existsByLoanId(Long loanId);
|
||||||
|
|
||||||
LoanTransactionData retrieveManualInterestRefundTemplate(Long loanId, Long targetTransactionId);
|
LoanTransactionData retrieveManualInterestRefundTemplate(Long loanId, Long targetTransactionId);
|
||||||
|
|
||||||
|
Long getResolvedLoanId(ExternalId loanExternalId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.api;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.PathParam;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||||
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.BuyDownFeeAmortizationDetails;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeReadPlatformService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Path("/v1/loans")
|
||||||
|
@Component
|
||||||
|
@Tag(name = "Loan Buy Down Fees", description = "Loan Buy Down Fees")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoanBuyDownFeeApiResource {
|
||||||
|
|
||||||
|
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "LOAN";
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final BuyDownFeeReadPlatformService buyDownFeeReadPlatformService;
|
||||||
|
private final LoanReadPlatformService loanReadPlatformService;
|
||||||
|
|
||||||
|
@Path("/{loanId}/buydown-fees")
|
||||||
|
@GET
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Get the amortization details of Buy Down fees for a loan", description = "Returns a list of all Buy Down fee entries with amortization details for the specified loan.")
|
||||||
|
@ApiResponses({
|
||||||
|
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = BuyDownFeeAmortizationDetails.class)))) })
|
||||||
|
public List<BuyDownFeeAmortizationDetails> retrieveLoanBuyDownFeeAmortizationDetails(
|
||||||
|
@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId) {
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
|
|
||||||
|
return this.buyDownFeeReadPlatformService.retrieveLoanBuyDownFeeAmortizationDetails(loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/external-id/{loanExternalId}/buydown-fees")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Get the amortization details of Buy Down fees for a loan by external ID", description = "Returns a list of all Buy Down fee entries with amortization details for the loan specified by external ID.")
|
||||||
|
@ApiResponses({
|
||||||
|
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = BuyDownFeeAmortizationDetails.class)))) })
|
||||||
|
public List<BuyDownFeeAmortizationDetails> retrieveLoanBuyDownFeeAmortizationDetailsByExternalId(
|
||||||
|
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId) {
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
|
|
||||||
|
final ExternalId externalId = ExternalIdFactory.produce(loanExternalId);
|
||||||
|
final Long resolvedLoanId = loanReadPlatformService.getResolvedLoanId(externalId);
|
||||||
|
|
||||||
|
return this.buyDownFeeReadPlatformService.retrieveLoanBuyDownFeeAmortizationDetails(resolvedLoanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public record BuyDownFeeAmortizationDetails(Long id, Long loanId, Long transactionId, LocalDate buyDownFeeDate, BigDecimal buyDownFeeAmount,
|
||||||
|
BigDecimal amortizedAmount, BigDecimal notYetAmortizedAmount, BigDecimal adjustedAmount, BigDecimal chargedOffAmount) {
|
||||||
|
|
||||||
|
}
|
||||||
+1
@@ -33,4 +33,5 @@ import lombok.ToString;
|
|||||||
public class LoanDeferredIncomeData {
|
public class LoanDeferredIncomeData {
|
||||||
|
|
||||||
private List<CapitalizedIncomeDetails> capitalizedIncomeData;
|
private List<CapitalizedIncomeDetails> capitalizedIncomeData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-16
@@ -18,16 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.loanaccount.repository;
|
package org.apache.fineract.portfolio.loanaccount.repository;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
|
||||||
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;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.query.Param;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface LoanBuyDownFeeBalanceRepository
|
public interface LoanBuyDownFeeBalanceRepository
|
||||||
extends JpaRepository<LoanBuyDownFeeBalance, Long>, JpaSpecificationExecutor<LoanBuyDownFeeBalance> {
|
extends JpaRepository<LoanBuyDownFeeBalance, Long>, JpaSpecificationExecutor<LoanBuyDownFeeBalance> {
|
||||||
|
|
||||||
@@ -35,15 +30,4 @@ public interface LoanBuyDownFeeBalanceRepository
|
|||||||
|
|
||||||
LoanBuyDownFeeBalance findByLoanIdAndLoanTransactionId(Long loanId, Long transactionId);
|
LoanBuyDownFeeBalance findByLoanIdAndLoanTransactionId(Long loanId, Long transactionId);
|
||||||
|
|
||||||
@Query("SELECT lbfb FROM LoanBuyDownFeeBalance lbfb WHERE lbfb.loan.id = :loanId ORDER BY lbfb.date ASC")
|
|
||||||
List<LoanBuyDownFeeBalance> findRepaymentPeriodDataByLoanId(@Param("loanId") Long loanId);
|
|
||||||
|
|
||||||
@Query("SELECT COALESCE(SUM(lbfb.amount), 0) FROM LoanBuyDownFeeBalance lbfb WHERE lbfb.loan.id = :loanId")
|
|
||||||
BigDecimal calculateBuyDownFee(@Param("loanId") Long loanId);
|
|
||||||
|
|
||||||
@Query("SELECT COALESCE(SUM(lbfb.amountAdjustment), 0) FROM LoanBuyDownFeeBalance lbfb WHERE lbfb.loan.id = :loanId")
|
|
||||||
BigDecimal calculateBuyDownFeeAdjustment(@Param("loanId") Long loanId);
|
|
||||||
|
|
||||||
@Query("SELECT lbfb FROM LoanBuyDownFeeBalance lbfb WHERE lbfb.loan.id = :loanId AND lbfb.amountAdjustment IS NULL ORDER BY lbfb.date DESC")
|
|
||||||
List<LoanBuyDownFeeBalance> findBalanceForAdjustment(@Param("loanId") Long loanId);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.BuyDownFeeAmortizationDetails;
|
||||||
|
|
||||||
|
public interface BuyDownFeeReadPlatformService {
|
||||||
|
|
||||||
|
List<BuyDownFeeAmortizationDetails> retrieveLoanBuyDownFeeAmortizationDetails(Long loanId);
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.BuyDownFeeAmortizationDetails;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.repository.LoanBuyDownFeeBalanceRepository;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BuyDownFeeReadPlatformServiceImpl implements BuyDownFeeReadPlatformService {
|
||||||
|
|
||||||
|
private final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository;
|
||||||
|
private final LoanRepository loanRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BuyDownFeeAmortizationDetails> retrieveLoanBuyDownFeeAmortizationDetails(final Long loanId) {
|
||||||
|
if (!loanRepository.existsById(loanId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.is.not.found", "Loan: %s is not found".formatted(loanId), loanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loanRepository.isEnabledBuyDownFee(loanId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.is.not.enabled.buydown.fee",
|
||||||
|
"Loan: %s is not enabled Buydown fee feature".formatted(loanId), loanId);
|
||||||
|
}
|
||||||
|
final List<LoanBuyDownFeeBalance> buyDownFeeBalances = loanBuyDownFeeBalanceRepository.findAllByLoanId(loanId);
|
||||||
|
|
||||||
|
return buyDownFeeBalances.stream().map(this::mapToLoanBuyDownFeeAmortizationData).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BuyDownFeeAmortizationDetails mapToLoanBuyDownFeeAmortizationData(final LoanBuyDownFeeBalance balance) {
|
||||||
|
final BigDecimal amortizedAmount = balance.getAmount() //
|
||||||
|
.subtract(MathUtil.nullToZero(balance.getUnrecognizedAmount())) //
|
||||||
|
.subtract(MathUtil.nullToZero(balance.getAmountAdjustment())) //
|
||||||
|
.subtract(MathUtil.nullToZero(balance.getChargedOffAmount()));
|
||||||
|
|
||||||
|
return new BuyDownFeeAmortizationDetails(balance.getId(), balance.getLoan().getId(), balance.getLoanTransaction().getId(),
|
||||||
|
balance.getDate(), balance.getAmount(), amortizedAmount, balance.getUnrecognizedAmount(), balance.getAmountAdjustment(),
|
||||||
|
balance.getChargedOffAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+7
-19
@@ -63,7 +63,6 @@ import org.apache.fineract.portfolio.charge.exception.LoanChargeNotFoundExceptio
|
|||||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -421,7 +420,7 @@ public class LoanChargesApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
||||||
|
|
||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanCharge(resolvedLoanId, resolvedLoanChargeId).build();
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanCharge(resolvedLoanId, resolvedLoanChargeId).build();
|
||||||
@@ -438,7 +437,7 @@ public class LoanChargesApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
||||||
|
|
||||||
final LoanChargeData loanCharge = this.loanChargeReadPlatformService.retrieveLoanChargeDetails(resolvedLoanChargeId,
|
final LoanChargeData loanCharge = this.loanChargeReadPlatformService.retrieveLoanChargeDetails(resolvedLoanChargeId,
|
||||||
@@ -457,7 +456,7 @@ public class LoanChargesApiResource {
|
|||||||
final String apiRequestBodyAsJson) {
|
final String apiRequestBodyAsJson) {
|
||||||
|
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
CommandProcessingResult result;
|
CommandProcessingResult result;
|
||||||
if (CommandParameterUtil.is(commandParam, COMMAND_PAY)) {
|
if (CommandParameterUtil.is(commandParam, COMMAND_PAY)) {
|
||||||
@@ -483,7 +482,7 @@ public class LoanChargesApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
||||||
|
|
||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
@@ -513,7 +512,7 @@ public class LoanChargesApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
ExternalId loanChargeExternalId = ExternalIdFactory.produce(loanChargeExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
Long resolvedLoanChargeId = getResolvedLoanChargeId(loanChargeId, loanChargeExternalId);
|
||||||
|
|
||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateLoanCharge(resolvedLoanId, resolvedLoanChargeId)
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateLoanCharge(resolvedLoanId, resolvedLoanChargeId)
|
||||||
@@ -528,7 +527,7 @@ public class LoanChargesApiResource {
|
|||||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
|
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
final Collection<LoanChargeData> loanCharges = this.loanChargeReadPlatformService.retrieveLoanCharges(resolvedLoanId);
|
final Collection<LoanChargeData> loanCharges = this.loanChargeReadPlatformService.retrieveLoanCharges(resolvedLoanId);
|
||||||
|
|
||||||
@@ -540,7 +539,7 @@ public class LoanChargesApiResource {
|
|||||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
|
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
final List<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(resolvedLoanId,
|
final List<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(resolvedLoanId,
|
||||||
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT });
|
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT });
|
||||||
@@ -562,15 +561,4 @@ public class LoanChargesApiResource {
|
|||||||
return resolvedLoanChargeId;
|
return resolvedLoanChargeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getResolvedLoanId(final Long loanId, final ExternalId loanExternalId) {
|
|
||||||
Long resolvedLoanId = loanId;
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
loanExternalId.throwExceptionIfEmpty();
|
|
||||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
throw new LoanNotFoundException(loanExternalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resolvedLoanId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-19
@@ -91,8 +91,6 @@ public class LoanTransactionsApiResource {
|
|||||||
public static final String REAMORTIZE = "reAmortize";
|
public static final String REAMORTIZE = "reAmortize";
|
||||||
public static final String UNDO_REAMORTIZE = "undoReAmortize";
|
public static final String UNDO_REAMORTIZE = "undoReAmortize";
|
||||||
public static final String CAPITALIZED_INCOME = "capitalizedIncome";
|
public static final String CAPITALIZED_INCOME = "capitalizedIncome";
|
||||||
public static final String CAPITALIZED_INCOME_ADJUSTMENT = "capitalizedIncomeAdjustment";
|
|
||||||
public static final String CONTRACT_TERMINATION = "contractTermination";
|
|
||||||
public static final String INTEREST_REFUND_COMMAND_VALUE = "interest-refund";
|
public static final String INTEREST_REFUND_COMMAND_VALUE = "interest-refund";
|
||||||
private final Set<String> responseDataParameters = new HashSet<>(Arrays.asList("id", "type", "date", "currency", "amount", "externalId",
|
private final Set<String> responseDataParameters = new HashSet<>(Arrays.asList("id", "type", "date", "currency", "amount", "externalId",
|
||||||
LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME, LoanApiConstants.REVERSED_ON_DATE_PARAMNAME));
|
LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME, LoanApiConstants.REVERSED_ON_DATE_PARAMNAME));
|
||||||
@@ -471,7 +469,7 @@ public class LoanTransactionsApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedLoanTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
Long resolvedLoanTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||||
|
|
||||||
LoanTransactionData transactionData = this.loanReadPlatformService.retrieveLoanTransaction(resolvedLoanId,
|
LoanTransactionData transactionData = this.loanReadPlatformService.retrieveLoanTransaction(resolvedLoanId,
|
||||||
@@ -552,7 +550,7 @@ public class LoanTransactionsApiResource {
|
|||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
|
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
CommandWrapper commandRequest = null;
|
CommandWrapper commandRequest = null;
|
||||||
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
||||||
@@ -618,7 +616,7 @@ public class LoanTransactionsApiResource {
|
|||||||
|
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
LoanTransactionData transactionData;
|
LoanTransactionData transactionData;
|
||||||
|
|
||||||
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
||||||
@@ -714,7 +712,7 @@ public class LoanTransactionsApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||||
CommandWrapper commandRequest;
|
CommandWrapper commandRequest;
|
||||||
if (CommandParameterUtil.is(commandParam, LoanApiConstants.CHARGEBACK_TRANSACTION_COMMAND)) {
|
if (CommandParameterUtil.is(commandParam, LoanApiConstants.CHARGEBACK_TRANSACTION_COMMAND)) {
|
||||||
@@ -739,7 +737,7 @@ public class LoanTransactionsApiResource {
|
|||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||||
|
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().undoWaiveChargeTransaction(resolvedLoanId, resolvedTransactionId)
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().undoWaiveChargeTransaction(resolvedLoanId, resolvedTransactionId)
|
||||||
.build();
|
.build();
|
||||||
@@ -759,18 +757,6 @@ public class LoanTransactionsApiResource {
|
|||||||
return resolvedLoanTransactionId;
|
return resolvedLoanTransactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getResolvedLoanId(final Long loanId, final ExternalId loanExternalId) {
|
|
||||||
Long resolvedLoanId = loanId;
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
loanExternalId.throwExceptionIfEmpty();
|
|
||||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
throw new LoanNotFoundException(loanExternalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resolvedLoanId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Long getResolvedLoanIdWithExistsCheck(final Long loanId, final ExternalId loanExternalId) {
|
private Long getResolvedLoanIdWithExistsCheck(final Long loanId, final ExternalId loanExternalId) {
|
||||||
if (loanId != null) {
|
if (loanId != null) {
|
||||||
if (!loanReadPlatformService.existsByLoanId(loanId)) {
|
if (!loanReadPlatformService.existsByLoanId(loanId)) {
|
||||||
|
|||||||
+11
-24
@@ -145,7 +145,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryBalancesRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryBalancesRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepaymentPeriodData;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepaymentPeriodData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTemplateTypeRequiredException;
|
import org.apache.fineract.portfolio.loanaccount.exception.LoanTemplateTypeRequiredException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTemplateTypeException;
|
import org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTemplateTypeException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
|
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
|
||||||
@@ -560,7 +559,6 @@ public class LoansApiResource {
|
|||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createLoanApplication().withJson(apiRequestBodyAsJson).build();
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().createLoanApplication().withJson(apiRequestBodyAsJson).build();
|
||||||
|
|
||||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
return this.toApiJsonSerializer.serialize(result);
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -931,7 +929,7 @@ public class LoansApiResource {
|
|||||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
LoanApprovalData loanApprovalTemplate = null;
|
LoanApprovalData loanApprovalTemplate = null;
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
if (templateType == null) {
|
if (templateType == null) {
|
||||||
final String errorMsg = "Loan template type must be provided";
|
final String errorMsg = "Loan template type must be provided";
|
||||||
throw new LoanTemplateTypeRequiredException(errorMsg);
|
throw new LoanTemplateTypeRequiredException(errorMsg);
|
||||||
@@ -947,7 +945,7 @@ public class LoansApiResource {
|
|||||||
final UriInfo uriInfo) {
|
final UriInfo uriInfo) {
|
||||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(resolvedLoanId);
|
LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(resolvedLoanId);
|
||||||
if (loanBasicDetails.isInterestRecalculationEnabled()) {
|
if (loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||||
Collection<CalendarData> interestRecalculationCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(
|
Collection<CalendarData> interestRecalculationCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(
|
||||||
@@ -1241,7 +1239,7 @@ public class LoansApiResource {
|
|||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
CommandWrapper commandRequest;
|
CommandWrapper commandRequest;
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
if (CommandParameterUtil.is(commandParam, LoanApiConstants.MARK_AS_FRAUD_COMMAND)) {
|
if (CommandParameterUtil.is(commandParam, LoanApiConstants.MARK_AS_FRAUD_COMMAND)) {
|
||||||
commandRequest = builder.markAsFraud(resolvedLoanId).build();
|
commandRequest = builder.markAsFraud(resolvedLoanId).build();
|
||||||
} else {
|
} else {
|
||||||
@@ -1249,12 +1247,13 @@ public class LoansApiResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
return this.toApiJsonSerializer.serialize(result);
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String deleteLoanApplication(final Long loanId, final String loanExternalIdStr) {
|
private String deleteLoanApplication(final Long loanId, final String loanExternalIdStr) {
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanApplication(resolvedLoanId).build();
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanApplication(resolvedLoanId).build();
|
||||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
return this.toApiJsonSerializer.serialize(result);
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
@@ -1263,7 +1262,7 @@ public class LoansApiResource {
|
|||||||
private String stateTransitions(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
private String stateTransitions(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
||||||
final String apiRequestBodyAsJson) {
|
final String apiRequestBodyAsJson) {
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
CommandWrapper commandRequest = null;
|
CommandWrapper commandRequest = null;
|
||||||
if (CommandParameterUtil.is(commandParam, "reject")) {
|
if (CommandParameterUtil.is(commandParam, "reject")) {
|
||||||
@@ -1309,28 +1308,16 @@ public class LoansApiResource {
|
|||||||
private String getDelinquencyTagHistory(final Long loanId, final String loanExternalIdStr, final UriInfo uriInfo) {
|
private String getDelinquencyTagHistory(final Long loanId, final String loanExternalIdStr, final UriInfo uriInfo) {
|
||||||
context.authenticatedUser().validateHasReadPermission("DELINQUENCY_TAGS");
|
context.authenticatedUser().validateHasReadPermission("DELINQUENCY_TAGS");
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
final Collection<LoanDelinquencyTagHistoryData> loanDelinquencyTagHistoryData = this.delinquencyReadPlatformService
|
final Collection<LoanDelinquencyTagHistoryData> loanDelinquencyTagHistoryData = this.delinquencyReadPlatformService
|
||||||
.retrieveDelinquencyRangeHistory(resolvedLoanId);
|
.retrieveDelinquencyRangeHistory(resolvedLoanId);
|
||||||
return this.jsonSerializerTagHistory.serialize(loanDelinquencyTagHistoryData);
|
return this.jsonSerializerTagHistory.serialize(loanDelinquencyTagHistoryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getResolvedLoanId(final Long loanId, final ExternalId loanExternalId) {
|
|
||||||
Long resolvedLoanId = loanId;
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
loanExternalId.throwExceptionIfEmpty();
|
|
||||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
throw new LoanNotFoundException(loanExternalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resolvedLoanId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getLoanDelinquencyActions(final Long loanId, final String loanExternalIdStr, final UriInfo uriInfo) {
|
private String getLoanDelinquencyActions(final Long loanId, final String loanExternalIdStr, final UriInfo uriInfo) {
|
||||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
final Collection<LoanDelinquencyAction> delinquencyActions = this.delinquencyReadPlatformService
|
final Collection<LoanDelinquencyAction> delinquencyActions = this.delinquencyReadPlatformService
|
||||||
.retrieveLoanDelinquencyActions(resolvedLoanId);
|
.retrieveLoanDelinquencyActions(resolvedLoanId);
|
||||||
@@ -1340,7 +1327,7 @@ public class LoansApiResource {
|
|||||||
|
|
||||||
private String createLoanDelinquencyAction(Long loanId, ExternalId loanExternalId, String apiRequestBodyAsJson) {
|
private String createLoanDelinquencyAction(Long loanId, ExternalId loanExternalId, String apiRequestBodyAsJson) {
|
||||||
context.authenticatedUser().validateHasCreatePermission(RESOURCE_NAME_FOR_DELINQUENCY_ACTION_PERMISSIONS);
|
context.authenticatedUser().validateHasCreatePermission(RESOURCE_NAME_FOR_DELINQUENCY_ACTION_PERMISSIONS);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
|
|
||||||
CommandWrapperBuilder builder = new CommandWrapperBuilder().createDelinquencyAction(resolvedLoanId);
|
CommandWrapperBuilder builder = new CommandWrapperBuilder().createDelinquencyAction(resolvedLoanId);
|
||||||
builder.withJson(apiRequestBodyAsJson);
|
builder.withJson(apiRequestBodyAsJson);
|
||||||
@@ -1349,7 +1336,7 @@ public class LoansApiResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CommandProcessingResult modifyLoanApprovedAmount(Long loanId, ExternalId loanExternalId, String apiRequestBodyAsJson) {
|
private CommandProcessingResult modifyLoanApprovedAmount(Long loanId, ExternalId loanExternalId, String apiRequestBodyAsJson) {
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
CommandWrapper commandRequest = builder.updateLoanApprovedAmount(resolvedLoanId).build();
|
CommandWrapper commandRequest = builder.updateLoanApprovedAmount(resolvedLoanId).build();
|
||||||
|
|
||||||
@@ -1358,7 +1345,7 @@ public class LoansApiResource {
|
|||||||
|
|
||||||
private List<LoanApprovedAmountHistoryData> getLoanApprovedAmountHistory(Long loanId, ExternalId loanExternalId) {
|
private List<LoanApprovedAmountHistoryData> getLoanApprovedAmountHistory(Long loanId, ExternalId loanExternalId) {
|
||||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||||
Pageable sortedByCreationDate = Pageable.unpaged(Sort.by("createdDate").ascending());
|
Pageable sortedByCreationDate = Pageable.unpaged(Sort.by("createdDate").ascending());
|
||||||
return loanApprovedAmountHistoryRepository.findAllByLoanId(resolvedLoanId, sortedByCreationDate);
|
return loanApprovedAmountHistoryRepository.findAllByLoanId(resolvedLoanId, sortedByCreationDate);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-11
@@ -30,7 +30,6 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
|||||||
import org.apache.fineract.portfolio.loanaccount.api.pointintime.data.RetrieveLoansPointInTimeExternalIdsRequest;
|
import org.apache.fineract.portfolio.loanaccount.api.pointintime.data.RetrieveLoansPointInTimeExternalIdsRequest;
|
||||||
import org.apache.fineract.portfolio.loanaccount.api.pointintime.data.RetrieveLoansPointInTimeRequest;
|
import org.apache.fineract.portfolio.loanaccount.api.pointintime.data.RetrieveLoansPointInTimeRequest;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanPointInTimeData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanPointInTimeData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanPointInTimeService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanPointInTimeService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -56,9 +55,9 @@ public class LoansPointInTimeApiDelegate implements LoansPointInTimeApi {
|
|||||||
String locale) {
|
String locale) {
|
||||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||||
Long loanId = resolveExternalId(loanExternalId);
|
Long resolvedLoanId = loanReadPlatformService.getResolvedLoanId(loanExternalId);
|
||||||
|
|
||||||
return getLoanPointInTime(loanId, dateParam, dateFormat, locale);
|
return getLoanPointInTime(resolvedLoanId, dateParam, dateFormat, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,12 +102,4 @@ public class LoansPointInTimeApiDelegate implements LoansPointInTimeApi {
|
|||||||
return loanReadPlatformService.retrieveLoanIdsByExternalIds(loanExternalIds);
|
return loanReadPlatformService.retrieveLoanIdsByExternalIds(loanExternalIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long resolveExternalId(ExternalId loanExternalId) {
|
|
||||||
loanExternalId.throwExceptionIfEmpty();
|
|
||||||
Long resolvedLoanId = loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
|
||||||
if (resolvedLoanId == null) {
|
|
||||||
throw new LoanNotFoundException(loanExternalId);
|
|
||||||
}
|
|
||||||
return resolvedLoanId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -2469,6 +2469,19 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
interestRefundAmount, paymentTypeOptions, loan.getCurrency().toData());
|
interestRefundAmount, paymentTypeOptions, loan.getCurrency().toData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getResolvedLoanId(final ExternalId loanExternalId) {
|
||||||
|
loanExternalId.throwExceptionIfEmpty();
|
||||||
|
|
||||||
|
final Long resolvedLoanId = retrieveLoanIdByExternalId(loanExternalId);
|
||||||
|
|
||||||
|
if (resolvedLoanId == null) {
|
||||||
|
throw new LoanNotFoundException(loanExternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvedLoanId;
|
||||||
|
}
|
||||||
|
|
||||||
private LoanTransaction deriveDefaultInterestWaiverTransaction(final Loan loan) {
|
private LoanTransaction deriveDefaultInterestWaiverTransaction(final Loan loan) {
|
||||||
final Money totalInterestOutstanding = loan.getTotalInterestOutstandingOnLoan();
|
final Money totalInterestOutstanding = loan.getTotalInterestOutstandingOnLoan();
|
||||||
Money possibleInterestToWaive = totalInterestOutstanding.copy();
|
Money possibleInterestToWaive = totalInterestOutstanding.copy();
|
||||||
|
|||||||
+9
@@ -105,6 +105,8 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanUpdateCommand
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.BulkLoansReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.BulkLoansReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.BulkLoansReadPlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.BulkLoansReadPlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeePlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeePlatformService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeReadPlatformService;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeReadPlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeWritePlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeWritePlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformServiceImpl;
|
||||||
@@ -403,6 +405,13 @@ public class LoanAccountConfiguration {
|
|||||||
businessEventNotifierService, loanTransactionRelationRepository);
|
businessEventNotifierService, loanTransactionRelationRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(BuyDownFeeReadPlatformService.class)
|
||||||
|
public BuyDownFeeReadPlatformService buyDownFeeReadPlatformService(
|
||||||
|
final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository, final LoanRepository loanRepository) {
|
||||||
|
return new BuyDownFeeReadPlatformServiceImpl(loanBuyDownFeeBalanceRepository, loanRepository);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanWritePlatformService.class)
|
@ConditionalOnMissingBean(LoanWritePlatformService.class)
|
||||||
public LoanWritePlatformService loanWritePlatformService(PlatformSecurityContext context,
|
public LoanWritePlatformService loanWritePlatformService(PlatformSecurityContext context,
|
||||||
|
|||||||
+53
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.integrationtests;
|
package org.apache.fineract.integrationtests;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@@ -31,6 +32,7 @@ import java.util.Optional;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.BuyDownFeeAmortizationDetails;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||||
import org.apache.fineract.client.models.PostClientsResponse;
|
import org.apache.fineract.client.models.PostClientsResponse;
|
||||||
@@ -576,6 +578,57 @@ public class LoanBuyDownFeeTest extends BaseLoanIntegrationTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRetrieveBuyDownFeeAmortizationDetails() {
|
||||||
|
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
|
||||||
|
final PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(createProgressiveLoanProductWithBuyDownFee());
|
||||||
|
|
||||||
|
final long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 February 2024", 1000.0,
|
||||||
|
7.0, 6, null);
|
||||||
|
|
||||||
|
disburseLoan(loanId, BigDecimal.valueOf(1000), "1 February 2024");
|
||||||
|
|
||||||
|
addBuyDownFeeForLoan(loanId, 100.0, "1 February 2024");
|
||||||
|
|
||||||
|
final List<BuyDownFeeAmortizationDetails> amortizationDetails = loanTransactionHelper.fetchBuyDownFeeAmortizationDetails(loanId);
|
||||||
|
|
||||||
|
assertNotNull(amortizationDetails);
|
||||||
|
assertFalse(amortizationDetails.isEmpty());
|
||||||
|
|
||||||
|
final BuyDownFeeAmortizationDetails amortizationDetail = amortizationDetails.getFirst();
|
||||||
|
assertNotNull(amortizationDetail);
|
||||||
|
assertNotNull(amortizationDetail.getId());
|
||||||
|
assertEquals(loanId, amortizationDetail.getLoanId());
|
||||||
|
assertNotNull(amortizationDetail.getTransactionId());
|
||||||
|
assertEquals(LocalDate.of(2024, 2, 1), amortizationDetail.getBuyDownFeeDate());
|
||||||
|
assertNotNull(amortizationDetail.getBuyDownFeeAmount());
|
||||||
|
assertEquals(0, BigDecimal.valueOf(100.0).compareTo(amortizationDetail.getBuyDownFeeAmount()));
|
||||||
|
assertNotNull(amortizationDetail.getAmortizedAmount());
|
||||||
|
assertEquals(0, amortizationDetail.getAmortizedAmount().signum());
|
||||||
|
assertNotNull(amortizationDetail.getNotYetAmortizedAmount());
|
||||||
|
assertEquals(0, BigDecimal.valueOf(100.0).compareTo(amortizationDetail.getNotYetAmortizedAmount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRetrieveBuyDownFeeAmortizationDetails_notEnabled() {
|
||||||
|
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
|
||||||
|
final PostLoanProductsResponse loanProduct = loanProductHelper
|
||||||
|
.createLoanProduct(createProgressiveLoanProductWithBuyDownFee().enableBuyDownFee(false));
|
||||||
|
|
||||||
|
final long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 February 2024", 1000.0,
|
||||||
|
7.0, 6, null);
|
||||||
|
|
||||||
|
disburseLoan(loanId, BigDecimal.valueOf(1000), "1 February 2024");
|
||||||
|
|
||||||
|
final CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> {
|
||||||
|
addBuyDownFeeForLoan(loanId, 100.0, "1 February 2024");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(400, exception.getResponse().code());
|
||||||
|
assertTrue(exception.getMessage().contains("buy.down.fee.not.enabled"));
|
||||||
|
assertTrue(exception.getMessage().contains("Buy down fee is not enabled for this loan product"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReverseBuyDownFeeTransaction() {
|
public void testReverseBuyDownFeeTransaction() {
|
||||||
final AtomicReference<Long> buyDownFeeTransactionIdIdRef = new AtomicReference<>();
|
final AtomicReference<Long> buyDownFeeTransactionIdIdRef = new AtomicReference<>();
|
||||||
|
|||||||
+5
@@ -45,6 +45,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fineract.client.models.AdvancedPaymentData;
|
import org.apache.fineract.client.models.AdvancedPaymentData;
|
||||||
|
import org.apache.fineract.client.models.BuyDownFeeAmortizationDetails;
|
||||||
import org.apache.fineract.client.models.CommandProcessingResult;
|
import org.apache.fineract.client.models.CommandProcessingResult;
|
||||||
import org.apache.fineract.client.models.DeleteLoansLoanIdChargesChargeIdResponse;
|
import org.apache.fineract.client.models.DeleteLoansLoanIdChargesChargeIdResponse;
|
||||||
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
|
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
|
||||||
@@ -3177,4 +3178,8 @@ public class LoanTransactionHelper {
|
|||||||
.build(clientID.toString(), loanProductID.toString(), savingsId);
|
.build(clientID.toString(), loanProductID.toString(), savingsId);
|
||||||
return getLoanId(loanApplicationJSON);
|
return getLoanId(loanApplicationJSON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BuyDownFeeAmortizationDetails> fetchBuyDownFeeAmortizationDetails(Long loanId) {
|
||||||
|
return Calls.ok(FineractClientHelper.getFineractClient().loanBuyDownFeesApi.retrieveLoanBuyDownFeeAmortizationDetails(loanId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user