Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ public enum LoanTransactionType {
CAPITALIZED_INCOME(35, "loanTransactionType.capitalizedIncome"), //
CAPITALIZED_INCOME_AMORTIZATION(36, "loanTransactionType.capitalizedIncomeAmortization"), //
CAPITALIZED_INCOME_ADJUSTMENT(37, "loanTransactionType.capitalizedIncomeAdjustment"), //
CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT(39, "loanTransactionType.capitalizedIncomeAmortizationAdjustment"), //
// Kind of Final Transactions
CONTRACT_TERMINATION(38, "loanTransactionType.contractTermination"), //

CAPITALIZED_INCOME_AMORTIZATION_ADJUSTMENT(39, "loanTransactionType.capitalizedIncomeAmortizationAdjustment"), //
BUY_DOWN_FEE(40, "loanTransactionType.buyDownFee"), //
BUY_DOWN_FEE_ADJUSTMENT(41, "loanTransactionType.buyDownFeeAdjustment"), //
BUY_DOWN_FEE_AMORTIZATION(42, "loanTransactionType.buyDownFeeAmortization"), //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ public class LoanBuyDownFeeBalance extends AbstractAuditableWithUTCDateTimeCusto

@Column(name = "amount_adjustment", scale = 6, precision = 19)
private BigDecimal amountAdjustment;

}
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,8 @@ private String retrieveTransactionTemplate(Long loanId, String loanExternalIdStr
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId,
LoanTransactionType.CAPITALIZED_INCOME_ADJUSTMENT, transactionId);
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.BUY_DOWN_FEE_COMMAND)) {
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId);
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId, LoanTransactionType.BUY_DOWN_FEE,
transactionId);
} else if (CommandParameterUtil.is(commandParam, LoanApiConstants.BUY_DOWN_FEE_ADJUSTMENT_COMMAND)) {
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId,
LoanTransactionType.BUY_DOWN_FEE_ADJUSTMENT, transactionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.apache.fineract.portfolio.loanaccount.domain.LoanBuyDownFeeBalance;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.loanaccount.repository.LoanBuyDownFeesBalanceRepository;
import org.apache.fineract.portfolio.loanaccount.repository.LoanBuyDownFeeBalanceRepository;
import org.apache.fineract.portfolio.loanaccount.util.BuyDownFeeAmortizationUtil;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
Expand All @@ -44,7 +44,7 @@
public class LoanBuyDownFeeAmortizationProcessingServiceImpl implements LoanBuyDownFeeAmortizationProcessingService {

private final LoanTransactionRepository loanTransactionRepository;
private final LoanBuyDownFeesBalanceRepository loanBuyDownFeesBalanceRepository;
private final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository;
private final BusinessEventNotifierService businessEventNotifierService;
private final LoanJournalEntryPoster journalEntryPoster;
private final ExternalIdFactory externalIdFactory;
Expand All @@ -55,7 +55,7 @@ public void processBuyDownFeeAmortizationTillDate(@NonNull Loan loan, @NonNull L
final List<Long> existingTransactionIds = loanTransactionRepository.findTransactionIdsByLoan(loan);
final List<Long> existingReversedTransactionIds = loanTransactionRepository.findReversedTransactionIdsByLoan(loan);

List<LoanBuyDownFeeBalance> balances = loanBuyDownFeesBalanceRepository.findAllByLoanId(loan.getId());
List<LoanBuyDownFeeBalance> balances = loanBuyDownFeeBalanceRepository.findAllByLoanId(loan.getId());

LocalDate maturityDate = loan.getMaturityDate() != null ? loan.getMaturityDate()
: getFinalBuyDownFeeAmortizationTransactionDate(loan);
Expand All @@ -75,7 +75,7 @@ public void processBuyDownFeeAmortizationTillDate(@NonNull Loan loan, @NonNull L
.subtract(amortizationTillDate.getAmount()));
}

loanBuyDownFeesBalanceRepository.saveAll(balances);
loanBuyDownFeeBalanceRepository.saveAll(balances);

BigDecimal totalAmortized = loanTransactionRepository.getAmortizedAmountBuyDownFee(loan);
BigDecimal totalAmortizationAmount = totalAmortization.getAmount().subtract(totalAmortized);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,16 +484,41 @@ public LoanTransactionData retrieveLoanTransactionTemplate(final Long loanId, fi
switch (transactionType) {
case CAPITALIZED_INCOME:
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
BigDecimal capitalizedIncomeBalance = BigDecimal.ZERO;
BigDecimal buyDownFeeBalance = BigDecimal.ZERO;
if (loan.getLoanProduct().getLoanProductRelatedDetail().isEnableIncomeCapitalization()) {
final BigDecimal capitalizedIncomeBalance = loanCapitalizedIncomeBalanceRepository.findAllByLoanId(loanId).stream()
capitalizedIncomeBalance = loanCapitalizedIncomeBalanceRepository.findAllByLoanId(loanId).stream()
.map(LoanCapitalizedIncomeBalance::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
transactionAmount = loan.getApprovedPrincipal().subtract(loan.getDisbursedAmount()).subtract(capitalizedIncomeBalance);
}
// Calculate Buy Down Fee balance to subtract from Capitalized Income formula
buyDownFeeBalance = loanBuyDownFeeBalanceRepository.findAllByLoanId(loanId).stream().map(LoanBuyDownFeeBalance::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
transactionAmount = loan.getApprovedPrincipal().subtract(loan.getDisbursedAmount()).subtract(capitalizedIncomeBalance)
.subtract(buyDownFeeBalance);
paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
loanTransactionData = LoanTransactionData.loanTransactionDataForCreditTemplate(
LoanEnumerations.transactionType(transactionType), DateUtils.getBusinessLocalDate(), transactionAmount,
paymentOptions, retriveLoanCurrencyData(loanId));
break;
case BUY_DOWN_FEE:
final Loan buyDownLoan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
BigDecimal buyDownFeeBalanceForCalc = BigDecimal.ZERO;
BigDecimal capitalizedIncomeBalanceForCalc = BigDecimal.ZERO;

// Calculate existing Buy Down Fee balance
buyDownFeeBalanceForCalc = loanBuyDownFeeBalanceRepository.findAllByLoanId(loanId).stream()
.map(LoanBuyDownFeeBalance::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
// Calculate Capitalized Income balance to subtract from Buy Down Fee formula
if (buyDownLoan.getLoanProduct().getLoanProductRelatedDetail().isEnableIncomeCapitalization()) {
capitalizedIncomeBalanceForCalc = loanCapitalizedIncomeBalanceRepository.findAllByLoanId(loanId).stream()
.map(LoanCapitalizedIncomeBalance::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
}
transactionAmount = buyDownLoan.getApprovedPrincipal().subtract(buyDownLoan.getDisbursedAmount())
.subtract(buyDownFeeBalanceForCalc).subtract(capitalizedIncomeBalanceForCalc);
paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
loanTransactionData = LoanTransactionData.loanTransactionDataForCreditTemplate(
LoanEnumerations.transactionType(transactionType), DateUtils.getBusinessLocalDate(), transactionAmount,
paymentOptions, retriveLoanCurrencyData(loanId));

break;
case CAPITALIZED_INCOME_ADJUSTMENT:
final LoanCapitalizedIncomeBalance loanCapitalizedIncomeBalance = loanCapitalizedIncomeBalanceRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,10 @@ public LoanCapitalizedIncomeAmortizationProcessingService loanCapitalizedIncomeA
@ConditionalOnMissingBean(LoanBuyDownFeeAmortizationProcessingService.class)
public LoanBuyDownFeeAmortizationProcessingService loanBuyDownFeeAmortizationProcessingService(
final LoanTransactionRepository loanTransactionRepository,
final LoanBuyDownFeesBalanceRepository loanBuyDownFeesBalanceRepository,
final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository,
final BusinessEventNotifierService businessEventNotifierService, final LoanJournalEntryPoster journalEntryPoster,
final ExternalIdFactory externalIdFactory) {
return new LoanBuyDownFeeAmortizationProcessingServiceImpl(loanTransactionRepository, loanBuyDownFeesBalanceRepository,
return new LoanBuyDownFeeAmortizationProcessingServiceImpl(loanTransactionRepository, loanBuyDownFeeBalanceRepository,
businessEventNotifierService, journalEntryPoster, externalIdFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,33 @@ public void testGetLoanTransactionTemplateForBuyDownFeeAdjustment() {
});
}

@Test
public void testGetLoanTransactionTemplateForBuyDownFee() {
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());

final PostLoanProductsResponse loanProductsResponse = loanProductHelper
.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
.incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
.capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE));

final String loanExternalIdStr = UUID.randomUUID().toString();

runAt("20 December 2024", () -> {
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductsResponse.getResourceId(), "20 December 2024",
430.0, 7.0, 6, (request) -> request.externalId(loanExternalIdStr));

disburseLoan(loanId, BigDecimal.valueOf(230), "20 December 2024");

final GetLoansLoanIdTransactionsTemplateResponse transactionTemplate = loanTransactionHelper.retrieveTransactionTemplate(loanId,
buyDownFeeCommand, null, null, null);

assertNotNull(transactionTemplate);
assertEquals("loanTransactionType." + buyDownFeeCommand, transactionTemplate.getType().getCode());
assertEquals(transactionTemplate.getAmount(), 200);
assertThat(transactionTemplate.getPaymentTypeOptions().size() > 0);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -636,15 +636,15 @@ public static ArrayList<Map<String, Object>> getDefaultExternalEventConfiguratio
loanTransactionUndoContractTerminationBusinessEvent.put("enabled", false);
defaults.add(loanTransactionUndoContractTerminationBusinessEvent);

Map<String, Object> loanBuyDownFeeTransactionCreatedBusinessEvent = new HashMap<>();
loanBuyDownFeeTransactionCreatedBusinessEvent.put("type", "LoanBuyDownFeeTransactionCreatedBusinessEvent");
loanBuyDownFeeTransactionCreatedBusinessEvent.put("enabled", false);
defaults.add(loanBuyDownFeeTransactionCreatedBusinessEvent);

Map<String, Object> loanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent = new HashMap<>();
loanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent.put("type", "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent");
loanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent.put("enabled", false);
defaults.add(loanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent);
Map<String, Object> loanTransactionBuyDownFeePostBusinessEvent = new HashMap<>();
loanTransactionBuyDownFeePostBusinessEvent.put("type", "LoanBuyDownFeeTransactionCreatedBusinessEvent");
loanTransactionBuyDownFeePostBusinessEvent.put("enabled", false);
defaults.add(loanTransactionBuyDownFeePostBusinessEvent);

Map<String, Object> loanTransactionBuyDownFeeAdjustmentPostBusinessEvent = new HashMap<>();
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("type", "LoanBuyDownFeeAdjustmentTransactionCreatedBusinessEvent");
loanTransactionBuyDownFeeAdjustmentPostBusinessEvent.put("enabled", false);
defaults.add(loanTransactionBuyDownFeeAdjustmentPostBusinessEvent);

Map<String, Object> loanBuyDownFeeAmortizationTransactionCreatedBusinessEvent = new HashMap<>();
loanBuyDownFeeAmortizationTransactionCreatedBusinessEvent.put("type", "LoanBuyDownFeeAmortizationTransactionCreatedBusinessEvent");
Expand Down
Loading