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]

Reply via email to