This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit 52c41b147151ffd453afa2b071599c11a1dad4cf
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Wed Mar 19 09:03:35 2025 -0500

    FINERACT-2190: Avoid recreation of loan repayment schedule periods
---
 .../portfolio/loanaccount/domain/Loan.java         |  51 ----------
 .../domain/LoanRepaymentScheduleInstallment.java   | 106 ++++++++++++++++-----
 .../loanaccount/service/LoanScheduleService.java   |  18 ++--
 .../service/schedule/LoanScheduleComponent.java    |  91 ++++++++++++++++++
 ...dvancedPaymentScheduleTransactionProcessor.java |   8 +-
 ...cedPaymentScheduleTransactionProcessorTest.java |   4 +-
 ...nRescheduleRequestWritePlatformServiceImpl.java |  10 +-
 .../loanaccount/service/LoanAssemblerImpl.java     |   8 +-
 .../starter/LoanAccountAutoStarter.java            |   6 +-
 .../starter/LoanAccountConfiguration.java          |  10 +-
 .../ClientLoanIntegrationTest.java                 |  12 +--
 ...LoanSpecificDueDateChargeAfterMaturityTest.java |  16 ++--
 .../integrationtests/SchedulerJobsTestResults.java |   6 +-
 13 files changed, 229 insertions(+), 117 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 3d6cec432c..460036c47d 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -57,7 +57,6 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
@@ -112,7 +111,6 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
-import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
 import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
 import 
org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
@@ -610,8 +608,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
         this.interestChargedFromDate = 
loanApplicationTerms.getInterestChargedFromDate();
         this.submittedOnDate = submittedOnDate != null ? submittedOnDate : 
DateUtils.getBusinessLocalDate();
 
-        updateLoanSchedule(loanScheduleModel);
-
         
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
 
         // Copy interest recalculation settings if interest recalculation is 
enabled
@@ -1005,53 +1001,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
         this.rates.addAll(loanRates);
     }
 
