Repository: incubator-fineract
Updated Branches:
  refs/heads/develop ff58f74d7 -> ca1adedd4


fix for performance issues


Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/ca1adedd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/ca1adedd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/ca1adedd

Branch: refs/heads/develop
Commit: ca1adedd408b3be6e7caddb5fbb5500775a58471
Parents: ff58f74
Author: pramod <[email protected]>
Authored: Fri Aug 26 19:05:30 2016 +0530
Committer: pramod <[email protected]>
Committed: Fri Aug 26 19:05:30 2016 +0530

----------------------------------------------------------------------
 .../domain/ConfigurationDomainService.java      |  3 +
 .../domain/ConfigurationDomainServiceJpa.java   | 82 ++++++++++-------
 .../domain/GlobalConfigurationProperty.java     | 15 ++-
 ...onWritePlatformServiceJpaRepositoryImpl.java |  7 +-
 .../FloatingRatesReadPlatformService.java       |  2 +-
 .../FloatingRatesReadPlatformServiceImpl.java   | 12 ++-
 .../loanaccount/api/LoansApiResource.java       |  2 +-
 .../loanaccount/data/LoanAccountData.java       | 18 ++++
 .../data/LoanApplicationTimelineData.java       |  8 ++
 .../service/LoanReadPlatformService.java        |  2 +-
 .../service/LoanReadPlatformServiceImpl.java    | 25 +++--
 .../loanproduct/data/LoanProductData.java       | 97 ++++++++++++++++++++
 .../service/LoanProductReadPlatformService.java |  2 +
 .../LoanProductReadPlatformServiceImpl.java     | 53 +++++++++++
 14 files changed, 267 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
index 58494c2..4abbb4b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.infrastructure.configuration.domain;
 
 import java.util.Date;
