You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2024/08/15 11:19:06 UTC

(fineract) branch develop updated: FINERACT-2081: Rework Loan Account data

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


The following commit(s) were added to refs/heads/develop by this push:
     new 2a445a586 FINERACT-2081: Rework Loan Account data
2a445a586 is described below

commit 2a445a5862a432dcfb4e49559c3f717ad4d5f26a
Author: Adam Saghy <ad...@gmail.com>
AuthorDate: Tue Aug 13 19:43:26 2024 +0200

    FINERACT-2081: Rework Loan Account data
---
 .../portfolio/loanaccount/data/CollectionData.java |   8 +-
 .../data/LoanApplicationTimelineData.java          | 138 ++--
 .../data/LoanInterestRecalculationData.java        |  57 +-
 .../guarantor/GuarantorWorkbookPopulator.java      |   2 +-
 .../group/service/GroupReadPlatformService.java    |   2 +
 .../service/GroupReadPlatformServiceImpl.java      |  21 +
 .../group/starter/GroupConfiguration.java          |   5 +-
 .../loanaccount/api/LoansApiResource.java          | 123 ++--
 .../loanaccount/data/LoanAccountData.java          | 693 ++-------------------
 .../service/LoanReadPlatformService.java           |   6 -
 .../service/LoanReadPlatformServiceImpl.java       |  86 +--
 11 files changed, 239 insertions(+), 902 deletions(-)

diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java
index fa4e4f6c8..a89cd3e61 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java
@@ -22,14 +22,10 @@ import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.Collection;
 import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.ToString;
+import lombok.Data;
 
+@Data
 @AllArgsConstructor
