Java tutorial
/* * eGov SmartCity eGovernance suite aims to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) 2017 eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * Further, all user interfaces, including but not limited to citizen facing interfaces, * Urban Local Bodies interfaces, dashboards, mobile applications, of the program and any * derived works should carry eGovernments Foundation logo on the top right corner. * * For the logo, please refer http://egovernments.org/html/logo/egov_logo.png. * For any further queries on attribution, including queries on brand guidelines, * please contact contact@egovernments.org * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. * */ package org.egov.wtms.service.es; import org.apache.commons.lang3.StringUtils; import org.egov.commons.CFinancialYear; import org.egov.commons.service.CFinancialYearService; import org.egov.infra.config.core.ApplicationThreadLocals; import org.egov.infra.utils.DateUtils; import org.egov.ptis.constants.PropertyTaxConstants; import org.egov.ptis.domain.entity.es.BillCollectorIndex; import org.egov.ptis.domain.model.ErrorDetails; import org.egov.wtms.bean.dashboard.TaxPayerResponseDetails; import org.egov.wtms.bean.dashboard.WaterChargeDashBoardRequest; import org.egov.wtms.bean.dashboard.WaterChargeDashBoardResponse; import org.egov.wtms.bean.dashboard.WaterTaxDefaulters; import org.egov.wtms.bean.dashboard.WaterTaxPayerDetails; import org.egov.wtms.entity.es.WaterChargeDocument; import org.egov.wtms.repository.es.WaterChargeDocumentRepository; import org.egov.wtms.utils.constants.WaterTaxConstants; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.bucket.terms.StringTerms; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.sum.Sum; import org.elasticsearch.search.sort.FieldSortBuilder; import org.elasticsearch.search.sort.SortOrder; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import static org.egov.ptis.constants.PropertyTaxConstants.DASHBOARD_GROUPING_BILLCOLLECTORWISE; import static org.egov.ptis.constants.PropertyTaxConstants.DASHBOARD_GROUPING_WARDWISE; import static org.egov.wtms.utils.constants.WaterTaxConstants.WATER_TAX_INDEX_NAME; @Service public class WaterChargeElasticSearchService { private static final Logger LOGGER = LoggerFactory.getLogger(WaterChargeElasticSearchService.class); private final WaterChargeDocumentRepository waterChargeIndexRepository; private static final String TOTAL_COLLECTION = "total_collection"; private static final String AGGREGATION_FIELD = "by_aggregationField"; private static final String TOTAL_DEMAND = "totalDemand"; private static final String TOTALDEMAND = "totaldemand"; @Autowired private ElasticsearchTemplate elasticsearchTemplate; @Autowired private CFinancialYearService cFinancialYearService; @Autowired private WaterChargeCollectionDocService waterChargeCollDocService; @Autowired public WaterChargeElasticSearchService(final WaterChargeDocumentRepository waterChargeIndexRepository) { this.waterChargeIndexRepository = waterChargeIndexRepository; } public Page<WaterChargeDocument> findByConsumercode(final String consumerCode) { return waterChargeIndexRepository.findByConsumerCodeAndCityName(consumerCode, ApplicationThreadLocals.getCityName(), new PageRequest(0, 10)); } /** * API returns the current year total demand from WaterCharge index * * @return BigDecimal */ public BigDecimal getTotalDemand() { final SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(WATER_TAX_INDEX_NAME) .addAggregation(AggregationBuilders.sum(WaterTaxConstants.WATERCHARGETOTALDEMAND) .field(WaterTaxConstants.WATERCHARGETOTALDEMAND)) .build(); final Aggregations aggregations = elasticsearchTemplate.query(searchQuery, response -> response.getAggregations()); final Sum aggr = aggregations.get(WaterTaxConstants.WATERCHARGETOTALDEMAND); return BigDecimal.valueOf(aggr.getValue()).setScale(0, BigDecimal.ROUND_HALF_UP); } /** * Populates the consolidated demand information in CollectionIndexDetails * * @param waterChargedashBoardRequest * @param collectionIndexDetails */ public List<WaterChargeDashBoardResponse> getConsolidatedDemandInfo( final WaterChargeDashBoardRequest waterChargedashBoardRequest) { final List<WaterChargeDashBoardResponse> collectionIndexDetailsList = new ArrayList<>(); final WaterChargeDashBoardResponse collectionIndexDetails = new WaterChargeDashBoardResponse(); Date fromDate; Date toDate; /** * For fetching total demand between the date ranges if dates are sent * in the request, consider fromDate and toDate+1 , else calculate from * current year start date till current date+1 day */ if (StringUtils.isNotBlank(waterChargedashBoardRequest.getFromDate()) && StringUtils.isNotBlank(waterChargedashBoardRequest.getToDate())) { fromDate = DateUtils.getDate(waterChargedashBoardRequest.getFromDate(), "yyyy-MM-dd"); toDate = org.apache.commons.lang3.time.DateUtils .addDays(DateUtils.getDate(waterChargedashBoardRequest.getToDate(), "yyyy-MM-dd"), 1); } else { fromDate = new DateTime().withMonthOfYear(4).dayOfMonth().withMinimumValue().toDate(); toDate = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), 1); } Long startTime = System.currentTimeMillis(); final BigDecimal totalDemand = getTotalDemandBasedOnInputFilters(waterChargedashBoardRequest); Long timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug("Time taken by getTotalDemandBasedOnInputFilters() is (millisecs) : " + timeTaken); startTime = System.currentTimeMillis(); final int noOfMonths = DateUtils.noOfMonthsBetween(fromDate, toDate) + 1; collectionIndexDetails.setTotalDmd(totalDemand); // Proportional Demand = (totalDemand/12)*noOfmonths final BigDecimal proportionalDemand = totalDemand.divide(BigDecimal.valueOf(12), BigDecimal.ROUND_HALF_UP) .multiply(BigDecimal.valueOf(noOfMonths)); collectionIndexDetails.setCurrentYearTillDateDmd(proportionalDemand.setScale(0, BigDecimal.ROUND_HALF_UP)); // performance = (current year tilldate collection * 100)/(proportional // demand) collectionIndexDetails.setPerformance( collectionIndexDetails.getCurrentYearTillDateColl().multiply(WaterTaxConstants.BIGDECIMAL_100) .divide(proportionalDemand, 1, BigDecimal.ROUND_HALF_UP)); // variance = ((currentYearCollection - // lastYearCollection)*100)/lastYearCollection BigDecimal variation; if (collectionIndexDetails.getLastYearTillDateColl().compareTo(BigDecimal.ZERO) == 0) variation = WaterTaxConstants.BIGDECIMAL_100; else variation = collectionIndexDetails.getCurrentYearTillDateColl() .subtract(collectionIndexDetails.getLastYearTillDateColl()) .multiply(WaterTaxConstants.BIGDECIMAL_100) .divide(collectionIndexDetails.getLastYearTillDateColl(), 1, BigDecimal.ROUND_HALF_UP); collectionIndexDetails.setLastYearVar(variation); timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug( "Time taken for setting values in getConsolidatedDemandInfo() is (millisecs) : " + timeTaken); final ErrorDetails errorDetails = new ErrorDetails(); errorDetails.setErrorCode(WaterTaxConstants.THIRD_PARTY_ERR_CODE_SUCCESS); errorDetails.setErrorMessage(WaterTaxConstants.THIRD_PARTY_ERR_MSG_SUCCESS); collectionIndexDetails.setErrorDetails(errorDetails); collectionIndexDetailsList.add(collectionIndexDetails); return collectionIndexDetailsList; } /** * Returns total demand from WaterCharge index, based on input filters * * @param waterChargedashBoardRequest * @return */ public BigDecimal getTotalDemandBasedOnInputFilters( final WaterChargeDashBoardRequest waterChargedashBoardRequest) { final BoolQueryBuilder boolQuery = waterChargeCollDocService.prepareWhereClause(waterChargedashBoardRequest, null); final SearchQuery searchQueryColl = new NativeSearchQueryBuilder().withIndices(WATER_TAX_INDEX_NAME) .withQuery(boolQuery) .addAggregation(AggregationBuilders.sum(WaterTaxConstants.WATERCHARGETOTALDEMAND) .field(WaterTaxConstants.WATERCHARGETOTALDEMAND)) .build(); final Aggregations collAggr = elasticsearchTemplate.query(searchQueryColl, response -> response.getAggregations()); final Sum aggr = collAggr.get(WaterTaxConstants.WATERCHARGETOTALDEMAND); return BigDecimal.valueOf(aggr.getValue()).setScale(0, BigDecimal.ROUND_HALF_UP); } /** * Returns List of Top Ten Tax Performers * * @param waterChargedashBoardRequest * @return */ public TaxPayerResponseDetails getTopTenTaxPerformers( final WaterChargeDashBoardRequest waterChargedashBoardRequest) { List<WaterTaxPayerDetails> taxProducers; List<WaterTaxPayerDetails> taxAchievers; final TaxPayerResponseDetails topTaxPerformers = new TaxPayerResponseDetails(); if (StringUtils.isNotBlank(waterChargedashBoardRequest.getType()) && waterChargedashBoardRequest.getType() .equalsIgnoreCase(PropertyTaxConstants.DASHBOARD_GROUPING_BILLCOLLECTORWISE)) { final List<WaterTaxPayerDetails> wardWiseTaxProducers = returnUlbWiseAggregationResults( waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, false, TOTAL_COLLECTION, 250, true); final Map<String, WaterTaxPayerDetails> wardWiseTaxPayersDetails = new HashMap<>(); final Map<String, List<WaterTaxPayerDetails>> billCollectorWiseMap = new LinkedHashMap<>(); final List<WaterTaxPayerDetails> taxPayerDetailsList = new ArrayList<>(); final List<WaterTaxPayerDetails> billCollectorWiseTaxPayerDetails = new ArrayList<>(); // Get ward wise tax payers details prepareWardWiseTaxPayerDetails(wardWiseTaxProducers, wardWiseTaxPayersDetails); // Group the revenue ward details by bill collector prepareBillCollectorWiseMapData(waterChargedashBoardRequest, wardWiseTaxPayersDetails, billCollectorWiseMap, taxPayerDetailsList); // Prepare Bill Collector wise tax payers details prepareTaxersInfoForBillCollectors(waterChargedashBoardRequest, billCollectorWiseMap, billCollectorWiseTaxPayerDetails); taxProducers = getTaxPayersForBillCollector(true, wardWiseTaxProducers, billCollectorWiseTaxPayerDetails, true); taxAchievers = getTaxPayersForBillCollector(true, wardWiseTaxProducers, billCollectorWiseTaxPayerDetails, false); } else { taxProducers = returnUlbWiseAggregationResults(waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, false, TOTAL_COLLECTION, 10, false); taxAchievers = returnUlbWiseAggregationResults(waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, false, TOTAL_COLLECTION, 120, false); } topTaxPerformers.setProducers(taxProducers); topTaxPerformers.setAchievers(taxAchievers); return topTaxPerformers; } /* * Prepare ward wise tax payers details - Map of ward name and tax paers * bean * @param wardWiseTaxProducers * @param wardWiseTaxPayersDetails */ private void prepareWardWiseTaxPayerDetails(final List<WaterTaxPayerDetails> wardWiseTaxProducers, final Map<String, WaterTaxPayerDetails> wardWiseTaxPayersDetails) { for (final WaterTaxPayerDetails taxPayers : wardWiseTaxProducers) wardWiseTaxPayersDetails.put(taxPayers.getWardName(), taxPayers); } /** * Returns List of Bottom Ten Tax Performers * * @param waterChargedashBoardRequest * @return */ public TaxPayerResponseDetails getBottomTenTaxPerformers( final WaterChargeDashBoardRequest waterChargedashBoardRequest) { final TaxPayerResponseDetails topTaxPerformers = new TaxPayerResponseDetails(); List<WaterTaxPayerDetails> taxProducers; List<WaterTaxPayerDetails> taxAchievers; if (StringUtils.isNotBlank(waterChargedashBoardRequest.getType()) && waterChargedashBoardRequest.getType() .equalsIgnoreCase(PropertyTaxConstants.DASHBOARD_GROUPING_BILLCOLLECTORWISE)) { final List<WaterTaxPayerDetails> wardWiseTaxProducers = returnUlbWiseAggregationResults( waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, false, TOTAL_COLLECTION, 250, true); final Map<String, WaterTaxPayerDetails> wardWiseTaxPayersDetails = new HashMap<>(); final Map<String, List<WaterTaxPayerDetails>> billCollectorWiseMap = new LinkedHashMap<>(); final List<WaterTaxPayerDetails> taxPayerDetailsList = new ArrayList<>(); final List<WaterTaxPayerDetails> billCollectorWiseTaxPayerDetails = new ArrayList<>(); // Get ward wise tax payers details prepareWardWiseTaxPayerDetails(wardWiseTaxProducers, wardWiseTaxPayersDetails); // Group the revenue ward details by bill collector prepareBillCollectorWiseMapData(waterChargedashBoardRequest, wardWiseTaxPayersDetails, billCollectorWiseMap, taxPayerDetailsList); // Prepare Bill Collector wise tax payers details prepareTaxersInfoForBillCollectors(waterChargedashBoardRequest, billCollectorWiseMap, billCollectorWiseTaxPayerDetails); taxProducers = getTaxPayersForBillCollector(true, wardWiseTaxProducers, billCollectorWiseTaxPayerDetails, true); taxAchievers = getTaxPayersForBillCollector(true, wardWiseTaxProducers, billCollectorWiseTaxPayerDetails, false); } else { taxProducers = returnUlbWiseAggregationResults(waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, true, TOTAL_COLLECTION, 10, false); taxAchievers = returnUlbWiseAggregationResults(waterChargedashBoardRequest, WATER_TAX_INDEX_NAME, true, TOTAL_COLLECTION, 120, false); } topTaxPerformers.setProducers(taxProducers); topTaxPerformers.setAchievers(taxAchievers); return topTaxPerformers; } /** * Returns Top Ten with ULB wise grouping and total amount aggregation * * @param waterChargedashBoardRequest * @param indexName * @param order * @param orderingAggregationName * @return */ public List<WaterTaxPayerDetails> returnUlbWiseAggregationResults( final WaterChargeDashBoardRequest waterChargedashBoardRequest, final String indexName, final Boolean order, final String orderingAggregationName, final int size, final boolean isBillCollectorWise) { final List<WaterTaxPayerDetails> taxPayers = new ArrayList<>(); Map<String, BillCollectorIndex> wardWiseBillCollectors = new HashMap<>(); final BoolQueryBuilder boolQuery = waterChargeCollDocService.prepareWhereClause(waterChargedashBoardRequest, null); CFinancialYear currFinYear = cFinancialYearService.getCurrentFinancialYear(); // orderingAggregationName is the aggregation name by which we have to // order the results // IN this case can be one of "totaldemand" or TOTAL_COLLECTION or // "avg_achievement" String groupingField; if (StringUtils.isNotBlank(waterChargedashBoardRequest.getUlbCode()) || StringUtils .isNotBlank(waterChargedashBoardRequest.getType()) && (waterChargedashBoardRequest.getType().equals(DASHBOARD_GROUPING_WARDWISE) || waterChargedashBoardRequest.getType().equals(DASHBOARD_GROUPING_BILLCOLLECTORWISE))) groupingField = WaterTaxConstants.REVENUEWARDAGGREGATIONFIELD; else groupingField = WaterTaxConstants.CITYNAMEAGGREGATIONFIELD; Long startTime = System.currentTimeMillis(); @SuppressWarnings("rawtypes") AggregationBuilder aggregation; SearchQuery searchQueryColl; // Apply the ordering and max results size only if the type is not // billcollector if (!isBillCollectorWise) { aggregation = AggregationBuilders.terms(AGGREGATION_FIELD).field(groupingField).size(size) .order(Terms.Order.aggregation(orderingAggregationName, order)) .subAggregation(AggregationBuilders.sum(TOTALDEMAND).field(TOTAL_DEMAND)) .subAggregation(AggregationBuilders.sum(TOTAL_COLLECTION).field("totalCollection")); searchQueryColl = new NativeSearchQueryBuilder().withIndices(indexName).withQuery(boolQuery) .addAggregation(aggregation).build(); } else { aggregation = AggregationBuilders.terms(AGGREGATION_FIELD).field(groupingField).size(250) .subAggregation(AggregationBuilders.sum(TOTALDEMAND).field(TOTAL_DEMAND)) .subAggregation(AggregationBuilders.sum(TOTAL_COLLECTION).field("totalCollection")); searchQueryColl = new NativeSearchQueryBuilder().withIndices(indexName).withQuery(boolQuery) .withPageable(new PageRequest(0, 250)).addAggregation(aggregation).build(); } final Aggregations collAggr = elasticsearchTemplate.query(searchQueryColl, response -> response.getAggregations()); // Fetch ward wise Bill Collector details for ward based grouping if (DASHBOARD_GROUPING_WARDWISE.equalsIgnoreCase(waterChargedashBoardRequest.getType())) wardWiseBillCollectors = waterChargeCollDocService .getWardWiseBillCollectors(waterChargedashBoardRequest); Long timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug("Time taken by ulbWiseAggregations is (millisecs) : " + timeTaken); WaterTaxPayerDetails taxDetail; startTime = System.currentTimeMillis(); final Date fromDate = DateUtils.startOfDay(currFinYear.getStartingDate()); final Date toDate = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), 1); final Date lastYearFromDate = org.apache.commons.lang3.time.DateUtils.addYears(fromDate, -1); final Date lastYearToDate = org.apache.commons.lang3.time.DateUtils.addYears(toDate, -1); final StringTerms totalAmountAggr = collAggr.get(AGGREGATION_FIELD); for (final Terms.Bucket entry : totalAmountAggr.getBuckets()) { taxDetail = new WaterTaxPayerDetails(); taxDetail.setRegionName(waterChargedashBoardRequest.getRegionName()); taxDetail.setDistrictName(waterChargedashBoardRequest.getDistrictName()); taxDetail.setUlbGrade(waterChargedashBoardRequest.getUlbGrade()); final String fieldName = String.valueOf(entry.getKey()); if (groupingField.equals(WaterTaxConstants.REVENUEWARDAGGREGATIONFIELD)) { taxDetail.setWardName(fieldName); if (DASHBOARD_GROUPING_WARDWISE.equalsIgnoreCase(waterChargedashBoardRequest.getType()) && !wardWiseBillCollectors.isEmpty()) taxDetail.setBillCollector(wardWiseBillCollectors.get(fieldName) == null ? StringUtils.EMPTY : wardWiseBillCollectors.get(fieldName).getBillCollector()); } else taxDetail.setUlbName(fieldName); // Proportional Demand = (totalDemand/12)*noOfmonths final int noOfMonths = DateUtils.noOfMonthsBetween(fromDate, toDate) + 1; final Sum totalDemandAggregation = entry.getAggregations().get(TOTALDEMAND); final Sum totalCollectionAggregation = entry.getAggregations().get(TOTAL_COLLECTION); final BigDecimal totalDemandValue = BigDecimal.valueOf(totalDemandAggregation.getValue()).setScale(0, BigDecimal.ROUND_HALF_UP); final BigDecimal totalCollections = BigDecimal.valueOf(totalCollectionAggregation.getValue()) .setScale(0, BigDecimal.ROUND_HALF_UP); final BigDecimal proportionalDemand = totalDemandValue .divide(BigDecimal.valueOf(12), BigDecimal.ROUND_HALF_UP) .multiply(BigDecimal.valueOf(noOfMonths)); taxDetail.setTotalDmd(totalDemandValue); taxDetail.setCurrentYearTillDateColl(totalCollections); taxDetail.setCurrentYearTillDateDmd(proportionalDemand); taxDetail.setAchievement(totalCollections.multiply(WaterTaxConstants.BIGDECIMAL_100) .divide(proportionalDemand, 1, BigDecimal.ROUND_HALF_UP)); taxDetail.setCurrentYearTillDateBalDmd(proportionalDemand.subtract(totalCollections)); final BigDecimal lastYearCollection = waterChargeCollDocService.getCollectionBetweenDates( waterChargedashBoardRequest, lastYearFromDate, lastYearToDate, fieldName); // variance = ((lastYearCollection/currentYearCollection )*100) BigDecimal variation = BigDecimal.ZERO; taxDetail.setLastYearTillDateColl(lastYearCollection); if (lastYearCollection.compareTo(BigDecimal.ZERO) == 0) variation = WaterTaxConstants.BIGDECIMAL_100; else if (totalCollections.compareTo(BigDecimal.ZERO) > 0) variation = taxDetail.getCurrentYearTillDateColl().subtract(taxDetail.getLastYearTillDateColl()) .multiply(WaterTaxConstants.BIGDECIMAL_100) .divide(taxDetail.getLastYearTillDateColl(), 1, BigDecimal.ROUND_HALF_UP); /* * variation * =taxDetail.getLastYearTillDateColl().multiply(WaterTaxConstants. * BIGDECIMAL_100) .divide(totalCollections, 1, * BigDecimal.ROUND_HALF_UP); */ taxDetail.setLastYearVar(variation); taxPayers.add(taxDetail); } timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug("Time taken for setting values in returnUlbWiseAggregationResults() is (millisecs) : " + timeTaken); return returnTopResults(taxPayers, size, order); } private List<WaterTaxPayerDetails> returnTopResults(final List<WaterTaxPayerDetails> taxPayers, final int size, final Boolean order) { if (size > 10) { if (order) Collections.sort(taxPayers); else Collections.sort(taxPayers, Collections.reverseOrder()); return taxPayers.subList(0, taxPayers.size() < 10 ? taxPayers.size() : 10); } return taxPayers; } /** * Prepare a Map of Bill Collector names and the tax payers list for their * respective wards * * @param collectionDetailsRequest * @param wardWiseTaxPayersDetails * @param billCollectorWiseMap * @param taxPayerDetailsList */ private void prepareBillCollectorWiseMapData(final WaterChargeDashBoardRequest collectionDetailsRequest, final Map<String, WaterTaxPayerDetails> wardWiseTaxPayersDetails, final Map<String, List<WaterTaxPayerDetails>> billCollectorWiseMap, List<WaterTaxPayerDetails> taxPayerDetailsList) { String billCollectorNameNumber; final List<BillCollectorIndex> billCollectorsList = waterChargeCollDocService .getBillCollectorDetails(collectionDetailsRequest); for (final BillCollectorIndex billCollIndex : billCollectorsList) if (wardWiseTaxPayersDetails.get(billCollIndex.getRevenueWard()) != null && StringUtils.isNotBlank(billCollIndex.getRevenueWard())) { billCollectorNameNumber = billCollIndex.getBillCollector()/* * .concat("~") * .concat(StringUtils.isBlank( * billCollIndex.getMobileNumber()) ? * StringUtils.EMPTY : * billCollIndex.getMobileNumber()) */; if (billCollectorWiseMap.isEmpty()) { taxPayerDetailsList.add(wardWiseTaxPayersDetails.get(billCollIndex.getRevenueWard())); billCollectorWiseMap.put(billCollectorNameNumber, taxPayerDetailsList); } else if (!billCollectorWiseMap.containsKey(billCollectorNameNumber)) { taxPayerDetailsList = new ArrayList<>(); taxPayerDetailsList.add(wardWiseTaxPayersDetails.get(billCollIndex.getRevenueWard())); billCollectorWiseMap.put(billCollectorNameNumber, taxPayerDetailsList); } else billCollectorWiseMap.get(billCollectorNameNumber) .add(wardWiseTaxPayersDetails.get(billCollIndex.getRevenueWard())); } } /** * Prepares the Producers and Acheivers list - Bill Collector wise * * @param collectionDetailsRequest * @param order * @param wardWiseTaxProducers * @param billCollectorWiseTaxPayerDetails * @param isForProducers * @return */ private List<WaterTaxPayerDetails> getTaxPayersForBillCollector(final boolean order, final List<WaterTaxPayerDetails> wardWiseTaxProducers, final List<WaterTaxPayerDetails> billCollectorWiseTaxPayerDetails, final boolean isForProducers) { final Map<BigDecimal, WaterTaxPayerDetails> sortedTaxersMap = new HashMap<>(); // For propducers, prepare sorted list of totalCollection // For achievers, prepare sorted list of achievement if (isForProducers) for (final WaterTaxPayerDetails payerDetails : billCollectorWiseTaxPayerDetails) sortedTaxersMap.put(payerDetails.getCurrentYearTillDateColl(), payerDetails); else for (final WaterTaxPayerDetails payerDetails : billCollectorWiseTaxPayerDetails) sortedTaxersMap.put(payerDetails.getAchievement(), payerDetails); final List<BigDecimal> sortedList = new ArrayList<>(sortedTaxersMap.keySet()); // Decides whether API should return in ascending or descending order if (order) Collections.sort(sortedList); else Collections.sort(sortedList, Collections.reverseOrder()); final List<WaterTaxPayerDetails> taxersResult = new ArrayList<>(); for (final BigDecimal amount : sortedList) taxersResult.add(sortedTaxersMap.get(amount)); if (taxersResult.size() > 10) return taxersResult.subList(0, taxersResult.size() < 10 ? taxersResult.size() : 10); else return taxersResult; } /** * Prepare list of WaterTaxPayerDetails for each bill collector by summing * up the values in each ward for the respective bil collector * * @param waterChargedashBoardRequest * @param billCollectorWiseMap * @param billCollectorWiseWaterTaxPayerDetails */ private void prepareTaxersInfoForBillCollectors(final WaterChargeDashBoardRequest waterChargedashBoardRequest, final Map<String, List<WaterTaxPayerDetails>> billCollectorWiseMap, final List<WaterTaxPayerDetails> billCollectorWiseWaterTaxPayerDetails) { BigDecimal cytdColl; BigDecimal lytdColl; BigDecimal cytdDmd; BigDecimal totalDmd; WaterTaxPayerDetails waterTaxPayerDetails; for (final Entry<String, List<WaterTaxPayerDetails>> entry : billCollectorWiseMap.entrySet()) { waterTaxPayerDetails = new WaterTaxPayerDetails(); cytdColl = BigDecimal.ZERO; lytdColl = BigDecimal.ZERO; cytdDmd = BigDecimal.ZERO; totalDmd = BigDecimal.ZERO; for (final WaterTaxPayerDetails taxPayer : entry.getValue()) { totalDmd = totalDmd.add(taxPayer.getTotalDmd() == null ? BigDecimal.ZERO : taxPayer.getTotalDmd()); cytdColl = cytdColl.add(taxPayer.getCurrentYearTillDateColl() == null ? BigDecimal.ZERO : taxPayer.getCurrentYearTillDateColl()); cytdDmd = cytdDmd.add(taxPayer.getCurrentYearTillDateDmd() == null ? BigDecimal.ZERO : taxPayer.getCurrentYearTillDateDmd()); lytdColl = lytdColl.add(taxPayer.getLastYearTillDateColl() == null ? BigDecimal.ZERO : taxPayer.getLastYearTillDateColl()); } waterTaxPayerDetails.setBillCollector(entry.getKey()); waterTaxPayerDetails.setRegionName(waterChargedashBoardRequest.getRegionName()); waterTaxPayerDetails.setDistrictName(waterChargedashBoardRequest.getDistrictName()); waterTaxPayerDetails.setUlbGrade(waterChargedashBoardRequest.getUlbGrade()); waterTaxPayerDetails.setCurrentYearTillDateColl(cytdColl); waterTaxPayerDetails.setCurrentYearTillDateDmd(cytdDmd); waterTaxPayerDetails.setCurrentYearTillDateBalDmd(cytdDmd.subtract(cytdColl)); waterTaxPayerDetails.setTotalDmd(totalDmd); waterTaxPayerDetails.setLastYearTillDateColl(lytdColl); waterTaxPayerDetails.setAchievement(cytdColl.multiply(WaterTaxConstants.BIGDECIMAL_100).divide(cytdDmd, 1, BigDecimal.ROUND_HALF_UP)); if (lytdColl.compareTo(BigDecimal.ZERO) > 0) cytdColl.subtract(lytdColl).multiply(WaterTaxConstants.BIGDECIMAL_100).divide(lytdColl, 1, BigDecimal.ROUND_HALF_UP); billCollectorWiseWaterTaxPayerDetails.add(waterTaxPayerDetails); } } /** * Returns top 100 tax defaulters * * @param propertyTaxDefaultersRequest * @return */ public List<WaterTaxDefaulters> getTopDefaulters( final WaterChargeDashBoardRequest waterChargeDefaultersRequest) { Long startTime = System.currentTimeMillis(); BoolQueryBuilder boolQuery = filterBasedOnRequest(waterChargeDefaultersRequest); boolQuery = boolQuery.filter(QueryBuilders.matchQuery("status", "ACTIVE")); final SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(WATER_TAX_INDEX_NAME) .withQuery(boolQuery).withSort(new FieldSortBuilder("waterTaxDue").order(SortOrder.DESC)) .withPageable(new PageRequest(0, 100)).build(); final Page<WaterChargeDocument> waterChargeRecords = elasticsearchTemplate.queryForPage(searchQuery, WaterChargeDocument.class); Long timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug("Time taken by defaulters aggregation is (millisecs) " + timeTaken); final List<WaterTaxDefaulters> taxDefaulters = new ArrayList<>(); WaterTaxDefaulters taxDfaulter; startTime = System.currentTimeMillis(); for (final WaterChargeDocument waterChargedoc : waterChargeRecords) { taxDfaulter = new WaterTaxDefaulters(); taxDfaulter.setOwnerName(waterChargedoc.getConsumerName()); taxDfaulter.setConnectionType(waterChargedoc.getUsage()); taxDfaulter.setUlbName(waterChargedoc.getCityName()); taxDfaulter.setBalance(BigDecimal.valueOf(waterChargedoc.getWaterTaxDue())); taxDfaulter.setPeriod(StringUtils.isBlank(waterChargedoc.getDuePeriod()) ? StringUtils.EMPTY : waterChargedoc.getDuePeriod()); taxDefaulters.add(taxDfaulter); } timeTaken = System.currentTimeMillis() - startTime; if (LOGGER.isDebugEnabled()) LOGGER.debug("Time taken for setting values in getTopDefaulters() is (millisecs) : " + timeTaken); return taxDefaulters; } /** * This is used for top 100 defaulter's since ward level filtering is also * present Query which filters documents from index based on request * * @param propertyTaxDefaultersRequest * @return */ private BoolQueryBuilder filterBasedOnRequest(final WaterChargeDashBoardRequest waterChargeDefaultersRequest) { BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() .filter(QueryBuilders.rangeQuery(TOTAL_DEMAND).from(0).to(null)); if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getRegionName())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.REGIONNAMEAGGREGATIONFIELD, waterChargeDefaultersRequest.getRegionName())); if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getDistrictName())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.DISTRICTNAMEAGGREGATIONFIELD, waterChargeDefaultersRequest.getDistrictName())); if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getUlbCode())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.CITYCODEAGGREGATIONFIELD, waterChargeDefaultersRequest.getUlbCode())); if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getUlbGrade())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.CITYGRADEAGGREGATIONFIELD, waterChargeDefaultersRequest.getUlbGrade())); if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getWardName())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.REVENUEWARDAGGREGATIONFIELD, waterChargeDefaultersRequest.getWardName())); boolQuery = filterBoolQueryByTypeForDefaulters(waterChargeDefaultersRequest, boolQuery); return boolQuery; } protected BoolQueryBuilder filterBoolQueryByTypeForDefaulters( final WaterChargeDashBoardRequest waterChargeDefaultersRequest, BoolQueryBuilder boolQuery) { if (StringUtils.isNotBlank(waterChargeDefaultersRequest.getType())) if (waterChargeDefaultersRequest.getType() .equalsIgnoreCase(WaterTaxConstants.DASHBOARD_GROUPING_REGIONWISE) && StringUtils.isNotBlank(waterChargeDefaultersRequest.getRegionName())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.REGIONNAMEAGGREGATIONFIELD, waterChargeDefaultersRequest.getRegionName())); else if (waterChargeDefaultersRequest.getType() .equalsIgnoreCase(WaterTaxConstants.DASHBOARD_GROUPING_DISTRICTWISE) && StringUtils.isNotBlank(waterChargeDefaultersRequest.getDistrictName())) boolQuery = boolQuery .filter(QueryBuilders.matchQuery(WaterTaxConstants.DISTRICTNAMEAGGREGATIONFIELD, waterChargeDefaultersRequest.getDistrictName())); else if (waterChargeDefaultersRequest.getType() .equalsIgnoreCase(WaterTaxConstants.DASHBOARD_GROUPING_CITYWISE) && StringUtils.isNotBlank(waterChargeDefaultersRequest.getUlbCode())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.CITYCODEAGGREGATIONFIELD, waterChargeDefaultersRequest.getUlbCode())); else if (waterChargeDefaultersRequest.getType() .equalsIgnoreCase(WaterTaxConstants.DASHBOARD_GROUPING_GRADEWISE) && StringUtils.isNotBlank(waterChargeDefaultersRequest.getUlbGrade())) boolQuery = boolQuery.filter(QueryBuilders.matchQuery(WaterTaxConstants.CITYGRADEAGGREGATIONFIELD, waterChargeDefaultersRequest.getUlbGrade())); return boolQuery; } }