FINERACT-2348: Calculate and store Capitalized income / Buydown fee amortization allocation schedule
This commit is contained in:
committed by
Adam Saghy
parent
9790f59e4a
commit
cd0ecfcda0
+108
@@ -31,14 +31,24 @@ 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.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.BuyDownFeeAmortizationDetails;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAmortizationAllocationData;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.BuyDownFeeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAmortizationAllocationService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -48,9 +58,15 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class LoanBuyDownFeeApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList("loanId", "loanExternalId", "baseLoanTransactionId", "baseLoanTransactionDate", "baseLoanTransactionAmount",
|
||||
"unrecognizedAmount", "chargedOffAmount", "adjustmentAmount", "amortizationMappings"));
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "LOAN";
|
||||
private final PlatformSecurityContext context;
|
||||
private final BuyDownFeeReadPlatformService buyDownFeeReadPlatformService;
|
||||
private final LoanAmortizationAllocationService loanAmortizationAllocationService;
|
||||
private final DefaultToApiJsonSerializer<LoanAmortizationAllocationData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final LoanReadPlatformService loanReadPlatformService;
|
||||
|
||||
@Path("/{loanId}/buydown-fees")
|
||||
@@ -84,4 +100,96 @@ public class LoanBuyDownFeeApiResource {
|
||||
return this.buyDownFeeReadPlatformService.retrieveLoanBuyDownFeeAmortizationDetails(resolvedLoanId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BuyDown Fees allocation data by loan ID and transaction ID
|
||||
*/
|
||||
@GET
|
||||
@Path("{loanId}/buydown-fees/{loanTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a BuyDown Fees allocation data", description = "Retrieves BuyDown Fees allocation data according to the Loan ID and Loan Transaction ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/1/buydown-fees/1\n" + "\n" + "\n"
|
||||
+ "/loans/1/buydown-fees/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String retrieveBuyDownFeesAllocationData(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("loanTransactionId") @Parameter(description = "loanTransactionId") final Long loanTransactionId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveBuyDownFeesAllocationData(loanId, null, loanTransactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BuyDown Fees allocation data by loan external ID and transaction ID
|
||||
*/
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/buydown-fees/{loanTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a BuyDown Fees allocation data", description = "Retrieves BuyDown Fees allocation data according to the Loan external ID and Loan Transaction ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/external-id/1/buydown-fees/1\n" + "\n" + "\n"
|
||||
+ "/loans/external-id/1/buydown-fees/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getBuyDownFeesAllocationDataByLoanExternalId(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId") final String loanExternalId,
|
||||
@PathParam("loanTransactionId") @Parameter(description = "loanTransactionId") final Long loanTransactionId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveBuyDownFeesAllocationData(null, loanExternalId, loanTransactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BuyDown Fees allocation data by loan ID and transaction external ID
|
||||
*/
|
||||
@GET
|
||||
@Path("{loanId}/buydown-fees/external-id/{loanTransactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a BuyDown Fees allocation data", description = "Retrieves BuyDown Fees allocation data according to the Loan ID and Loan Transaction external ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/1/buydown-fees/external-id/1\n" + "\n" + "\n"
|
||||
+ "/loans/1/buydown-fees/external-id/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getBuyDownFeesAllocationDataByTransactionExternalId(
|
||||
@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("loanTransactionExternalId") @Parameter(description = "loanTransactionExternalId") final String loanTransactionExternalId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveBuyDownFeesAllocationData(loanId, null, null, loanTransactionExternalId, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BuyDown Fees allocation data by loan external ID and transaction external ID
|
||||
*/
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/buydown-fees/external-id/{loanTransactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a BuyDown Fees allocation data", description = "Retrieves BuyDown Fees allocation data according to the Loan external ID and Loan Transaction external ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/external-id/1/buydown-fees/1\n" + "\n" + "\n"
|
||||
+ "/loans/external-id/1/buydown-fees/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getBuyDownFeesAllocationDataByExternalIds(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId") final String loanExternalId,
|
||||
@PathParam("loanTransactionExternalId") @Parameter(description = "loanTransactionExternalId") final String loanTransactionExternalId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveBuyDownFeesAllocationData(null, loanExternalId, null, loanTransactionExternalId, uriInfo);
|
||||
}
|
||||
|
||||
private String retrieveBuyDownFeesAllocationData(final Long loanId, final String loanExternalIdStr, final Long loanTransactionId,
|
||||
final String loanTransactionExternalIdStr, final UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
final ExternalId loanTransactionExternalId = ExternalIdFactory.produce(loanTransactionExternalIdStr);
|
||||
|
||||
final Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||
final Long resolvedLoanTransactionId = loanReadPlatformService.getResolvedLoanTransactionId(loanTransactionId,
|
||||
loanTransactionExternalId);
|
||||
|
||||
final LoanAmortizationAllocationData loanAmortizationAllocationData = loanAmortizationAllocationService
|
||||
.retrieveLoanAmortizationAllocationsForBuyDownFeeTransaction(resolvedLoanTransactionId, resolvedLoanId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return toApiJsonSerializer.serialize(settings, loanAmortizationAllocationData, RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
}
|
||||
|
||||
+108
@@ -30,15 +30,25 @@ 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.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.CapitalizedIncomeDetails;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAmortizationAllocationData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanCapitalizedIncomeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.CapitalizedIncomeBalanceReadService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAmortizationAllocationService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -48,9 +58,15 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class LoanCapitalizedIncomeApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList("loanId", "loanExternalId", "baseLoanTransactionId", "baseLoanTransactionDate", "baseLoanTransactionAmount",
|
||||
"unrecognizedAmount", "chargedOffAmount", "adjustmentAmount", "amortizationMappings"));
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "LOAN";
|
||||
private final PlatformSecurityContext context;
|
||||
private final CapitalizedIncomeBalanceReadService capitalizedIncomeBalanceReadService;
|
||||
private final LoanAmortizationAllocationService loanAmortizationAllocationService;
|
||||
private final DefaultToApiJsonSerializer<LoanAmortizationAllocationData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final LoanReadPlatformService loanReadPlatformService;
|
||||
|
||||
@Path("/{loanId}/deferredincome")
|
||||
@@ -109,4 +125,96 @@ public class LoanCapitalizedIncomeApiResource {
|
||||
return this.capitalizedIncomeBalanceReadService.fetchLoanCapitalizedIncomeDetails(resolvedLoanId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get capitalized income allocation data by loan ID and transaction ID
|
||||
*/
|
||||
@GET
|
||||
@Path("{loanId}/capitalized-incomes/{loanTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a capitalized income allocation data", description = "Retrieves capitalized income allocation data according to the Loan ID and Loan Transaction ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/1/capitalized-incomes/1\n" + "\n" + "\n"
|
||||
+ "/loans/1/capitalized-incomes/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String retrieveCapitalizedIncomeAllocationData(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("loanTransactionId") @Parameter(description = "loanTransactionId") final Long loanTransactionId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveCapitalizedIncomeAllocationData(loanId, null, loanTransactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get capitalized income allocation data by loan external ID and transaction ID
|
||||
*/
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/capitalized-incomes/{loanTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a capitalized income allocation data", description = "Retrieves capitalized income allocation data according to the Loan external ID and Loan Transaction ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/external-id/1/capitalized-incomes/1\n" + "\n" + "\n"
|
||||
+ "/loans/external-id/1/capitalized-incomes/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getCapitalizedIncomeAllocationDataByLoanExternalId(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId") final String loanExternalId,
|
||||
@PathParam("loanTransactionId") @Parameter(description = "loanTransactionId") final Long loanTransactionId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveCapitalizedIncomeAllocationData(null, loanExternalId, loanTransactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get capitalized income allocation data by loan ID and transaction external ID
|
||||
*/
|
||||
@GET
|
||||
@Path("{loanId}/capitalized-incomes/external-id/{loanTransactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a capitalized income allocation data", description = "Retrieves capitalized income allocation data according to the Loan ID and Loan Transaction external ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/1/capitalized-incomes/external-id/1\n" + "\n" + "\n"
|
||||
+ "/loans/1/capitalized-incomes/external-id/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getCapitalizedIncomeAllocationDataByTransactionExternalId(
|
||||
@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("loanTransactionExternalId") @Parameter(description = "loanTransactionExternalId") final String loanTransactionExternalId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveCapitalizedIncomeAllocationData(loanId, null, null, loanTransactionExternalId, uriInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get capitalized income allocation data by loan external ID and transaction external ID
|
||||
*/
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/capitalized-incomes/external-id/{loanTransactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a capitalized income allocation data", description = "Retrieves capitalized income allocation data according to the Loan external ID and Loan Transaction external ID"
|
||||
+ "Example Requests:\n" + "\n" + "/loans/external-id/1/capitalized-incomes/1\n" + "\n" + "\n"
|
||||
+ "/loans/external-id/1/capitalized-incomes/1?fields=baseLoanTransaction,unrecognizedAmount")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanAmortizationAllocationApiResourceSwagger.LoanAmortizationAllocationResponse.class))) })
|
||||
public String getCapitalizedIncomeAllocationDataByExternalIds(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId") final String loanExternalId,
|
||||
@PathParam("loanTransactionExternalId") @Parameter(description = "loanTransactionExternalId") final String loanTransactionExternalId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveCapitalizedIncomeAllocationData(null, loanExternalId, null, loanTransactionExternalId, uriInfo);
|
||||
}
|
||||
|
||||
private String retrieveCapitalizedIncomeAllocationData(final Long loanId, final String loanExternalIdStr, final Long loanTransactionId,
|
||||
final String loanTransactionExternalIdStr, final UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
final ExternalId loanTransactionExternalId = ExternalIdFactory.produce(loanTransactionExternalIdStr);
|
||||
|
||||
final Long resolvedLoanId = loanId == null ? loanReadPlatformService.getResolvedLoanId(loanExternalId) : loanId;
|
||||
final Long resolvedLoanTransactionId = loanReadPlatformService.getResolvedLoanTransactionId(loanTransactionId,
|
||||
loanTransactionExternalId);
|
||||
|
||||
final LoanAmortizationAllocationData loanAmortizationAllocationData = loanAmortizationAllocationService
|
||||
.retrieveLoanAmortizationAllocationsForCapitalizedIncomeTransaction(resolvedLoanTransactionId, resolvedLoanId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return toApiJsonSerializer.serialize(settings, loanAmortizationAllocationData, RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -62,4 +62,9 @@ public class LoanBuyDownFeeBalance extends AbstractAuditableWithUTCDateTimeCusto
|
||||
@Column(name = "amount_adjustment", scale = 6, precision = 19)
|
||||
private BigDecimal amountAdjustment;
|
||||
|
||||
@Column(name = "is_deleted", nullable = false)
|
||||
private boolean deleted = false;
|
||||
|
||||
@Column(name = "is_closed", nullable = false)
|
||||
private boolean closed = false;
|
||||
}
|
||||
|
||||
+6
@@ -61,4 +61,10 @@ public class LoanCapitalizedIncomeBalance extends AbstractAuditableWithUTCDateTi
|
||||
|
||||
@Column(name = "amount_adjustment", scale = 6, precision = 19)
|
||||
private BigDecimal amountAdjustment;
|
||||
|
||||
@Column(name = "is_deleted", nullable = false)
|
||||
private boolean deleted = false;
|
||||
|
||||
@Column(name = "is_closed", nullable = false)
|
||||
private boolean closed = false;
|
||||
}
|
||||
|
||||
+20
-4
@@ -19,18 +19,34 @@
|
||||
package org.apache.fineract.portfolio.loanaccount.repository;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AmortizationAllocationBaseTransactionDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface LoanBuyDownFeeBalanceRepository
|
||||
extends JpaRepository<LoanBuyDownFeeBalance, Long>, JpaSpecificationExecutor<LoanBuyDownFeeBalance> {
|
||||
|
||||
List<LoanBuyDownFeeBalance> findAllByLoanId(Long loanId);
|
||||
@Query("SELECT lbdfb FROM LoanBuyDownFeeBalance lbdfb WHERE lbdfb.loan.id=:loanId AND lbdfb.closed = FALSE ORDER BY lbdfb.date, lbdfb.createdDate")
|
||||
List<LoanBuyDownFeeBalance> findAllByLoanIdAndClosedFalse(@Param("loanId") Long loanId);
|
||||
|
||||
LoanBuyDownFeeBalance findByLoanIdAndLoanTransactionId(Long loanId, Long transactionId);
|
||||
@Query("SELECT lbdfb FROM LoanBuyDownFeeBalance lbdfb WHERE lbdfb.loan.id=:loanId AND lbdfb.closed = FALSE AND lbdfb.deleted = FALSE ORDER BY lbdfb.date, lbdfb.createdDate")
|
||||
List<LoanBuyDownFeeBalance> findAllByLoanIdAndDeletedFalseAndClosedFalse(@Param("loanId") Long loanId);
|
||||
|
||||
@Query("SELECT lbdfb FROM LoanBuyDownFeeBalance lbdfb, LoanTransaction lt, LoanTransactionRelation ltr WHERE lt.loan.id = lbdfb.loan.id AND ltr.fromTransaction.id =:transactionId AND ltr.toTransaction.id=lt.id AND lbdfb.loanTransaction.id = lt.id")
|
||||
LoanBuyDownFeeBalance findBalanceForAdjustment(Long transactionId);
|
||||
LoanBuyDownFeeBalance findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(Long loanId, Long transactionId);
|
||||
|
||||
@Query("SELECT lbdfb FROM LoanBuyDownFeeBalance lbdfb, LoanTransaction lt, LoanTransactionRelation ltr WHERE lt.loan.id = lbdfb.loan.id AND ltr.fromTransaction.id =:transactionId AND ltr.toTransaction.id=lt.id AND lbdfb.loanTransaction.id = lt.id AND lbdfb.deleted = false AND lbdfb.closed = false")
|
||||
LoanBuyDownFeeBalance findBalanceForAdjustment(@Param("transactionId") Long transactionId);
|
||||
|
||||
@Query("""
|
||||
SELECT new org.apache.fineract.portfolio.loanaccount.data.AmortizationAllocationBaseTransactionDTO(
|
||||
l.id, l.externalId, lbdfb.loanTransaction.id, lbdfb.date, lbdfb.amount,
|
||||
lbdfb.unrecognizedAmount, lbdfb.chargedOffAmount, lbdfb.amountAdjustment
|
||||
) FROM LoanBuyDownFeeBalance lbdfb JOIN lbdfb.loan l JOIN lbdfb.loanTransaction bt
|
||||
WHERE lbdfb.loanTransaction.id = :loanTransactionId AND l.id = :loanId
|
||||
""")
|
||||
AmortizationAllocationBaseTransactionDTO findBaseTransactionInfo(@Param("loanTransactionId") Long loanTransactionId,
|
||||
@Param("loanId") Long loanId);
|
||||
}
|
||||
|
||||
+23
-6
@@ -20,30 +20,47 @@ package org.apache.fineract.portfolio.loanaccount.repository;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AmortizationAllocationBaseTransactionDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeBalance;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepaymentPeriodData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface LoanCapitalizedIncomeBalanceRepository extends JpaRepository<LoanCapitalizedIncomeBalance, Long>,
|
||||
JpaSpecificationExecutor<LoanCapitalizedIncomeBalance>, CustomizedLoanCapitalizedIncomeBalanceRepository {
|
||||
|
||||
String FIND_BALANCE_REPAYMENT_SCHEDULE_DATA = "SELECT new org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepaymentPeriodData(lcib.loanTransaction.id, lcib.loan.id, lcib.loanTransaction.dateOf, lcib.loanTransaction.reversed, lcib.amount, lcib.unrecognizedAmount, lcib.loanTransaction.feeChargesPortion) FROM LoanCapitalizedIncomeBalance lcib ";
|
||||
|
||||
List<LoanCapitalizedIncomeBalance> findAllByLoanId(Long loanId);
|
||||
@Query("SELECT lcib FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id=:loanId AND lcib.closed = FALSE ORDER BY lcib.date, lcib.createdDate")
|
||||
List<LoanCapitalizedIncomeBalance> findAllByLoanIdAndClosedFalse(@Param("loanId") Long loanId);
|
||||
|
||||
LoanCapitalizedIncomeBalance findByLoanIdAndLoanTransactionId(Long loanId, Long transactionId);
|
||||
@Query("SELECT lcib FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id=:loanId AND lcib.closed = FALSE AND lcib.deleted = FALSE ORDER BY lcib.date, lcib.createdDate")
|
||||
List<LoanCapitalizedIncomeBalance> findAllByLoanIdAndDeletedFalseAndClosedFalse(@Param("loanId") Long loanId);
|
||||
|
||||
@Query(FIND_BALANCE_REPAYMENT_SCHEDULE_DATA + " WHERE lcib.loan.id = :loanId")
|
||||
LoanCapitalizedIncomeBalance findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(Long loanId, Long transactionId);
|
||||
|
||||
@Query(FIND_BALANCE_REPAYMENT_SCHEDULE_DATA
|
||||
+ " WHERE lcib.loan.id = :loanId AND lcib.deleted = false AND lcib.closed = false ORDER BY lcib.date, lcib.createdDate")
|
||||
List<LoanTransactionRepaymentPeriodData> findRepaymentPeriodDataByLoanId(Long loanId);
|
||||
|
||||
@Query("SELECT SUM(lcib.amount) FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id = :loanId")
|
||||
@Query("SELECT SUM(lcib.amount) FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id = :loanId AND lcib.deleted = false AND lcib.closed = false")
|
||||
BigDecimal calculateCapitalizedIncome(Long loanId);
|
||||
|
||||
@Query("SELECT SUM(lcib.amountAdjustment) FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id = :loanId")
|
||||
@Query("SELECT SUM(lcib.amountAdjustment) FROM LoanCapitalizedIncomeBalance lcib WHERE lcib.loan.id = :loanId AND lcib.deleted = false AND lcib.closed = false")
|
||||
BigDecimal calculateCapitalizedIncomeAdjustment(Long loanId);
|
||||
|
||||
@Query("SELECT lcib FROM LoanCapitalizedIncomeBalance lcib, LoanTransaction lt, LoanTransactionRelation ltr WHERE lt.loan.id = lcib.loan.id AND ltr.fromTransaction.id =:transactionId AND ltr.toTransaction.id=lt.id AND lcib.loanTransaction.id = lt.id")
|
||||
@Query("SELECT lcib FROM LoanCapitalizedIncomeBalance lcib, LoanTransaction lt, LoanTransactionRelation ltr WHERE lt.loan.id = lcib.loan.id AND ltr.fromTransaction.id =:transactionId AND ltr.toTransaction.id=lt.id AND lcib.loanTransaction.id = lt.id AND lcib.deleted = false AND lcib.closed = false")
|
||||
LoanCapitalizedIncomeBalance findBalanceForAdjustment(Long transactionId);
|
||||
|
||||
@Query("""
|
||||
SELECT new org.apache.fineract.portfolio.loanaccount.data.AmortizationAllocationBaseTransactionDTO(
|
||||
l.id, l.externalId, lcib.loanTransaction.id, lcib.date, lcib.amount,
|
||||
lcib.unrecognizedAmount, lcib.chargedOffAmount, lcib.amountAdjustment
|
||||
) FROM LoanCapitalizedIncomeBalance lcib JOIN lcib.loan l JOIN lcib.loanTransaction bt
|
||||
WHERE lcib.loanTransaction.id = :loanTransactionId AND l.id = :loanId
|
||||
""")
|
||||
AmortizationAllocationBaseTransactionDTO findBaseTransactionInfo(@Param("loanTransactionId") Long loanTransactionId,
|
||||
@Param("loanId") Long loanId);
|
||||
}
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@ public class BuyDownFeeReadPlatformServiceImpl implements BuyDownFeeReadPlatform
|
||||
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);
|
||||
final List<LoanBuyDownFeeBalance> buyDownFeeBalances = loanBuyDownFeeBalanceRepository
|
||||
.findAllByLoanIdAndDeletedFalseAndClosedFalse(loanId);
|
||||
|
||||
return buyDownFeeBalances.stream().map(this::mapToLoanBuyDownFeeAmortizationData).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
+2
-2
@@ -165,8 +165,8 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
LoanTransaction savedBuyDownFeeAdjustment = loanTransactionRepository.saveAndFlush(buyDownFeeAdjustment);
|
||||
|
||||
// Update buy down fee balance
|
||||
LoanBuyDownFeeBalance buydownFeeBalance = loanBuyDownFeeBalanceRepository.findByLoanIdAndLoanTransactionId(loanId,
|
||||
buyDownFeeTransactionId);
|
||||
LoanBuyDownFeeBalance buydownFeeBalance = loanBuyDownFeeBalanceRepository
|
||||
.findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(loanId, buyDownFeeTransactionId);
|
||||
if (buydownFeeBalance != null) {
|
||||
buydownFeeBalance.setAmountAdjustment(MathUtil.nullToZero(buydownFeeBalance.getAmountAdjustment()).add(transactionAmount));
|
||||
buydownFeeBalance
|
||||
|
||||
+4
-2
@@ -43,7 +43,8 @@ public class CapitalizedIncomeBalanceReadServiceImpl implements CapitalizedIncom
|
||||
if (loanRepository.isEnabledCapitalizedIncome(loanId)) {
|
||||
|
||||
List<CapitalizedIncomeDetails> capitalizedIncomeData = new ArrayList<>();
|
||||
List<LoanCapitalizedIncomeBalance> capitalizedIncomeBalances = capitalizedIncomeBalanceRepository.findAllByLoanId(loanId);
|
||||
List<LoanCapitalizedIncomeBalance> capitalizedIncomeBalances = capitalizedIncomeBalanceRepository
|
||||
.findAllByLoanIdAndDeletedFalseAndClosedFalse(loanId);
|
||||
for (final LoanCapitalizedIncomeBalance capitalizedIncomeBalance : capitalizedIncomeBalances) {
|
||||
final BigDecimal amortizedAmount = capitalizedIncomeBalance.getAmount() //
|
||||
.subtract(MathUtil.nullToZero(capitalizedIncomeBalance.getUnrecognizedAmount())) //
|
||||
@@ -67,7 +68,8 @@ public class CapitalizedIncomeBalanceReadServiceImpl implements CapitalizedIncom
|
||||
if (loanRepository.isEnabledCapitalizedIncome(loanId)) {
|
||||
|
||||
List<CapitalizedIncomeDetails> capitalizedIncomeData = new ArrayList<>();
|
||||
List<LoanCapitalizedIncomeBalance> capitalizedIncomeBalances = capitalizedIncomeBalanceRepository.findAllByLoanId(loanId);
|
||||
List<LoanCapitalizedIncomeBalance> capitalizedIncomeBalances = capitalizedIncomeBalanceRepository
|
||||
.findAllByLoanIdAndDeletedFalseAndClosedFalse(loanId);
|
||||
for (final LoanCapitalizedIncomeBalance capitalizedIncomeBalance : capitalizedIncomeBalances) {
|
||||
final BigDecimal amortizedAmount = capitalizedIncomeBalance.getAmount() //
|
||||
.subtract(MathUtil.nullToZero(capitalizedIncomeBalance.getUnrecognizedAmount())) //
|
||||
|
||||
+2
-2
@@ -159,8 +159,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedCapitalizedIncomeAdjustment, false, false);
|
||||
|
||||
LoanCapitalizedIncomeBalance capitalizedIncomeBalance = capitalizedIncomeBalanceRepository.findByLoanIdAndLoanTransactionId(loanId,
|
||||
capitalizedIncomeTransactionId);
|
||||
LoanCapitalizedIncomeBalance capitalizedIncomeBalance = capitalizedIncomeBalanceRepository
|
||||
.findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(loanId, capitalizedIncomeTransactionId);
|
||||
capitalizedIncomeBalance
|
||||
.setAmountAdjustment(MathUtil.nullToZero(capitalizedIncomeBalance.getAmountAdjustment()).add(transactionAmount));
|
||||
capitalizedIncomeBalance.setUnrecognizedAmount(
|
||||
|
||||
+3
-3
@@ -224,7 +224,7 @@ public class ProgressiveLoanTransactionValidatorImpl implements ProgressiveLoanT
|
||||
}
|
||||
if (transactionAmount != null) {
|
||||
LoanCapitalizedIncomeBalance capitalizedIncomeBalance = loanCapitalizedIncomeBalanceRepository
|
||||
.findByLoanIdAndLoanTransactionId(loanId, capitalizedIncomeTransactionId);
|
||||
.findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(loanId, capitalizedIncomeTransactionId);
|
||||
if (MathUtil.isLessThan(capitalizedIncomeBalance.getAmount()
|
||||
.subtract(MathUtil.nullToZero(capitalizedIncomeBalance.getAmountAdjustment())), transactionAmount)) {
|
||||
baseDataValidator.reset().parameter("transactionAmount").value(transactionAmount).failWithCode(
|
||||
@@ -401,8 +401,8 @@ public class ProgressiveLoanTransactionValidatorImpl implements ProgressiveLoanT
|
||||
|
||||
}
|
||||
if (transactionAmount != null) {
|
||||
LoanBuyDownFeeBalance buydownFeeBalance = loanBuydownFeeBalanceRepository.findByLoanIdAndLoanTransactionId(loanId,
|
||||
buyDownFeeTransactionId);
|
||||
LoanBuyDownFeeBalance buydownFeeBalance = loanBuydownFeeBalanceRepository
|
||||
.findByLoanIdAndLoanTransactionIdAndDeletedFalseAndClosedFalse(loanId, buyDownFeeTransactionId);
|
||||
if (buydownFeeBalance == null) {
|
||||
baseDataValidator.reset().parameter("buyDownFeeTransactionId").failWithCode("buydown.fee.balance.not.found",
|
||||
"Buy down fee balance not found for the specified transaction.");
|
||||
|
||||
+1
@@ -123,6 +123,7 @@
|
||||
<class>org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement</class>
|
||||
<class>org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain</class>
|
||||
<class>org.apache.fineract.portfolio.collateral.domain.LoanCollateral</class>
|
||||
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanAmortizationAllocationMapping</class>
|
||||
|
||||
<!-- Loan Module Converters -->
|
||||
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationTypeListConverter</class>
|
||||
|
||||
Reference in New Issue
Block a user