-@ToString
-@Getter
-@Setter
 public final class CollectionData {
 
     private BigDecimal availableDisbursementAmount;
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
index 52b36d52d..8bb982272 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
@@ -18,108 +18,58 @@
  */
 package org.apache.fineract.portfolio.loanaccount.data;
 
-import java.math.BigDecimal;
 import java.time.LocalDate;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
 
 /**
- * Immutable data object represent the important time-line events of a loan application and loan.
+ * Data object represent the important time-line events of a loan application and loan.
  */
-@Getter
-@RequiredArgsConstructor
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
 public class LoanApplicationTimelineData {
 
-    private final LocalDate submittedOnDate;
-    private final String submittedByUsername;
-    private final String submittedByFirstname;
-    private final String submittedByLastname;
-    private final LocalDate rejectedOnDate;
-    private final String rejectedByUsername;
-    private final String rejectedByFirstname;
-    private final String rejectedByLastname;
-    private final LocalDate withdrawnOnDate;
-    private final String withdrawnByUsername;
-    private final String withdrawnByFirstname;
-    private final String withdrawnByLastname;
-    private final LocalDate approvedOnDate;
-    private final String approvedByUsername;
-    private final String approvedByFirstname;
-    private final String approvedByLastname;
-    private final LocalDate expectedDisbursementDate;
-    private final LocalDate actualDisbursementDate;
-    private final String disbursedByUsername;
-    private final String disbursedByFirstname;
-    private final String disbursedByLastname;
-    private final LocalDate closedOnDate;
-    private final String closedByUsername;
-    private final String closedByFirstname;
-    private final String closedByLastname;
+    private LocalDate submittedOnDate;
+    private String submittedByUsername;
+    private String submittedByFirstname;
+    private String submittedByLastname;
+    private LocalDate rejectedOnDate;
+    private String rejectedByUsername;
+    private String rejectedByFirstname;
+    private String rejectedByLastname;
+    private LocalDate withdrawnOnDate;
+    private String withdrawnByUsername;
+    private String withdrawnByFirstname;
+    private String withdrawnByLastname;
+    private LocalDate approvedOnDate;
+    private String approvedByUsername;
+    private String approvedByFirstname;
+    private String approvedByLastname;
+    private LocalDate expectedDisbursementDate;
+    private LocalDate actualDisbursementDate;
+    private String disbursedByUsername;
+    private String disbursedByFirstname;
+    private String disbursedByLastname;
+    private LocalDate closedOnDate;
+    private String closedByUsername;
+    private String closedByFirstname;
+    private String closedByLastname;
 
-    private final LocalDate actualMaturityDate;
-    private final LocalDate expectedMaturityDate;
-    private final LocalDate writeOffOnDate;
-    private final String writeOffByUsername;
-    private final String writeOffByFirstname;
-    private final String writeOffByLastname;
+    private LocalDate actualMaturityDate;
+    private LocalDate expectedMaturityDate;
+    private LocalDate writeOffOnDate;
+    private String writeOffByUsername;
+    private String writeOffByFirstname;
+    private String writeOffByLastname;
 
-    private final LocalDate chargedOffOnDate;
-    private final String chargedOffByUsername;
-    private final String chargedOffByFirstname;
-    private final String chargedOffByLastname;
-
-    public static LoanApplicationTimelineData templateDefault(final LocalDate expectedDisbursementDate) {
-
-        final LocalDate submittedOnDate = null;
-        final String submittedByUsername = null;
-        final String submittedByFirstname = null;
-        final String submittedByLastname = null;
-        final LocalDate rejectedOnDate = null;
-        final String rejectedByUsername = null;
-        final String rejectedByFirstname = null;
-        final String rejectedByLastname = null;
-        final LocalDate withdrawnOnDate = null;
-        final String withdrawnByUsername = null;
-        final String withdrawnByFirstname = null;
-        final String withdrawnByLastname = null;
-        final LocalDate approvedOnDate = null;
-        final String approvedByUsername = null;
-        final String approvedByFirstname = null;
-        final String approvedByLastname = null;
-        final LocalDate actualDisbursementDate = null;
-        final String disbursedByUsername = null;
-        final String disbursedByFirstname = null;
-        final String disbursedByLastname = null;
-        final LocalDate closedOnDate = null;
-        final String closedByUsername = null;
-        final String closedByFirstname = null;
-        final String closedByLastname = null;
-        final LocalDate expectedMaturityDate = null;
-        final LocalDate writeOffOnDate = null;
-        final String writeOffByUsername = null;
-        final String writeOffByFirstname = null;
-        final String writeOffByLastname = null;
-        final LocalDate chargedOffOnDate = null;
-        final String chargedOffByUsername = null;
-        final String chargedOffByFirstname = null;
-        final String chargedOffByLastname = null;
-        final LocalDate actualMaturityDate = null;
-
-        return new LoanApplicationTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname,
-                rejectedOnDate, rejectedByUsername, rejectedByFirstname, rejectedByLastname, withdrawnOnDate, withdrawnByUsername,
-                withdrawnByFirstname, withdrawnByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname,
-                expectedDisbursementDate, actualDisbursementDate, disbursedByUsername, disbursedByFirstname, disbursedByLastname,
-                closedOnDate, closedByUsername, closedByFirstname, closedByLastname, actualMaturityDate, expectedMaturityDate,
-                writeOffOnDate, writeOffByUsername, writeOffByFirstname, writeOffByLastname, chargedOffOnDate, chargedOffByUsername,
-                chargedOffByFirstname, chargedOffByLastname);
-    }
-
-    public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData(final CurrencyData currency, final BigDecimal principal,
-            final BigDecimal approvedPrincipal, final BigDecimal inArrearsTolerance, final BigDecimal totalFeeChargesAtDisbursement) {
-        return new RepaymentScheduleRelatedLoanData(this.expectedDisbursementDate, this.actualDisbursementDate, currency, principal,
-                inArrearsTolerance, totalFeeChargesAtDisbursement);
-    }
+    private LocalDate chargedOffOnDate;
+    private String chargedOffByUsername;
+    private String chargedOffByFirstname;
+    private String chargedOffByLastname;
 
     public LocalDate getDisbursementDate() {
         LocalDate disbursementDate = this.expectedDisbursementDate;
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanInterestRecalculationData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanInterestRecalculationData.java
index c4dd5e434..6c5c6aa41 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanInterestRecalculationData.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanInterestRecalculationData.java
@@ -18,31 +18,35 @@
  */
 package org.apache.fineract.portfolio.loanaccount.data;
 
-import lombok.Getter;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
 
-@Getter
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
 public class LoanInterestRecalculationData {
 
-    private final Long id;
-    private final Long loanId;
-    private final EnumOptionData interestRecalculationCompoundingType;
-    private final EnumOptionData rescheduleStrategyType;
-    private final CalendarData calendarData;
-    private final EnumOptionData recalculationRestFrequencyType;
-    private final Integer recalculationRestFrequencyInterval;
-    private final EnumOptionData recalculationRestFrequencyNthDay;
-    private final EnumOptionData recalculationRestFrequencyWeekday;
-    private final Integer recalculationRestFrequencyOnDay;
-    private final EnumOptionData recalculationCompoundingFrequencyType;
-    private final Integer recalculationCompoundingFrequencyInterval;
-    private final EnumOptionData recalculationCompoundingFrequencyNthDay;
-    private final EnumOptionData recalculationCompoundingFrequencyWeekday;
-    private final Integer recalculationCompoundingFrequencyOnDay;
-    private final Boolean isCompoundingToBePostedAsTransaction;
-    private final CalendarData compoundingCalendarData;
-    private final Boolean allowCompoundingOnEod;
+    private Long id;
+    private Long loanId;
+    private EnumOptionData interestRecalculationCompoundingType;
+    private EnumOptionData rescheduleStrategyType;
+    private CalendarData calendarData;
+    private EnumOptionData recalculationRestFrequencyType;
+    private Integer recalculationRestFrequencyInterval;
+    private EnumOptionData recalculationRestFrequencyNthDay;
+    private EnumOptionData recalculationRestFrequencyWeekday;
+    private Integer recalculationRestFrequencyOnDay;
+    private EnumOptionData recalculationCompoundingFrequencyType;
+    private Integer recalculationCompoundingFrequencyInterval;
+    private EnumOptionData recalculationCompoundingFrequencyNthDay;
+    private EnumOptionData recalculationCompoundingFrequencyWeekday;
+    private Integer recalculationCompoundingFrequencyOnDay;
+    private Boolean isCompoundingToBePostedAsTransaction;
+    private CalendarData compoundingCalendarData;
+    private Boolean allowCompoundingOnEod;
 
     public LoanInterestRecalculationData(final Long id, final Long loanId, final EnumOptionData interestRecalculationCompoundingType,
             final EnumOptionData rescheduleStrategyType, final CalendarData calendarData,
@@ -73,17 +77,8 @@ public class LoanInterestRecalculationData {
         this.allowCompoundingOnEod = allowCompoundingOnEod;
     }
 
-    public static LoanInterestRecalculationData withCalendarData(final LoanInterestRecalculationData recalculationData,
-            final CalendarData calendarData, CalendarData compoundingCalendarData) {
-        return new LoanInterestRecalculationData(recalculationData.id, recalculationData.loanId,
-                recalculationData.interestRecalculationCompoundingType, recalculationData.rescheduleStrategyType, calendarData,
-                recalculationData.recalculationRestFrequencyType, recalculationData.recalculationRestFrequencyInterval,
-                recalculationData.recalculationRestFrequencyNthDay, recalculationData.recalculationRestFrequencyWeekday,
-                recalculationData.recalculationRestFrequencyOnDay, compoundingCalendarData,
-                recalculationData.recalculationCompoundingFrequencyType, recalculationData.recalculationCompoundingFrequencyInterval,
-                recalculationData.recalculationCompoundingFrequencyNthDay, recalculationData.recalculationCompoundingFrequencyWeekday,
-                recalculationData.recalculationCompoundingFrequencyOnDay, recalculationData.isCompoundingToBePostedAsTransaction,
-                recalculationData.allowCompoundingOnEod);
+    public LoanInterestRecalculationData withCalendarData(final CalendarData calendarData, CalendarData compoundingCalendarData) {
+        return this.setCalendarData(calendarData).setCompoundingCalendarData(compoundingCalendarData);
     }
 
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java
index a702d8b61..984bee37d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/guarantor/GuarantorWorkbookPopulator.java
@@ -147,7 +147,7 @@ public class GuarantorWorkbookPopulator extends AbstractWorkbookPopulator {
         dateCellStyle.setDataFormat(df);
         int rowIndex = 1;
         Row row;
-        Collections.sort(loans, LoanAccountData.ClientNameComparator);
+        loans.sort(LoanAccountData.LOAN_ACCOUNT_DATA_COMPARATOR_BY_CLIENT_NAME);
         for (LoanAccountData loan : loans) {
             if (addGuarantorSheet.getRow(rowIndex) == null) {
                 row = addGuarantorSheet.createRow(rowIndex++);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformService.java
index 5cd6432d4..c8b3a08aa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformService.java
@@ -37,4 +37,6 @@ public interface GroupReadPlatformService {
     Collection<GroupGeneralData> retrieveGroupsForLookup(Long officeId);
 
     GroupGeneralData retrieveGroupWithClosureReasons();
+
+    GroupGeneralData retrieveGroupAndMembersDetails(Long groupId);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformServiceImpl.java
index f1bde4875..8d798feee 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupReadPlatformServiceImpl.java
@@ -43,10 +43,13 @@ import org.apache.fineract.organisation.office.data.OfficeData;
 import org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
 import org.apache.fineract.organisation.staff.data.StaffData;
 import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
+import org.apache.fineract.portfolio.calendar.data.CalendarData;
 import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants;
 import org.apache.fineract.portfolio.group.data.CenterData;
 import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.fineract.portfolio.group.data.GroupRoleData;
 import org.apache.fineract.portfolio.group.domain.GroupTypes;
 import org.apache.fineract.portfolio.group.exception.GroupNotFoundException;
 import org.apache.fineract.useradministration.domain.AppUser;
@@ -74,6 +77,7 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
     private final DatabaseSpecificSQLGenerator sqlGenerator;
     private final PaginationParametersDataValidator paginationParametersDataValidator;
     private final ColumnValidator columnValidator;
+    private final ClientReadPlatformService clientReadPlatformService;
 
     @Override
     public GroupGeneralData retrieveTemplate(final Long officeId, final boolean isCenterGroup, final boolean staffInSelectedOfficeOnly) {
@@ -246,6 +250,23 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
         return GroupGeneralData.withClosureReasons(closureReasons);
     }
 
+    @Override
+    public GroupGeneralData retrieveGroupAndMembersDetails(Long groupId) {
+        GroupGeneralData groupAccount = retrieveOne(groupId);
+
+        // get group associations
+        final Collection<ClientData> membersOfGroup = clientReadPlatformService.retrieveActiveClientMembersOfGroup(groupId);
+        if (!CollectionUtils.isEmpty(membersOfGroup)) {
+            final Collection<ClientData> activeClientMembers = null;
+            final Collection<CalendarData> calendarsData = null;
+            final CalendarData collectionMeetingCalendar = null;
+            final Collection<GroupRoleData> groupRoles = null;
+            groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup, activeClientMembers, groupRoles, calendarsData,
+                    collectionMeetingCalendar);
+        }
+        return groupAccount;
+    }
+
     private static final class GroupLookupDataMapper implements RowMapper<GroupGeneralData> {
 
         public static final String G_ID_AS_ID_G_ACCOUNT_NO_AS_ACCOUNT_NO_G_DISPLAY_NAME_AS_DISPLAY_NAME_FROM_M_GROUP_G_WHERE_G_LEVEL_ID_2 = "g.id as id, g.account_no as accountNo, g.display_name as displayName from m_group g where g.level_id = 2 ";
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/starter/GroupConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/starter/GroupConfiguration.java
index f48b83aa7..ebd60f843 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/starter/GroupConfiguration.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/starter/GroupConfiguration.java
@@ -114,10 +114,11 @@ public class GroupConfiguration {
             OfficeReadPlatformService officeReadPlatformService, StaffReadPlatformService staffReadPlatformService,
             CenterReadPlatformService centerReadPlatformService, CodeValueReadPlatformService codeValueReadPlatformService,
             PaginationHelper paginationHelper, DatabaseSpecificSQLGenerator sqlGenerator,
-            PaginationParametersDataValidator paginationParametersDataValidator, ColumnValidator columnValidator) {
+            PaginationParametersDataValidator paginationParametersDataValidator, ColumnValidator columnValidator,
+            ClientReadPlatformService clientReadPlatformService) {
         return new GroupReadPlatformServiceImpl(jdbcTemplate, context, officeReadPlatformService, staffReadPlatformService,
                 centerReadPlatformService, codeValueReadPlatformService, paginationHelper, sqlGenerator, paginationParametersDataValidator,
-                columnValidator);
+                columnValidator, clientReadPlatformService);
     }
 
     @Bean
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index 393ecbe7f..9ab94e1c9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -47,6 +47,7 @@ import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.UriInfo;
 import java.io.InputStream;
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -78,6 +79,7 @@ import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSeria
 import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import org.apache.fineract.infrastructure.core.service.CommandParameterUtil;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
 import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
@@ -104,6 +106,7 @@ import org.apache.fineract.portfolio.charge.data.ChargeData;
 import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
 import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
 import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
 import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
@@ -283,6 +286,7 @@ public class LoansApiResource {
     private final DelinquencyReadPlatformService delinquencyReadPlatformService;
     private final SqlValidator sqlValidator;
     private final LoanSummaryBalancesRepository loanSummaryBalancesRepository;
+    private final ClientReadPlatformService clientReadPlatformService;
 
     /*
      * This template API is used for loan approval, ideally this should be invoked on loan that are pending for
@@ -326,10 +330,11 @@ public class LoansApiResource {
         final Collection<LoanProductData> productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup(onlyActive);
 
         // options
-        Collection<StaffData> allowedLoanOfficers = null;
-        Collection<CodeValueData> loanCollateralOptions = null;
+        Collection<StaffData> allowedLoanOfficers;
+        Collection<CodeValueData> loanCollateralOptions;
         Collection<CalendarData> calendarOptions = null;
-        LoanAccountData newLoanAccount = null;
+        LoanAccountData newLoanAccount = new LoanAccountData();
+        LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
         Long officeId = null;
         Collection<PortfolioAccountData> accountLinkingOptions = null;
         boolean isRatesEnabled = this.configurationDomainService.isSubRatesEnabled();
@@ -343,66 +348,54 @@ public class LoansApiResource {
             throw new LoanTemplateTypeRequiredException(errorMsg);
         } else if (templateType.equals("collateral")) {
             loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral");
-            newLoanAccount = LoanAccountData.collateralTemplate(loanCollateralOptions);
+            newLoanAccount = newLoanAccount.setLoanCollateralOptions(loanCollateralOptions);
         } else {
             // for JLG loan both client and group details are required
-            if (templateType.equals("individual") || templateType.equals("jlg")) {
-
-                if (clientId == null) {
-                    newLoanAccount = newLoanAccount == null ? LoanAccountData.collateralTemplate(null) : newLoanAccount;
-                } else {
-                    final LoanAccountData loanAccountClientDetails = this.loanReadPlatformService.retrieveClientDetailsTemplate(clientId);
-
-                    officeId = loanAccountClientDetails.getClientOfficeId();
-
-                    if (officeId == null && loanAccountClientDetails.getGroup() != null) {
-                        officeId = loanAccountClientDetails.getGroup().getOfficeId();
+            switch (templateType) {
+                case "individual", "jlg" -> {
+                    if (clientId != null) {
+                        final ClientData clientData = this.clientReadPlatformService.retrieveOne(clientId);
+                        officeId = clientData.getOfficeId();
+                        newLoanAccount = newLoanAccount.withClientData(clientData).withExpectedDisbursementDate(expectedDisbursementDate);
+                    }
+                    // if it's JLG loan add group details
+                    if (templateType.equals("jlg")) {
+                        final GroupGeneralData groupData = this.groupReadPlatformService.retrieveOne(groupId);
+                        newLoanAccount = newLoanAccount.setGroup(groupData);
+                        calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
                     }
-                    newLoanAccount = newLoanAccount == null ? loanAccountClientDetails
-                            : LoanAccountData.populateClientDefaults(newLoanAccount, loanAccountClientDetails);
                 }
-
-                // if it's JLG loan add group details
-                if (templateType.equals("jlg")) {
-                    final GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId);
-                    newLoanAccount = LoanAccountData.associateGroup(newLoanAccount, group);
+                case "group" -> {
+                    final GroupGeneralData groupData = this.groupReadPlatformService.retrieveOne(groupId);
+                    officeId = groupData.getOfficeId();
                     calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
+                    newLoanAccount = newLoanAccount.setGroup(groupData).withExpectedDisbursementDate(expectedDisbursementDate);
+                    accountLinkingOptions = getAccountLinkingOptions(newLoanAccount, clientId, groupId);
                 }
-
-            } else if (templateType.equals("group")) {
-
-                final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupDetailsTemplate(groupId);
-                officeId = loanAccountGroupData.getGroup() != null ? loanAccountGroupData.getGroup().getOfficeId() : null;
-                calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
-                newLoanAccount = newLoanAccount == null ? loanAccountGroupData
-                        : LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData);
-                accountLinkingOptions = getAccountLinkingOptions(newLoanAccount, clientId, groupId);
-
-            } else if (templateType.equals("jlgbulk")) {
-                // get group details along with members in that group
-                final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupAndMembersDetailsTemplate(groupId);
-                officeId = loanAccountGroupData.getGroup() != null ? loanAccountGroupData.getGroup().getOfficeId() : null;
-                calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
-                newLoanAccount = newLoanAccount == null ? loanAccountGroupData
-                        : LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData);
-                if (productId != null) {
-                    Map<Long, Integer> memberLoanCycle = new HashMap<>();
-                    Collection<ClientData> members = loanAccountGroupData.getGroup().clientMembers();
-                    accountLinkingOptions = new ArrayList<>();
-                    if (members != null) {
-                        for (ClientData clientData : members) {
-                            Integer loanCounter = this.loanReadPlatformService.retriveLoanCounter(clientData.getId(), productId);
-                            memberLoanCycle.put(clientData.getId(), loanCounter);
-                            accountLinkingOptions.addAll(getAccountLinkingOptions(newLoanAccount, clientData.getId(), groupId));
+                case "jlgbulk" -> {
+                    // get group details along with members in that group
+                    final GroupGeneralData groupData = this.groupReadPlatformService.retrieveGroupAndMembersDetails(groupId);
+                    officeId = groupData.getOfficeId();
+                    calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
+                    newLoanAccount = newLoanAccount.setGroup(groupData).withExpectedDisbursementDate(expectedDisbursementDate);
+                    if (productId != null) {
+                        Map<Long, Integer> memberLoanCycle = new HashMap<>();
+                        Collection<ClientData> members = groupData.clientMembers();
+                        accountLinkingOptions = new ArrayList<>();
+                        if (members != null) {
+                            for (ClientData clientData : members) {
+                                Integer loanCounter = this.loanReadPlatformService.retriveLoanCounter(clientData.getId(), productId);
+                                memberLoanCycle.put(clientData.getId(), loanCounter);
+                                accountLinkingOptions.addAll(getAccountLinkingOptions(newLoanAccount, clientData.getId(), groupId));
+                            }
                         }
+                        newLoanAccount = newLoanAccount.associateMemberVariations(memberLoanCycle);
                     }
-
-                    newLoanAccount = LoanAccountData.associateMemberVariations(newLoanAccount, memberLoanCycle);
                 }
-
-            } else {
-                final String errorMsg = "Loan template type '" + templateType + "' is not supported";
-                throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType);
+                default -> {
+                    final String errorMsg = "Loan template type '" + templateType + "' is not supported";
+                    throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType);
+                }
             }
 
             allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly);
@@ -413,7 +406,7 @@ public class LoansApiResource {
 
             // add product options, allowed loan officers and calendar options
             // (calendar options will be null in individual loan)
-            newLoanAccount = LoanAccountData.associationsAndTemplate(newLoanAccount, productOptions, allowedLoanOfficers, calendarOptions,
+            newLoanAccount = newLoanAccount.associationsAndTemplate(productOptions, allowedLoanOfficers, calendarOptions,
                     accountLinkingOptions, isRatesEnabled);
         }
         final List<DatatableData> datatableTemplates = this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
@@ -880,8 +873,7 @@ public class LoansApiResource {
             if (!CollectionUtils.isEmpty(interestRecalculationCompoundingCalendarDatas)) {
                 compoundingCalendarData = interestRecalculationCompoundingCalendarDatas.iterator().next();
             }
-            loanBasicDetails = LoanAccountData.withInterestRecalculationCalendarData(loanBasicDetails, calendarData,
-                    compoundingCalendarData);
+            loanBasicDetails = loanBasicDetails.withInterestRecalculationCalendarData(calendarData, compoundingCalendarData);
         }
         if (loanBasicDetails.getRepaymentFrequencyType() != null
                 && loanBasicDetails.getRepaymentFrequencyType().getId().intValue() == PeriodFrequencyType.MONTHS.getValue()) {
@@ -892,7 +884,7 @@ public class LoansApiResource {
                 calendarData = loanCalendarDatas.iterator().next();
             }
             if (calendarData != null) {
-                loanBasicDetails = LoanAccountData.withLoanCalendarData(loanBasicDetails, calendarData);
+                loanBasicDetails = loanBasicDetails.setMeeting(calendarData);
             }
         }
         Collection<InterestRatePeriodData> interestRatesPeriods = this.loanReadPlatformService
@@ -952,10 +944,11 @@ public class LoansApiResource {
 
             if (associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
                 mandatoryResponseParameters.add(DataTableApiConstant.repaymentScheduleAssociateParamName);
-                final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.getTimeline()
-                        .repaymentScheduleRelatedData(loanBasicDetails.getCurrency(), loanBasicDetails.getPrincipal(),
-                                loanBasicDetails.getApprovedPrincipal(), loanBasicDetails.getInArrearsTolerance(),
-                                loanBasicDetails.getFeeChargesAtDisbursementCharged());
+                final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = new RepaymentScheduleRelatedLoanData(
+                        loanBasicDetails.getTimeline().getExpectedDisbursementDate(),
+                        loanBasicDetails.getTimeline().getActualDisbursementDate(), loanBasicDetails.getCurrency(),
+                        loanBasicDetails.getPrincipal(), loanBasicDetails.getInArrearsTolerance(),
+                        loanBasicDetails.getFeeChargesAtDisbursementCharged());
                 repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(resolvedLoanId, repaymentScheduleRelatedData,
                         disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
                         LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
@@ -973,7 +966,7 @@ public class LoansApiResource {
                     LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(
                             resolvedLoanId, repaymentScheduleRelatedData, disbursementData,
                             LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
-                    loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
+                    loanBasicDetails = loanBasicDetails.setOriginalSchedule(loanScheduleData);
                 }
             }
 
@@ -1118,8 +1111,8 @@ public class LoansApiResource {
                             LoanApiConstants.LOAN_SUMMARY_TRANSACTION_TYPES)));
         }
 
-        final LoanAccountData loanAccount = LoanAccountData.associationsAndTemplate(loanBasicDetails, repaymentSchedule, loanRepayments,
-                charges, loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions,
+        final LoanAccountData loanAccount = loanBasicDetails.associationsAndTemplate(repaymentSchedule, loanRepayments, charges,
+                loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions,
                 repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions,
                 repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
                 interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
index 20350f534..8b382aacd 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
@@ -42,6 +42,7 @@ import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
 import org.apache.fineract.portfolio.calendar.data.CalendarData;
 import org.apache.fineract.portfolio.charge.data.ChargeData;
 import org.apache.fineract.portfolio.charge.util.ConvertChargeDataToSpecificChargeData;
+import org.apache.fineract.portfolio.client.data.ClientData;
 import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
 import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
 import org.apache.fineract.portfolio.fund.data.FundData;
@@ -230,7 +231,7 @@ public class LoanAccountData {
     private Integer minimumGap;
     private Integer maximumGap;
 
-    private List<DatatableData> datatables = null;
+    private List<DatatableData> datatables;
     // TODO: avoid prefix "is"
     private Boolean isEqualAmortization;
     private BigDecimal fixedPrincipalPercentagePerInstallment;
@@ -316,176 +317,23 @@ public class LoanAccountData {
                 .setFixedLength(fixedLength);
     }
 
-    /**
-     * Used to produce a {@link LoanAccountData} with only collateral options for now.
-     */
-    public static LoanAccountData collateralTemplate(final Collection<CodeValueData> loanCollateralOptions) {
-
-        return new LoanAccountData().setIsVariableInstallmentsAllowed(false).setDelinquent(CollectionData.template())
-                .setLoanCollateralOptions(loanCollateralOptions);
-    }
-
-    /**
-     * Used to produce a {@link LoanAccountData} with only client information defaulted.
-     */
-    public static LoanAccountData clientDefaults(final Long clientId, final String clientAccountNo, final String clientName,
-            final Long clientOfficeId, final ExternalId clientExternalId, final LocalDate expectedDisbursementDate) {
-
-        return new LoanAccountData().setTimeline(LoanApplicationTimelineData.templateDefault(expectedDisbursementDate))
-                .setIsVariableInstallmentsAllowed(false).setDelinquent(CollectionData.template()).setClientId(clientId)
-                .setClientAccountNo(clientAccountNo).setClientName(clientName).setClientOfficeId(clientOfficeId)
-                .setClientExternalId(clientExternalId).setExpectedDisbursementDate(expectedDisbursementDate);
-    }
-
-    public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(clientAcc.clientId).setClientAccountNo(clientAcc.clientAccountNo).setClientName(clientAcc.clientName)
-                .setClientOfficeId(clientAcc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(clientAcc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setLoanScheduleType(acc.loanScheduleType).setLoanScheduleProcessingType(acc.loanScheduleProcessingType)
-                .setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
-    }
-
-    /**
-     * Used to produce a {@link LoanAccountData} with only group information defaulted.
-     */
-    public static LoanAccountData groupDefaults(final GroupGeneralData group, final LocalDate expectedDisbursementDate) {
-
-        return new LoanAccountData().setTimeline(LoanApplicationTimelineData.templateDefault(expectedDisbursementDate))
-                .setIsVariableInstallmentsAllowed(false).setDelinquent(CollectionData.template()).setGroup(group)
-                .setExpectedDisbursementDate(expectedDisbursementDate);
+    public LoanAccountData withClientData(final ClientData clientData) {
+        return this.setClientId(clientData.getId()) //
+                .setClientAccountNo(clientData.getAccountNo()) //
+                .setClientName(clientData.getDisplayName()) //
+                .setClientOfficeId(clientData.getOfficeId()) //
+                .setClientExternalId(clientData.getExternalId()); //
     }
 
-    public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(groupAcc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(groupAcc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setLoanScheduleType(acc.loanScheduleType).setLoanScheduleProcessingType(acc.loanScheduleProcessingType)
-                .setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
+    public LoanAccountData withExpectedDisbursementDate(final LocalDate expectedDisbursementDate) {
+        if (getTimeline() == null) {
+            setTimeline(new LoanApplicationTimelineData());
+        }
+        this.getTimeline().setExpectedDisbursementDate(expectedDisbursementDate);
+        return this.setExpectedDisbursementDate(expectedDisbursementDate);
     }
 
-    public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
-            final Collection<EnumOptionData> termFrequencyTypeOptions, final Collection<EnumOptionData> repaymentFrequencyTypeOptions,
-            final Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions,
-            final Collection<EnumOptionData> repaymentFrequencyDayOfWeekTypeOptions,
-            final Collection<TransactionProcessingStrategyData> repaymentStrategyOptions,
-            final Collection<EnumOptionData> interestRateFrequencyTypeOptions, final Collection<EnumOptionData> amortizationTypeOptions,
-            final Collection<EnumOptionData> interestTypeOptions, final Collection<EnumOptionData> interestCalculationPeriodTypeOptions,
-            final Collection<FundData> fundOptions, final Collection<ChargeData> chargeOptions,
-            final Collection<CodeValueData> loanPurposeOptions, final Collection<CodeValueData> loanCollateralOptions,
-            final Integer loanCycleNumber, final Collection<LoanAccountSummaryData> clientActiveLoanOptions,
-            final List<EnumOptionData> loanScheduleTypeOptions, final List<EnumOptionData> loanScheduleProcessingTypeOptions) {
+    public LoanAccountData withProductData(final LoanProductData product, final Integer loanCycleNumber) {
 
         final EnumOptionData termPeriodFrequencyType = product.getRepaymentFrequencyType();
 
@@ -538,8 +386,7 @@ public class LoanAccountData {
             numberOfRepayments = product.getNumberOfRepayments();
         }
 
-        return new LoanAccountData().setProductId(product.getId()).setLoanProductName(product.getName())
-                .setLoanProductDescription(product.getDescription())
+        return this.setProductId(product.getId()).setLoanProductName(product.getName()).setLoanProductDescription(product.getDescription())
                 .setLoanProductLinkedToFloatingRate(product.isLinkedToFloatingInterestRates()).setFundId(product.getFundId())
                 .setFundName(product.getFundName()).setCurrency(product.getCurrency()).setProposedPrincipal(proposedPrincipal)
                 .setPrincipal(principal).setApprovedPrincipal(principal).setNetDisbursalAmount(netDisbursalAmount)
@@ -557,15 +404,7 @@ public class LoanAccountData {
                 .setRecurringMoratoriumOnPrincipalPeriods(product.getRecurringMoratoriumOnPrincipalPeriods())
                 .setGraceOnInterestPayment(product.getGraceOnInterestPayment())
                 .setGraceOnInterestCharged(product.getGraceOnInterestCharged()).setCharges(charges)
-                .setTermFrequencyTypeOptions(termFrequencyTypeOptions).setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(repaymentFrequencyDayOfWeekTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(repaymentFrequencyNthDayTypeOptions)
-                .setTransactionProcessingStrategyOptions(repaymentStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions).setAmortizationTypeOptions(amortizationTypeOptions)
-                .setInterestTypeOptions(interestTypeOptions).setInterestCalculationPeriodTypeOptions(interestCalculationPeriodTypeOptions)
-                .setFundOptions(fundOptions).setChargeOptions(chargeOptions).setLoanPurposeOptions(loanPurposeOptions)
-                .setLoanCollateralOptions(loanCollateralOptions).setMultiDisburseLoan(product.getMultiDisburseLoan())
-                .setCanDefineInstallmentAmount(product.isCanDefineInstallmentAmount())
+                .setMultiDisburseLoan(product.getMultiDisburseLoan()).setCanDefineInstallmentAmount(product.isCanDefineInstallmentAmount())
                 .setMaxOutstandingLoanBalance(product.getOutstandingLoanBalance()).setProduct(product)
                 .setGraceOnArrearsAgeing(product.getGraceOnArrearsAgeing()).setOverdueCharges(product.overdueFeeCharges())
                 .setDaysInMonthType(product.getDaysInMonthType()).setDaysInYearType(product.getDaysInYearType())
@@ -573,79 +412,10 @@ public class LoanAccountData {
                 .setInterestRecalculationData(product.toLoanInterestRecalculationData())
                 .setIsVariableInstallmentsAllowed(product.isAllowVariableInstallments()).setMinimumGap(product.getMinimumGap())
                 .setMaximumGap(product.getMaximumGap()).setTopup(product.isCanUseForTopup())
-                .setClientActiveLoanOptions(clientActiveLoanOptions).setIsEqualAmortization(product.isEqualAmortization())
+                .setIsEqualAmortization(product.isEqualAmortization())
                 .setFixedPrincipalPercentagePerInstallment(product.getFixedPrincipalPercentagePerInstallment())
                 .setDelinquent(CollectionData.template()).setDisallowExpectedDisbursements(product.getDisallowExpectedDisbursements())
-                .setLoanScheduleType(product.getLoanScheduleType()).setLoanScheduleProcessingType(product.getLoanScheduleProcessingType())
-                .setLoanScheduleTypeOptions(loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(loanScheduleProcessingTypeOptions);
-    }
-
-    public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
-
-        final Integer termFrequency = product.getNumberOfRepayments() * product.getRepaymentEvery();
-        final EnumOptionData termPeriodFrequencyType = product.getRepaymentFrequencyType();
-
-        final Collection<LoanChargeData> charges = new ArrayList<LoanChargeData>();
-        for (final ChargeData charge : product.charges()) {
-            charges.add(ConvertChargeDataToSpecificChargeData.toLoanChargeData(charge));
-        }
-
-        BigDecimal netDisbursalAmount = product.getPrincipal();
-        if (!charges.isEmpty()) {
-            for (LoanChargeData charge : charges) {
-                netDisbursalAmount = netDisbursalAmount.subtract(charge.getAmount());
-            }
-        }
-        final CollectionData delinquent = CollectionData.template();
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setId(product.getId()).setLoanProductName(product.getName())
-                .setLoanProductDescription(product.getDescription())
-                .setLoanProductLinkedToFloatingRate(product.isLinkedToFloatingInterestRates()).setFundId(product.getFundId())
-                .setFundName(product.getFundName()).setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName)
-                .setLoanOfficerId(acc.loanOfficerId).setLoanOfficerName(acc.loanOfficerName).setCurrency(product.getCurrency())
-                .setPrincipal(product.getPrincipal()).setPrincipal(product.getPrincipal()).setPrincipal(product.getPrincipal())
-                .setNetDisbursalAmount(netDisbursalAmount).setTotalOverpaid(acc.totalOverpaid)
-                .setInArrearsTolerance(product.getInArrearsTolerance()).setTermFrequency(termFrequency)
-                .setTermPeriodFrequencyType(termPeriodFrequencyType).setNumberOfRepayments(product.getNumberOfRepayments())
-                .setRepaymentEvery(product.getRepaymentEvery()).setRepaymentFrequencyType(product.getRepaymentFrequencyType())
-                .setTransactionProcessingStrategyCode(product.getTransactionProcessingStrategyCode())
-                .setTransactionProcessingStrategyName(product.getTransactionProcessingStrategyName())
-                .setAmortizationType(product.getAmortizationType()).setInterestRatePerPeriod(product.getInterestRatePerPeriod())
-                .setInterestRateFrequencyType(product.getInterestRateFrequencyType()).setAnnualInterestRate(product.getAnnualInterestRate())
-                .setInterestType(product.getInterestType()).setFloatingInterestRate(product.isFloatingInterestRateCalculationAllowed())
-                .setInterestRateDifferential(product.getDefaultDifferentialLendingRate())
-                .setInterestCalculationPeriodType(product.getInterestCalculationPeriodType())
-                .setAllowPartialPeriodInterestCalculation(product.isAllowPartialPeriodInterestCalculation())
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate)
-                .setGraceOnPrincipalPayment(product.getGraceOnPrincipalPayment())
-                .setRecurringMoratoriumOnPrincipalPeriods(product.getRecurringMoratoriumOnPrincipalPeriods())
-                .setGraceOnInterestPayment(product.getGraceOnInterestPayment())
-                .setGraceOnInterestCharged(product.getGraceOnInterestCharged()).setInterestChargedFromDate(acc.interestChargedFromDate)
-                .setTimeline(acc.timeline).setSummary(acc.summary).setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged)
-                .setCharges(charges).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting).setLoanCounter(acc.loanCounter)
-                .setLoanProductCounter(acc.loanProductCounter).setAccountLinkingOptions(acc.accountLinkingOptions)
-                .setLinkedAccount(acc.linkedAccount).setDisbursementDetails(acc.disbursementDetails)
-                .setMultiDisburseLoan(product.getMultiDisburseLoan()).setCanDefineInstallmentAmount(product.isCanDefineInstallmentAmount())
-                .setFixedEmiAmount(acc.fixedEmiAmount).setMaxOutstandingLoanBalance(product.getOutstandingLoanBalance())
-                .setEmiAmountVariations(acc.emiAmountVariations).setMemberVariations(acc.memberVariations).setProduct(product)
-                .setInArrears(acc.inArrears).setGraceOnArrearsAgeing(product.getGraceOnArrearsAgeing())
-                .setOverdueCharges(product.overdueFeeCharges()).setIsNPA(acc.isNPA).setDaysInMonthType(product.getDaysInMonthType())
-                .setDaysInYearType(product.getDaysInYearType()).setInterestRecalculationEnabled(product.isInterestRecalculationEnabled())
-                .setInterestRecalculationData(product.toLoanInterestRecalculationData()).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(product.isAllowVariableInstallments())
-                .setMinimumGap(product.getMinimumGap()).setMaximumGap(product.getMaximumGap()).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(product.isEqualAmortization()).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(product.getFixedPrincipalPercentagePerInstallment()).setDelinquent(delinquent)
-                .setDisallowExpectedDisbursements(product.getDisallowExpectedDisbursements()).setFraud(acc.fraud)
-                .setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff).setLoanScheduleType(acc.getLoanScheduleType())
-                .setLoanScheduleProcessingType(acc.getLoanScheduleProcessingType()).setFixedLength(product.getFixedLength());
+                .setLoanScheduleType(product.getLoanScheduleType()).setLoanScheduleProcessingType(product.getLoanScheduleProcessingType());
     }
 
     /*
@@ -732,7 +502,7 @@ public class LoanAccountData {
     /*
      * Used to combine the associations and template data on top of exist loan account data
      */
-    public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final LoanScheduleData repaymentSchedule,
+    public LoanAccountData associationsAndTemplate(final LoanScheduleData repaymentSchedule,
             final Collection<LoanTransactionData> transactions, final Collection<LoanChargeData> charges,
             final Collection<LoanCollateralManagementData> collateral, final Collection<GuarantorData> guarantors,
             final CalendarData calendarData, final Collection<LoanProductData> productOptions,
@@ -755,34 +525,8 @@ public class LoanAccountData {
 
         // TODO: why are these variables 'calendarData', 'chargeTemplate' never used (see original private constructor)
 
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType).setFixedLength(acc.fixedLength)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(repaymentSchedule)
-                .setTransactions(transactions).setCharges(charges).setCollateral(collateral).setGuarantors(guarantors)
-                .setProductOptions(productOptions).setTermFrequencyTypeOptions(termFrequencyTypeOptions)
+        return this.setRepaymentSchedule(repaymentSchedule).setTransactions(transactions).setCharges(charges).setCollateral(collateral)
+                .setGuarantors(guarantors).setProductOptions(productOptions).setTermFrequencyTypeOptions(termFrequencyTypeOptions)
                 .setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions)
                 .setRepaymentFrequencyNthDayTypeOptions(repaymentFrequencyNthDayTypeOptions)
                 .setRepaymentFrequencyDaysOfWeekTypeOptions(repaymentFrequencyDayOfWeekTypeOptions)
@@ -792,128 +536,38 @@ public class LoanAccountData {
                 .setFundOptions(fundOptions).setChargeOptions(chargeOptions).setLoanOfficerOptions(loanOfficerOptions)
                 .setLoanPurposeOptions(loanPurposeOptions).setLoanCollateralOptions(loanCollateralOptions)
                 // .setMeeting(calendarData)
-                .setCalendarOptions(calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(notes)
-                .setAccountLinkingOptions(accountLinkingOptions).setLinkedAccount(linkedAccount).setDisbursementDetails(disbursementDetails)
-                .setEmiAmountVariations(emiAmountVariations).setOverdueCharges(overdueCharges).setPaidInAdvance(paidInAdvance)
-                .setInterestRatesPeriods(interestRatesPeriods).setClientActiveLoanOptions(clientActiveLoanOptions).setRates(rates)
-                .setIsRatesEnabled(isRatesEnabled).setDelinquent(delinquent).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setMemberVariations(acc.memberVariations)
-                .setProduct(acc.product).setInArrears(acc.inArrears).setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement)
-                .setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed).setMinimumGap(acc.minimumGap)
-                .setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus).setCanUseForTopup(acc.canUseForTopup).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setLastClosedBusinessDate(acc.getLastClosedBusinessDate()).setOverpaidOnDate(acc.overpaidOnDate)
-                .setChargedOff(acc.chargedOff).setEnableDownPayment(acc.enableDownPayment)
-                .setDisbursedAmountPercentageForDownPayment(acc.disbursedAmountPercentageForDownPayment)
-                .setEnableAutoRepaymentForDownPayment(acc.enableAutoRepaymentForDownPayment)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(loanScheduleTypeOptions)
+                .setCalendarOptions(calendarOptions).setNotes(notes).setAccountLinkingOptions(accountLinkingOptions)
+                .setLinkedAccount(linkedAccount).setDisbursementDetails(disbursementDetails).setEmiAmountVariations(emiAmountVariations)
+                .setOverdueCharges(overdueCharges).setPaidInAdvance(paidInAdvance).setInterestRatesPeriods(interestRatesPeriods)
+                .setClientActiveLoanOptions(clientActiveLoanOptions).setRates(rates).setIsRatesEnabled(isRatesEnabled)
+                .setDelinquent(delinquent).setLoanScheduleTypeOptions(loanScheduleTypeOptions)
                 .setLoanScheduleProcessingTypeOptions(loanScheduleProcessingTypeOptions);
     }
 
-    public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection<LoanProductData> productOptions,
+    public LoanAccountData associationsAndTemplate(final Collection<LoanProductData> productOptions,
             final Collection<StaffData> allowedLoanOfficers, final Collection<CalendarData> calendarOptions,
             final Collection<PortfolioAccountData> accountLinkingOptions, final Boolean isRatesEnabled) {
-
-        return associationsAndTemplate(acc, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors,
-                acc.meeting, productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions,
-                acc.repaymentFrequencyNthDayTypeOptions, acc.repaymentFrequencyDaysOfWeekTypeOptions,
-                acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
-                acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
-                allowedLoanOfficers, acc.loanPurposeOptions, acc.loanCollateralOptions, calendarOptions, acc.notes, accountLinkingOptions,
-                acc.linkedAccount, acc.disbursementDetails, acc.emiAmountVariations, acc.overdueCharges, acc.paidInAdvance,
-                acc.interestRatesPeriods, acc.clientActiveLoanOptions, acc.rates, isRatesEnabled, acc.delinquent,
-                acc.loanScheduleTypeOptions, acc.loanScheduleProcessingTypeOptions);
-    }
-
-    public static LoanAccountData associateGroup(final LoanAccountData acc, final GroupGeneralData group) {
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(group).setLoanType(acc.loanType)
-                .setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
+        return this.setProductOptions(productOptions) //
+                .setLoanOfficerOptions(allowedLoanOfficers) //
+                .setCalendarOptions(calendarOptions) //
+                .setAccountLinkingOptions(accountLinkingOptions) //
+                .setIsRatesEnabled(isRatesEnabled); //
     }
 
-    public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map<Long, Integer> memberLoanCycle) {
-
-        final Map<Long, LoanBorrowerCycleData> memberVariations = new HashMap<Long, LoanBorrowerCycleData>();
+    public LoanAccountData associateMemberVariations(final Map<Long, Integer> memberLoanCycle) {
+        final Map<Long, LoanBorrowerCycleData> memberVariations = new HashMap<>();
         for (Map.Entry<Long, Integer> mapEntry : memberLoanCycle.entrySet()) {
             BigDecimal principal = null;
             BigDecimal interestRatePerPeriod = null;
             Integer numberOfRepayments = null;
             Long clientId = mapEntry.getKey();
             Integer loanCycleNumber = mapEntry.getValue();
-            if (acc.product.isUseBorrowerCycle() && loanCycleNumber != null && loanCycleNumber > 0) {
-                Collection<LoanProductBorrowerCycleVariationData> principalVariationsForBorrowerCycle = acc.product
+            if (product.isUseBorrowerCycle() && loanCycleNumber != null && loanCycleNumber > 0) {
+                Collection<LoanProductBorrowerCycleVariationData> principalVariationsForBorrowerCycle = product
                         .getPrincipalVariationsForBorrowerCycle();
-                Collection<LoanProductBorrowerCycleVariationData> interestForVariationsForBorrowerCycle = acc.product
+                Collection<LoanProductBorrowerCycleVariationData> interestForVariationsForBorrowerCycle = product
                         .getInterestRateVariationsForBorrowerCycle();
-                Collection<LoanProductBorrowerCycleVariationData> repaymentVariationsForBorrowerCycle = acc.product
+                Collection<LoanProductBorrowerCycleVariationData> repaymentVariationsForBorrowerCycle = product
                         .getNumberOfRepaymentVariationsForBorrowerCycle();
                 principal = fetchLoanCycleDefaultValue(principalVariationsForBorrowerCycle, loanCycleNumber);
                 interestRatePerPeriod = fetchLoanCycleDefaultValue(interestForVariationsForBorrowerCycle, loanCycleNumber);
@@ -923,276 +577,33 @@ public class LoanAccountData {
                 }
             }
             if (principal == null) {
-                principal = acc.product.getPrincipal();
+                principal = product.getPrincipal();
             }
             if (interestRatePerPeriod == null) {
-                interestRatePerPeriod = acc.product.getInterestRatePerPeriod();
+                interestRatePerPeriod = product.getInterestRatePerPeriod();
             }
             if (numberOfRepayments == null) {
-                numberOfRepayments = acc.product.getNumberOfRepayments();
+                numberOfRepayments = product.getNumberOfRepayments();
             }
-            final Integer termFrequency = numberOfRepayments * acc.product.getRepaymentEvery();
+            final Integer termFrequency = numberOfRepayments * product.getRepaymentEvery();
             LoanBorrowerCycleData borrowerCycleData = new LoanBorrowerCycleData(principal, interestRatePerPeriod, numberOfRepayments,
                     termFrequency);
             memberVariations.put(clientId, borrowerCycleData);
         }
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType).setFixedLength(acc.fixedLength)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
+        return this.setMemberVariations(memberVariations);
     }
 
-    public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData,
+    public LoanAccountData withInterestRecalculationCalendarData(final CalendarData calendarData,
             final CalendarData compoundingCalendarData) {
-
-        final LoanInterestRecalculationData interestRecalculationData = LoanInterestRecalculationData
-                .withCalendarData(acc.interestRecalculationData, calendarData, compoundingCalendarData);
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled).setInterestRecalculationData(interestRecalculationData)
-                .setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
-    }
-
-    public static LoanAccountData withLoanCalendarData(final LoanAccountData acc, final CalendarData calendarData) {
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType).setMeeting(calendarData)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(acc.originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
-    }
-
-    public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) {
-
-        return new LoanAccountData().setId(acc.id).setAccountNo(acc.accountNo).setStatus(acc.status).setExternalId(acc.externalId)
-                .setClientId(acc.clientId).setClientAccountNo(acc.clientAccountNo).setClientName(acc.clientName)
-                .setClientOfficeId(acc.clientOfficeId).setClientExternalId(acc.clientExternalId).setGroup(acc.group)
-                .setLoanType(acc.loanType).setLoanProductId(acc.loanProductId).setLoanProductName(acc.loanProductName)
-                .setLoanProductDescription(acc.loanProductDescription)
-                .setLoanProductLinkedToFloatingRate(acc.isLoanProductLinkedToFloatingRate).setFundId(acc.fundId).setFundName(acc.fundName)
-                .setLoanPurposeId(acc.loanPurposeId).setLoanPurposeName(acc.loanPurposeName).setLoanOfficerId(acc.loanOfficerId)
-                .setLoanOfficerName(acc.loanOfficerName).setCurrency(acc.currency).setProposedPrincipal(acc.proposedPrincipal)
-                .setPrincipal(acc.principal).setApprovedPrincipal(acc.approvedPrincipal).setNetDisbursalAmount(acc.netDisbursalAmount)
-                .setTotalOverpaid(acc.totalOverpaid).setInArrearsTolerance(acc.inArrearsTolerance).setTermFrequency(acc.termFrequency)
-                .setTermPeriodFrequencyType(acc.termPeriodFrequencyType).setNumberOfRepayments(acc.numberOfRepayments)
-                .setRepaymentEvery(acc.repaymentEvery).setRepaymentFrequencyType(acc.repaymentFrequencyType)
-                .setRepaymentFrequencyNthDayType(acc.repaymentFrequencyNthDayType)
-                .setRepaymentFrequencyDayOfWeekType(acc.repaymentFrequencyDayOfWeekType).setFixedLength(acc.fixedLength)
-                .setTransactionProcessingStrategyCode(acc.transactionProcessingStrategyCode)
-                .setTransactionProcessingStrategyName(acc.transactionProcessingStrategyName).setAmortizationType(acc.amortizationType)
-                .setInterestRatePerPeriod(acc.interestRatePerPeriod).setInterestRateFrequencyType(acc.interestRateFrequencyType)
-                .setAnnualInterestRate(acc.annualInterestRate).setInterestType(acc.interestType)
-                .setFloatingInterestRate(acc.isFloatingInterestRate).setInterestRateDifferential(acc.interestRateDifferential)
-                .setInterestCalculationPeriodType(acc.interestCalculationPeriodType)
-                .setAllowPartialPeriodInterestCalculation(acc.allowPartialPeriodInterestCalculation)
-                .setExpectedFirstRepaymentOnDate(acc.expectedFirstRepaymentOnDate).setGraceOnPrincipalPayment(acc.graceOnPrincipalPayment)
-                .setRecurringMoratoriumOnPrincipalPeriods(acc.recurringMoratoriumOnPrincipalPeriods)
-                .setGraceOnInterestPayment(acc.graceOnInterestPayment).setGraceOnInterestCharged(acc.graceOnInterestCharged)
-                .setInterestChargedFromDate(acc.interestChargedFromDate).setTimeline(acc.timeline).setSummary(acc.summary)
-                .setFeeChargesAtDisbursementCharged(acc.feeChargesAtDisbursementCharged).setRepaymentSchedule(acc.repaymentSchedule)
-                .setTransactions(acc.transactions).setCharges(acc.charges).setCollateral(acc.collateral).setGuarantors(acc.guarantors)
-                .setMeeting(acc.meeting).setProductOptions(acc.productOptions).setTermFrequencyTypeOptions(acc.termFrequencyTypeOptions)
-                .setRepaymentFrequencyTypeOptions(acc.repaymentFrequencyTypeOptions)
-                .setRepaymentFrequencyNthDayTypeOptions(acc.repaymentFrequencyNthDayTypeOptions)
-                .setRepaymentFrequencyDaysOfWeekTypeOptions(acc.repaymentFrequencyDaysOfWeekTypeOptions)
-                .setTransactionProcessingStrategyOptions(acc.transactionProcessingStrategyOptions)
-                .setInterestRateFrequencyTypeOptions(acc.interestRateFrequencyTypeOptions)
-                .setAmortizationTypeOptions(acc.amortizationTypeOptions).setInterestTypeOptions(acc.interestTypeOptions)
-                .setInterestCalculationPeriodTypeOptions(acc.interestCalculationPeriodTypeOptions).setFundOptions(acc.fundOptions)
-                .setChargeOptions(acc.chargeOptions).setLoanOfficerOptions(acc.loanOfficerOptions)
-                .setLoanPurposeOptions(acc.loanPurposeOptions).setLoanCollateralOptions(acc.loanCollateralOptions)
-                .setCalendarOptions(acc.calendarOptions).setSyncDisbursementWithMeeting(acc.syncDisbursementWithMeeting)
-                .setLoanCounter(acc.loanCounter).setLoanProductCounter(acc.loanProductCounter).setNotes(acc.notes)
-                .setAccountLinkingOptions(acc.accountLinkingOptions).setLinkedAccount(acc.linkedAccount)
-                .setDisbursementDetails(acc.disbursementDetails).setMultiDisburseLoan(acc.multiDisburseLoan)
-                .setCanDefineInstallmentAmount(acc.canDefineInstallmentAmount).setFixedEmiAmount(acc.fixedEmiAmount)
-                .setMaxOutstandingLoanBalance(acc.maxOutstandingLoanBalance).setEmiAmountVariations(acc.emiAmountVariations)
-                .setMemberVariations(acc.memberVariations).setProduct(acc.product).setInArrears(acc.inArrears)
-                .setGraceOnArrearsAgeing(acc.graceOnArrearsAgeing).setOverdueCharges(acc.overdueCharges).setIsNPA(acc.isNPA)
-                .setDaysInMonthType(acc.daysInMonthType).setDaysInYearType(acc.daysInYearType)
-                .setInterestRecalculationEnabled(acc.isInterestRecalculationEnabled)
-                .setInterestRecalculationData(acc.interestRecalculationData).setOriginalSchedule(originalSchedule)
-                .setCreateStandingInstructionAtDisbursement(acc.createStandingInstructionAtDisbursement).setPaidInAdvance(acc.paidInAdvance)
-                .setInterestRatesPeriods(acc.interestRatesPeriods).setIsVariableInstallmentsAllowed(acc.isVariableInstallmentsAllowed)
-                .setMinimumGap(acc.minimumGap).setMaximumGap(acc.maximumGap).setSubStatus(acc.subStatus)
-                .setCanUseForTopup(acc.canUseForTopup).setClientActiveLoanOptions(acc.clientActiveLoanOptions).setTopup(acc.isTopup)
-                .setClosureLoanId(acc.closureLoanId).setClosureLoanAccountNo(acc.closureLoanAccountNo).setTopupAmount(acc.topupAmount)
-                .setIsEqualAmortization(acc.isEqualAmortization).setRates(acc.rates).setIsRatesEnabled(acc.isRatesEnabled)
-                .setFixedPrincipalPercentagePerInstallment(acc.fixedPrincipalPercentagePerInstallment).setDelinquent(acc.delinquent)
-                .setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
-                .setFraud(acc.fraud).setOverpaidOnDate(acc.overpaidOnDate).setChargedOff(acc.chargedOff)
-                .setEnableInstallmentLevelDelinquency(acc.enableInstallmentLevelDelinquency).setLoanScheduleType(acc.loanScheduleType)
-                .setLoanScheduleProcessingType(acc.loanScheduleProcessingType).setLoanScheduleTypeOptions(acc.loanScheduleTypeOptions)
-                .setLoanScheduleProcessingTypeOptions(acc.loanScheduleProcessingTypeOptions);
+        if (interestRecalculationData == null) {
+            interestRecalculationData = new LoanInterestRecalculationData();
+        }
+        final LoanInterestRecalculationData newInterestRecalculationData = interestRecalculationData.withCalendarData(calendarData,
+                compoundingCalendarData);
+        return this.setInterestRecalculationData(newInterestRecalculationData);
     }
 
-    public static final Comparator<LoanAccountData> ClientNameComparator = (loan1, loan2) -> {
+    public static final Comparator<LoanAccountData> LOAN_ACCOUNT_DATA_COMPARATOR_BY_CLIENT_NAME = (loan1, loan2) -> {
         String clientOfLoan1 = loan1.getClientName().toUpperCase(Locale.ENGLISH);
         String clientOfLoan2 = loan2.getClientName().toUpperCase(Locale.ENGLISH);
         return clientOfLoan1.compareTo(clientOfLoan2);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
index 278df26d6..9d626b4d5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
@@ -74,12 +74,6 @@ public interface LoanReadPlatformService {
 
     LoanAccountData retrieveLoanProductDetailsTemplate(Long productId, Long clientId, Long groupId);
 
-    LoanAccountData retrieveClientDetailsTemplate(Long clientId);
-
-    LoanAccountData retrieveGroupDetailsTemplate(Long groupId);
-
-    LoanAccountData retrieveGroupAndMembersDetailsTemplate(Long groupId);
-
     Collection<CalendarData> retrieveCalendars(Long groupId);
 
     Page<LoanAccountData> retrieveAll(SearchParameters searchParameters);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index b30c2e0a4..d662fd3db 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -235,9 +235,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
 
     @Override
     public LoanAccountData fetchRepaymentScheduleData(LoanAccountData accountData) {
-        final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = accountData.getTimeline().repaymentScheduleRelatedData(
-                accountData.getCurrency(), accountData.getPrincipal(), accountData.getApprovedPrincipal(),
-                accountData.getInArrearsTolerance(), accountData.getFeeChargesAtDisbursementCharged());
+        final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = new RepaymentScheduleRelatedLoanData(
+                accountData.getTimeline().getExpectedDisbursementDate(), accountData.getTimeline().getActualDisbursementDate(),
+                accountData.getCurrency(), accountData.getPrincipal(), accountData.getInArrearsTolerance(),
+                accountData.getFeeChargesAtDisbursementCharged());
 
         final Collection<DisbursementData> disbursementData = retrieveLoanDisbursementDetails(accountData.getId());
         final LoanScheduleData repaymentSchedule = retrieveRepaymentSchedule(accountData.getId(), repaymentScheduleRelatedData,
@@ -384,15 +385,15 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
 
         final ClientData clientAccount = this.clientReadPlatformService.retrieveOne(clientId);
         final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-        LoanAccountData loanTemplateDetails = LoanAccountData.clientDefaults(clientAccount.getId(), clientAccount.getAccountNo(),
-                clientAccount.getDisplayName(), clientAccount.getOfficeId(), clientAccount.getExternalId(), expectedDisbursementDate);
+        LoanAccountData loanDetails = new LoanAccountData().withClientData(clientAccount)
+                .setExpectedDisbursementDate(expectedDisbursementDate);
 
         if (productId != null) {
             final LoanProductData selectedProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
-            loanTemplateDetails = LoanAccountData.populateLoanProductDefaults(loanTemplateDetails, selectedProduct);
+            loanDetails = loanDetails.withProductData(selectedProduct, null);
         }
 
-        return loanTemplateDetails;
+        return loanDetails;
     }
 
     @Override
@@ -402,11 +403,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
 
         final GroupGeneralData groupAccount = this.groupReadPlatformService.retrieveOne(groupId);
         final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-        LoanAccountData loanDetails = LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
+        LoanAccountData loanDetails = new LoanAccountData().setGroup(groupAccount).withExpectedDisbursementDate(expectedDisbursementDate);
 
         if (productId != null) {
             final LoanProductData selectedProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
-            loanDetails = LoanAccountData.populateLoanProductDefaults(loanDetails, selectedProduct);
+            loanDetails = loanDetails.withProductData(selectedProduct, null);
         }
 
         return loanDetails;
@@ -430,11 +431,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
         }
 
         final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-        LoanAccountData loanDetails = LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
+        LoanAccountData loanDetails = new LoanAccountData().setGroup(groupAccount).withExpectedDisbursementDate(expectedDisbursementDate);
 
         if (productId != null) {
             final LoanProductData selectedProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
-            loanDetails = LoanAccountData.populateLoanProductDefaults(loanDetails, selectedProduct);
+            loanDetails = loanDetails.withProductData(selectedProduct, null);
         }
 
         return loanDetails;
@@ -1521,7 +1522,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
                 .retrieveLoanAmortizationTypeOptions();
         Collection<EnumOptionData> interestTypeOptions = null;
         if (loanProduct.isLinkedToFloatingInterestRates()) {
-            interestTypeOptions = Arrays.asList(interestType(InterestMethod.DECLINING_BALANCE));
+            interestTypeOptions = List.of(interestType(InterestMethod.DECLINING_BALANCE));
         } else {
             interestTypeOptions = this.loanDropdownReadPlatformService.retrieveLoanInterestTypeOptions();
         }
@@ -1558,50 +1559,23 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
             activeLoanOptions = this.accountDetailsReadPlatformService.retrieveGroupActiveLoanAccountSummary(groupId);
         }
 
-        return LoanAccountData.loanProductWithTemplateDefaults(loanProduct, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
-                repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDaysOfWeekTypeOptions, repaymentStrategyOptions,
-                interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
-                fundOptions, chargeOptions, loanPurposeOptions, loanCollateralOptions, loanCycleCounter, activeLoanOptions,
-                LoanScheduleType.getValuesAsEnumOptionDataList(), LoanScheduleProcessingType.getValuesAsEnumOptionDataList());
-    }
-
-    @Override
-    public LoanAccountData retrieveClientDetailsTemplate(final Long clientId) {
-
-        this.context.authenticatedUser();
-
-        final ClientData clientAccount = this.clientReadPlatformService.retrieveOne(clientId);
-        final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-
-        return LoanAccountData.clientDefaults(clientAccount.getId(), clientAccount.getAccountNo(), clientAccount.getDisplayName(),
-                clientAccount.getOfficeId(), clientAccount.getExternalId(), expectedDisbursementDate);
-    }
-
-    @Override
-    public LoanAccountData retrieveGroupDetailsTemplate(final Long groupId) {
-        this.context.authenticatedUser();
-        final GroupGeneralData groupAccount = this.groupReadPlatformService.retrieveOne(groupId);
-        final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-        return LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
-    }
-
-    @Override
-    public LoanAccountData retrieveGroupAndMembersDetailsTemplate(final Long groupId) {
-        GroupGeneralData groupAccount = this.groupReadPlatformService.retrieveOne(groupId);
-        final LocalDate expectedDisbursementDate = DateUtils.getBusinessLocalDate();
-
-        // get group associations
-        final Collection<ClientData> membersOfGroup = this.clientReadPlatformService.retrieveActiveClientMembersOfGroup(groupId);
-        if (!CollectionUtils.isEmpty(membersOfGroup)) {
-            final Collection<ClientData> activeClientMembers = null;
-            final Collection<CalendarData> calendarsData = null;
-            final CalendarData collectionMeetingCalendar = null;
-            final Collection<GroupRoleData> groupRoles = null;
-            groupAccount = GroupGeneralData.withAssocations(groupAccount, membersOfGroup, activeClientMembers, groupRoles, calendarsData,
-                    collectionMeetingCalendar);
-        }
-
-        return LoanAccountData.groupDefaults(groupAccount, expectedDisbursementDate);
+        return new LoanAccountData().withProductData(loanProduct, loanCycleCounter) //
+                .setTermFrequencyTypeOptions(loanTermFrequencyTypeOptions) //
+                .setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions) //
+                .setRepaymentFrequencyNthDayTypeOptions(repaymentFrequencyNthDayTypeOptions) //
+                .setRepaymentFrequencyDaysOfWeekTypeOptions(repaymentFrequencyDaysOfWeekTypeOptions) //
+                .setTransactionProcessingStrategyOptions(repaymentStrategyOptions) //
+                .setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions) //
+                .setAmortizationTypeOptions(amortizationTypeOptions) //
+                .setInterestTypeOptions(interestTypeOptions) //
+                .setInterestCalculationPeriodTypeOptions(interestCalculationPeriodTypeOptions) //
+                .setFundOptions(fundOptions) //
+                .setChargeOptions(chargeOptions) //
+                .setLoanPurposeOptions(loanPurposeOptions) //
+                .setLoanCollateralOptions(loanCollateralOptions) //
+                .setClientActiveLoanOptions(activeLoanOptions) //
+                .setLoanScheduleTypeOptions(LoanScheduleType.getValuesAsEnumOptionDataList()) //
+                .setLoanScheduleProcessingTypeOptions(LoanScheduleProcessingType.getValuesAsEnumOptionDataList()); //
     }
 
     @Override