4444import java .util .HashMap ;
4545import java .util .LinkedHashMap ;
4646import java .util .LinkedHashSet ;
47+ import java .util .LinkedList ;
4748import java .util .List ;
4849import java .util .ListIterator ;
4950import java .util .Map ;
@@ -1699,10 +1700,9 @@ private void recalculateRepaymentPeriodsWithEMICalculation(final Money amortizab
16991700 .allMatch (i -> i .getDueDate ().isBefore (transactionDate ));
17001701
17011702 if (amortizableAmount .isGreaterThanZero ()) {
1702- Optional <LoanRepaymentScheduleInstallment > additionalInstallmentOptional = installments .stream ()
1703- .filter (LoanRepaymentScheduleInstallment ::isAdditional ).findFirst ();
17041703 if (isPostMaturityDisbursement ) {
1705- LoanRepaymentScheduleInstallment additionalInstallment = additionalInstallmentOptional .orElse (null );
1704+ LoanRepaymentScheduleInstallment additionalInstallment = installments .stream ()
1705+ .filter (LoanRepaymentScheduleInstallment ::isAdditional ).findFirst ().orElse (null );
17061706 if (additionalInstallment != null && additionalInstallment .getPrincipal (currency ).isZero ()) {
17071707 additionalInstallment .updatePrincipal (amortizableAmount .getAmount ());
17081708 }
@@ -1712,28 +1712,14 @@ private void recalculateRepaymentPeriodsWithEMICalculation(final Money amortizab
17121712 final AtomicInteger installmentCounter = new AtomicInteger ();
17131713 final ILoanConfigurationDetails loanProductRelatedDetail = model .loanProductRelatedDetail ();
17141714
1715+ List <LoanRepaymentScheduleInstallment > newInstallments = new LinkedList <>();
1716+
17151717 model .repaymentPeriods ().forEach (rm -> {
17161718 LoanRepaymentScheduleInstallment installment = null ;
17171719 while (iterator .hasNext () && (installment == null || installment .isAdditional () || installment .isDownPayment ())) {
17181720 installment = iterator .next ();
17191721 installmentCounter .getAndIncrement ();
17201722 }
1721- if (installment == null ) {
1722- Optional <LoanRepaymentScheduleInstallment > additional = installments .stream ()
1723- .filter (LoanRepaymentScheduleInstallment ::isAdditional ).findAny ();
1724- if (additional .isPresent ()) {
1725- installment = additional .get ();
1726- }
1727- }
1728- boolean mergeToAdditional = installment != null && installment .isAdditional ()
1729- && !installment .getDueDate ().isAfter (rm .getDueDate ());
1730- boolean adjustAdditional = installment != null && installment .isAdditional ()
1731- && installment .getDueDate ().isAfter (rm .getDueDate ());
1732- if (mergeToAdditional ) {
1733- installment .setFromDate (rm .getFromDate ());
1734- installment .setDueDate (rm .getDueDate ());
1735- installment .setAdditional (false );
1736- }
17371723
17381724 if (installment != null && installment .getDueDate ().equals (rm .getDueDate ())
17391725 && !installment .getDueDate ().isBefore (transactionDate )) {
@@ -1743,9 +1729,7 @@ private void recalculateRepaymentPeriodsWithEMICalculation(final Money amortizab
17431729 } else {
17441730 if (loanProductRelatedDetail != null && loanProductRelatedDetail .isAllowFullTermForTranche ()
17451731 && loanProductRelatedDetail .getNumberOfRepayments () > 0 && !rm .getDueDate ().isBefore (transactionDate )) {
1746-
1747- // fix new installment index.
1748- if (!adjustAdditional ) {
1732+ if (installment == null || !installment .isAdditional ()) {
17491733 installmentCounter .getAndIncrement ();
17501734 }
17511735 final LoanRepaymentScheduleInstallment newInstallment = new LoanRepaymentScheduleInstallment (
@@ -1754,21 +1738,28 @@ private void recalculateRepaymentPeriodsWithEMICalculation(final Money amortizab
17541738 false , false , false );
17551739
17561740 newInstallment .updateObligationsMet (currency , transactionDate );
1757- // fix order of installments in the list.
1758- iterator .previous ();
17591741 iterator .add (newInstallment );
1760- iterator .next ();
1761- if (adjustAdditional ) {
1762- // fix installment and charge relation due to updated maturity date
1763- moveRelatedChargesToInstallment (processedLoanCharges , newInstallment , List .of (installment ), currency );
1764- }
1742+ newInstallments .add (newInstallment );
17651743 }
17661744 }
1767- if (adjustAdditional ) {
1768- installment .setFromDate (rm .getDueDate ());
1769- installment .setInstallmentNumber (installmentCounter .incrementAndGet ());
1770- }
17711745 });
1746+ // fix additional installment
1747+ Optional <LoanRepaymentScheduleInstallment > additionalInstallmentOptional = installments .stream ()
1748+ .filter (LoanRepaymentScheduleInstallment ::isAdditional ).findFirst ();
1749+ if (additionalInstallmentOptional .isPresent () && !newInstallments .isEmpty ()) {
1750+ LoanRepaymentScheduleInstallment additional = additionalInstallmentOptional .get ();
1751+ // iterate trough new installments to fix charges
1752+ for (LoanRepaymentScheduleInstallment installment : newInstallments ) {
1753+ moveRelatedChargesToInstallment (processedLoanCharges , installment , List .of (additional ), currency );
1754+ additional .setFromDate (installment .getDueDate ());
1755+ additional .setInstallmentNumber (installment .getInstallmentNumber () + 1 );
1756+ }
1757+ installments .remove (additional );
1758+ if (additional .getDueDate ().isAfter (model .getMaturityDate ())) {
1759+ // step is needed to move the additional installment to the end of the list.
1760+ installments .add (additional );
1761+ }
1762+ }
17721763 }
17731764 }
17741765
@@ -3892,11 +3883,11 @@ private void handleReAgeWithCommonStrategy(LoanTransaction loanTransaction, Comm
38923883 }
38933884
38943885 private void moveRelatedChargesToInstallment (Set <LoanCharge > charges , LoanRepaymentScheduleInstallment target ,
3895- List <LoanRepaymentScheduleInstallment > installments , MonetaryCurrency currency ) {
3896- int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper .fetchFirstNormalInstallmentNumber (installments );
3886+ List <LoanRepaymentScheduleInstallment > sources , MonetaryCurrency currency ) {
3887+ int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper .fetchFirstNormalInstallmentNumber (sources );
38973888 Set <LoanCharge > chargesOfNewInstallment = getLoanChargesOfInstallment (charges , target , firstNormalInstallmentNumber );
38983889 Integer targetInstallmentNumber = target .getInstallmentNumber ();
3899- installments .stream ().filter (i -> Objects .equals (i .getInstallmentNumber (), targetInstallmentNumber )).findFirst ()
3890+ sources .stream ().filter (source -> Objects .equals (source .getInstallmentNumber (), targetInstallmentNumber )).findFirst ()
39003891 .filter (source -> source != target ).ifPresent (source -> {
39013892 // move fees
39023893 chargesOfNewInstallment .stream ().filter (LoanCharge ::isNotFullyPaid ).filter (LoanCharge ::isFeeCharge )
0 commit comments