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
