http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 12a2db3..5bd7a0b 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -40,6 +40,7 @@ import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Embedded;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -130,8 +131,6 @@ import 
org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyTy
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.apache.fineract.useradministration.domain.AppUser;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.joda.time.Days;
 import org.joda.time.LocalDate;
 import org.joda.time.LocalDateTime;
@@ -172,23 +171,23 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "loan_type_enum", nullable = false)
     private Integer loanType;
 
-    @ManyToOne
+    @ManyToOne(fetch=FetchType.EAGER)
     @JoinColumn(name = "product_id", nullable = false)
     private LoanProduct loanProduct;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.EAGER)
     @JoinColumn(name = "fund_id", nullable = true)
     private Fund fund;
 
-    @ManyToOne
+    @ManyToOne(fetch=FetchType.EAGER)
     @JoinColumn(name = "loan_officer_id", nullable = true)
     private Staff loanOfficer;
 
-    @ManyToOne
+    @ManyToOne(fetch=FetchType.LAZY)
     @JoinColumn(name = "loanpurpose_cv_id", nullable = true)
     private CodeValue loanPurpose;
 
-    @ManyToOne
+    @ManyToOne(fetch=FetchType.EAGER)
     @JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
     private LoanTransactionProcessingStrategy transactionProcessingStrategy;
 
@@ -212,7 +211,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "submittedon_date")
     private Date submittedOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "submittedon_userid", nullable = true)
     private AppUser submittedBy;
 
@@ -220,7 +219,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "rejectedon_date")
     private Date rejectedOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "rejectedon_userid", nullable = true)
     private AppUser rejectedBy;
 
@@ -228,7 +227,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "withdrawnon_date")
     private Date withdrawnOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "withdrawnon_userid", nullable = true)
     private AppUser withdrawnBy;
 
@@ -236,7 +235,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "approvedon_date")
     private Date approvedOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "approvedon_userid", nullable = true)
     private AppUser approvedBy;
 
@@ -248,7 +247,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "disbursedon_date")
     private Date actualDisbursementDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "disbursedon_userid", nullable = true)
     private AppUser disbursedBy;
 
@@ -256,7 +255,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "closedon_date")
     private Date closedOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "closedon_userid", nullable = true)
     private AppUser closedBy;
 
@@ -268,7 +267,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "rescheduledon_date")
     private Date rescheduledOnDate;
 
-    @ManyToOne(optional = true)
+    @ManyToOne(optional = true, fetch=FetchType.LAZY)
     @JoinColumn(name = "rescheduledon_userid", nullable = true)
     private AppUser rescheduledByUser;
 
@@ -297,36 +296,38 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "loan_product_counter")
     private Integer loanProductCounter;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
     private Set<LoanCharge> charges = new HashSet<>();
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
     private Set<LoanTrancheCharge> trancheCharges = new HashSet<>();
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.LAZY)
     private Set<LoanCollateral> collateral = null;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.LAZY)
     private Set<LoanOfficerAssignmentHistory> loanOfficerHistory;
 
     // see
     // 
http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags
-    @LazyCollection(LazyCollectionOption.FALSE)
     @OrderBy(value = "installmentNumber")
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
-    private final List<LoanRepaymentScheduleInstallment> 
repaymentScheduleInstallments = new ArrayList<>();
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
+    private final Set<LoanRepaymentScheduleInstallment> 
repaymentScheduleInstallments = new HashSet<>();
 
     // see
     // 
http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags
     @OrderBy(value = "dateOf, id")
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
-    private final List<LoanTransaction> loanTransactions = new ArrayList<>();
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
+    private final Set<LoanTransaction> loanTransactions = new HashSet<>();
 
+    private transient List<LoanTransaction> sortedTransactions = null ;
+    
+    private transient boolean isTransactionsListDirty = false ;
+    
+    private transient List<LoanRepaymentScheduleInstallment> 
sortedrepaymentScheduleInstallments = null ;
+    
+    private transient boolean isrepaymentScheduleInstallmentsListDirty = false 
;
+    
     @Embedded
     private LoanSummary summary;
 
@@ -352,21 +353,18 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "max_outstanding_loan_balance", scale = 6, precision = 19, 
nullable = false)
     private BigDecimal maxOutstandingLoanBalance;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
     @OrderBy(value = "expectedDisbursementDate, id")
     private Set<LoanDisbursementDetails> disbursementDetails = new HashSet<>();
 
     @OrderBy(value = "termApplicableFrom, id")
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true)
-    private final List<LoanTermVariations> loanTermVariations = new 
ArrayList<>();
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = 
true, fetch=FetchType.EAGER)
+    private final Set<LoanTermVariations> loanTermVariations = new HashSet<>();
 
     @Column(name = "total_recovered_derived", scale = 6, precision = 19)
     private BigDecimal totalRecovered;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToOne(cascade = CascadeType.ALL, mappedBy = "loan", optional = true, 
orphanRemoval = true)
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "loan", optional = true, 
orphanRemoval = true, fetch=FetchType.EAGER)
     private LoanInterestRecalculationDetails loanInterestRecalculationDetails;
 
     @Column(name = "is_npa", nullable = false)
@@ -392,7 +390,7 @@ public class Loan extends AbstractPersistable<Long> {
     @Column(name = "interest_rate_differential", scale = 6, precision = 19, 
nullable = true)
     private BigDecimal interestRateDifferential;
     
-    @ManyToOne
+    @ManyToOne(fetch=FetchType.LAZY)
     @JoinColumn(name = "writeoff_reason_cv_id", nullable = true)
     private CodeValue writeOffReason;
 
@@ -616,7 +614,7 @@ public class Loan extends AbstractPersistable<Long> {
         // store Id's of existing loan transactions and existing reversed loan
         // transactions
         final LoanRepaymentScheduleProcessingWrapper wrapper = new 
LoanRepaymentScheduleProcessingWrapper();
-        wrapper.reprocess(getCurrency(), getDisbursementDate(), 
this.repaymentScheduleInstallments, charges());
+        wrapper.reprocess(getCurrency(), getDisbursementDate(), 
getRepaymentScheduleInstallments(), charges());
         updateLoanSummaryDerivedFields();
 
     }
@@ -627,11 +625,12 @@ public class Loan extends AbstractPersistable<Long> {
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanTransaction> allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
         changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
-                allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments, charges());
+                allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(), charges());
         for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
             mapEntry.getValue().updateLoan(this);
         }
         
this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values());
+        this.isTransactionsListDirty = true ;
         updateLoanSummaryDerivedFields();
         
this.loanTransactions.removeAll(changedTransactionDetail.getNewTransactionMappings().values());
         return changedTransactionDetail;
@@ -681,7 +680,7 @@ public class Loan extends AbstractPersistable<Long> {
         final LoanChargePaidBy loanChargePaidBy = new 
LoanChargePaidBy(applyLoanChargeTransaction, loanCharge, loanCharge.getAmount(
                 getCurrency()).getAmount(), installmentNumber);
         applyLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
-        this.loanTransactions.add(applyLoanChargeTransaction);
+        addLoanTransaction(applyLoanChargeTransaction);
         return applyLoanChargeTransaction;
     }
 
@@ -691,7 +690,7 @@ public class Loan extends AbstractPersistable<Long> {
         final LoanChargePaidBy loanChargePaidBy = new 
LoanChargePaidBy(chargesPayment, charge, chargesPayment.getAmount(getCurrency())
                 .getAmount(), installmentNumber);
         chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
-        this.loanTransactions.add(chargesPayment);
+        addLoanTransaction(chargesPayment);
         final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT,
                 LoanStatus.fromInt(this.loanStatus));
         this.loanStatus = statusEnum.getValue();
