/* * Copyright (C) 2015 Arthur Gregorio, AG.Software * * 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 * (at your option) 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/>. */ package br.com.webbudget.application.controller; import br.com.webbudget.application.component.chart.donut.DonutChartModel; import br.com.webbudget.domain.model.entity.miscellany.FinancialPeriod; import br.com.webbudget.domain.model.entity.financial.Movement; import br.com.webbudget.domain.misc.MovementCalculator; import br.com.webbudget.application.component.chart.line.LineChartDatasetBuilder; import br.com.webbudget.application.component.chart.line.LineChartModel; import br.com.webbudget.domain.misc.ex.InternalServiceError; import br.com.webbudget.domain.model.entity.entries.MovementClassType; import br.com.webbudget.domain.model.service.FinancialPeriodService; import br.com.webbudget.domain.model.service.MovementService; import br.com.webbudget.domain.model.service.PeriodDetailService; import br.com.webbudget.infraestructure.configuration.ApplicationUtils; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; import lombok.Getter; /** * Mbean utilizado na dashboard do sistema, por ele carregamos os graficos da * dashboard e tambem alguns elementos da template, como o nome no botao de * informacoes da conta do usuario * * @author Arthur Gregorio * * @version 2.0.0 * @since 1.0.0, 27/02/2014 */ @Named @ViewScoped public class DashboardBean extends AbstractBean { @Getter private LineChartModel lineChartModel; @Getter private BigDecimal accumulated; @Getter private BigDecimal totalRevenueGoal; @Getter private BigDecimal totalExpensesGoal; @Getter private BigDecimal totalCreditCardGoal; @Getter private DonutChartModel expensesCostCenterModel; @Getter private DonutChartModel revenuesCostCenterModel; @Getter private int percentageExpenses; @Getter private int percentageRevenues; @Getter private int percentageCreditCard; private List<FinancialPeriod> openPeriods; private List<FinancialPeriod> closedPeriods; @Getter private MovementCalculator calculator; @Inject private MovementService movementService; @Inject private PeriodDetailService periodDetailService; @Inject private FinancialPeriodService financialPeriodService; /** * Inicializa a dashboard do sistema */ public void initialize() { this.accumulated = BigDecimal.ZERO; this.totalRevenueGoal = BigDecimal.ZERO; this.totalExpensesGoal = BigDecimal.ZERO; this.totalCreditCardGoal = BigDecimal.ZERO; this.closedPeriods = new ArrayList<>(); try { this.openPeriods = this.financialPeriodService .listOpenFinancialPeriods(); this.initializePeriodSummary(); this.initializeBalanceHistory(); this.initializeClosingsGraph(); this.initializeCostCentersGraphs(); this.countGoals(); this.calculatePercentages(); } catch (InternalServiceError ex) { this.addError(true, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(true, "error.undefined-error", ex.getMessage()); } } /** * @return a versao da aplicacao */ public String getVersion() { return ApplicationUtils.getConfiguration("application.version"); } /** * Porcentagem da meta de receitas */ private void calculatePercentages() { this.percentageCreditCard = this.percentageOf( this.calculator.getTotalPaidOnCreditCard(), this.totalCreditCardGoal); this.percentageExpenses = this.percentageOf( this.calculator.getExpensesTotal(), this.totalExpensesGoal); this.percentageRevenues = this.percentageOf( this.calculator.getRevenuesTotal(), this.totalRevenueGoal); } /** * Inicializa o bloco com as informacoes sobre os periodos ativos */ private void initializePeriodSummary() { final List<Movement> movements = new ArrayList<>(); this.openPeriods.stream().forEach(period -> { movements.addAll( this.movementService.listOnlyMovementsByPeriod(period)); }); // cria a calculadora coma lista gerada this.calculator = new MovementCalculator(movements); } /** * Inicializa o historico de saldos */ private void initializeBalanceHistory() { this.closedPeriods = this.financialPeriodService.listLastSixClosedPeriods(); final FinancialPeriod latestClosedPeriod = this.financialPeriodService.findLatestClosedPeriod(); if (latestClosedPeriod != null) { this.accumulated = latestClosedPeriod.getAccumulated() .add(this.calculator.getBalance()); } else { this.accumulated = this.calculator.getBalance(); } } /** * Monta o grafico */ private void initializeClosingsGraph() { final LineChartDatasetBuilder<BigDecimal> revenueDatasetBuilder = new LineChartDatasetBuilder<>() .withLabel(this.translate("dashboard.revenue-serie")) .filledByColor("rgba(140,217,140,0.2)") .withStrokeColor("rgba(51,153,51,1)") .withPointColor("rgba(45,134,45,1)") .withPointStrokeColor("#fff") .withPointHighlightFillColor("#fff") .withPointHighlightStroke("rgba(45,134,45,1)"); final LineChartDatasetBuilder<BigDecimal> expenseDatasetBuilder = new LineChartDatasetBuilder<>() .withLabel(this.translate("dashboard.expenses-serie")) .filledByColor("rgba(255,153,153,0.2)") .withStrokeColor("rgba(255,77,77,1)") .withPointColor("rgba(204,0,0,1)") .withPointStrokeColor("#fff") .withPointHighlightFillColor("#fff") .withPointHighlightStroke("rgba(204,0,0,1)"); this.lineChartModel = new LineChartModel(); // ordena pela inclusao, do mais velho para o menos novo this.closedPeriods.sort((v1, v2) -> v1.getInclusion().compareTo(v2.getInclusion())); // coloca o nome das series e os dados this.closedPeriods.stream().forEach(period -> { this.lineChartModel.addLabel(period.getIdentification()); revenueDatasetBuilder.andData(period.getRevenuesTotal()); expenseDatasetBuilder.andData(period.getExpensesTotal()); }); this.lineChartModel.addDataset(revenueDatasetBuilder.build()); this.lineChartModel.addDataset(expenseDatasetBuilder.build()); if (!this.lineChartModel.isEmptyChart()) { this.drawLineChart("closingsChart", lineChartModel); } } /** * A somatoria das metas para os periodos em aberto */ private void countGoals() { this.totalCreditCardGoal = this.openPeriods.stream() .map(FinancialPeriod::getCreditCardGoal) .reduce(BigDecimal.ZERO, BigDecimal::add); this.totalExpensesGoal = this.openPeriods.stream() .map(FinancialPeriod::getExpensesGoal) .reduce(BigDecimal.ZERO, BigDecimal::add); this.totalRevenueGoal = this.openPeriods.stream() .map(FinancialPeriod::getRevenuesGoal) .reduce(BigDecimal.ZERO, BigDecimal::add); } /** * Inicializa o grafico de consumo e receita por centro de custo */ private void initializeCostCentersGraphs() { this.revenuesCostCenterModel = this.periodDetailService .buidCostCenterChart(this.openPeriods, MovementClassType.IN); if (this.revenuesCostCenterModel.containsData()) { this.drawDonutChart("revenuesByCostCenter", this.revenuesCostCenterModel); } this.expensesCostCenterModel = this.periodDetailService .buidCostCenterChart(this.openPeriods, MovementClassType.OUT); if (this.expensesCostCenterModel.containsData()) { this.drawDonutChart("expensesByCostCenter", this.expensesCostCenterModel); } } }