fix for performance issues

This commit is contained in:
pramod
2016-08-26 19:05:30 +05:30
parent ff58f74d79
commit ca1adedd40
14 changed files with 267 additions and 61 deletions
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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);
}
@@ -35,6 +35,6 @@ public interface FloatingRatesReadPlatformService {
FloatingRateData retrieveBaseLendingRate();
List<InterestRatePeriodData> retrieveInterestRatePeriods(Long floatingRateId);
List<InterestRatePeriodData> retrieveInterestRatePeriods(Long productId);
}
@@ -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
@@ -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;
@@ -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;
}
}
@@ -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;
}
}
@@ -125,7 +125,7 @@ public interface LoanReadPlatformService {
LoanTransactionData retrieveRefundByCashTemplate(Long loanId);
Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long loanId);
Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(LoanAccountData loan);
Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions();
@@ -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;
@@ -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;
}
}
@@ -46,4 +46,6 @@ public interface LoanProductReadPlatformService {
Collection<LoanProductData> retrieveAllowedProductsForMix(Long productId);
Collection<LoanProductBorrowerCycleVariationData> retrieveLoanProductBorrowerCycleVariations(Long loanProductId);
LoanProductData retrieveLoanProductFloatingDetails(Long loanProductId);
}
@@ -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);
}
}
}