fix for performance issues
This commit is contained in:
+3
@@ -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);
|
||||
|
||||
}
|
||||
+49
-33
@@ -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);
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ public interface FloatingRatesReadPlatformService {
|
||||
|
||||
FloatingRateData retrieveBaseLendingRate();
|
||||
|
||||
List<InterestRatePeriodData> retrieveInterestRatePeriods(Long floatingRateId);
|
||||
List<InterestRatePeriodData> retrieveInterestRatePeriods(Long productId);
|
||||
|
||||
}
|
||||
|
||||
+7
-5
@@ -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
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+18
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -125,7 +125,7 @@ public interface LoanReadPlatformService {
|
||||
|
||||
LoanTransactionData retrieveRefundByCashTemplate(Long loanId);
|
||||
|
||||
Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long loanId);
|
||||
Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(LoanAccountData loan);
|
||||
|
||||
Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions();
|
||||
|
||||
|
||||
+11
-14
@@ -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;
|
||||
|
||||
+97
@@ -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;
|
||||
}
|
||||
}
|
||||
+2
@@ -46,4 +46,6 @@ public interface LoanProductReadPlatformService {
|
||||
Collection<LoanProductData> retrieveAllowedProductsForMix(Long productId);
|
||||
|
||||
Collection<LoanProductBorrowerCycleVariationData> retrieveLoanProductBorrowerCycleVariations(Long loanProductId);
|
||||
|
||||
LoanProductData retrieveLoanProductFloatingDetails(Long loanProductId);
|
||||
}
|
||||
+53
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user