@@ -700,7 +699,8 @@ public class Loan extends AbstractPersistable<Long> {
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments 
= new ArrayList<>();
         LocalDate startDate = getDisbursementDate();
-        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
             if (installmentNumber == null && 
charge.isDueForCollectionFromAndUpToAndIncluding(startDate, 
installment.getDueDate())) {
                 chargePaymentInstallments.add(installment);
                 break;
@@ -743,7 +743,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     private LocalDate getLastRepaymentPeriodDueDate(final boolean 
includeRecalculatedInterestComponent) {
         LocalDate lastRepaymentDate = getDisbursementDate();
-        for (LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (LoanRepaymentScheduleInstallment installment : installments) {
             if ((includeRecalculatedInterestComponent || 
!installment.isRecalculatedInterestComponent())
                     && installment.getDueDate().isAfter(lastRepaymentDate)) {
                 lastRepaymentDate = installment.getDueDate();
@@ -765,7 +766,7 @@ public class Loan extends AbstractPersistable<Long> {
         if (removed) {
             loanCharge.setActive(false);
             final LoanRepaymentScheduleProcessingWrapper wrapper = new 
LoanRepaymentScheduleProcessingWrapper();
-            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
this.repaymentScheduleInstallments, charges());
+            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
getRepaymentScheduleInstallments(), charges());
             
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
         }
 
@@ -784,7 +785,7 @@ public class Loan extends AbstractPersistable<Long> {
              ***/
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
 allNonContraTransactionsPostDisbursement,
-                    getCurrency(), this.repaymentScheduleInstallments, 
charges());
+                    getCurrency(), getRepaymentScheduleInstallments(), 
charges());
         }
         this.charges.remove(loanCharge);
         updateLoanSummaryDerivedFields();
@@ -793,7 +794,8 @@ public class Loan extends AbstractPersistable<Long> {
     private void 
removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final 
LoanCharge loanCharge) {
         if (loanCharge.isDueAtDisbursement()) {
             LoanTransaction transactionToRemove = null;
-            for (final LoanTransaction transaction : this.loanTransactions) {
+            List<LoanTransaction> transactions = getLoanTransactions() ;
+            for (final LoanTransaction transaction : transactions) {
                 if (transaction.isRepaymentAtDisbursement() && 
transaction.getLoanChargesPaid().contains(loanCharge)) {
 
                     final MonetaryCurrency currency = loanCurrency();
@@ -842,11 +844,11 @@ public class Loan extends AbstractPersistable<Long> {
              ***/
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
 allNonContraTransactionsPostDisbursement,
-                    getCurrency(), this.repaymentScheduleInstallments, 
charges());
+                    getCurrency(), getRepaymentScheduleInstallments(), 
charges());
         } else {
             // reprocess loan schedule based on charge been waived.
             final LoanRepaymentScheduleProcessingWrapper wrapper = new 
LoanRepaymentScheduleProcessingWrapper();
-            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
this.repaymentScheduleInstallments, charges());
+            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
getRepaymentScheduleInstallments(), charges());
         }
 
         updateLoanSummaryDerivedFields();
@@ -889,7 +891,7 @@ public class Loan extends AbstractPersistable<Long> {
      * @return
      */
     public BigDecimal getTotalInterest() {
-        return 
this.loanSummaryWrapper.calculateTotalInterestCharged(this.repaymentScheduleInstallments,
 getCurrency()).getAmount();
+        return 
this.loanSummaryWrapper.calculateTotalInterestCharged(getRepaymentScheduleInstallments(),
 getCurrency()).getAmount();
     }
 
     private BigDecimal calculatePerInstallmentChargeAmount(final LoanCharge 
loanCharge) {
@@ -898,7 +900,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     public BigDecimal calculatePerInstallmentChargeAmount(final 
ChargeCalculationType calculationType, final BigDecimal percentage) {
         Money amount = Money.zero(getCurrency());
-        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
             amount = 
amount.plus(calculateInstallmentChargeAmount(calculationType, percentage, 
installment));
         }
         return amount.getAmount();
@@ -995,8 +998,7 @@ public class Loan extends AbstractPersistable<Long> {
         final LoanChargePaidBy loanChargePaidBy = new 
LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge, 
waiveLoanChargeTransaction
                 .getAmount(getCurrency()).getAmount(), loanInstallmentNumber);
         waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
-        this.loanTransactions.add(waiveLoanChargeTransaction);
-
+        addLoanTransaction(waiveLoanChargeTransaction) ;
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()
                 && (loanCharge.getDueLocalDate() == null || 
LocalDate.now().isAfter(loanCharge.getDueLocalDate()))) {
             
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
@@ -1016,11 +1018,11 @@ public class Loan extends AbstractPersistable<Long> {
              ***/
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
 allNonContraTransactionsPostDisbursement,
-                    getCurrency(), this.repaymentScheduleInstallments, 
charges());
+                    getCurrency(), getRepaymentScheduleInstallments(), 
charges());
         } else {
             // reprocess loan schedule based on charge been waived.
             final LoanRepaymentScheduleProcessingWrapper wrapper = new 
LoanRepaymentScheduleProcessingWrapper();
-            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
this.repaymentScheduleInstallments, charges());
+            wrapper.reprocess(getCurrency(), getDisbursementDate(), 
getRepaymentScheduleInstallments(), charges());
         }
 
         updateLoanSummaryDerivedFields();
@@ -1139,7 +1141,7 @@ public class Loan extends AbstractPersistable<Long> {
 
     public void updateLoanSchedule(final LoanScheduleModel 
modifiedLoanSchedule, AppUser currentUser) {
         this.repaymentScheduleInstallments.clear();
-
+        this.isrepaymentScheduleInstallmentsListDirty = true ;
         for (final LoanScheduleModelPeriod scheduledLoanInstallment : 
modifiedLoanSchedule.getPeriods()) {
 
             if (scheduledLoanInstallment.isRepaymentPeriod()) {
@@ -1149,7 +1151,7 @@ public class Loan extends AbstractPersistable<Long> {
                         scheduledLoanInstallment.interestDue(), 
scheduledLoanInstallment.feeChargesDue(),
                         scheduledLoanInstallment.penaltyChargesDue(), 
scheduledLoanInstallment.isRecalculatedInterestComponent(),
                         scheduledLoanInstallment.getLoanCompoundingDetails());
-                addRepaymentScheduleInstallment(installment);
+                addLoanRepaymentScheduleInstallment(installment);
             }
         }
 
@@ -1161,8 +1163,9 @@ public class Loan extends AbstractPersistable<Long> {
 
     public void updateLoanSchedule(final 
Collection<LoanRepaymentScheduleInstallment> installments, AppUser currentUser) 
{
         this.repaymentScheduleInstallments.clear();
+        this.isrepaymentScheduleInstallmentsListDirty = true ;
         for (final LoanRepaymentScheduleInstallment installment : 
installments) {
-            addRepaymentScheduleInstallment(installment);
+            addLoanRepaymentScheduleInstallment(installment);
         }
         updateLoanScheduleDependentDerivedFields();
         updateLoanSummaryDerivedFields();
@@ -1184,8 +1187,8 @@ public class Loan extends AbstractPersistable<Long> {
     }
 
     private void applyPeriodicAccruals(final Collection<LoanTransaction> 
accruals) {
-
-        for (LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (LoanRepaymentScheduleInstallment installment : installments) {
             Money interest = Money.zero(getCurrency());
             Money fee = Money.zero(getCurrency());
             Money penality = Money.zero(getCurrency());
@@ -1207,8 +1210,8 @@ public class Loan extends AbstractPersistable<Long> {
             }
             installment.updateAccrualPortion(interest, fee, penality);
         }
-        LoanRepaymentScheduleInstallment lastInstallment = 
this.repaymentScheduleInstallments
-                .get(this.repaymentScheduleInstallments.size() - 1);
+        LoanRepaymentScheduleInstallment lastInstallment = 
getRepaymentScheduleInstallments()
+                .get(getRepaymentScheduleInstallments().size() - 1);
         for (LoanTransaction loanTransaction : accruals) {
             if 
(loanTransaction.getTransactionDate().isAfter(lastInstallment.getDueDate()) && 
!loanTransaction.isReversed()) {
                 loanTransaction.reverse();
@@ -1226,7 +1229,7 @@ public class Loan extends AbstractPersistable<Long> {
                     final LocalDateTime currentDateTime = 
DateUtils.getLocalDateTimeOfTenant();
                     final LoanTransaction interestAppliedTransaction = 
LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
                             getDisbursementDate(), currentDateTime, 
currentUser);
-                    this.loanTransactions.add(interestAppliedTransaction);
+                    addLoanTransaction(interestAppliedTransaction) ;
                 }
             } else {
                 Set<LoanChargePaidBy> chargePaidBies = 
loanTransaction.getLoanChargesPaid();
@@ -1262,7 +1265,7 @@ public class Loan extends AbstractPersistable<Long> {
             this.totalRecovered = 
recoveredAmount.getAmountDefaultedToNullIfZero();
 
             final Money principal = 
this.loanRepaymentScheduleDetail.getPrincipal();
-            this.summary.updateSummary(loanCurrency(), principal, 
this.repaymentScheduleInstallments, this.loanSummaryWrapper,
+            this.summary.updateSummary(loanCurrency(), principal, 
getRepaymentScheduleInstallments(), this.loanSummaryWrapper,
                     isDisbursed(), this.charges);
             updateLoanOutstandingBalaces();
         }
@@ -1885,9 +1888,11 @@ public class Loan extends AbstractPersistable<Long> {
     }
 
     private void removeFirstDisbursementTransaction() {
-        for (final LoanTransaction loanTransaction : this.loanTransactions) {
+        List<LoanTransaction> transactions = getLoanTransactions() ;
+        for (final LoanTransaction loanTransaction : transactions) {
             if (loanTransaction.isDisbursement()) {
                 this.loanTransactions.remove(loanTransaction);
+                transactions.remove(loanTransaction) ;
                 break;
             }
         }
@@ -1970,8 +1975,9 @@ public class Loan extends AbstractPersistable<Long> {
 
     private LocalDate determineExpectedMaturityDate() {
         final int numberOfInstallments = 
this.repaymentScheduleInstallments.size();
-        LocalDate maturityDate = 
this.repaymentScheduleInstallments.get(numberOfInstallments - 1).getDueDate();
-        ListIterator<LoanRepaymentScheduleInstallment> iterator = 
this.repaymentScheduleInstallments.listIterator(numberOfInstallments);
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        LocalDate maturityDate = installments.get(numberOfInstallments - 
1).getDueDate();
+        ListIterator<LoanRepaymentScheduleInstallment> iterator = 
installments.listIterator(numberOfInstallments);
         while(iterator.hasPrevious()){
             LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment 
= iterator.previous();
             
if(!loanRepaymentScheduleInstallment.isRecalculatedInterestComponent()){
@@ -2240,8 +2246,8 @@ public class Loan extends AbstractPersistable<Long> {
     public Collection<Long> findExistingTransactionIds() {
 
         final Collection<Long> ids = new ArrayList<>();
-
-        for (final LoanTransaction transaction : this.loanTransactions) {
+        List<LoanTransaction> transactions = getLoanTransactions() ;
+        for (final LoanTransaction transaction : transactions) {
             ids.add(transaction.getId());
         }
 
@@ -2251,8 +2257,8 @@ public class Loan extends AbstractPersistable<Long> {
     public Collection<Long> findExistingReversedTransactionIds() {
 
         final Collection<Long> ids = new ArrayList<>();
-
-        for (final LoanTransaction transaction : this.loanTransactions) {
+        List<LoanTransaction> transactions = getLoanTransactions() ;
+        for (final LoanTransaction transaction : transactions) {
             if (transaction.isReversed()) {
                 ids.add(transaction.getId());
             }
@@ -2304,10 +2310,10 @@ public class Loan extends AbstractPersistable<Long> {
          **/
 
         if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()
-                       && ((isMultiDisburmentLoan() && 
getDisbursedLoanDisbursementDetails().size() == 1) || 
!isMultiDisburmentLoan())) {
+                        && ((isMultiDisburmentLoan() && 
getDisbursedLoanDisbursementDetails().size() == 1) || 
!isMultiDisburmentLoan())) {
             final LoanTransaction interestAppliedTransaction = 
LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
                     actualDisbursementDate, createdDate, currentUser);
-            this.loanTransactions.add(interestAppliedTransaction);
+            addLoanTransaction(interestAppliedTransaction) ;
         }
 
         return reprocessTransactionForDisbursement();
@@ -2315,18 +2321,18 @@ public class Loan extends AbstractPersistable<Long> {
     }
 
     private List<LoanDisbursementDetails> 
getDisbursedLoanDisbursementDetails() {
-       List<LoanDisbursementDetails> ret = new ArrayList<>();
-       if(this.disbursementDetails != null && this.disbursementDetails.size() 
> 0){
+        List<LoanDisbursementDetails> ret = new ArrayList<>();
+        if(this.disbursementDetails != null && this.disbursementDetails.size() 
> 0){
             for (LoanDisbursementDetails disbursementDetail : 
this.disbursementDetails) {
                 if (disbursementDetail.actualDisbursementDate() != null) {
                     ret.add(disbursementDetail);
                 }
             }
-       }
-               return ret;
-       }
+        }
+                return ret;
+        }
 
-       public void regenerateScheduleOnDisbursement(final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final boolean recalculateSchedule,
+        public void regenerateScheduleOnDisbursement(final 
ScheduleGeneratorDTO scheduleGeneratorDTO, final boolean recalculateSchedule,
             final LocalDate actualDisbursementDate, BigDecimal emiAmount, 
final AppUser currentUser, LocalDate nextPossibleRepaymentDate,
             Date rescheduledRepaymentDate) {
         boolean isEmiAmountChanged = false;
@@ -2456,7 +2462,7 @@ public class Loan extends AbstractPersistable<Long> {
                 final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
                         
.determineProcessor(this.transactionProcessingStrategy);
                 changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
-                        allNonContraTransactionsPostDisbursement, 
getCurrency(), this.repaymentScheduleInstallments, charges());
+                        allNonContraTransactionsPostDisbursement, 
getCurrency(), getRepaymentScheduleInstallments(), charges());
                 for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                     mapEntry.getValue().updateLoan(this);
                 }
@@ -2556,8 +2562,8 @@ public class Loan extends AbstractPersistable<Long> {
     }
 
     private void updateLoanRepaymentPeriodsDerivedFields(final LocalDate 
actualDisbursementDate) {
-
-        for (final LoanRepaymentScheduleInstallment repaymentPeriod : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment repaymentPeriod : 
installments) {
             repaymentPeriod.updateDerivedFields(loanCurrency(), 
actualDisbursementDate);
         }
     }
@@ -2667,7 +2673,7 @@ public class Loan extends AbstractPersistable<Long> {
             final Money zero = Money.zero(getCurrency());
             chargesPayment.updateComponentsAndTotal(zero, zero, 
disbursentMoney, zero);
             chargesPayment.updateLoan(this);
-            this.loanTransactions.add(chargesPayment);
+            addLoanTransaction(chargesPayment) ;
             updateLoanOutstandingBalaces();
         }
 
@@ -2713,7 +2719,7 @@ public class Loan extends AbstractPersistable<Long> {
         final Money zero = Money.zero(getCurrency());
         chargesPayment.updateComponents(zero, zero, 
charge.getAmount(getCurrency()), zero);
         chargesPayment.updateLoan(this);
-        this.loanTransactions.add(chargesPayment);
+        addLoanTransaction(chargesPayment) ;
         updateLoanOutstandingBalaces();
         charge.markAsFullyPaid();
         return chargesPayment;
@@ -2786,8 +2792,8 @@ public class Loan extends AbstractPersistable<Long> {
                 charge.resetToOriginal(loanCurrency());
             }
         }
-
-        for (final LoanRepaymentScheduleInstallment currentInstallment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment currentInstallment : 
installments) {
             currentInstallment.resetDerivedComponents();
         }
         final List<LoanTermVariations> removeTerms = new 
ArrayList<>(this.loanTermVariations.size());
@@ -2798,7 +2804,7 @@ public class Loan extends AbstractPersistable<Long> {
         }
         this.loanTermVariations.removeAll(removeTerms);
         final LoanRepaymentScheduleProcessingWrapper wrapper = new 
LoanRepaymentScheduleProcessingWrapper();
-        wrapper.reprocess(getCurrency(), getDisbursementDate(), 
this.repaymentScheduleInstallments, charges());
+        wrapper.reprocess(getCurrency(), getDisbursementDate(), 
getRepaymentScheduleInstallments(), charges());
 
         updateLoanSummaryDerivedFields();
     }
@@ -2899,7 +2905,7 @@ public class Loan extends AbstractPersistable<Long> {
                 final String errorMessage = "The refund amount must be less 
than or equal to overpaid amount ";
                 throw new InvalidLoanStateTransitionException("transaction", 
"is.exceeding.overpaid.amount", errorMessage,
                         this.totalOverpaid, 
loanTransaction.getAmount(getCurrency()).getAmount());
-            } else if (!isAfterLatRepayment(loanTransaction, 
this.loanTransactions)) {
+            } else if (!isAfterLatRepayment(loanTransaction, 
getLoanTransactions())) {
                 final String errorMessage = "Transfer funds is allowed only 
after last repayment date";
                 throw new InvalidLoanStateTransitionException("transaction", 
"is.not.after.repayment.date", errorMessage);
             }
@@ -2910,7 +2916,7 @@ public class Loan extends AbstractPersistable<Long> {
         loanTransaction.updateLoan(this);
 
         if (loanTransaction.isNotZero(loanCurrency())) {
-            this.loanTransactions.add(loanTransaction);
+            addLoanTransaction(loanTransaction) ;
         }
         updateLoanSummaryDerivedFields();
         doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), 
loanLifecycleStateMachine);
@@ -2939,10 +2945,10 @@ public class Loan extends AbstractPersistable<Long> {
 
         loanTransaction.updateLoan(this);
 
-        final boolean isTransactionChronologicallyLatest = 
isChronologicallyLatestRepaymentOrWaiver(loanTransaction, 
this.loanTransactions);
+        final boolean isTransactionChronologicallyLatest = 
isChronologicallyLatestRepaymentOrWaiver(loanTransaction, 
getLoanTransactions());
 
         if (loanTransaction.isNotZero(loanCurrency())) {
-            this.loanTransactions.add(loanTransaction);
+            addLoanTransaction(loanTransaction) ;
         }
 
         if (loanTransaction.isNotRepayment() && loanTransaction.isNotWaiver() 
&& loanTransaction.isNotRecoveryRepayment()) {
@@ -3000,7 +3006,7 @@ public class Loan extends AbstractPersistable<Long> {
 
         if (isTransactionChronologicallyLatest && adjustedTransaction == null
                 && (!reprocess || 
!this.repaymentScheduleDetail().isInterestRecalculationEnabled()) && 
!isForeclosure()) {
-            
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, 
getCurrency(), this.repaymentScheduleInstallments,
+            
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, 
getCurrency(), getRepaymentScheduleInstallments(),
                     charges());
             reprocess = false;
             if 
(this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
@@ -3021,7 +3027,7 @@ public class Loan extends AbstractPersistable<Long> {
             }
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
-                    allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments, charges());
+                    allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(), charges());
             for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                 mapEntry.getValue().updateLoan(this);
             }
@@ -3031,6 +3037,7 @@ public class Loan extends AbstractPersistable<Long> {
              * transactions first and then new transactions.
              */
             
this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values());
+            this.isTransactionsListDirty = true ;
         }
 
         updateLoanSummaryDerivedFields();
@@ -3061,7 +3068,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     private LoanRepaymentScheduleInstallment 
fetchLoanRepaymentScheduleInstallment(LocalDate dueDate) {
         LoanRepaymentScheduleInstallment installment = null;
-        for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment 
: this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment 
: installments) {
             if (dueDate.equals(loanRepaymentScheduleInstallment.getDueDate())) 
{
                 installment = loanRepaymentScheduleInstallment;
                 break;
@@ -3072,7 +3080,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     private List<LoanTransaction> retreiveListOfIncomePostingTransactions() {
         final List<LoanTransaction> incomePostTransactions = new ArrayList<>();
-        for (final LoanTransaction transaction : this.loanTransactions) {
+        List<LoanTransaction> trans = getLoanTransactions() ;
+        for (final LoanTransaction transaction : trans) {
             if (transaction.isNotReversed() && transaction.isIncomePosting()) {
                 incomePostTransactions.add(transaction);
             }
@@ -3084,7 +3093,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     private List<LoanTransaction> retreiveListOfTransactionsPostDisbursement() 
{
         final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
-        for (final LoanTransaction transaction : this.loanTransactions) {
+        List<LoanTransaction> trans = getLoanTransactions() ;
+        for (final LoanTransaction transaction : trans) {
             if (transaction.isNotReversed() && !(transaction.isDisbursement() 
|| transaction.isNonMonetaryTransaction())) {
                 repaymentsOrWaivers.add(transaction);
             }
@@ -3185,7 +3195,7 @@ public class Loan extends AbstractPersistable<Long> {
             BigDecimal amountToPost = 
interestToPost.add(feeToPost).add(penaltyToPost);
             LoanTransaction finalIncomeTransaction = 
LoanTransaction.incomePosting(this, this.getOffice(), closedDate, amountToPost,
                     interestToPost, feeToPost, penaltyToPost, null);
-            this.loanTransactions.add(finalIncomeTransaction);
+            addLoanTransaction(finalIncomeTransaction) ;
             if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
                 List<LoanTransaction> updatedAccrualTransactions = 
retreiveListOfAccrualTransactions();
                 LocalDate lastAccruedDate = this.getDisbursementDate();
@@ -3197,7 +3207,7 @@ public class Loan extends AbstractPersistable<Long> {
                 LoanTransaction finalAccrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), closedLocalDate, 
amountToPost,
                         interestToPost, feeToPost, penaltyToPost, null);
                 updateLoanChargesPaidBy(finalAccrual, feeDetails, null);
-                this.loanTransactions.add(finalAccrual);
+                addLoanTransaction(finalAccrual) ;
             }
         }
         updateLoanOutstandingBalaces();
@@ -3207,7 +3217,8 @@ public class Loan extends AbstractPersistable<Long> {
         BigDecimal interest = BigDecimal.ZERO;
         BigDecimal fee = BigDecimal.ZERO;
         BigDecimal penalty = BigDecimal.ZERO;
-        for (LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (LoanRepaymentScheduleInstallment installment : installments) {
             interest = 
interest.add(installment.getInterestCharged(getCurrency()).getAmount());
             fee = 
fee.add(installment.getFeeChargesCharged(getCurrency()).getAmount());
             penalty = 
penalty.add(installment.getPenaltyChargesCharged(getCurrency()).getAmount());
@@ -3295,7 +3306,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     public LocalDate possibleNextRepaymentDate() {
         LocalDate earliestUnpaidInstallmentDate = new LocalDate();
-        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
             if (installment.isNotFullyPaidOff()) {
                 earliestUnpaidInstallmentDate = installment.getDueDate();
                 break;
@@ -3319,8 +3331,8 @@ public class Loan extends AbstractPersistable<Long> {
 
     public LoanRepaymentScheduleInstallment possibleNextRepaymentInstallment() 
{
         LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = 
null;
-
-        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment installment : 
installments) {
             if (installment.isNotFullyPaidOff()) {
                 loanRepaymentScheduleInstallment = installment;
                 break;
@@ -3339,7 +3351,8 @@ public class Loan extends AbstractPersistable<Long> {
         if (totalInterestOutstanding.isGreaterThanZero()) {
             // find earliest known instance of overdue interest and default to
             // that
-            for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
this.repaymentScheduleInstallments) {
+            List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+            for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
installments) {
 
                 final Money outstandingForPeriod = 
scheduledRepayment.getInterestOutstanding(loanCurrency());
                 if (scheduledRepayment.isOverdueOn(new LocalDate()) && 
scheduledRepayment.isNotFullyPaidOff()
@@ -3418,7 +3431,7 @@ public class Loan extends AbstractPersistable<Long> {
             
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
         }
         ChangedTransactionDetail changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(
-                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments,
+                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(),
                 charges());
         updateLoanSummaryDerivedFields();
         return changedTransactionDetail;
@@ -3447,8 +3460,8 @@ public class Loan extends AbstractPersistable<Long> {
         final MonetaryCurrency currency = loanCurrency();
         Money cumulativeTotalPaidOnInstallments = Money.zero(currency);
         Money cumulativeTotalWaivedOnInstallments = Money.zero(currency);
-
-        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
installments) {
 
             cumulativeTotalPaidOnInstallments = 
cumulativeTotalPaidOnInstallments
                     
.plus(scheduledRepayment.getPrincipalCompleted(currency).plus(scheduledRepayment.getInterestPaid(currency)))
@@ -3533,9 +3546,8 @@ public class Loan extends AbstractPersistable<Long> {
                         writtenOffOnLocalDate);
             }
 
-            this.loanTransactions.add(loanTransaction);
-
-            
loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, 
loanCurrency(), this.repaymentScheduleInstallments);
+            addLoanTransaction(loanTransaction) ;
+            
loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, 
loanCurrency(), getRepaymentScheduleInstallments());
 
             updateLoanSummaryDerivedFields();
         }
@@ -3558,10 +3570,10 @@ public class Loan extends AbstractPersistable<Long> {
             }
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
-                    allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments, charges());
+                    allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(), charges());
             for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                 mapEntry.getValue().updateLoan(this);
-                this.loanTransactions.add(mapEntry.getValue());
+                addLoanTransaction(mapEntry.getValue()) ;
             }
             updateLoanSummaryDerivedFields();
             LoanTransaction loanTransaction = findlatestTransaction();
@@ -3627,17 +3639,16 @@ public class Loan extends AbstractPersistable<Long> {
                 this.closedOnDate = closureDate.toDate();
                 loanTransaction = LoanTransaction.writeoff(this, getOffice(), 
closureDate, txnExternalId,
                         DateUtils.getLocalDateTimeOfTenant(), currentUser);
-                final boolean isLastTransaction = 
isChronologicallyLatestTransaction(loanTransaction, this.loanTransactions);
+                final boolean isLastTransaction = 
isChronologicallyLatestTransaction(loanTransaction, getLoanTransactions());
                 if (!isLastTransaction) {
                     final String errorMessage = "The closing date of the loan 
must be on or after latest transaction date.";
                     throw new 
InvalidLoanStateTransitionException("close.loan", 
"must.occur.on.or.after.latest.transaction.date",
                             errorMessage, closureDate);
                 }
 
-                this.loanTransactions.add(loanTransaction);
-
+                addLoanTransaction(loanTransaction) ;
                 
loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, 
loanCurrency(),
-                        this.repaymentScheduleInstallments);
+                        getRepaymentScheduleInstallments());
 
                 updateLoanSummaryDerivedFields();
             } else if (totalOutstanding.isGreaterThanZero()) {
@@ -3871,11 +3882,6 @@ public class Loan extends AbstractPersistable<Long> {
         return firstRepaymentDate;
     }
 
-    private void addRepaymentScheduleInstallment(final 
LoanRepaymentScheduleInstallment installment) {
-        installment.updateLoan(this);
-        this.repaymentScheduleInstallments.add(installment);
-    }
-
     private boolean isActualDisbursedOnDateEarlierOrLaterThanExpected(final 
LocalDate actualDisbursedOnDate) {
         boolean isRegenerationRequired = false;
         if (this.loanProduct.isMultiDisburseLoan()) {
@@ -3917,7 +3923,8 @@ public class Loan extends AbstractPersistable<Long> {
     private Money getTotalInterestOutstandingOnLoan() {
         Money cumulativeInterest = Money.zero(loanCurrency());
 
-        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
installments) {
             cumulativeInterest = 
cumulativeInterest.plus(scheduledRepayment.getInterestOutstanding(loanCurrency()));
         }
 
@@ -3927,8 +3934,8 @@ public class Loan extends AbstractPersistable<Long> {
     @SuppressWarnings("unused")
     private Money getTotalInterestOverdueOnLoan() {
         Money cumulativeInterestOverdue = 
Money.zero(this.loanRepaymentScheduleDetail.getPrincipal().getCurrency());
-
-        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
installments) {
 
             final Money interestOutstandingForPeriod = 
scheduledRepayment.getInterestOutstanding(loanCurrency());
             if (scheduledRepayment.isOverdueOn(new LocalDate())) {
@@ -4263,7 +4270,8 @@ public class Loan extends AbstractPersistable<Long> {
         LocalDate newRepaymentDate = null;
         Boolean isFirstTime = true;
         LocalDate latestRepaymentDate = null;
-        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : installments) {
 
             LocalDate oldDueDate = 
loanRepaymentScheduleInstallment.getDueDate();
 
@@ -4319,7 +4327,8 @@ public class Loan extends AbstractPersistable<Long> {
         LocalDate newRepaymentDate = null;
         LocalDate seedDate = meetingStartDate;
         LocalDate latestRepaymentDate = null;
-        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : installments) {
 
             LocalDate oldDueDate = 
loanRepaymentScheduleInstallment.getDueDate();
 
@@ -4387,7 +4396,8 @@ public class Loan extends AbstractPersistable<Long> {
         // first repayment's from date is same as disbursement date.
         LocalDate tmpFromDate = getDisbursementDate();
         // Loop through all loanRepayments
-        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment : installments) {
             final LocalDate oldDueDate = 
loanRepaymentScheduleInstallment.getDueDate();
 
             // update from date if it's not same as previous installament's due
@@ -4495,10 +4505,21 @@ public class Loan extends AbstractPersistable<Long> {
         return this.termPeriodFrequencyType;
     }
 
+    //This method returns copy of all transactions
     public List<LoanTransaction> getLoanTransactions() {
-        return this.loanTransactions;
+        if(this.sortedTransactions == null || isTransactionsListDirty) {
+            this.sortedTransactions = new ArrayList<>(this.loanTransactions) ;
+            this.sortedTransactions.sort(new LoanTransactionComparator());
+            this.isTransactionsListDirty = false ;
+        }
+        return sortedTransactions;
     }
 
+    public void addLoanTransaction(final LoanTransaction loanTransaction) {
+        this.loanTransactions.add(loanTransaction) ;
+        this.isTransactionsListDirty = true ;
+    }
+    
     public void setLoanStatus(final Integer loanStatus) {
         this.loanStatus = loanStatus;
     }
@@ -4680,7 +4701,8 @@ public class Loan extends AbstractPersistable<Long> {
     public Set<LoanInstallmentCharge> generateInstallmentLoanCharges(final 
LoanCharge loanCharge) {
         final Set<LoanInstallmentCharge> loanChargePerInstallments = new 
HashSet<>();
         if (loanCharge.isInstalmentFee()) {
-            for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+            List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+            for (final LoanRepaymentScheduleInstallment installment : 
installments) {
                 BigDecimal amount = BigDecimal.ZERO;
                 if (loanCharge.getChargeCalculation().isFlat()) {
                     amount = loanCharge.amountOrPercentage();
@@ -4900,11 +4922,11 @@ public class Loan extends AbstractPersistable<Long> {
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanTransaction> allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
         ChangedTransactionDetail changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(
-                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments,
+                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(),
                 charges());
         for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
             mapEntry.getValue().updateLoan(this);
-            this.loanTransactions.add(mapEntry.getValue());
+            addLoanTransaction(mapEntry.getValue());
         }
 
         return changedTransactionDetail;
@@ -4925,7 +4947,8 @@ public class Loan extends AbstractPersistable<Long> {
     public LoanRepaymentScheduleInstallment 
fetchRepaymentScheduleInstallment(final Integer installmentNumber) {
         LoanRepaymentScheduleInstallment installment = null;
         if (installmentNumber == null) { return installment; }
-        for (final LoanRepaymentScheduleInstallment scheduleInstallment : 
this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment scheduleInstallment : 
installments) {
             if 
(scheduleInstallment.getInstallmentNumber().equals(installmentNumber)) {
                 installment = scheduleInstallment;
                 break;
@@ -5006,7 +5029,7 @@ public class Loan extends AbstractPersistable<Long> {
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanTransaction> allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
         ChangedTransactionDetail changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(
-                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments,
+                getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(),
                 charges());
         for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
             mapEntry.getValue().updateLoan(this);
@@ -5017,7 +5040,7 @@ public class Loan extends AbstractPersistable<Long> {
          * first and then new transactions.
          */
         
this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values());
-
+        this.isTransactionsListDirty = true ;
         updateLoanSummaryDerivedFields();
 
         
this.loanTransactions.removeAll(changedTransactionDetail.getNewTransactionMappings().values());
@@ -5094,8 +5117,8 @@ public class Loan extends AbstractPersistable<Long> {
                         accrualTransaction);
                 lastCompoundingDate = compoundingDetail.getEffectiveDate();
             }
-            LoanRepaymentScheduleInstallment lastInstallment = 
this.repaymentScheduleInstallments.get(this.repaymentScheduleInstallments
-                    .size() - 1);
+            List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+            LoanRepaymentScheduleInstallment lastInstallment = 
installments.get(installments.size() - 1);
             reverseTransactionsPostEffectiveDate(incomeTransactions, 
lastInstallment.getDueDate());
             reverseTransactionsPostEffectiveDate(accrualTransactions, 
lastInstallment.getDueDate());
         }
@@ -5137,12 +5160,12 @@ public class Loan extends AbstractPersistable<Long> {
         if (existingIncomeTransaction == null) {
             LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(), compoundingDetail.getEffectiveDate()
                     .toDate(), compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
-            this.loanTransactions.add(transaction);
+            addLoanTransaction(transaction);
         } else if 
(existingIncomeTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount())
 != 0) {
             existingIncomeTransaction.reverse();
             LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(), compoundingDetail.getEffectiveDate()
                     .toDate(), compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
-            this.loanTransactions.add(transaction);
+            addLoanTransaction(transaction);
         }
 
         if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
@@ -5150,13 +5173,13 @@ public class Loan extends AbstractPersistable<Long> {
                 LoanTransaction accrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), 
compoundingDetail.getEffectiveDate(),
                         compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
                 updateLoanChargesPaidBy(accrual, feeDetails, null);
-                this.loanTransactions.add(accrual);
+                addLoanTransaction(accrual);
             } else if 
(existingAccrualTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount())
 != 0) {
                 existingAccrualTransaction.reverse();
                 LoanTransaction accrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), 
compoundingDetail.getEffectiveDate(),
                         compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
                 updateLoanChargesPaidBy(accrual, feeDetails, null);
-                this.loanTransactions.add(accrual);
+                addLoanTransaction(accrual);
             }
         }
         updateLoanOutstandingBalaces();
@@ -5167,7 +5190,8 @@ public class Loan extends AbstractPersistable<Long> {
         BigDecimal penalties = BigDecimal.ZERO;
 
         List<Integer> installments = new ArrayList<>();
-        for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment 
: this.repaymentScheduleInstallments) {
+        List<LoanRepaymentScheduleInstallment> repaymentSchedule = 
getRepaymentScheduleInstallments() ;
+        for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment 
: repaymentSchedule) {
             if (loanRepaymentScheduleInstallment.getDueDate().isAfter(fromDate)
                     && 
!loanRepaymentScheduleInstallment.getDueDate().isAfter(toDate)) {
                 
installments.add(loanRepaymentScheduleInstallment.getInstallmentNumber());
@@ -5218,8 +5242,9 @@ public class Loan extends AbstractPersistable<Long> {
 
     private List<LoanInterestRecalcualtionAdditionalDetails> 
extractInterestRecalculationAdditionalDetails() {
         List<LoanInterestRecalcualtionAdditionalDetails> retDetails = new 
ArrayList<>();
+        List<LoanRepaymentScheduleInstallment> repaymentSchedule = 
getRepaymentScheduleInstallments() ;
         if (null != this.repaymentScheduleInstallments && 
this.repaymentScheduleInstallments.size() > 0) {
-            Iterator<LoanRepaymentScheduleInstallment> installmentsItr = 
this.repaymentScheduleInstallments.iterator();
+            Iterator<LoanRepaymentScheduleInstallment> installmentsItr = 
repaymentSchedule.iterator();
             while (installmentsItr.hasNext()) {
                 LoanRepaymentScheduleInstallment installment = 
installmentsItr.next();
                 if (null != installment.getLoanCompoundingDetails()) {
@@ -5247,7 +5272,7 @@ public class Loan extends AbstractPersistable<Long> {
                 
copyTransactions.add(LoanTransaction.copyTransactionProperties(loanTransaction));
             }
             
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
 copyTransactions, getCurrency(),
-                    this.repaymentScheduleInstallments, charges());
+                    getRepaymentScheduleInstallments(), charges());
 
             updateLoanSummaryDerivedFields();
         }
@@ -5269,7 +5294,7 @@ public class Loan extends AbstractPersistable<Long> {
 
         return loanScheduleGenerator.rescheduleNextInstallments(mc, 
loanApplicationTerms, charges(), generatorDTO.getHolidayDetailDTO(),
                 retreiveListOfTransactionsPostDisbursementExcludeAccruals(), 
loanRepaymentScheduleTransactionProcessor,
-                repaymentScheduleInstallments, 
generatorDTO.getRecalculateFrom());
+                getRepaymentScheduleInstallments(), 
generatorDTO.getRecalculateFrom());
     }
 
     public LoanRepaymentScheduleInstallment fetchPrepaymentDetail(final 
ScheduleGeneratorDTO scheduleGeneratorDTO, final LocalDate onDate) {
@@ -5287,7 +5312,7 @@ public class Loan extends AbstractPersistable<Long> {
                     .determineProcessor(this.transactionProcessingStrategy);
             installment = 
loanScheduleGenerator.calculatePrepaymentAmount(getCurrency(), onDate, 
loanApplicationTerms, mc, charges(),
                     scheduleGeneratorDTO.getHolidayDetailDTO(), 
retreiveListOfTransactionsPostDisbursementExcludeAccruals(),
-                    loanRepaymentScheduleTransactionProcessor, 
this.fetchRepaymentScheduleInstallments());
+                    loanRepaymentScheduleTransactionProcessor, 
getRepaymentScheduleInstallments());
         } else {
             installment = this.getTotalOutstandingOnLoan();
         }
@@ -5348,7 +5373,7 @@ public class Loan extends AbstractPersistable<Long> {
                 this.loanProduct.getInstallmentAmountInMultiplesOf(), 
recalculationFrequencyType, restCalendarInstance, compoundingMethod,
                 compoundingCalendarInstance, compoundingFrequencyType, 
this.loanProduct.preCloseInterestCalculationStrategy(),
                 rescheduleStrategyMethod, calendar, getApprovedPrincipal(), 
annualNominalInterestRate, loanTermVariations, calendarHistoryDataWrapper,
-               scheduleGeneratorDTO.getNumberOfdays(), 
scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth(), holidayDetailDTO, 
allowCompoundingOnEod);
+                scheduleGeneratorDTO.getNumberOfdays(), 
scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth(), holidayDetailDTO, 
allowCompoundingOnEod);
         return loanApplicationTerms;
     }
 
@@ -5366,8 +5391,9 @@ public class Loan extends AbstractPersistable<Long> {
         Money penaltyCharges = Money.zero(loanCurrency());
         Money totalPrincipal = Money.zero(loanCurrency());
         Money totalInterest = Money.zero(loanCurrency());
-        final List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
-        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
this.repaymentScheduleInstallments) {
+        final Set<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
+        List<LoanRepaymentScheduleInstallment> repaymentSchedule = 
getRepaymentScheduleInstallments() ;
+        for (final LoanRepaymentScheduleInstallment scheduledRepayment : 
repaymentSchedule) {
             totalPrincipal = 
totalPrincipal.plus(scheduledRepayment.getPrincipalOutstanding(loanCurrency()));
             totalInterest = 
totalInterest.plus(scheduledRepayment.getInterestOutstanding(loanCurrency()));
             feeCharges = 
feeCharges.plus(scheduledRepayment.getFeeChargesOutstanding(loanCurrency()));
@@ -5377,10 +5403,6 @@ public class Loan extends AbstractPersistable<Long> {
                 totalInterest.getAmount(), feeCharges.getAmount(), 
penaltyCharges.getAmount(), false, compoundingDetails);
     }
 
-    public List<LoanRepaymentScheduleInstallment> 
fetchRepaymentScheduleInstallments() {
-        return this.repaymentScheduleInstallments;
-    }
-
     public LocalDate getAccruedTill() {
         LocalDate accruedTill = null;
         if (this.accruedTill != null) {
@@ -5431,9 +5453,21 @@ public class Loan extends AbstractPersistable<Long> {
      * @return List of loan repayments schedule objects
      **/
     public List<LoanRepaymentScheduleInstallment> 
getRepaymentScheduleInstallments() {
-        return this.repaymentScheduleInstallments;
+        if (this.sortedrepaymentScheduleInstallments == null || 
this.isrepaymentScheduleInstallmentsListDirty) {
+            this.sortedrepaymentScheduleInstallments = new 
ArrayList<>(this.repaymentScheduleInstallments);
+            
this.sortedrepaymentScheduleInstallments.sort(LoanRepaymentScheduleInstallment.installmentNumberComparator);
+        }
+        return sortedrepaymentScheduleInstallments;
     }
 
+    public Integer getLoanRepaymentScheduleInstallmentsSize() {
+        return this.repaymentScheduleInstallments.size() ;
+    }
+    public void addLoanRepaymentScheduleInstallment(final 
LoanRepaymentScheduleInstallment installment) {
+        installment.updateLoan(this);
+        this.repaymentScheduleInstallments.add(installment);
+        this.isrepaymentScheduleInstallmentsListDirty = true ;
+    }
     /**
      * @return Loan product minimum repayments schedule related detail
      **/
@@ -5464,7 +5498,8 @@ public class Loan extends AbstractPersistable<Long> {
         LoanRepaymentScheduleInstallment installment = null;
 
         if (dueDate != null) {
-            for (LoanRepaymentScheduleInstallment repaymentScheduleInstallment 
: this.repaymentScheduleInstallments) {
+            List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+            for (LoanRepaymentScheduleInstallment repaymentScheduleInstallment 
: installments) {
 
                 if 
(repaymentScheduleInstallment.getDueDate().isEqual(dueDate)) {
                     installment = repaymentScheduleInstallment;
@@ -5747,7 +5782,7 @@ public class Loan extends AbstractPersistable<Long> {
         }
 
         if (loanTransaction.isNotZero(loanCurrency())) {
-            this.loanTransactions.add(loanTransaction);
+            addLoanTransaction(loanTransaction);
         }
 
         if (loanTransaction.isNotRefundForActiveLoan()) {
@@ -5782,12 +5817,12 @@ public class Loan extends AbstractPersistable<Long> {
 
         // If is a refund
         if (adjustedTransaction == null) {
-            
loanRepaymentScheduleTransactionProcessor.handleRefund(loanTransaction, 
getCurrency(), this.repaymentScheduleInstallments,
+            
loanRepaymentScheduleTransactionProcessor.handleRefund(loanTransaction, 
getCurrency(), getRepaymentScheduleInstallments(),
                     charges());
         } else {
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
-                    allNonContraTransactionsPostDisbursement, getCurrency(), 
this.repaymentScheduleInstallments, charges());
+                    allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(), charges());
             for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                 mapEntry.getValue().updateLoan(this);
             }
@@ -5932,7 +5967,7 @@ public class Loan extends AbstractPersistable<Long> {
         this.interestRateDifferential = interestRateDifferential;
     }
 
-    public List<LoanTermVariations> getLoanTermVariations() {
+    public Set<LoanTermVariations> getLoanTermVariations() {
         return this.loanTermVariations;
     }
 
@@ -5950,8 +5985,9 @@ public class Loan extends AbstractPersistable<Long> {
 
     public int fetchNumberOfInstallmensAfterExceptions() {
         if (this.repaymentScheduleInstallments.size() > 0) {
+            List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
             int numberOfInstallments = 0;
-            for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+            for (final LoanRepaymentScheduleInstallment installment : 
installments) {
                 if (!installment.isRecalculatedInterestComponent()) {
                     numberOfInstallments++;
                 }
@@ -5973,7 +6009,8 @@ public class Loan extends AbstractPersistable<Long> {
         LocalDate nextRepaymentDate = new LocalDate();
         for (LoanDisbursementDetails loanDisbursementDetail : 
loanDisbursementDetails) {
             if (loanDisbursementDetail.actualDisbursementDate() == null) {
-                for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
+                List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments() ;
+                for (final LoanRepaymentScheduleInstallment installment : 
installments) {
                     if 
(installment.getDueDate().isEqual(loanDisbursementDetail.expectedDisbursementDateAsLocalDate())
                             || 
installment.getDueDate().isAfter(loanDisbursementDetail.expectedDisbursementDateAsLocalDate())
                             && installment.isNotFullyPaidOff()) {
@@ -6009,12 +6046,12 @@ public class Loan extends AbstractPersistable<Long> {
     public LoanProduct getLoanProduct() {
         return loanProduct;
     }
-       
+        
     public LoanRepaymentScheduleInstallment fetchLoanForeclosureDetail(final 
LocalDate closureDate) {        
         Money[] receivables = retriveIncomeOutstandingTillDate(closureDate);
         Money totalPrincipal = (Money.of(getCurrency(), 
this.getSummary().getTotalPrincipalOutstanding()));
         totalPrincipal = totalPrincipal.minus(receivables[3]);
-        final List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
+        final Set<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
         final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
         return new LoanRepaymentScheduleInstallment(null, 0, currentDate, 
currentDate, totalPrincipal.getAmount(),
                 receivables[0].getAmount(), receivables[1].getAmount(), 
receivables[2].getAmount(), false, compoundingDetails);
@@ -6278,7 +6315,7 @@ public class Loan extends AbstractPersistable<Long> {
     public void updateLoanScheduleOnForeclosure(final 
Collection<LoanRepaymentScheduleInstallment> installments) {
         this.repaymentScheduleInstallments.clear();
         for (final LoanRepaymentScheduleInstallment installment : 
installments) {
-            addRepaymentScheduleInstallment(installment);
+            addLoanRepaymentScheduleInstallment(installment);
         }
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index aa204e7..1f7e0fd 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -192,7 +192,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             for (Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                 
saveLoanTransactionWithDataIntegrityViolationChecks(mapEntry.getValue());
                 // update loan with references to the newly created 
transactions
-                loan.getLoanTransactions().add(mapEntry.getValue());
+                loan.addLoanTransaction(mapEntry.getValue());
                 updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
             }
         }
@@ -235,7 +235,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
     private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan 
loan) {
         try {
-            List<LoanRepaymentScheduleInstallment> installments = 
loan.fetchRepaymentScheduleInstallments();
+            List<LoanRepaymentScheduleInstallment> installments = 
loan.getRepaymentScheduleInstallments();
             for (LoanRepaymentScheduleInstallment installment : installments) {
                 if (installment.getId() == null) {
                     
this.repaymentScheduleInstallmentRepository.save(installment);
@@ -257,7 +257,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     @Override
     public void saveLoanWithDataIntegrityViolationChecks(final Loan loan) {
         try {
-            List<LoanRepaymentScheduleInstallment> installments = 
loan.fetchRepaymentScheduleInstallments();
+            List<LoanRepaymentScheduleInstallment> installments = 
loan.getRepaymentScheduleInstallments();
             for (LoanRepaymentScheduleInstallment installment : installments) {
                 if (installment.getId() == null) {
                     
this.repaymentScheduleInstallmentRepository.save(installment);
@@ -410,7 +410,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         LoanTransaction disbursementTransaction = 
LoanTransaction.disbursement(loan.getOffice(), amount, paymentDetail, 
transactionDate,
                 txnExternalId, DateUtils.getLocalDateTimeOfTenant(), 
currentUser);
         disbursementTransaction.updateLoan(loan);
-        loan.getLoanTransactions().add(disbursementTransaction);
+        loan.addLoanTransaction(disbursementTransaction);
         
saveLoanTransactionWithDataIntegrityViolationChecks(disbursementTransaction);
         saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
 
@@ -448,7 +448,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         if (!loan.isPeriodicAccrualAccountingEnabledOnLoanProduct() || 
!loan.repaymentScheduleDetail().isInterestRecalculationEnabled()
                 || accruedTill == null || loan.isNpa() || 
!loan.status().isActive()) { return; }
         Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = new 
ArrayList<>();
-        List<LoanRepaymentScheduleInstallment> installments = 
loan.fetchRepaymentScheduleInstallments();
+        List<LoanRepaymentScheduleInstallment> installments = 
loan.getRepaymentScheduleInstallments();
         Long loanId = loan.getId();
         Long officeId = loan.getOfficeId();
         LocalDate accrualStartDate = null;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
index 0c0bcbf..0189ee4 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
@@ -53,8 +53,6 @@ import 
org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
 import 
org.apache.fineract.portfolio.charge.exception.LoanChargeWithoutMandatoryFieldException;
 import org.apache.fineract.portfolio.loanaccount.command.LoanChargeCommand;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidDetail;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.joda.time.LocalDate;
 import org.springframework.data.jpa.domain.AbstractPersistable;
 
@@ -122,8 +120,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
     @Column(name = "max_cap", scale = 6, precision = 19, nullable = true)
     private BigDecimal maxCap;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loancharge", 
orphanRemoval = true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loancharge", 
orphanRemoval = true, fetch=FetchType.EAGER)
     private final Set<LoanInstallmentCharge> loanInstallmentCharge = new 
HashSet<>();
 
     @Column(name = "is_active", nullable = false)

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
index 0e5ce09..d95d741 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
@@ -19,14 +19,15 @@
 package org.apache.fineract.portfolio.loanaccount.domain;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -38,8 +39,6 @@ import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.useradministration.domain.AppUser;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.joda.time.LocalDate;
 
 @Entity
@@ -131,10 +130,9 @@ public final class LoanRepaymentScheduleInstallment 
extends AbstractAuditableCus
     @Column(name = "recalculated_interest_component", nullable = false)
     private boolean recalculatedInterestComponent;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, 
fetch=FetchType.EAGER)
     @JoinColumn(name = "loan_repayment_schedule_id", referencedColumnName = 
"id", nullable = false)
-    private List<LoanInterestRecalcualtionAdditionalDetails> 
loanCompoundingDetails = new ArrayList<>();
+    private Set<LoanInterestRecalcualtionAdditionalDetails> 
loanCompoundingDetails = new HashSet<>();
     protected LoanRepaymentScheduleInstallment() {
         this.installmentNumber = null;
         this.fromDate = null;
@@ -145,7 +143,7 @@ public final class LoanRepaymentScheduleInstallment extends 
AbstractAuditableCus
     public LoanRepaymentScheduleInstallment(final Loan loan, final Integer 
installmentNumber, final LocalDate fromDate,
             final LocalDate dueDate, final BigDecimal principal, final 
BigDecimal interest, final BigDecimal feeCharges,
             final BigDecimal penaltyCharges, final boolean 
recalculatedInterestComponent,
-            final List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails) {
+            final Set<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails) {
         this.loan = loan;
         this.installmentNumber = installmentNumber;
         this.fromDate = fromDate.toDateTimeAtStartOfDay().toDate();
@@ -782,7 +780,7 @@ public final class LoanRepaymentScheduleInstallment extends 
AbstractAuditableCus
     public Money getDue(MonetaryCurrency currency) {
         return 
getPrincipal(currency).plus(getInterestCharged(currency)).plus(getFeeChargesCharged(currency)).plus(getPenaltyChargesCharged(currency));
     }
-    public List<LoanInterestRecalcualtionAdditionalDetails> 
getLoanCompoundingDetails() {
+    public Set<LoanInterestRecalcualtionAdditionalDetails> 
getLoanCompoundingDetails() {
         return this.loanCompoundingDetails;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index 70a2238..414ca14 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -31,6 +31,7 @@ import java.util.Set;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -51,8 +52,6 @@ import 
org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import org.apache.fineract.useradministration.domain.AppUser;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.joda.time.LocalDate;
 import org.joda.time.LocalDateTime;
 import org.springframework.data.jpa.domain.AbstractPersistable;
@@ -123,8 +122,7 @@ public final class LoanTransaction extends 
AbstractPersistable<Long> {
     @JoinColumn(name = "appuser_id", nullable = true)
     private final AppUser appUser;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loanTransaction", 
orphanRemoval = true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "loanTransaction", 
orphanRemoval = true, fetch=FetchType.EAGER)
     private Set<LoanChargePaidBy> loanChargesPaid = new HashSet<>();
 
     @Column(name = "outstanding_loan_balance_derived", scale = 6, precision = 
19, nullable = true)
@@ -133,9 +131,8 @@ public final class LoanTransaction extends 
AbstractPersistable<Long> {
     @Column(name = "manually_adjusted_or_reversed", nullable = false)
     private boolean manuallyAdjustedOrReversed;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
-    @JoinColumn(name = "loan_transaction_id", referencedColumnName = "id", 
nullable = false)
+    @OneToMany(cascade = CascadeType.ALL,  orphanRemoval = true, 
fetch=FetchType.EAGER)
+    @JoinColumn(name = "loan_transaction_id", referencedColumnName= "id" , 
nullable = false)
     private Set<LoanTransactionToRepaymentScheduleMapping> 
loanTransactionToRepaymentScheduleMappings = new HashSet<>();
 
     protected LoanTransaction() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/Guarantor.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/Guarantor.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/Guarantor.java
index 2aa2405..b52e4e7 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/Guarantor.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/Guarantor.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -39,8 +40,6 @@ import 
org.apache.fineract.infrastructure.codes.domain.CodeValue;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import 
org.apache.fineract.portfolio.loanaccount.guarantor.GuarantorConstants.GUARANTOR_JSON_INPUT_PARAMS;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.springframework.data.jpa.domain.AbstractPersistable;
 
 @Entity
@@ -101,8 +100,7 @@ public class Guarantor extends AbstractPersistable<Long> {
     @Column(name = "is_active", nullable = false)
     private boolean active;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "guarantor", 
orphanRemoval = true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "guarantor", 
orphanRemoval = true, fetch=FetchType.EAGER)
     private final List<GuarantorFundingDetails> guarantorFundDetails = new 
ArrayList<>();
 
     protected Guarantor() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/9e5e7329/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingDetails.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingDetails.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingDetails.java
index fe7ce85..0179cb2 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingDetails.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/domain/GuarantorFundingDetails.java
@@ -25,6 +25,7 @@ import java.util.List;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -33,8 +34,6 @@ import javax.persistence.Table;
 import org.apache.fineract.portfolio.account.domain.AccountAssociations;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
 import org.springframework.data.jpa.domain.AbstractPersistable;
 
 @Entity
@@ -64,8 +63,7 @@ public class GuarantorFundingDetails extends 
AbstractPersistable<Long> {
     @Column(name = "amount_transfered_derived", scale = 6, precision = 19, 
nullable = true)
     private BigDecimal amountTransfered;
 
-    @LazyCollection(LazyCollectionOption.FALSE)
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = 
"guarantorFundingDetails", orphanRemoval = true)
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = 
"guarantorFundingDetails", orphanRemoval = true, fetch=FetchType.EAGER)
     private final List<GuarantorFundingTransaction> 
guarantorFundingTransactions = new ArrayList<>();
 
     protected GuarantorFundingDetails() {}


Reply via email to