-    public void updateLoanSchedule(final LoanScheduleModel 
modifiedLoanSchedule) {
-        this.repaymentScheduleInstallments.clear();
-        for (final LoanScheduleModelPeriod scheduledLoanInstallment : 
modifiedLoanSchedule.getPeriods()) {
-
-            if (scheduledLoanInstallment.isRepaymentPeriod() || 
scheduledLoanInstallment.isDownPaymentPeriod()) {
-                final LoanRepaymentScheduleInstallment installment = new 
LoanRepaymentScheduleInstallment(this,
-                        scheduledLoanInstallment.periodNumber(), 
scheduledLoanInstallment.periodFromDate(),
-                        scheduledLoanInstallment.periodDueDate(), 
scheduledLoanInstallment.principalDue(),
-                        scheduledLoanInstallment.interestDue(), 
scheduledLoanInstallment.feeChargesDue(),
-                        scheduledLoanInstallment.penaltyChargesDue(), 
scheduledLoanInstallment.isRecalculatedInterestComponent(),
-                        scheduledLoanInstallment.getLoanCompoundingDetails(), 
scheduledLoanInstallment.rescheduleInterestPortion(),
-                        scheduledLoanInstallment.isDownPaymentPeriod());
-                addLoanRepaymentScheduleInstallment(installment);
-            }
-        }
-        updateLoanScheduleDependentDerivedFields();
-        updateLoanSummaryDerivedFields();
-    }
-
-    public void updateLoanSchedule(final 
Collection<LoanRepaymentScheduleInstallment> installments) {
-        List<LoanRepaymentScheduleInstallment> existingInstallments = new 
ArrayList<>(this.repaymentScheduleInstallments);
-        repaymentScheduleInstallments.clear();
-        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
-            LoanRepaymentScheduleInstallment existingInstallment = 
findByInstallmentNumber(existingInstallments,
-                    installment.getInstallmentNumber());
-            if (existingInstallment != null) {
-                Set<LoanInstallmentCharge> existingCharges = 
existingInstallment.getInstallmentCharges();
-                installment.getInstallmentCharges().addAll(existingCharges);
-                existingCharges.forEach(c -> c.setInstallment(installment));
-                existingInstallment.getInstallmentCharges().clear();
-            }
-            addLoanRepaymentScheduleInstallment(installment);
-        }
-        updateLoanScheduleDependentDerivedFields();
-        updateLoanSummaryDerivedFields();
-    }
-
-    private LoanRepaymentScheduleInstallment 
findByInstallmentNumber(Collection<LoanRepaymentScheduleInstallment> 
installments,
-            Integer installmentNumber) {
-        for (LoanRepaymentScheduleInstallment installment : installments) {
-            if (Objects.equals(installment.getInstallmentNumber(), 
installmentNumber)) {
-                return installment;
-            }
-        }
-        return null;
-    }
-
     public void updateLoanScheduleDependentDerivedFields() {
         if (this.getLoanRepaymentScheduleInstallmentsSize() > 0) {
             this.expectedMaturityDate = determineExpectedMaturityDate();
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
index e3c64e4b3a..80c299aacc 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
@@ -38,10 +38,12 @@ import 
org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
 import org.apache.fineract.portfolio.loanproduct.domain.AllocationType;
 import 
org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks;
 
 @Getter
+@Setter
 @Entity
 @Table(name = "m_loan_repayment_schedule")
 public class LoanRepaymentScheduleInstallment extends 
AbstractAuditableWithUTCDateTimeCustom<Long>
@@ -60,67 +62,67 @@ public class LoanRepaymentScheduleInstallment extends 
AbstractAuditableWithUTCDa
     @Column(name = "duedate", nullable = false)
     private LocalDate dueDate;
 
-    @Column(name = "principal_amount", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "principal_amount", scale = 6, precision = 19)
     private BigDecimal principal;
 
-    @Column(name = "principal_completed_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "principal_completed_derived", scale = 6, precision = 19)
     private BigDecimal principalCompleted;
 
-    @Column(name = "principal_writtenoff_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "principal_writtenoff_derived", scale = 6, precision = 19)
     private BigDecimal principalWrittenOff;
 
-    @Column(name = "interest_amount", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "interest_amount", scale = 6, precision = 19)
     private BigDecimal interestCharged;
 
-    @Column(name = "interest_completed_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "interest_completed_derived", scale = 6, precision = 19)
     private BigDecimal interestPaid;
 
-    @Column(name = "interest_waived_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "interest_waived_derived", scale = 6, precision = 19)
     private BigDecimal interestWaived;
 
-    @Column(name = "interest_writtenoff_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "interest_writtenoff_derived", scale = 6, precision = 19)
     private BigDecimal interestWrittenOff;
 
-    @Column(name = "accrual_interest_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "accrual_interest_derived", scale = 6, precision = 19)
     private BigDecimal interestAccrued;
 
-    @Column(name = "reschedule_interest_portion", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "reschedule_interest_portion", scale = 6, precision = 19)
     private BigDecimal rescheduleInterestPortion;
 
-    @Column(name = "fee_charges_amount", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "fee_charges_amount", scale = 6, precision = 19)
     private BigDecimal feeChargesCharged;
 
-    @Column(name = "fee_charges_completed_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "fee_charges_completed_derived", scale = 6, precision = 19)
     private BigDecimal feeChargesPaid;
 
-    @Column(name = "fee_charges_writtenoff_derived", scale = 6, precision = 
19, nullable = true)
+    @Column(name = "fee_charges_writtenoff_derived", scale = 6, precision = 19)
     private BigDecimal feeChargesWrittenOff;
 
-    @Column(name = "fee_charges_waived_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "fee_charges_waived_derived", scale = 6, precision = 19)
     private BigDecimal feeChargesWaived;
 
-    @Column(name = "accrual_fee_charges_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "accrual_fee_charges_derived", scale = 6, precision = 19)
     private BigDecimal feeAccrued;
 
-    @Column(name = "penalty_charges_amount", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "penalty_charges_amount", scale = 6, precision = 19)
     private BigDecimal penaltyCharges;
 
-    @Column(name = "penalty_charges_completed_derived", scale = 6, precision = 
19, nullable = true)
+    @Column(name = "penalty_charges_completed_derived", scale = 6, precision = 
19)
     private BigDecimal penaltyChargesPaid;
 
-    @Column(name = "penalty_charges_writtenoff_derived", scale = 6, precision 
= 19, nullable = true)
+    @Column(name = "penalty_charges_writtenoff_derived", scale = 6, precision 
= 19)
     private BigDecimal penaltyChargesWrittenOff;
 
-    @Column(name = "penalty_charges_waived_derived", scale = 6, precision = 
19, nullable = true)
+    @Column(name = "penalty_charges_waived_derived", scale = 6, precision = 19)
     private BigDecimal penaltyChargesWaived;
 
-    @Column(name = "accrual_penalty_charges_derived", scale = 6, precision = 
19, nullable = true)
+    @Column(name = "accrual_penalty_charges_derived", scale = 6, precision = 
19)
     private BigDecimal penaltyAccrued;
 
-    @Column(name = "total_paid_in_advance_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "total_paid_in_advance_derived", scale = 6, precision = 19)
     private BigDecimal totalPaidInAdvance;
 
-    @Column(name = "total_paid_late_derived", scale = 6, precision = 19, 
nullable = true)
+    @Column(name = "total_paid_late_derived", scale = 6, precision = 19)
     private BigDecimal totalPaidLate;
 
     @Column(name = "completed_derived", nullable = false)
@@ -139,17 +141,17 @@ public class LoanRepaymentScheduleInstallment extends 
AbstractAuditableWithUTCDa
     // approach
     // 
https://blog.thepete.net/blog/2023/12/05/expand/contract-making-a-breaking-change-without-a-big-bang/
     @Setter
-    @Column(name = "credits_amount", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "credits_amount", scale = 6, precision = 19)
     private BigDecimal creditedPrincipal;
 
     @Setter
-    @Column(name = "credited_interest", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "credited_interest", scale = 6, precision = 19)
     private BigDecimal creditedInterest;
 
-    @Column(name = "credited_fee", scale = 6, precision = 19, nullable = true)
+    @Column(name = "credited_fee", scale = 6, precision = 19)
     private BigDecimal creditedFee;
 
-    @Column(name = "credited_penalty", scale = 6, precision = 19, nullable = 
true)
+    @Column(name = "credited_penalty", scale = 6, precision = 19)
     private BigDecimal creditedPenalty;
 
     @Column(name = "is_down_payment", nullable = false)
@@ -1068,4 +1070,58 @@ public class LoanRepaymentScheduleInstallment extends 
AbstractAuditableWithUTCDa
                 MathUtil.nullToZero(MathUtil.add(getPrincipal(), 
getInterestCharged(), getFeeChargesCharged(), getPenaltyCharges())));
     }
 
+    public void copyFrom(final LoanScheduleModelPeriod period) {
+        resetBalances();
+        setFromDate(period.periodFromDate());
+        setDueDate(period.periodDueDate());
+        setPrincipal(period.principalDue());
+        setInterestCharged(period.interestDue());
+        setFeeChargesCharged(period.feeChargesDue());
+        setPenaltyCharges(period.penaltyChargesDue());
+
+        
setRecalculatedInterestComponent(period.isRecalculatedInterestComponent());
+        if (getLoanCompoundingDetails() != null) {
+            getLoanCompoundingDetails().clear();
+        }
+        if (period.getLoanCompoundingDetails() != null) {
+            period.getLoanCompoundingDetails().forEach(lcd -> {
+                lcd.setLoanRepaymentScheduleInstallment(this);
+                getLoanCompoundingDetails().add(lcd);
+            });
+        }
+        setRescheduleInterestPortion(period.rescheduleInterestPortion());
+        setDownPayment(period.isDownPaymentPeriod());
+
+        setAdditional(false);
+        setReAged(false);
+    }
+
+    public void copyFrom(final LoanRepaymentScheduleInstallment installment) {
+        setFromDate(installment.getFromDate());
+        setDueDate(installment.getDueDate());
+
+        setPrincipal(installment.getPrincipal());
+        setInterestCharged(installment.getInterestCharged());
+        setFeeChargesCharged(installment.getFeeChargesCharged());
+        setPenaltyCharges(installment.getPenaltyCharges());
+        
setRecalculatedInterestComponent(installment.isRecalculatedInterestComponent());
+        if (getLoanCompoundingDetails() != null) {
+            getLoanCompoundingDetails().clear();
+        }
+        if (installment.getLoanCompoundingDetails() != null) {
+            installment.getLoanCompoundingDetails().forEach(lcd -> {
+                lcd.setLoanRepaymentScheduleInstallment(this);
+                getLoanCompoundingDetails().add(lcd);
+            });
+        }
+
+        Set<LoanInstallmentCharge> installmentCharges = 
installment.getInstallmentCharges();
+        installmentCharges.forEach(c -> c.setInstallment(this));
+        getInstallmentCharges().addAll(installmentCharges);
+
+        setAdditional(installment.isAdditional());
+        setReAged(installment.isReAged());
+        setDownPayment(installment.isDownPayment());
+    }
+
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanScheduleService.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanScheduleService.java
index 99c2e9763c..057b4b6b36 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanScheduleService.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanScheduleService.java
@@ -29,6 +29,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 
 @RequiredArgsConstructor
 public class LoanScheduleService {
@@ -36,16 +37,17 @@ public class LoanScheduleService {
     private final LoanChargeService loanChargeService;
     private final ReprocessLoanTransactionsService 
reprocessLoanTransactionsService;
     private final LoanTransactionProcessingService 
loadTransactionProcessingService;
+    private final LoanScheduleComponent loanSchedule;
 
     /**
      * Ability to regenerate the repayment schedule based on the loans current 
details/state.
      */
     public void regenerateRepaymentSchedule(final Loan loan, final 
ScheduleGeneratorDTO scheduleGeneratorDTO) {
-        final LoanScheduleModel loanSchedule = 
loan.regenerateScheduleModel(scheduleGeneratorDTO);
-        if (loanSchedule == null) {
+        final LoanScheduleModel loanScheduleModel = 
loan.regenerateScheduleModel(scheduleGeneratorDTO);
+        if (loanScheduleModel == null) {
             return;
         }
-        loan.updateLoanSchedule(loanSchedule);
+        loanSchedule.updateLoanSchedule(loan, loanScheduleModel);
         final Set<LoanCharge> charges = loan.getActiveCharges();
         for (final LoanCharge loanCharge : charges) {
             if (!loanCharge.isWaived()) {
@@ -80,15 +82,15 @@ public class LoanScheduleService {
 
     public void regenerateRepaymentScheduleWithInterestRecalculation(final 
Loan loan, final ScheduleGeneratorDTO generatorDTO) {
         final LocalDate lastTransactionDate = 
loan.getLastUserTransactionDate();
-        final LoanScheduleDTO loanSchedule = 
loadTransactionProcessingService.getRecalculatedSchedule(generatorDTO, loan);
-        if (loanSchedule == null) {
+        final LoanScheduleDTO loanScheduleDTO = 
loadTransactionProcessingService.getRecalculatedSchedule(generatorDTO, loan);
+        if (loanScheduleDTO == null) {
             return;
         }
         // Either the installments got recalculated or the model
-        if (loanSchedule.getInstallments() != null) {
-            loan.updateLoanSchedule(loanSchedule.getInstallments());
+        if (loanScheduleDTO.getInstallments() != null) {
+            loanSchedule.updateLoanSchedule(loan, 
loanScheduleDTO.getInstallments());
         } else {
-            loan.updateLoanSchedule(loanSchedule.getLoanScheduleModel());
+            loanSchedule.updateLoanSchedule(loan, 
loanScheduleDTO.getLoanScheduleModel());
         }
         loan.setInterestRecalculatedOn(DateUtils.getBusinessLocalDate());
         final LocalDate lastRepaymentDate = 
loan.getLastRepaymentPeriodDueDate(true);
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/schedule/LoanScheduleComponent.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/schedule/LoanScheduleComponent.java
new file mode 100644
index 0000000000..48029d58a2
--- /dev/null
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/schedule/LoanScheduleComponent.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.service.schedule;
+
+import java.util.Collection;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LoanScheduleComponent {
+
+    public void updateLoanSchedule(Loan loan, final LoanScheduleModel 
modifiedLoanSchedule) {
+        final List<LoanScheduleModelPeriod> periods = 
modifiedLoanSchedule.getPeriods();
+        for (final LoanScheduleModelPeriod scheduledLoanInstallment : 
modifiedLoanSchedule.getPeriods()) {
+            if (scheduledLoanInstallment.isRepaymentPeriod() || 
scheduledLoanInstallment.isDownPaymentPeriod()) {
+                LoanRepaymentScheduleInstallment existingInstallment = 
findByInstallmentNumber(loan.getRepaymentScheduleInstallments(),
+                        scheduledLoanInstallment.periodNumber());
+                if (existingInstallment == null) {
+                    final LoanRepaymentScheduleInstallment installment = new 
LoanRepaymentScheduleInstallment(loan,
+                            scheduledLoanInstallment.periodNumber(), 
scheduledLoanInstallment.periodFromDate(),
+                            scheduledLoanInstallment.periodDueDate(), 
scheduledLoanInstallment.principalDue(),
+                            scheduledLoanInstallment.interestDue(), 
scheduledLoanInstallment.feeChargesDue(),
+                            scheduledLoanInstallment.penaltyChargesDue(), 
scheduledLoanInstallment.isRecalculatedInterestComponent(),
+                            
scheduledLoanInstallment.getLoanCompoundingDetails(), 
scheduledLoanInstallment.rescheduleInterestPortion(),
+                            scheduledLoanInstallment.isDownPaymentPeriod());
+                    loan.addLoanRepaymentScheduleInstallment(installment);
+                } else {
+                    existingInstallment.copyFrom(scheduledLoanInstallment);
+                }
+            }
+        }
+        // Review Installments removed
+        loan.getRepaymentScheduleInstallments().removeIf(i -> 
!existInstallment(periods, i.getInstallmentNumber()));
+
+        loan.updateLoanScheduleDependentDerivedFields();
+        loan.updateLoanSummaryDerivedFields();
+    }
+
+    public void updateLoanSchedule(Loan loan, final 
List<LoanRepaymentScheduleInstallment> installments) {
+        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
+            LoanRepaymentScheduleInstallment existingInstallment = 
findByInstallmentNumber(loan.getRepaymentScheduleInstallments(),
+                    installment.getInstallmentNumber());
+            if (existingInstallment != null) {
+                existingInstallment.copyFrom(installment);
+            } else {
+                loan.addLoanRepaymentScheduleInstallment(installment);
+            }
+        }
+        // Review Installments removed
+        loan.getRepaymentScheduleInstallments().removeIf(i -> 
!existInstallment(installments, i.getInstallmentNumber()));
+
+        loan.updateLoanScheduleDependentDerivedFields();
+        loan.updateLoanSummaryDerivedFields();
+    }
+
+    private LoanRepaymentScheduleInstallment findByInstallmentNumber(final 
Collection<LoanRepaymentScheduleInstallment> installments,
+            final Integer installmentNumber) {
+        return installments.stream().filter(i -> 
installmentNumber.compareTo(i.getInstallmentNumber()) == 
0).findFirst().orElse(null);
+    }
+
+    private boolean existInstallment(final 
Collection<LoanRepaymentScheduleInstallment> installments, final Integer 
installmentNumber) {
+        return installments.stream().anyMatch(i -> 
installmentNumber.compareTo(i.getInstallmentNumber()) == 0);
+    }
+
+    private boolean existInstallment(final List<LoanScheduleModelPeriod> 
periods, final Integer installmentNumber) {
+        return periods.stream().anyMatch(p -> p.periodNumber() != null && 
installmentNumber.compareTo(p.periodNumber()) == 0);
+    }
+
+}
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index cdba9c9f41..5133ae504d 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -91,6 +91,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Mon
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
 import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
 import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
@@ -114,13 +115,15 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
     private final EMICalculator emiCalculator;
     private final LoanRepositoryWrapper loanRepositoryWrapper;
     private final InterestRefundService interestRefundService;
+    private final LoanScheduleComponent loanSchedule;
 
     public AdvancedPaymentScheduleTransactionProcessor(EMICalculator 
emiCalculator, LoanRepositoryWrapper loanRepositoryWrapper,
-            InterestRefundService interestRefundService, ExternalIdFactory 
externalIdFactory) {
+            InterestRefundService interestRefundService, ExternalIdFactory 
externalIdFactory, LoanScheduleComponent loanSchedule) {
         super(externalIdFactory);
         this.emiCalculator = emiCalculator;
         this.loanRepositoryWrapper = loanRepositoryWrapper;
         this.interestRefundService = interestRefundService;
+        this.loanSchedule = loanSchedule;
     }
 
     @Override
@@ -1460,8 +1463,7 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
                 }
             }
 
-            loan.updateLoanSchedule(installmentsUpToTransactionDate);
-            loan.updateLoanScheduleDependentDerivedFields();
+            loanSchedule.updateLoanSchedule(loan, 
installmentsUpToTransactionDate);
 
             if (transactionCtx instanceof ProgressiveTransactionCtx 
progressiveTransactionCtx && loan.isInterestRecalculationEnabled()) {
                 
updateRepaymentPeriodsAfterChargeOff(progressiveTransactionCtx, 
transactionDate, transactionsToBeReprocessed);
diff --git 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
index f6552d7c16..ea8a7f4f7f 100644
--- 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
+++ 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
@@ -69,6 +69,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.domain.AllocationType;
@@ -98,6 +99,7 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
     private AdvancedPaymentScheduleTransactionProcessor underTest;
     private static final EMICalculator emiCalculator = 
Mockito.mock(EMICalculator.class);
     private static final LoanRepositoryWrapper loanRepositoryWrapper = 
Mockito.mock(LoanRepositoryWrapper.class);
+    private static final LoanScheduleComponent loanSchedule = 
Mockito.mock(LoanScheduleComponent.class);
 
     @BeforeAll
     public static void init() {
@@ -112,7 +114,7 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
 
     @BeforeEach
     public void setUp() {
-        underTest = new 
AdvancedPaymentScheduleTransactionProcessor(emiCalculator, 
loanRepositoryWrapper, null, null);
+        underTest = new 
AdvancedPaymentScheduleTransactionProcessor(emiCalculator, 
loanRepositoryWrapper, null, null, loanSchedule);
 
         ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, 
"default", "Default", "Asia/Kolkata", null));
         ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index 815aaf991d..4f61df5e9f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -79,6 +79,7 @@ import 
org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
 import org.apache.fineract.portfolio.loanaccount.service.LoanChargeService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
 import 
org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -115,6 +116,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl 
implements LoanResche
     private final LoanAccrualsProcessingService loanAccrualsProcessingService;
     private final LoanChargeService loanChargeService;
     private final ReprocessLoanTransactionsService 
reprocessLoanTransactionsService;
+    private final LoanScheduleComponent loanSchedule;
 
     /**
      * create a new instance of the LoanRescheduleRequest object from the 
JsonCommand object and persist
@@ -423,14 +425,14 @@ public class 
LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
                     loanApplicationTerms.getInterestMethod());
             final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
             loan.setHelpers(loanLifecycleStateMachine);
-            final LoanScheduleDTO loanSchedule = 
loanScheduleGenerator.rescheduleNextInstallments(mathContext, 
loanApplicationTerms, loan,
+            final LoanScheduleDTO loanScheduleDTO = 
loanScheduleGenerator.rescheduleNextInstallments(mathContext, 
loanApplicationTerms, loan,
                     loanApplicationTerms.getHolidayDetailDTO(), 
loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
 
             // Either the installments got recalculated or the model
-            if (loanSchedule.getInstallments() != null) {
-                loan.updateLoanSchedule(loanSchedule.getInstallments());
+            if (loanScheduleDTO.getInstallments() != null) {
+                loanSchedule.updateLoanSchedule(loan, 
loanScheduleDTO.getInstallments());
             } else {
-                loan.updateLoanSchedule(loanSchedule.getLoanScheduleModel());
+                loanSchedule.updateLoanSchedule(loan, 
loanScheduleDTO.getLoanScheduleModel());
             }
             loanAccrualsProcessingService.reprocessExistingAccruals(loan);
             loanChargeService.recalculateAllCharges(loan);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java
index d878159434..6d8ff28723 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java
@@ -93,6 +93,7 @@ import 
org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanSchedu
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
 import org.apache.fineract.portfolio.loanaccount.mapper.LoanChargeMapper;
 import 
org.apache.fineract.portfolio.loanaccount.mapper.LoanCollateralManagementMapper;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
@@ -137,6 +138,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
     private final LoanDisbursementService loanDisbursementService;
     private final LoanChargeService loanChargeService;
     private final LoanOfficerService loanOfficerService;
+    private final LoanScheduleComponent loanSchedule;
 
     @Override
     public Loan assembleFrom(final Long accountId) {
@@ -293,6 +295,8 @@ public class LoanAssemblerImpl implements LoanAssembler {
             throw new IllegalStateException("No loan application exists for 
either a client or group (or both).");
         }
 
+        loanSchedule.updateLoanSchedule(loanApplication, loanScheduleModel);
+
         
copyAdvancedPaymentRulesIfApplicable(transactionProcessingStrategyCode, 
loanProduct, loanApplication);
         loanApplication.setHelpers(defaultLoanLifecycleStateMachine);
         // TODO: review
@@ -858,8 +862,8 @@ public class LoanAssemblerImpl implements LoanAssembler {
             final JsonElement parsedQuery = 
this.fromApiJsonHelper.parse(command.json());
             final JsonQuery query = JsonQuery.from(command.json(), 
parsedQuery, this.fromApiJsonHelper);
 
-            final LoanScheduleModel loanSchedule = 
this.calculationPlatformService.calculateLoanSchedule(query, false);
-            loan.updateLoanSchedule(loanSchedule);
+            final LoanScheduleModel loanScheduleModel = 
this.calculationPlatformService.calculateLoanSchedule(query, false);
+            loanSchedule.updateLoanSchedule(loan, loanScheduleModel);
             loanAccrualsProcessingService.reprocessExistingAccruals(loan);
             loanChargeService.recalculateAllCharges(loan);
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java
index 4a88a47def..2901e07160 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java
@@ -34,6 +34,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.imp
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
 import 
org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanInterestRefundServiceImpl;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
 import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.context.annotation.Bean;
@@ -118,8 +119,9 @@ public class LoanAccountAutoStarter {
     @Conditional(AdvancedPaymentScheduleTransactionProcessorCondition.class)
     public AdvancedPaymentScheduleTransactionProcessor 
advancedPaymentScheduleTransactionProcessor(EMICalculator emiCalculator,
             LoanRepositoryWrapper loanRepositoryWrapper,
-            @Lazy ProgressiveLoanInterestRefundServiceImpl 
progressiveLoanInterestRefundService, ExternalIdFactory externalIdFactory) {
+            @Lazy ProgressiveLoanInterestRefundServiceImpl 
progressiveLoanInterestRefundService, ExternalIdFactory externalIdFactory,
+            LoanScheduleComponent loanSchedule) {
         return new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, 
loanRepositoryWrapper, progressiveLoanInterestRefundService,
-                externalIdFactory);
+                externalIdFactory, loanSchedule);
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
index 607dda3a76..cf957cd363 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
@@ -146,6 +146,7 @@ import 
org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusi
 import 
org.apache.fineract.portfolio.loanaccount.service.ReplayedTransactionBusinessEventServiceImpl;
 import 
org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
 import 
org.apache.fineract.portfolio.loanaccount.service.adjustment.LoanAdjustmentService;
+import 
org.apache.fineract.portfolio.loanaccount.service.schedule.LoanScheduleComponent;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
 import 
org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
 import 
org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
@@ -240,14 +241,15 @@ public class LoanAccountConfiguration {
             LoanCollateralAssembler loanCollateralAssembler, 
LoanScheduleCalculationPlatformService calculationPlatformService,
             LoanDisbursementDetailsAssembler loanDisbursementDetailsAssembler, 
LoanChargeMapper loanChargeMapper,
             LoanCollateralManagementMapper loanCollateralManagementMapper, 
LoanAccrualsProcessingService loanAccrualsProcessingService,
-            LoanDisbursementService loanDisbursementService, LoanChargeService 
loanChargeService, LoanOfficerService loanOfficerService) {
+            LoanDisbursementService loanDisbursementService, LoanChargeService 
loanChargeService, LoanOfficerService loanOfficerService,
+            LoanScheduleComponent loanSchedule) {
         return new LoanAssemblerImpl(fromApiJsonHelper, loanRepository, 
loanProductRepository, clientRepository, groupRepository,
                 fundRepository, staffRepository, codeValueRepository, 
loanScheduleAssembler, loanChargeAssembler, collateralAssembler,
                 loanRepaymentScheduleTransactionProcessorFactory, 
holidayRepository, configurationDomainService, workingDaysRepository,
                 rateAssembler, defaultLoanLifecycleStateMachine, 
externalIdFactory, accountNumberFormatRepository, glimRepository,
                 accountNumberGenerator, glimAccountInfoWritePlatformService, 
loanCollateralAssembler, calculationPlatformService,
                 loanDisbursementDetailsAssembler, loanChargeMapper, 
loanCollateralManagementMapper, loanAccrualsProcessingService,
-                loanDisbursementService, loanChargeService, 
loanOfficerService);
+                loanDisbursementService, loanChargeService, 
loanOfficerService, loanSchedule);
     }
 
     @Bean
@@ -461,8 +463,8 @@ public class LoanAccountConfiguration {
     @ConditionalOnMissingBean(LoanScheduleService.class)
     public LoanScheduleService loanScheduleService(LoanChargeService 
loanChargeService,
             ReprocessLoanTransactionsService reprocessLoanTransactionsService,
-            LoanTransactionProcessingService loanTransactionProcessingService) 
{
-        return new LoanScheduleService(loanChargeService, 
reprocessLoanTransactionsService, loanTransactionProcessingService);
+            LoanTransactionProcessingService loanTransactionProcessingService, 
LoanScheduleComponent loanSchedule) {
+        return new LoanScheduleService(loanChargeService, 
reprocessLoanTransactionsService, loanTransactionProcessingService, 
loanSchedule);
     }
 
     @Bean
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index dd26bfcfad..d58bf9f0da 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -5310,8 +5310,8 @@ public class ClientLoanIntegrationTest extends 
BaseLoanIntegrationTest {
 
             ArrayList<HashMap> loanSchedule = 
LOAN_TRANSACTION_HELPER.getLoanRepaymentSchedule(REQUEST_SPEC, RESPONSE_SPEC, 
loanID);
             assertEquals(2, loanSchedule.size());
-            assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
-            assertEquals(0, 
loanSchedule.get(1).get("penaltyChargesOutstanding"));
+            assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
+            assertEquals(0.0f, 
loanSchedule.get(1).get("penaltyChargesOutstanding"));
             assertEquals(1000.0f, 
loanSchedule.get(1).get("totalDueForPeriod"));
             assertEquals(1000.0f, 
loanSchedule.get(1).get("totalOutstandingForPeriod"));
             LocalDate targetDate = LocalDate.of(2022, 9, 7);
@@ -5906,10 +5906,10 @@ public class ClientLoanIntegrationTest extends 
BaseLoanIntegrationTest {
 
         ArrayList<HashMap> loanSchedule = 
LOAN_TRANSACTION_HELPER.getLoanRepaymentSchedule(REQUEST_SPEC, RESPONSE_SPEC, 
loanID);
         assertEquals(2, loanSchedule.size());
-        assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
+        assertEquals(0.0f, 
loanSchedule.get(1).get("penaltyChargesOutstanding"));
         assertEquals(1000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
         assertEquals(1000.0f, 
loanSchedule.get(1).get("totalOutstandingForPeriod"));
         LocalDate targetDate = LocalDate.of(2022, 9, 7);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
index bb7b14e3a4..6b8b286cc2 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
@@ -173,10 +173,10 @@ public class LoanSpecificDueDateChargeAfterMaturityTest 
extends BaseLoanIntegrat
 
         ArrayList<HashMap> loanSchedule = 
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, 
loanID);
         assertEquals(2, loanSchedule.size());
-        assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
+        assertEquals(0.0f, 
loanSchedule.get(1).get("penaltyChargesOutstanding"));
         assertEquals(10000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
         assertEquals(10000.0f, 
loanSchedule.get(1).get("totalOutstandingForPeriod"));
         targetDate = LocalDate.of(2011, 4, 5);
@@ -306,10 +306,10 @@ public class LoanSpecificDueDateChargeAfterMaturityTest 
extends BaseLoanIntegrat
 
         ArrayList<HashMap> loanSchedule = 
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, 
loanID);
         assertEquals(2, loanSchedule.size());
-        assertEquals(0, loanSchedule.get(1).get("feeChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("feeChargesOutstanding"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesDue"));
-        assertEquals(0, loanSchedule.get(1).get("penaltyChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesDue"));
+        assertEquals(0.0f, loanSchedule.get(1).get("feeChargesOutstanding"));
+        assertEquals(0.0f, loanSchedule.get(1).get("penaltyChargesDue"));
+        assertEquals(0.0f, 
loanSchedule.get(1).get("penaltyChargesOutstanding"));
         assertEquals(10000.0f, loanSchedule.get(1).get("totalDueForPeriod"));
         assertEquals(10000.0f, 
loanSchedule.get(1).get("totalOutstandingForPeriod"));
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
index d39e8012eb..3045df0243 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
@@ -844,7 +844,7 @@ public class SchedulerJobsTestResults extends 
IntegrationTest {
         ArrayList<HashMap> repaymentScheduleDataAfter = 
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
                 loanID);
 
-        Assertions.assertEquals(0, (Integer) 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+        Assertions.assertEquals(0.0f, 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
                 "Verifying From Penalty Charges due fot first Repayment after 
Successful completion of Scheduler Job");
 
     }
@@ -1085,7 +1085,7 @@ public class SchedulerJobsTestResults extends 
IntegrationTest {
             this.schedulerJobHelper.executeAndAwaitJob(jobName);
             List<HashMap> repaymentScheduleDataAfter = 
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
                     loanID);
-            Assertions.assertEquals(0, (Integer) 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+            Assertions.assertEquals(0.0f, 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
                     "Verifying From Penalty Charges due fot first Repayment 
after Successful completion of Scheduler Job");
 
             LocalDate lastBusinessDateBeforeFastForward = LocalDate.of(2019, 
4, 2);
@@ -1153,7 +1153,7 @@ public class SchedulerJobsTestResults extends 
IntegrationTest {
             this.schedulerJobHelper.executeAndAwaitJob(jobName);
             List<HashMap> repaymentScheduleDataAfter = 
this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
                     loanID2);
-            Assertions.assertEquals(0, (Integer) 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
+            Assertions.assertEquals(0.0f, 
repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
                     "Verifying From Penalty Charges due fot first Repayment 
after Successful completion of Scheduler Job");
 
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.COB_DATE, LocalDate.of(2020, 5, 3));

Reply via email to