blob: 451cc70e6b5719b325af958ae8e3f750022144e1 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.apache.fineract.portfolio.common.service.CommonEnumerations;
import org.apache.fineract.portfolio.interestratechart.incentive.InterestIncentiveAttributeName;
import org.apache.fineract.portfolio.interestratechart.service.InterestIncentiveDropdownReadPlatformService;
import org.apache.fineract.portfolio.interestratechart.service.InterestIncentivesEnumerations;
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartDropdownReadPlatformService;
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartEnumerations;
import org.apache.fineract.portfolio.savings.data.DepositAccountInterestIncentiveData;
import org.apache.fineract.portfolio.savings.data.DepositAccountInterestRateChartData;
import org.apache.fineract.portfolio.savings.data.DepositAccountInterestRateChartSlabData;
import org.apache.fineract.portfolio.savings.exception.DepositAccountInterestRateChartNotFoundException;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class DepositAccountInterestRateChartReadPlatformServiceImpl implements DepositAccountInterestRateChartReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final DepositAccountInterestRateChartMapper chartRowMapper = new DepositAccountInterestRateChartMapper();
private final DepositAccountInterestRateChartExtractor chartExtractor = new DepositAccountInterestRateChartExtractor();
private final InterestRateChartDropdownReadPlatformService chartDropdownReadPlatformService;
private final InterestIncentiveDropdownReadPlatformService interestIncentiveDropdownReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
@Autowired
public DepositAccountInterestRateChartReadPlatformServiceImpl(PlatformSecurityContext context, final RoutingDataSource dataSource,
InterestRateChartDropdownReadPlatformService chartDropdownReadPlatformService,
final InterestIncentiveDropdownReadPlatformService interestIncentiveDropdownReadPlatformService,
final CodeValueReadPlatformService codeValueReadPlatformService) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.chartDropdownReadPlatformService = chartDropdownReadPlatformService;
this.interestIncentiveDropdownReadPlatformService = interestIncentiveDropdownReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
}
@Override
public DepositAccountInterestRateChartData retrieveOne(Long chartId) {
try {
this.context.authenticatedUser();
final String sql = "select " + this.chartRowMapper.schema() + " where irc.id = ? ";
return this.jdbcTemplate.queryForObject(sql, this.chartRowMapper, new Object[] { chartId });
} catch (final EmptyResultDataAccessException e) {
throw new DepositAccountInterestRateChartNotFoundException(chartId);
}
}
@Override
public DepositAccountInterestRateChartData retrieveOneWithSlabs(Long chartId) {
this.context.authenticatedUser();
StringBuilder sql = new StringBuilder();
sql.append("select ");
sql.append(this.chartExtractor.schema());
sql.append(" where irc.id = ? order by irc.id asc, ");
sql.append("CASE ");
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
sql.append("END,");
sql.append("ircd.from_period, ircd.to_period,");
sql.append("CASE ");
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
sql.append("END");
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
new Object[] { chartId });
if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(chartId); }
return chartDatas.iterator().next();
}
@Override
public DepositAccountInterestRateChartData retrieveWithTemplate(DepositAccountInterestRateChartData chartData) {
final List<CodeValueData> genderOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.GENDER));
final List<CodeValueData> clientTypeOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_TYPE));
final List<CodeValueData> clientClassificationOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_CLASSIFICATION));
return DepositAccountInterestRateChartData.withTemplate(chartData,
this.chartDropdownReadPlatformService.retrievePeriodTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveEntityTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveAttributeNameOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveConditionTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveIncentiveTypeOptions(), genderOptions, clientTypeOptions,
clientClassificationOptions);
}
@Override
public DepositAccountInterestRateChartData retrieveOneWithSlabsOnAccountId(Long accountId) {
this.context.authenticatedUser();
StringBuilder sql = new StringBuilder();
sql.append("select ");
sql.append(this.chartExtractor.schema());
sql.append(" where irc.savings_account_id = ? order by irc.id asc, ");
sql.append("CASE ");
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_from ");
sql.append("WHEN isPrimaryGroupingByAmount then ircd.amount_range_to ");
sql.append("END,");
sql.append("ircd.from_period, ircd.to_period,");
sql.append("CASE ");
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_from ");
sql.append("WHEN !isPrimaryGroupingByAmount then ircd.amount_range_to ");
sql.append("END");
Collection<DepositAccountInterestRateChartData> chartDatas = this.jdbcTemplate.query(sql.toString(), this.chartExtractor,
new Object[] { accountId });
if (chartDatas == null || chartDatas.isEmpty()) { throw new DepositAccountInterestRateChartNotFoundException(accountId); }
return chartDatas.iterator().next();
}
@Override
public DepositAccountInterestRateChartData template() {
final List<CodeValueData> genderOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.GENDER));
final List<CodeValueData> clientTypeOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_TYPE));
final List<CodeValueData> clientClassificationOptions = new ArrayList<>(
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_CLASSIFICATION));
return DepositAccountInterestRateChartData.template(this.chartDropdownReadPlatformService.retrievePeriodTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveEntityTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveAttributeNameOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveConditionTypeOptions(),
this.interestIncentiveDropdownReadPlatformService.retrieveIncentiveTypeOptions(), genderOptions, clientTypeOptions,
clientClassificationOptions);
}
private static final class DepositAccountInterestRateChartExtractor implements
ResultSetExtractor<Collection<DepositAccountInterestRateChartData>> {
DepositAccountInterestRateChartMapper chartMapper = new DepositAccountInterestRateChartMapper();
InterestRateChartSlabExtractor chartSlabsMapper = new InterestRateChartSlabExtractor();
private final String schemaSql;
public String schema() {
return this.schemaSql;
}
private DepositAccountInterestRateChartExtractor() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder
.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription,")
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
.append("ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, ")
.append("ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, ")
.append("ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, ")
.append("curr.code as currencyCode, curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ")
.append("curr.display_symbol as currencyDisplaySymbol, curr.decimal_places as currencyDigits, curr.currency_multiplesof as inMultiplesOf, ")
.append("sa.id as accountId, sa.account_no as accountNumber, ")
.append("iri.id as iriId, ")
.append(" iri.entiry_type as entityType, iri.attribute_name as attributeName ,")
.append(" iri.condition_type as conditionType, iri.attribute_value as attributeValue, ")
.append(" iri.incentive_type as incentiveType, iri.amount as amount, ")
.append("code.code_value as attributeValueDesc ")
.append("from ")
.append("m_savings_account_interest_rate_chart irc left join m_savings_account_interest_rate_slab ircd on irc.id=ircd.savings_account_interest_rate_chart_id ")
.append(" left join m_savings_interest_incentives iri on iri.deposit_account_interest_rate_slab_id =ircd.id ")
.append(" left join m_code_value code on code.id = iri.attribute_value ")
.append("left join m_currency curr on ircd.currency_code= curr.code ")
.append("left join m_savings_account sa on irc.savings_account_id=sa.id ");
this.schemaSql = sqlBuilder.toString();
}
@Override
public Collection<DepositAccountInterestRateChartData> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<DepositAccountInterestRateChartData> chartDataList = new ArrayList<>();
DepositAccountInterestRateChartData chartData = null;
Long interestRateChartId = null;
int ircIndex = 0;// Interest rate chart index
while (rs.next()) {
Long tempIrcId = rs.getLong("ircId");
// first row or when interest rate chart id changes
if (chartData == null || (interestRateChartId != null && !interestRateChartId.equals(tempIrcId))) {
interestRateChartId = tempIrcId;
chartData = chartMapper.mapRow(rs, ircIndex++);
chartDataList.add(chartData);
}
final DepositAccountInterestRateChartSlabData chartSlabsData = chartSlabsMapper.extractData(rs);
if (chartSlabsData != null) {
chartData.addChartSlab(chartSlabsData);
}
}
return chartDataList;
}
}
public static final class DepositAccountInterestRateChartMapper implements RowMapper<DepositAccountInterestRateChartData> {
private final String schemaSql;
public String schema() {
return this.schemaSql;
}
private DepositAccountInterestRateChartMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("irc.id as ircId, irc.name as ircName, irc.description as ircDescription, ")
.append("irc.from_date as ircFromDate, irc.end_date as ircEndDate, ")
.append("irc.is_primary_grouping_by_amount as isPrimaryGroupingByAmount,")
.append("sa.id as accountId, sa.account_no as accountNumber ").append("from ")
.append("m_savings_account_interest_rate_chart irc left join m_savings_account sa on irc.savings_account_id=sa.id ");
this.schemaSql = sqlBuilder.toString();
}
@Override
public DepositAccountInterestRateChartData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
final Long id = rs.getLong("ircId");
final String name = rs.getString("ircName");
final String description = rs.getString("ircDescription");
final LocalDate fromDate = JdbcSupport.getLocalDate(rs, "ircFromDate");
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "ircEndDate");
final boolean isPrimaryGroupingByAmount = rs.getBoolean("isPrimaryGroupingByAmount");
final Long accountId = rs.getLong("accountId");
final String accountNumber = rs.getString("accountNumber");
final Collection<EnumOptionData> periodTypes = InterestRateChartEnumerations.periodType(PeriodFrequencyType.values());
return DepositAccountInterestRateChartData.instance(id, name, description, fromDate, endDate, isPrimaryGroupingByAmount,
accountId, accountNumber, null, periodTypes);
}
}
private static final class InterestRateChartSlabExtractor implements ResultSetExtractor<DepositAccountInterestRateChartSlabData> {
DepositAccountInterestRateChartSlabsMapper chartSlabsMapper = new DepositAccountInterestRateChartSlabsMapper();
InterestIncentiveMapper incentiveMapper = new InterestIncentiveMapper();
@Override
public DepositAccountInterestRateChartSlabData extractData(ResultSet rs) throws SQLException, DataAccessException {
DepositAccountInterestRateChartSlabData chartSlabData = null;
Long interestRateChartSlabId = null;
int ircIndex = 0;// Interest rate chart index
int ircdIndex = 0;// Interest rate chart Slabs index
rs.previous();
while (rs.next()) {
Long tempIrcdId = rs.getLong("ircdId");
if (interestRateChartSlabId == null || interestRateChartSlabId.equals(tempIrcdId)) {
if (chartSlabData == null) {
interestRateChartSlabId = tempIrcdId;
chartSlabData = chartSlabsMapper.mapRow(rs, ircIndex++);
}
final DepositAccountInterestIncentiveData incentiveData = incentiveMapper.mapRow(rs, ircdIndex++);
if (incentiveData != null) {
chartSlabData.addIncentives(incentiveData);
}
} else {
rs.previous();
break;
}
}
return chartSlabData;
}
}
private static final class DepositAccountInterestRateChartSlabsMapper implements RowMapper<DepositAccountInterestRateChartSlabData> {
/*
* private final String schemaSql;
*
* public String schema() { return this.schemaSql; }
*
* private DepositAccountInterestRateChartSlabsMapper() { final
* StringBuilder sqlBuilder = new StringBuilder(400);
*
* sqlBuilder .append(
* "ircd.id as ircdId, ircd.description as ircdDescription, ircd.period_type_enum ircdPeriodTypeId, "
* ) .append(
* "ircd.from_period as ircdFromPeriod, ircd.to_period as ircdToPeriod, ircd.amount_range_from as ircdAmountRangeFrom, "
* ) .append(
* "ircd.amount_range_to as ircdAmountRangeTo, ircd.annual_interest_rate as ircdAnnualInterestRate, "
* ) .append(
* "curr.code as currencyCode, curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, "
* ) .append(
* "curr.display_symbol as currencyDisplaySymbol, curr.decimal_places as currencyDigits, curr.currency_multiplesof as inMultiplesOf "
* ) .append("from ").append(
* "m_savings_account_interest_rate_slab ircd ")
* .append("left join m_currency curr on ircd.currency_code= curr.code "
* ); this.schemaSql = sqlBuilder.toString(); }
*/
@Override
public DepositAccountInterestRateChartSlabData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
final Long id = JdbcSupport.getLongDefaultToNullIfZero(rs, "ircdId");
// If there are not chart Slabs are associated then in
// InterestRateChartExtractor the chart Slabs id will be null.
if (id == null) { return null; }
final String description = rs.getString("ircdDescription");
final Integer fromPeriod = JdbcSupport.getInteger(rs, "ircdFromPeriod");
final Integer toPeriod = JdbcSupport.getInteger(rs, "ircdToPeriod");
final Integer periodTypeId = JdbcSupport.getInteger(rs, "ircdPeriodTypeId");
final EnumOptionData periodType = InterestRateChartEnumerations.periodType(periodTypeId);
final BigDecimal amountRangeFrom = rs.getBigDecimal("ircdAmountRangeFrom");
final BigDecimal amountRangeTo = rs.getBigDecimal("ircdAmountRangeTo");
final BigDecimal annualInterestRate = rs.getBigDecimal("ircdAnnualInterestRate");
// currency Slabs
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
final String currencyNameCode = rs.getString("currencyNameCode");
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
// currency
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
currencyDisplaySymbol, currencyNameCode);
return DepositAccountInterestRateChartSlabData.instance(id, description, periodType, fromPeriod, toPeriod, amountRangeFrom,
amountRangeTo, annualInterestRate, currency);
}
}
private static final class InterestIncentiveMapper implements RowMapper<DepositAccountInterestIncentiveData> {
@Override
public DepositAccountInterestIncentiveData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
final Long id = JdbcSupport.getLongDefaultToNullIfZero(rs, "iriId");
// If there are not Incentive are associated then in
// InterestRateChartExtractor the incentive id will be null.
if (id == null) { return null; }
final String attributeValue = rs.getString("attributeValue");
String attributeValueDesc = null;
final Integer entityType = JdbcSupport.getInteger(rs, "entityType");
final EnumOptionData entityTypeData = InterestIncentivesEnumerations.entityType(entityType);
final Integer attributeName = JdbcSupport.getInteger(rs, "attributeName");
if (InterestIncentiveAttributeName.isCodeValueAttribute(InterestIncentiveAttributeName.fromInt(attributeName))) {
attributeValueDesc = rs.getString("attributeValueDesc");
}
final EnumOptionData attributeNameData = InterestIncentivesEnumerations.attributeName(attributeName);
final Integer conditionType = JdbcSupport.getInteger(rs, "conditionType");
final EnumOptionData conditionTypeData = CommonEnumerations.conditionType(conditionType, "incentive");
final Integer incentiveType = JdbcSupport.getInteger(rs, "incentiveType");
final EnumOptionData incentiveTypeData = InterestIncentivesEnumerations.incentiveType(incentiveType);
final BigDecimal amount = rs.getBigDecimal("amount");
return DepositAccountInterestIncentiveData.instance(id, entityTypeData, attributeNameData, conditionTypeData, attributeValue,
attributeValueDesc, incentiveTypeData, amount);
}
}
}