7070import org .apache .fineract .organisation .monetary .domain .MonetaryCurrency ;
7171import org .apache .fineract .organisation .monetary .domain .Money ;
7272import org .apache .fineract .organisation .monetary .domain .MoneyHelper ;
73- import org .apache .fineract .portfolio .charge .domain .ChargeCalculationType ;
7473import org .apache .fineract .portfolio .common .domain .PeriodFrequencyType ;
7574import org .apache .fineract .portfolio .loanaccount .data .LoanTermVariationsData ;
7675import org .apache .fineract .portfolio .loanaccount .data .OutstandingAmountsDTO ;
@@ -2686,6 +2685,7 @@ private Set<LoanCharge> getLoanChargesOfInstallment(final Set<LoanCharge> charge
26862685 final boolean isFirstInstallment = installment .getInstallmentNumber ().equals (firstInstallmentNumber );
26872686 return charges .stream ()
26882687 .filter (loanCharge -> (loanCharge .isInstalmentFee () && loanCharge .hasInstallmentFor (installment ))
2688+ || (installment .isReAged () && loanCharge .hasInstallmentFor (installment ))
26892689 || loanCharge .isDueInPeriod (installment .getFromDate (), installment .getDueDate (), isFirstInstallment ))
26902690 .collect (Collectors .toSet ());
26912691 }
@@ -3303,51 +3303,48 @@ private void handleReAgeWithCommonStrategy(LoanTransaction loanTransaction, Comm
33033303 Money principalValue = calculatedEMI .value .minus (calculatedInterest .value .add (calculatedFees .value ).add (calculatedPenalties .value ));
33043304 Money principalAdjust = outstandingBalances .principal .minus (principalValue .multipliedBy (numberOfReAgeInstallments ));
33053305 EqualAmortizationValues calculatedPrincipal = new EqualAmortizationValues (principalValue , principalAdjust );
3306+ List <ReAgedChargeEqualAmortizationValues > calculatedCharges = outstandingBalances .liftedLoanCharges ().stream ()
3307+ .map (loanCharge -> new ReAgedChargeEqualAmortizationValues (loanCharge , calculateEqualAmortizationValues (
3308+ loanCharge .getAmountOutstanding (currency ), numberOfReAgeInstallments , null , currency )))
3309+ .toList ();
33063310
33073311 FirstReAgeInstallmentProps firstReAgeInstallmentProps = calculateFirstReAgeInstallmentProps (installments ,
33083312 loanReAgeParameter .getStartDate ());
33093313
33103314 LoanRepaymentScheduleInstallment reAgedInstallment = LoanRepaymentScheduleInstallment .newReAgedInstallment (loan ,
33113315 firstReAgeInstallmentProps .reAgedInstallmentNumber , firstReAgeInstallmentProps .fromDate , loanReAgeParameter .getStartDate (),
33123316 calculatedPrincipal .value .getAmount (), calculatedInterest .value .getAmount (), calculatedFees .value .getAmount (),
3313- calculatedPenalties .value .getAmount ());
3314- // todo redistribute lifted fees and penalties
3315- createChargesDuringReAgingIfNeeded (calculatedFees .value .getAmount (), calculatedPenalties .value .getAmount (), outstandingBalances ,
3316- loan , loanReAgeParameter .getStartDate ());
3317- reAgedInstallment .setInterestAccrued (calculatedInterestAccrued .value .getAmount ());
3318- reAgedInstallment .setFeeAccrued (calculatedFeeAccrued .value .getAmount ());
3319- reAgedInstallment .setPenaltyAccrued (calculatedPenaltyAccrued .value .getAmount ());
3317+ calculatedPenalties .value .getAmount (), calculatedInterestAccrued .value .getAmount (), calculatedFeeAccrued .value .getAmount (),
3318+ calculatedPenaltyAccrued .value .getAmount ());
3319+
33203320 reAgedInstallment = insertOrReplaceRelatedInstallment (installments , reAgedInstallment , currency ,
33213321 loanTransaction .getTransactionDate (), settings .isEqualInstallmentForInterest (),
33223322 settings .isEqualInstallmentForFeesAndPenalties ());
3323+ createChargeMappingsForInstallment (reAgedInstallment , calculatedCharges , false );
33233324
33243325 for (int i = 1 ; i < numberOfReAgeInstallments ; i ++) {
33253326 LocalDate calculatedDueDate = calculateReAgedInstallmentDueDate (loanReAgeParameter , reAgedInstallment .getDueDate ());
33263327 int nextReAgedInstallmentNumber = firstReAgeInstallmentProps .reAgedInstallmentNumber + i ;
3327- if (i + 1 == numberOfReAgeInstallments ) {
3328+ boolean isLastInstallment = i + 1 == numberOfReAgeInstallments ;
3329+ if (isLastInstallment ) {
33283330 // Last installment values
33293331 reAgedInstallment = LoanRepaymentScheduleInstallment .newReAgedInstallment (reAgedInstallment .getLoan (),
33303332 nextReAgedInstallmentNumber , reAgedInstallment .getDueDate (), calculatedDueDate ,
33313333 calculatedPrincipal .getAdjustedValue ().getAmount (), calculatedInterest .getAdjustedValue ().getAmount (),
3332- calculatedFees .getAdjustedValue ().getAmount (), calculatedPenalties .getAdjustedValue ().getAmount ());
3333- reAgedInstallment .setInterestAccrued (calculatedInterestAccrued .getAdjustedValue ().getAmount ());
3334- reAgedInstallment .setFeeAccrued (calculatedFeeAccrued .getAdjustedValue ().getAmount ());
3335- reAgedInstallment .setPenaltyAccrued (calculatedPenaltyAccrued .getAdjustedValue ().getAmount ());
3336- // todo redistribute lifted fees and penalties
3337- createChargesDuringReAgingIfNeeded (calculatedFees .getAdjustedValue ().getAmount (),
3338- calculatedPenalties .getAdjustedValue ().getAmount (), outstandingBalances , loan , reAgedInstallment .getDueDate ());
3334+ calculatedFees .getAdjustedValue ().getAmount (), calculatedPenalties .getAdjustedValue ().getAmount (),
3335+ calculatedInterestAccrued .getAdjustedValue ().getAmount (), calculatedFeeAccrued .getAdjustedValue ().getAmount (),
3336+ calculatedPenaltyAccrued .getAdjustedValue ().getAmount ());
33393337 } else {
33403338 reAgedInstallment = LoanRepaymentScheduleInstallment .newReAgedInstallment (reAgedInstallment .getLoan (),
33413339 nextReAgedInstallmentNumber , reAgedInstallment .getDueDate (), calculatedDueDate ,
33423340 calculatedPrincipal .value .getAmount (), calculatedInterest .value .getAmount (), calculatedFees .value .getAmount (),
3343- calculatedPenalties .value .getAmount ());
3344- // todo redistribute lifted fees and penalties
3345- createChargesDuringReAgingIfNeeded (calculatedFees .value .getAmount (), calculatedPenalties .value .getAmount (),
3346- outstandingBalances , loan , reAgedInstallment .getDueDate ());
3341+ calculatedPenalties .value .getAmount (), calculatedInterestAccrued .value .getAmount (),
3342+ calculatedFeeAccrued .value .getAmount (), calculatedPenaltyAccrued .value .getAmount ());
33473343 }
33483344 reAgedInstallment = insertOrReplaceRelatedInstallment (installments , reAgedInstallment , currency ,
33493345 loanTransaction .getTransactionDate (), settings .isEqualInstallmentForInterest (),
33503346 settings .isEqualInstallmentForFeesAndPenalties ());
3347+ createChargeMappingsForInstallment (reAgedInstallment , calculatedCharges , isLastInstallment );
33513348 }
33523349 int lastReAgedInstallmentNumber = reAgedInstallment .getInstallmentNumber ();
33533350 List <LoanRepaymentScheduleInstallment > toRemove = installments .stream ()
@@ -3361,19 +3358,13 @@ private void handleReAgeWithCommonStrategy(LoanTransaction loanTransaction, Comm
33613358 }
33623359 }
33633360
3364- private void createChargesDuringReAgingIfNeeded (final BigDecimal calculatedFees , final BigDecimal calculatedPenalties ,
3365- final OutstandingBalances outstandingBalances , final Loan loan , final LocalDate chargeDueDate ) {
3366- if (MathUtil .nullToZero (calculatedFees ).compareTo (BigDecimal .ZERO ) > 0 ) {
3367- outstandingBalances .liftedLoanCharges ().forEach (charge -> {
3368- if (charge .isDueDateCharge ()) {
3369- final LoanCharge newLoanCharge = loanChargeService .create (loan , charge .getCharge (), null ,
3370- charge .isPenaltyCharge () ? calculatedPenalties : calculatedFees , charge .getChargeTimeType (),
3371- ChargeCalculationType .FLAT , chargeDueDate , charge .getChargePaymentMode (), null , null ,
3372- externalIdFactory .create ());
3373- loanChargeService .addLoanCharge (loan , newLoanCharge );
3374- }
3375- });
3376- }
3361+ private void createChargeMappingsForInstallment (final LoanRepaymentScheduleInstallment installment ,
3362+ List <ReAgedChargeEqualAmortizationValues > reAgedChargeEqualAmortizationValues , boolean isLastInstallment ) {
3363+ reAgedChargeEqualAmortizationValues .forEach (amortizationValue -> {
3364+ BigDecimal value = isLastInstallment ? amortizationValue .equalAmortizationValues .getAdjustedValue ().getAmount ()
3365+ : amortizationValue .equalAmortizationValues .value .getAmount ();
3366+ installment .getInstallmentCharges ().add (new LoanInstallmentCharge (value , amortizationValue .charge , installment ));
3367+ });
33773368 }
33783369
33793370 private FirstReAgeInstallmentProps calculateFirstReAgeInstallmentProps (List <LoanRepaymentScheduleInstallment > installments ,
@@ -3522,11 +3513,10 @@ OutstandingBalances liftOutstandingBalances(List<LoanRepaymentScheduleInstallmen
35223513 .stream ()//
35233514 .filter (c -> MathUtil .isGreaterThanZero (c .getAmountOutstanding ()))//
35243515 .forEach (loanInstallmentCharge -> {
3525- Money outstanding = loanInstallmentCharge .getAmountOutstanding (currency );
3526- if (MathUtil .nullToZero (loanInstallmentCharge .getAmountPaid ()).equals (ZERO )) {
3527- ctx .getCharges ().remove (loanInstallmentCharge );
3528- loanTransaction .getLoan ().getCharges ().remove (loanInstallmentCharge );
3529- }
3516+ // if (MathUtil.nullToZero(loanInstallmentCharge.getAmountPaid()).equals(ZERO)) {
3517+ // ctx.getCharges().remove(loanInstallmentCharge);
3518+ // loanTransaction.getLoan().getCharges().remove(loanInstallmentCharge);
3519+ // }
35303520 liftedLoanCharges .add (loanInstallmentCharge );
35313521 });
35323522 Money feesOutstanding = i .getFeeChargesOutstanding (currency );
@@ -3582,6 +3572,9 @@ private static final class CommonReAgeSettings {
35823572 boolean isEqualInstallmentForFeesAndPenalties = false ;
35833573 }
35843574
3575+ private record ReAgedChargeEqualAmortizationValues (LoanCharge charge , EqualAmortizationValues equalAmortizationValues ) {
3576+ }
3577+
35853578 private record FirstReAgeInstallmentProps (int reAgedInstallmentNumber , LocalDate fromDate ) {
35863579 }
35873580
0 commit comments