+
 import org.apache.fineract.infrastructure.cache.domain.CacheType;
 
 public interface ConfigurationDomainService {
@@ -82,5 +83,7 @@ public interface ConfigurationDomainService {
     boolean isDailyTPTLimitEnabled();
     
     Long getDailyTPTLimit();
+
+    void removeGlobalConfigurationPropertyDataFromCache(String propertyName);
     
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
index 67ebdc5..95170f8 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
@@ -19,11 +19,15 @@
 package org.apache.fineract.infrastructure.configuration.domain;
 
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.fineract.infrastructure.cache.domain.CacheType;
 import org.apache.fineract.infrastructure.cache.domain.PlatformCache;
 import org.apache.fineract.infrastructure.cache.domain.PlatformCacheRepository;
+import 
org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.useradministration.domain.Permission;
 import org.apache.fineract.useradministration.domain.PermissionRepository;
 import 
org.apache.fineract.useradministration.exception.PermissionNotFoundException;
@@ -37,6 +41,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     private final PermissionRepository permissionRepository;
     private final GlobalConfigurationRepositoryWrapper 
globalConfigurationRepository;
     private final PlatformCacheRepository cacheTypeRepository;
+    private static Map<String, GlobalConfigurationPropertyData> configurations 
= new HashMap<>();
 
     @Autowired
     public ConfigurationDomainServiceJpa(final PermissionRepository 
permissionRepository,
@@ -54,22 +59,20 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
         if (thisTask == null) { throw new 
PermissionNotFoundException(taskPermissionCode); }
 
         final String makerCheckerConfigurationProperty = "maker-checker";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository
-                
.findOneByNameWithNotFoundDetection(makerCheckerConfigurationProperty);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(makerCheckerConfigurationProperty);
 
         return thisTask.hasMakerCheckerEnabled() && property.isEnabled();
     }
 
     @Override
     public boolean isAmazonS3Enabled() {
-        return 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection("amazon-S3").isEnabled();
+        return getGlobalConfigurationPropertyData("amazon-S3").isEnabled();
     }
 
     @Override
     public boolean isRescheduleFutureRepaymentsEnabled() {
         final String rescheduleRepaymentsConfigurationProperty = 
"reschedule-future-repayments";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository
-                
.findOneByNameWithNotFoundDetection(rescheduleRepaymentsConfigurationProperty);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(rescheduleRepaymentsConfigurationProperty);
         return property.isEnabled();
     }
 
@@ -82,30 +85,28 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public boolean isRescheduleRepaymentsOnHolidaysEnabled() {
         final String holidaysConfigurationProperty = 
"reschedule-repayments-on-holidays";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository
-                
.findOneByNameWithNotFoundDetection(holidaysConfigurationProperty);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(holidaysConfigurationProperty);
         return property.isEnabled();
     }
 
     @Override
     public boolean allowTransactionsOnHolidayEnabled() {
         final String allowTransactionsOnHolidayProperty = 
"allow-transactions-on-holiday";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository
-                
.findOneByNameWithNotFoundDetection(allowTransactionsOnHolidayProperty);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(allowTransactionsOnHolidayProperty);
         return property.isEnabled();
     }
 
     @Override
     public boolean allowTransactionsOnNonWorkingDayEnabled() {
         final String propertyName = "allow-transactions-on-non_workingday";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
     @Override
     public boolean isConstraintApproachEnabledForDatatables() {
         final String propertyName = "constraint_approach_for_datatables";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
@@ -125,49 +126,49 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public Long retrievePenaltyWaitPeriod() {
         final String propertyName = "penalty-wait-period";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
     }
 
     @Override
     public Long retrieveGraceOnPenaltyPostingPeriod() {
         final String propertyName = "grace-on-penalty-posting";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
     }
 
     @Override
     public boolean isPasswordForcedResetEnable() {
         final String propertyName = "force-password-reset-days";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
     @Override
     public Long retrievePasswordLiveTime() {
         final String propertyName = "force-password-reset-days";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
     }
 
     @Override
     public Long retrieveOpeningBalancesContraAccount() {
         final String propertyName = "office-opening-balances-contra-account";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
     }
 
     @Override
     public boolean isSavingsInterestPostingAtCurrentPeriodEnd() {
         final String propertyName = 
"savings-interest-posting-current-period-end";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
     @Override
     public Integer retrieveFinancialYearBeginningMonth() {
         final String propertyName = "financial-year-beginning-month";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         if (property.isEnabled()) return property.getValue().intValue();
         return 1;
     }
@@ -175,7 +176,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public Integer retrieveMinAllowedClientsInGroup() {
         final String propertyName = "min-clients-in-group";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         if (property.isEnabled()) { return property.getValue().intValue(); }
         return null;
     }
@@ -183,7 +184,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public Integer retrieveMaxAllowedClientsInGroup() {
         final String propertyName = "max-clients-in-group";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         if (property.isEnabled()) { return property.getValue().intValue(); }
         return null;
     }
@@ -191,7 +192,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public boolean isMeetingMandatoryForJLGLoans() {
         final String propertyName = "meetings-mandatory-for-jlg-loans";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
@@ -199,7 +200,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     public int getRoundingMode() {
         final String propertyName = "rounding-mode";
         int defaultValue = 6; // 6 Stands for HALF-EVEN
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         if (property.isEnabled()) {
             int value = property.getValue().intValue();
             if (value < 0 || value > 6) {
@@ -213,40 +214,40 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public boolean isBackdatePenaltiesEnabled() {
         final String propertyName = "backdate-penalties-enabled";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
     @Override
     public boolean isOrganisationstartDateEnabled() {
         final String propertyName = "organisation-start-date";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
     @Override
     public Date retrieveOrganisationStartDate() {
         final String propertyName = "organisation-start-date";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getDateValue();
     }
 
        @Override
        public boolean isPaymnetypeApplicableforDisbursementCharge() {
                final String propertyName = 
"paymenttype-applicable-for-disbursement-charges";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
        }
        
     @Override
     public boolean isSkippingMeetingOnFirstDayOfMonthEnabled() {
-        return 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection("skip-repayment-on-first-day-of-month").isEnabled();
+        return 
getGlobalConfigurationPropertyData("skip-repayment-on-first-day-of-month").isEnabled();
     }
 
     @Override
     public Long retreivePeroidInNumberOfDaysForSkipMeetingDate() {
         final String propertyName = "skip-repayment-on-first-day-of-month";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
 
     }
@@ -254,30 +255,45 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
     @Override
     public boolean isInterestChargedFromDateSameAsDisbursementDate() {
         final String propertyName = 
"interest-charged-from-date-same-as-disbursal-date";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
     
     @Override
     public boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled() {
         final String propertyName = 
"change-emi-if-repaymentdate-same-as-disbursementdate";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
     }
 
        @Override
        public boolean isDailyTPTLimitEnabled() {
         final String propertyName = "daily-tpt-limit";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.isEnabled();
        }
 
        @Override
        public Long getDailyTPTLimit() {
         final String propertyName = "daily-tpt-limit";
-        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        final GlobalConfigurationPropertyData property = 
getGlobalConfigurationPropertyData(propertyName);
         return property.getValue();
        }
 
-  
+    @Override
+    public void removeGlobalConfigurationPropertyDataFromCache(final String 
propertyName) {
+        String identifier = 
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+        String key = identifier + "_" + propertyName;
+        configurations.remove(key);
+    }
+
+    private GlobalConfigurationPropertyData 
getGlobalConfigurationPropertyData(final String propertyName) {
+        String identifier = 
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+        String key = identifier + "_" + propertyName;
+        if (!configurations.containsKey(key)) {
+            GlobalConfigurationProperty configuration = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+            configurations.put(key, configuration.toData());
+        }
+        return configurations.get(key);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
index 169d532..40d681b 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
@@ -26,6 +26,7 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Table;
 
+import 
org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData;
 import 
org.apache.fineract.infrastructure.configuration.exception.GlobalConfigurationPropertyCannotBeModfied;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import 
org.apache.fineract.infrastructure.security.exception.ForcePasswordResetException;
@@ -84,11 +85,6 @@ public class GlobalConfigurationProperty extends 
AbstractPersistable<Long> {
         return this.dateValue;
     }
 
-    public boolean updateTo(final boolean value) {
-        final boolean updated = this.enabled != value;
-        this.enabled = value;
-        return updated;
-    }
 
     public Map<String, Object> update(final JsonCommand command) {
 
@@ -131,5 +127,14 @@ public class GlobalConfigurationProperty extends 
AbstractPersistable<Long> {
     public static GlobalConfigurationProperty newSurveyConfiguration(final 
String name) {
         return new GlobalConfigurationProperty(name, false, null, null, null, 
false);
     }
+    
+    public GlobalConfigurationPropertyData toData() {
+        return new GlobalConfigurationPropertyData(getName(), isEnabled(), 
getValue(), getDateValue(), this.getId(), this.description,
+                this.isTrapDoor);
+    }
+    
+    public String getName() {
+        return this.name;
+    }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/GlobalConfigurationWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/GlobalConfigurationWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/GlobalConfigurationWritePlatformServiceJpaRepositoryImpl.java
index d3fffa4..55bc7c3 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/GlobalConfigurationWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/GlobalConfigurationWritePlatformServiceJpaRepositoryImpl.java
@@ -21,6 +21,7 @@ package 
org.apache.fineract.infrastructure.configuration.service;
 import java.util.Map;
 
 import 
org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationDataValidator;
+import 
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
 import 
org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurationProperty;
 import 
org.apache.fineract.infrastructure.configuration.domain.GlobalConfigurationRepositoryWrapper;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
@@ -43,13 +44,16 @@ public class 
GlobalConfigurationWritePlatformServiceJpaRepositoryImpl implements
     private final PlatformSecurityContext context;
     private final GlobalConfigurationRepositoryWrapper repository;
     private final GlobalConfigurationDataValidator 
globalConfigurationDataValidator;
+    private final ConfigurationDomainService configurationDomainService;
 
     @Autowired
     public GlobalConfigurationWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
-            final GlobalConfigurationRepositoryWrapper codeRepository, final 
GlobalConfigurationDataValidator dataValidator) {
+            final GlobalConfigurationRepositoryWrapper codeRepository, final 
GlobalConfigurationDataValidator dataValidator,
+            final ConfigurationDomainService configurationDomainService) {
         this.context = context;
         this.repository = codeRepository;
         this.globalConfigurationDataValidator = dataValidator;
+        this.configurationDomainService = configurationDomainService;
 
     }
 
@@ -67,6 +71,7 @@ public class 
GlobalConfigurationWritePlatformServiceJpaRepositoryImpl implements
             final Map<String, Object> changes = 
configItemForUpdate.update(command);
 
             if (!changes.isEmpty()) {
+                
this.configurationDomainService.removeGlobalConfigurationPropertyDataFromCache(configItemForUpdate.getName());
                 this.repository.save(configItemForUpdate);
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformService.java
index 24e9f3a..4c4853e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformService.java
@@ -35,6 +35,6 @@ public interface FloatingRatesReadPlatformService {
 
        FloatingRateData retrieveBaseLendingRate();
 
-       List<InterestRatePeriodData> retrieveInterestRatePeriods(Long 
floatingRateId);
+       List<InterestRatePeriodData> retrieveInterestRatePeriods(Long 
productId);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
index 798a2b1..9593715 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
@@ -87,13 +87,13 @@ public class FloatingRatesReadPlatformServiceImpl implements
 
        @Override
        public List<InterestRatePeriodData> retrieveInterestRatePeriods(
-                       final Long floatingRateId) {
+                       final Long productId) {
                try {
                        FloatingInterestRatePeriodRowMapper mapper = new 
FloatingInterestRatePeriodRowMapper();
                        return this.jdbcTemplate.query(mapper.schema(), mapper,
-                                       new Object[] { floatingRateId });
+                                       new Object[] { productId });
                } catch (final EmptyResultDataAccessException e) {
-                       throw new FloatingRateNotFoundException(floatingRateId);
+                       throw new 
FloatingRateNotFoundException("error.msg.floatingrate.not.found.for.product");
                }
        }
 
@@ -242,7 +242,9 @@ public class FloatingRatesReadPlatformServiceImpl implements
                                .append("    
linkedrateperiods.is_differential_to_base_lending_rate as 
linkedrateperiods_is_differential_to_base_lending_rate, ")
                                .append("    baserate.from_date as 
baserate_from_date, ")
                                .append("    baserate.interest_rate as 
baserate_interest_rate ")
-                               .append("from m_floating_rates as linkedrate ")
+                               .append(" from m_product_loan as lp ")
+                                .append(" join m_product_loan_floating_rates 
as plfr on lp.id = plfr.loan_product_id ")
+                                .append(" join  m_floating_rates as linkedrate 
on linkedrate.id = plfr.floating_rates_id ")
                                .append("left join m_floating_rates_periods as 
linkedrateperiods on (linkedrate.id = linkedrateperiods.floating_rates_id and 
linkedrateperiods.is_active = 1) ")
                                .append("left join ( ")
                                .append("    select blr.name, ")
@@ -266,7 +268,7 @@ public class FloatingRatesReadPlatformServiceImpl implements
                                .append("            where 
blr.is_base_lending_rate = 1 and blr.is_active = 1 ")
                                .append("        ) as b ")
                                .append("        where b.from_date <= 
linkedrateperiods.from_date)) ")
-                               .append("and linkedrate.id = ? ")
+                               .append("and lp.id = ? ")
                                .append("order by linkedratePeriods_from_date 
desc ");
 
                @Override

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
----------------------------------------------------------------------
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 cfdf399..0b6fbf1 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
@@ -393,7 +393,7 @@ public class LoansApiResource {
                loanBasicDetails = 
LoanAccountData.withLoanCalendarData(loanBasicDetails, calendarData);
         }
 
-        Collection<InterestRatePeriodData> interestRatesPeriods = 
this.loanReadPlatformService.retrieveLoanInterestRatePeriodData(loanId);
+        Collection<InterestRatePeriodData> interestRatesPeriods = 
this.loanReadPlatformService.retrieveLoanInterestRatePeriodData(loanBasicDetails);
 
         Collection<LoanTransactionData> loanRepayments = null;
         LoanScheduleData repaymentSchedule = null;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
----------------------------------------------------------------------
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 7927b68..5a250b3 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
@@ -1600,4 +1600,22 @@ public class LoanAccountData {
         
         return LoanAccountData.collateralTemplate(loanCollateralOptions);
     }
+    
+    public boolean isLoanProductLinkedToFloatingRate() {
+        return this.isLoanProductLinkedToFloatingRate;
+    }
+    
+    public LocalDate getDisbursementDate(){
+        return this.timeline.getDisbursementDate();
+    }
+
+    
+    public boolean isFloatingInterestRate() {
+        return this.isFloatingInterestRate;
+    }
+
+    
+    public BigDecimal getInterestRateDifferential() {
+        return this.interestRateDifferential;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
index 656d718..a85f976 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanApplicationTimelineData.java
@@ -148,4 +148,12 @@ public class LoanApplicationTimelineData {
         return new 
RepaymentScheduleRelatedLoanData(this.expectedDisbursementDate, 
this.actualDisbursementDate, currency, principal,
                  inArrearsTolerance, totalFeeChargesAtDisbursement);
     }
+    
+    public LocalDate getDisbursementDate(){
+        LocalDate disbursementDate = this.expectedDisbursementDate;
+        if(this.actualDisbursementDate != null){
+            disbursementDate = this.actualDisbursementDate;
+        }
+        return disbursementDate;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
----------------------------------------------------------------------
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 51038d4..f7aeb60 100755
--- 
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
@@ -125,7 +125,7 @@ public interface LoanReadPlatformService {
 
     LoanTransactionData retrieveRefundByCashTemplate(Long loanId);
     
-    Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long 
loanId);
+    Collection<InterestRatePeriodData> 
retrieveLoanInterestRatePeriodData(LoanAccountData loan);
 
     Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions();
 

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
----------------------------------------------------------------------
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 a99064a..9d8d799 100755
--- 
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
@@ -62,7 +62,6 @@ import 
org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformServic
 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.api.ClientApiConstants;
 import org.apache.fineract.portfolio.client.data.ClientData;
 import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
 import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
@@ -2065,22 +2064,19 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService {
     }
 
     @Override
-    public Collection<InterestRatePeriodData> 
retrieveLoanInterestRatePeriodData(Long loanId) {
+    public Collection<InterestRatePeriodData> 
retrieveLoanInterestRatePeriodData(LoanAccountData loanData) {
         this.context.authenticatedUser();
 
-        final Loan loan = this.loanRepository.findOne(loanId);
-        if (loan == null) { throw new LoanNotFoundException(loanId); }
-
-        if (loan.loanProduct().isLinkedToFloatingInterestRate()) {
+        if (loanData.isLoanProductLinkedToFloatingRate()) {
             final Collection<InterestRatePeriodData> intRatePeriodData = new 
ArrayList<>();
-            final Collection<InterestRatePeriodData> intRates = 
this.floatingRatesReadPlatformService.retrieveInterestRatePeriods(loan
-                    
.loanProduct().getFloatingRates().getFloatingRate().getId());
+            final Collection<InterestRatePeriodData> intRates = 
this.floatingRatesReadPlatformService.retrieveInterestRatePeriods(loanData
+                    .loanProductId());
             for (final InterestRatePeriodData rate : intRates) {
-                if 
(rate.getFromDate().compareTo(loan.getDisbursementDate().toDate()) > 0 && 
loan.getIsFloatingInterestRate()) {
-                    updateInterestRatePeriodData(rate, loan);
+                if 
(rate.getFromDate().compareTo(loanData.getDisbursementDate().toDate()) > 0 && 
loanData.isFloatingInterestRate()) {
+                    updateInterestRatePeriodData(rate, loanData);
                     intRatePeriodData.add(rate);
-                } else if 
(rate.getFromDate().compareTo(loan.getDisbursementDate().toDate()) <= 0) {
-                    updateInterestRatePeriodData(rate, loan);
+                } else if 
(rate.getFromDate().compareTo(loanData.getDisbursementDate().toDate()) <= 0) {
+                    updateInterestRatePeriodData(rate, loanData);
                     intRatePeriodData.add(rate);
                     break;
                 }
@@ -2091,8 +2087,9 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService {
         return null;
     }
 
-    private void updateInterestRatePeriodData(InterestRatePeriodData rate, 
Loan loan) {
-        
rate.setLoanProductDifferentialInterestRate(loan.loanProduct().getFloatingRates().getInterestRateDifferential());
+    private void updateInterestRatePeriodData(InterestRatePeriodData rate, 
LoanAccountData loan) {
+        LoanProductData loanProductData = 
loanProductReadPlatformService.retrieveLoanProductFloatingDetails(loan.loanProductId());
+        
rate.setLoanProductDifferentialInterestRate(loanProductData.getInterestRateDifferential());
         
rate.setLoanDifferentialInterestRate(loan.getInterestRateDifferential());
 
         BigDecimal effectiveInterestRate = BigDecimal.ZERO;

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
index bf05d4e..44ade21 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
@@ -468,6 +468,99 @@ public class LoanProductData {
                 syncExpectedWithDisbursementDate, canUseForTopup);
 
     }
+    
+    public static LoanProductData loanProductWithFloatingRates(final Long id, 
final String name,
+            final boolean isLinkedToFloatingInterestRates, final Integer 
floatingRateId, final String floatingRateName,
+            final BigDecimal interestRateDifferential, final BigDecimal 
minDifferentialLendingRate,
+            final BigDecimal defaultDifferentialLendingRate, final BigDecimal 
maxDifferentialLendingRate,
+            final boolean isFloatingInterestRateCalculationAllowed) {
+        final String shortName = null;
+        final String description = null;
+        final CurrencyData currency = CurrencyData.blank();
+        final BigDecimal principal = null;
+        final BigDecimal minPrincipal = null;
+        final BigDecimal maxPrincipal = null;
+        final BigDecimal tolerance = null;
+        final Integer numberOfRepayments = null;
+        final Integer minNumberOfRepayments = null;
+        final Integer maxNumberOfRepayments = null;
+
+        final Integer repaymentEvery = null;
+        final BigDecimal interestRatePerPeriod = null;
+        final BigDecimal minInterestRatePerPeriod = null;
+        final BigDecimal maxInterestRatePerPeriod = null;
+        final BigDecimal annualInterestRate = null;
+        final boolean isVariableInstallmentsAllowed = false;
+        final Integer minimumGap = null;
+        final Integer maximumGap = null;
+        final EnumOptionData repaymentFrequencyType = 
LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
+        final EnumOptionData interestRateFrequencyType = 
LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
+        final EnumOptionData amortizationType = 
LoanEnumerations.amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS);
+        final EnumOptionData interestType = 
LoanEnumerations.interestType(InterestMethod.DECLINING_BALANCE);
+        final EnumOptionData interestCalculationPeriodType = LoanEnumerations
+                
.interestCalculationPeriodType(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD);
+        final Boolean allowPartialPeriodInterestCalcualtion = null;
+        final Long fundId = null;
+        final String fundName = null;
+        final Long transactionProcessingStrategyId = null;
+        final String transactionProcessingStrategyName = null;
+
+        final Integer graceOnPrincipalPayment = null;
+        final Integer recurringMoratoriumOnPrincipalPeriods = null;
+        final Integer graceOnInterestPayment = null;
+        final Integer graceOnInterestCharged = null;
+        final Integer graceOnArrearsAgeing = null;
+        final Integer overdueDaysForNPA = null;
+
+        final Collection<ChargeData> charges = null;
+        final Collection<LoanProductBorrowerCycleVariationData> 
principalVariationsForBorrowerCycle = new ArrayList<>(1);
+        final Collection<LoanProductBorrowerCycleVariationData> 
interestRateVariationsForBorrowerCycle = new ArrayList<>(1);
+        final Collection<LoanProductBorrowerCycleVariationData> 
numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(1);
+
+        final EnumOptionData accountingType = 
AccountingEnumerations.accountingRuleType(AccountingRuleType.NONE);
+        final boolean includeInBorrowerCycle = false;
+        final boolean useBorrowerCycle = false;
+        final LocalDate startDate = null;
+        final LocalDate closeDate = null;
+        final String status = null;
+        final String externalId = null;
+        final Boolean multiDisburseLoan = null;
+        final Integer maxTrancheCount = null;
+        final BigDecimal outstandingLoanBalance = null;
+
+        final EnumOptionData daysInMonthType = 
CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL);
+        final EnumOptionData daysInYearType = 
CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL);
+        final boolean isInterestRecalculationEnabled = false;
+        final LoanProductInterestRecalculationData interestRecalculationData = 
LoanProductInterestRecalculationData
+                .sensibleDefaultsForNewLoanProductCreation();
+        final Integer minimumDaysBetweenDisbursalAndFirstRepayment = null;
+        final Boolean holdGuaranteeFunds = false;
+        final LoanProductGuaranteeData productGuaranteeData = null;
+        final BigDecimal principalThresholdForLastInstallment = null;
+        final boolean accountMovesOutOfNPAOnlyOnArrearsCompletion = false;
+        final boolean canDefineInstallmentAmount = false;
+        final Integer installmentAmountInMultiplesOf = null;
+        final LoanProductConfigurableAttributes 
loanProductConfigurableAttributes = null;
+        final boolean syncExpectedWithDisbursementDate = false;
+        final boolean canUseForTopup = false;
+
+        return new LoanProductData(id, name, shortName, description, currency, 
principal, minPrincipal, maxPrincipal, tolerance,
+                numberOfRepayments, minNumberOfRepayments, 
maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
+                minInterestRatePerPeriod, maxInterestRatePerPeriod, 
annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
+                amortizationType, interestType, interestCalculationPeriodType, 
allowPartialPeriodInterestCalcualtion, fundId, fundName,
+                transactionProcessingStrategyId, 
transactionProcessingStrategyName, graceOnPrincipalPayment, 
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment,
+                graceOnInterestCharged, charges, accountingType, 
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status,
+                externalId, principalVariationsForBorrowerCycle, 
interestRateVariationsForBorrowerCycle,
+                numberOfRepaymentVariationsForBorrowerCycle, 
multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
+                graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, 
daysInYearType, isInterestRecalculationEnabled,
+                interestRecalculationData, 
minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, 
productGuaranteeData,
+                principalThresholdForLastInstallment, 
accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
+                installmentAmountInMultiplesOf, 
loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, 
floatingRateId,
+                floatingRateName, interestRateDifferential, 
minDifferentialLendingRate, defaultDifferentialLendingRate,
+                maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, 
minimumGap, maximumGap,
+                syncExpectedWithDisbursementDate, canUseForTopup);
+
+    }
 
     public static LoanProductData withAccountingDetails(final LoanProductData 
productData, final Map<String, Object> accountingMappings,
             final Collection<PaymentTypeToGLAccountMapper> 
paymentChannelToFundSourceMappings,
@@ -1100,4 +1193,8 @@ public class LoanProductData {
         public boolean canUseForTopup() {
             return this.canUseForTopup;
         }
+        
+    public BigDecimal getInterestRateDifferential() {
+        return this.interestRateDifferential;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
index 4808eef..eac39ec 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java
@@ -46,4 +46,6 @@ public interface LoanProductReadPlatformService {
     Collection<LoanProductData> retrieveAllowedProductsForMix(Long productId);
 
     Collection<LoanProductBorrowerCycleVariationData> 
retrieveLoanProductBorrowerCycleVariations(Long loanProductId);
+
+    LoanProductData retrieveLoanProductFloatingDetails(Long loanProductId);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/ca1adedd/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
index 00a3c59..6e416e7 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
@@ -617,5 +617,58 @@ public class LoanProductReadPlatformServiceImpl implements 
LoanProductReadPlatfo
 
         return this.jdbcTemplate.query(sql, rm, new Object[] { productId, 
productId });
     }
+    
+    @Override
+    public LoanProductData retrieveLoanProductFloatingDetails(final Long 
loanProductId) {
+
+        try {
+            final LoanProductFloatingRateMapper rm = new 
LoanProductFloatingRateMapper();
+            final String sql = "select " + rm.schema() + " where lp.id = ?";
+
+            return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { 
loanProductId });
+
+        } catch (final EmptyResultDataAccessException e) {
+            throw new LoanProductNotFoundException(loanProductId);
+        }
+    }
+    
+    
+    private static final class LoanProductFloatingRateMapper implements 
RowMapper<LoanProductData> {
+
+        public LoanProductFloatingRateMapper() {}
+
+        public String schema() {
+            return "lp.id as id,  lp.name as name," 
+                    + "lp.is_linked_to_floating_interest_rates as 
isLinkedToFloatingInterestRates, "
+                    + "lfr.floating_rates_id as floatingRateId, " + "fr.name 
as floatingRateName, "
+                    + "lfr.interest_rate_differential as 
interestRateDifferential, "
+                    + "lfr.min_differential_lending_rate as 
minDifferentialLendingRate, "
+                    + "lfr.default_differential_lending_rate as 
defaultDifferentialLendingRate, "
+                    + "lfr.max_differential_lending_rate as 
maxDifferentialLendingRate, "
+                    + "lfr.is_floating_interest_rate_calculation_allowed as 
isFloatingInterestRateCalculationAllowed "
+                    + " from m_product_loan lp " + " left join 
m_product_loan_floating_rates as lfr on lfr.loan_product_id = lp.id "
+                    + " left join m_floating_rates as fr on 
lfr.floating_rates_id = fr.id ";
+        }
+
+        @Override
+        public LoanProductData mapRow(final ResultSet rs, 
@SuppressWarnings("unused") final int rowNum) throws SQLException {
+
+            final Long id = JdbcSupport.getLong(rs, "id");
+            final String name = rs.getString("name");
+
+            final boolean isLinkedToFloatingInterestRates = 
rs.getBoolean("isLinkedToFloatingInterestRates");
+            final Integer floatingRateId = 
JdbcSupport.getIntegerDefaultToNullIfZero(rs, "floatingRateId");
+            final String floatingRateName = rs.getString("floatingRateName");
+            final BigDecimal interestRateDifferential = 
rs.getBigDecimal("interestRateDifferential");
+            final BigDecimal minDifferentialLendingRate = 
rs.getBigDecimal("minDifferentialLendingRate");
+            final BigDecimal defaultDifferentialLendingRate = 
rs.getBigDecimal("defaultDifferentialLendingRate");
+            final BigDecimal maxDifferentialLendingRate = 
rs.getBigDecimal("maxDifferentialLendingRate");
+            final boolean isFloatingInterestRateCalculationAllowed = 
rs.getBoolean("isFloatingInterestRateCalculationAllowed");
+
+            return LoanProductData.loanProductWithFloatingRates(id, name, 
isLinkedToFloatingInterestRates, floatingRateId,
+                    floatingRateName, interestRateDifferential, 
minDifferentialLendingRate, defaultDifferentialLendingRate,
+                    maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed);
+        }
+    }
 
 }
\ No newline at end of file

Reply via email to