adamsaghy commented on code in PR #4154:
URL: https://github.com/apache/fineract/pull/4154#discussion_r1840152935
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestRefundServiceImpl.java:
##########
@@ -76,52 +72,77 @@ private static void
simulateRepaymentForDisbursements(LoanTransaction lt, final
}
}
- private BigDecimal totalInterest(final Loan loan, BigDecimal refundAmount,
LocalDate relatedRefundTransactionDate) {
- final AtomicReference<BigDecimal> refundFinal = new
AtomicReference<>(refundAmount);
-
- BigDecimal payableInterest = BigDecimal.ZERO;
- if
(loan.getLoanTransactions().stream().anyMatch(LoanTransaction::isDisbursement))
{
- List<LoanTransaction> transactionsToReprocess = new ArrayList<>();
- List<LoanTransactionType> interestRefundTypes =
loan.getLoanProductRelatedDetail().getSupportedInterestRefundTypes().stream()
-
.map(LoanSupportedInterestRefundTypes::getTransactionType).toList();
- // add already interest refunded amounts to refund amount
- // it is necessary to avoid multi disbursed refund
- loan.getLoanTransactions().stream() //
- .filter(lt -> !lt.isReversed()) //
- .filter(lt ->
interestRefundTypes.contains(lt.getTypeOf())) //
- .forEach(t ->
refundFinal.set(refundFinal.get().add(t.getAmount()))); //
- loan.getLoanTransactions().stream() //
- .filter(lt -> !lt.isReversed()) //
- .filter(lt -> !lt.isAccrual() && !lt.isAccrualActivity()
&& !lt.isInterestRefund()) //
- .filter(loanTransaction ->
!interestRefundTypes.contains(loanTransaction.getTypeOf())) //
- .forEach(lt -> simulateRepaymentForDisbursements(lt,
refundFinal, transactionsToReprocess)); //
-
- List<LoanRepaymentScheduleInstallment> installmentsToReprocess =
new ArrayList<>(
- loan.getRepaymentScheduleInstallments().stream().filter(i
-> !i.isReAged() && !i.isAdditional()).toList());
-
- Pair<ChangedTransactionDetail,
ProgressiveLoanInterestScheduleModel> reprocessResult = processor
-
.reprocessProgressiveLoanTransactions(loan.getDisbursementDate(),
relatedRefundTransactionDate, transactionsToReprocess,
- loan.getCurrency(), installmentsToReprocess,
loan.getActiveCharges());
-
loan.getLoanTransactions().addAll(reprocessResult.getLeft().getCurrentTransactionToOldId().keySet());
- ProgressiveLoanInterestScheduleModel modelAfter =
reprocessResult.getRight();
-
- payableInterest = installmentsToReprocess.stream() //
- .map(installment -> emiCalculator //
- .getDueAmounts(modelAfter,
installment.getDueDate(), relatedRefundTransactionDate) //
- .getDueInterest() //
- .getAmount()) //
- .reduce(BigDecimal.ZERO, BigDecimal::add); //
- }
- return payableInterest;
+ private Money
recalculateTotalInterest(AdvancedPaymentScheduleTransactionProcessor processor,
Loan loan,
+ LocalDate relatedRefundTransactionDate, List<LoanTransaction>
transactionsToReprocess) {
+ List<LoanRepaymentScheduleInstallment> installmentsToReprocess = new
ArrayList<>(
+ loan.getRepaymentScheduleInstallments().stream().filter(i ->
!i.isReAged() && !i.isAdditional()).toList());
+
+ Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel>
reprocessResult = processor
+
.reprocessProgressiveLoanTransactions(loan.getDisbursementDate(),
relatedRefundTransactionDate, transactionsToReprocess,
+ loan.getCurrency(), installmentsToReprocess,
loan.getActiveCharges());
+
loan.getLoanTransactions().addAll(reprocessResult.getLeft().getCurrentTransactionToOldId().keySet());
+ ProgressiveLoanInterestScheduleModel modelAfter =
reprocessResult.getRight();
+
+ return emiCalculator.getSumOfDueInterestsOnDate(modelAfter,
relatedRefundTransactionDate);
+ }
+
+ @Override
+ public boolean canHandle(Loan loan) {
+ String s = loan.getTransactionProcessingStrategyCode();
+ return
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY_NAME.equalsIgnoreCase(s)
+ ||
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY.equalsIgnoreCase(s);
}
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
- public BigDecimal calculateInterestRefundAmount(Long loanId, BigDecimal
relatedRefundTransactionAmount,
- LocalDate relatedRefundTransactionDate) {
+ public Money
totalInterestByTransactions(LoanRepaymentScheduleTransactionProcessor
processor, final Long loanId,
+ LocalDate relatedRefundTransactionDate, List<LoanTransaction>
newTransactions, List<Long> oldTransactionIds) {
Loan loan = loanAssembler.assembleFrom(loanId);
- BigDecimal totalInterestBeforeRefund = totalInterest(loan,
BigDecimal.ZERO, relatedRefundTransactionDate);
- BigDecimal totalInterestAfterRefund = totalInterest(loan,
relatedRefundTransactionAmount, relatedRefundTransactionDate);
- return totalInterestBeforeRefund.subtract(totalInterestAfterRefund);
+ if (processor == null) {
+ processor = loan.getTransactionProcessor();
+ }
+ if (!(processor instanceof
AdvancedPaymentScheduleTransactionProcessor)) {
+ throw new IllegalArgumentException(
+ "Wrong processor implementation.
ProgressiveLoanInterestRefundServiceImpl requires
AdvancedPaymentScheduleTransactionProcessor");
+ }
+
+ final AtomicReference<BigDecimal> refundFinal = new
AtomicReference<>(BigDecimal.ZERO);
+
+ List<LoanTransaction> transactionsToReprocess = new ArrayList<>();
+ List<LoanTransactionType> interestRefundTypes =
loan.getSupportedInterestRefundTransactionTypes();
+
+ var oldTransactions = loan.getLoanTransactions().stream() //
+ .filter(LoanTransaction::isNotReversed) //
+ .filter(lt -> !lt.isAccrual() && !lt.isAccrualActivity() &&
!lt.isInterestRefund()) //
+ .filter(lt -> oldTransactionIds.contains(lt.getId())).toList();
+
+ oldTransactions.stream().filter(lt ->
interestRefundTypes.contains(lt.getTypeOf())) //
+ .forEach(t ->
refundFinal.set(refundFinal.get().add(t.getAmount()))); //
+
+ newTransactions.stream() //
+ .filter(LoanTransaction::isNotReversed) //
+ .filter(lt -> interestRefundTypes.contains(lt.getTypeOf())) //
+ .forEach(t ->
refundFinal.set(refundFinal.get().add(t.getAmount()))); //
+
+ oldTransactions.stream().filter(lt ->
oldTransactionIds.contains(lt.getId()))
+ .filter(loanTransaction ->
!interestRefundTypes.contains(loanTransaction.getTypeOf())) //
+ .forEach(lt -> simulateRepaymentForDisbursements(lt,
refundFinal, transactionsToReprocess)); //
+
+ newTransactions.stream() //
+ .filter(LoanTransaction::isNotReversed) //
+ .filter(lt -> !lt.isAccrual() && !lt.isAccrualActivity() &&
!lt.isInterestRefund()) //
+ .filter(loanTransaction ->
!interestRefundTypes.contains(loanTransaction.getTypeOf())) //
+ .map(LoanTransaction::copyTransactionProperties)
+ .forEach(lt -> simulateRepaymentForDisbursements(lt,
refundFinal, transactionsToReprocess)); //
+
+ return
recalculateTotalInterest((AdvancedPaymentScheduleTransactionProcessor)
processor, loan, relatedRefundTransactionDate,
+ transactionsToReprocess);
+ }
+
+ @Override
+ public Money getTotalInterestRefunded(List<LoanTransaction>
loanTransactions, Money zero) {
Review Comment:
Would you mind to remove the 2nd parameter? We should really not pass a
"zero" money object... Would you mind rather pass the currency? It would be a
little bit nicer...
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]