/* Copyright 2012-2017 Jose Robson Mariano Alves This file is part of bgfinancas. 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 package 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 badernageral.bgfinancas.modulo.relatorio; import badernageral.bgfinancas.biblioteca.ajuda.Ajuda; import badernageral.bgfinancas.biblioteca.contrato.Categoria; import badernageral.bgfinancas.biblioteca.contrato.Controlador; import badernageral.bgfinancas.modelo.Extrato; import badernageral.bgfinancas.biblioteca.contrato.Grafico; import badernageral.bgfinancas.biblioteca.sistema.Botao; import badernageral.bgfinancas.biblioteca.sistema.Janela; import badernageral.bgfinancas.biblioteca.sistema.Kernel; import badernageral.bgfinancas.biblioteca.sistema.Tabela; import badernageral.bgfinancas.biblioteca.tipo.Posicao; import badernageral.bgfinancas.biblioteca.tipo.Status; import badernageral.bgfinancas.idioma.Linguagem; import badernageral.bgfinancas.modelo.CartaoCredito; import badernageral.bgfinancas.modelo.Conta; import badernageral.bgfinancas.modelo.Despesa; import badernageral.bgfinancas.modelo.DespesaCategoria; import badernageral.bgfinancas.modelo.Receita; import badernageral.bgfinancas.modelo.Transferencia; import java.math.BigDecimal; import java.net.URL; import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.ResourceBundle; import javafx.beans.property.BooleanProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.print.PrinterJob; import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.chart.BarChart; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart.Series; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.DatePicker; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.Tooltip; import javafx.scene.control.cell.CheckBoxListCell; import javafx.scene.input.MouseEvent; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; public final class RelatoriosControlador implements Initializable, Controlador { private final String TITULO = idioma.getMensagem("relatorios"); @FXML private Button voltar; @FXML private Label labelRelatorio; @FXML private Label labelContaCartao; @FXML private Label labelInicio; @FXML private Label labelFim; @FXML private ComboBox<String> relatorio; @FXML private ComboBox<String> tipo; @FXML private ComboBox<Categoria> listaContaCartao; @FXML private DatePicker inicio; @FXML private DatePicker fim; @FXML private Button atualizar; @FXML private Button imprimir; @FXML private GridPane tabela; @FXML private GridPane barraSuperior; private BigDecimal valorTotal; private final NumberAxis xAxisPrincipal = new NumberAxis(); private final CategoryAxis yAxisPrincipal = new CategoryAxis(); private final BarChart<String,Number> graficoPrincipal = new BarChart<>(yAxisPrincipal,xAxisPrincipal); private final NumberAxis xAxisSecundario = new NumberAxis(); private final CategoryAxis yAxisSecundario = new CategoryAxis(); private final BarChart<String,Number> graficoSecundario = new BarChart<>(yAxisSecundario,xAxisSecundario); private final CategoryAxis xAxisLinhas = new CategoryAxis(); private final NumberAxis yAxisLinhas = new NumberAxis(); private final LineChart<String,Number> graficoLinhas = new LineChart<>(xAxisLinhas,yAxisLinhas); private final ListView<DespesaCategoria> listaCategorias = new ListView<>(); private final TableView<Despesa> listaDespesas = new TableView<>(); private final Tabela<Despesa> tabelaDespesas = new Tabela<>(); private final TableView<Extrato> listaExtrato = new TableView<>(); private final Tabela<Extrato> tabelaExtrato = new Tabela<>(); @Override public void initialize(URL url, ResourceBundle rb) { Kernel.setTitulo(TITULO); Botao.prepararBotaoVoltar(voltar); labelRelatorio.setText(idioma.getMensagem("selecione_relatorio")+":"); List<String> tipoRelatorio = Arrays.asList(idioma.getMensagem("despesas"),idioma.getMensagem("lista_despesas"),idioma.getMensagem("despesas_tempo"),idioma.getMensagem("despesas_agendadas"),idioma.getMensagem("receitas"),idioma.getMensagem("transferencias"),idioma.getMensagem("extrato")); relatorio.setItems(FXCollections.observableList(tipoRelatorio)); relatorio.getSelectionModel().select(0); labelInicio.setText(idioma.getMensagem("inicio")+":"); labelFim.setText(idioma.getMensagem("fim")+":"); LocalDate hoje = LocalDate.now(); inicio.setValue(hoje.withDayOfMonth(1)); fim.setValue(hoje.withDayOfMonth(hoje.lengthOfMonth())); prepararTabelas(); prepararTipoTempo(); prepararFiltro(); imprimir.setVisible(false); } private void prepararTabelas(){ tabelaDespesas.prepararTabela(listaDespesas); tabelaDespesas.adicionarColuna(listaDespesas, idioma.getMensagem("categoria"), "nomeCategoria"); tabelaDespesas.adicionarColuna(listaDespesas, idioma.getMensagem("item"), "nomeItem"); tabelaDespesas.adicionarColunaNumero(listaDespesas, idioma.getMensagem("quantidade"), "quantidade"); tabelaDespesas.adicionarColunaNumero(listaDespesas, idioma.getMensagem("valor"), "valor"); tabelaExtrato.prepararTabela(listaExtrato); TableColumn<Extrato,String> tipo = tabelaExtrato.adicionarColuna(listaExtrato, idioma.getMensagem("tipo"), "tipo"); tabelaExtrato.adicionarColunaDataHora(listaExtrato, idioma.getMensagem("data"), "dataHora"); tabelaExtrato.adicionarColuna(listaExtrato, idioma.getMensagem("categoria"), "nomeCategoria"); tabelaExtrato.adicionarColuna(listaExtrato, idioma.getMensagem("item"), "nomeItem"); tabelaExtrato.adicionarColunaNumero(listaExtrato, idioma.getMensagem("valor"), "valor"); TableColumn<Extrato,String> status = tabelaExtrato.adicionarColuna(listaExtrato, idioma.getMensagem("status"), "status"); status.setCellFactory(e -> new TableCell<Extrato, String>(){ @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); setText(item==null ? null : item); if (item != null) { setTextFill(item.equals(idioma.getMensagem("agendado")) ? Color.RED : Color.BLACK); } } }); tipo.setCellFactory(e -> new TableCell<Extrato, String>(){ @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); setText(item==null ? null : item); if (item != null) { setTextFill(item.equals(idioma.getMensagem("despesa")) ? Color.GREEN : Color.BLUE); } } }); } public void acaoImprimir() { // a ser implementado } private void prepararTipoTempo(){ tipo.getItems().add(idioma.getMensagem("semanal")); tipo.getItems().add(idioma.getMensagem("mensal")); tipo.getItems().add(idioma.getMensagem("anual")); tipo.getSelectionModel().select(1); tipo.setOnAction(e -> { carregarRelatorio(); }); } public void prepararFiltro(){ barraSuperior.getChildren().remove(atualizar); barraSuperior.getChildren().remove(tipo); if(relatorio.getSelectionModel().getSelectedItem().equals(idioma.getMensagem("despesas_tempo"))){ barraSuperior.add(tipo, 9, 0); barraSuperior.add(atualizar, 10, 0); }else{ barraSuperior.add(atualizar, 9, 0); } listaContaCartao.setOnAction(null); if(relatorio.getSelectionModel().getSelectedItem().equals(idioma.getMensagem("despesas_agendadas"))){ labelContaCartao.setText(idioma.getMensagem("cartao_credito")+":"); new CartaoCredito().montarSelectCategoria(listaContaCartao); CartaoCredito cartaoSemCartao = new CartaoCredito().setNome(idioma.getMensagem("sem_cartao_credito")); CartaoCredito cartaoSomenteCartao = new CartaoCredito().setNome(idioma.getMensagem("somente_cartao_credito")); CartaoCredito cartaoTodos = new CartaoCredito().setNome(idioma.getMensagem("todos")); listaContaCartao.getItems().add(cartaoSemCartao); listaContaCartao.getItems().add(cartaoSomenteCartao); listaContaCartao.getItems().add(cartaoTodos); listaContaCartao.getSelectionModel().select(cartaoTodos); }else{ labelContaCartao.setText(idioma.getMensagem("conta")+":"); new Conta().montarSelectCategoria(listaContaCartao); Conta contasTodas = new Conta().setNome(idioma.getMensagem("todas")); listaContaCartao.getItems().add(contasTodas); listaContaCartao.getSelectionModel().select(contasTodas); } listaContaCartao.setOnAction(e -> { carregarRelatorio(); }); carregarRelatorio(); } public void carregarRelatorio(){ removerGraficos(); switch(relatorio.getSelectionModel().getSelectedIndex()){ case 0: relatorioGraficoBarras(new Despesa().setAgendada("0")); break; case 1: relatorioListaDespesas(); break; case 2: relatorioGraficoLinhas(); break; case 3: relatorioGraficoBarras(new Despesa().setAgendada("1")); break; case 4: relatorioGraficoBarras(new Receita()); break; case 5: relatorioGraficoBarras(new Transferencia()); break; case 6: relatorioExtrato(); break; default: Janela.showMensagem(Status.ERRO, idioma.getMensagem("nao_encontrado")); } } private void removerGraficos(){ tabela.getChildren().remove(graficoPrincipal); tabela.getChildren().remove(graficoSecundario); tabela.getChildren().remove(graficoLinhas); tabela.getChildren().remove(listaCategorias); tabela.getChildren().remove(listaDespesas); tabela.getChildren().remove(listaExtrato); } private String getValorTotal(ObservableList<Series<String,Number>> series){ valorTotal = new BigDecimal("0.0"); series.stream().forEach((serie) -> { serie.getData().stream().forEach((item) -> { valorTotal = valorTotal.add(new BigDecimal(item.getYValue().toString())); }); }); return idioma.getMensagem("moeda")+" "+valorTotal; } private Integer getTipoCategoria(){ if(relatorio.getSelectionModel().getSelectedItem().equals(idioma.getMensagem("despesas_agendadas"))){ if(listaContaCartao.getSelectionModel().getSelectedItem().getNome().equals(idioma.getMensagem("somente_cartao_credito"))){ return 4; }else if(listaContaCartao.getSelectionModel().getSelectedItem().getNome().equals(idioma.getMensagem("sem_cartao_credito"))){ return 3; }else{ return 2; } } return 1; } private void relatorioListaDespesas(){ tabela.add(listaDespesas, 0, 1); GridPane.setColumnSpan(listaDespesas, GridPane.REMAINING); listaDespesas.setItems(new Despesa().listarPeriodoAgrupado(inicio.getValue(), fim.getValue())); } private void relatorioExtrato(){ tabela.add(listaExtrato, 0, 1); GridPane.setColumnSpan(listaExtrato, GridPane.REMAINING); ObservableList<Extrato> despesas = new Despesa().getExtrato(inicio.getValue(), fim.getValue()); ObservableList<Extrato> receitas = new Receita().getExtrato(inicio.getValue(), fim.getValue()); listaExtrato.setItems(despesas); listaExtrato.getItems().addAll(receitas); listaExtrato.getItems().sort((Extrato a, Extrato b) -> { return a.getDataHora().compareTo(b.getDataHora()); }); } private void relatorioGraficoBarras(Grafico objeto){ xAxisPrincipal.setLabel(idioma.getMensagem("valores")+" ("+idioma.getMensagem("moeda")+")"); xAxisSecundario.setLabel(idioma.getMensagem("valores")+" ("+idioma.getMensagem("moeda")+")"); ajustarColunas(50,50); tabela.add(graficoPrincipal, 0, 1); tabela.add(graficoSecundario, 1, 1); String id_categoria = listaContaCartao.getSelectionModel().getSelectedItem().getIdCategoria(); Integer tipo_categoria = getTipoCategoria(); graficoPrincipal.getData().setAll(objeto.getRelatorioMensalBarras(inicio.getValue(), fim.getValue(), null, id_categoria, tipo_categoria)); graficoPrincipal.getData().stream().forEach((serie) -> { serie.getData().stream().forEach((item) -> { item.getNode().setCursor(Cursor.HAND); item.getNode().setOnMouseClicked((MouseEvent event) -> { updateGraficoSecundario(serie.getName(), objeto); }); eventosGrafico(item.getNode(), serie.getName()+" - "+idioma.getMensagem("moeda")+" "+item.getYValue()); }); }); graficoPrincipal.setTitle(idioma.getMensagem("categorias")+" - "+getValorTotal(graficoPrincipal.getData())); graficoPrincipal.lookupAll("Label.chart-legend-item").stream().forEach((Node legenda) -> { legenda.setCursor(Cursor.HAND); legenda.setOnMouseClicked((MouseEvent event) -> { if(legenda instanceof Label){ Label texto = (Label) legenda; updateGraficoSecundario(texto.getText(), objeto); } }); }); try{ Series<String,Number> primeiraCategoria = graficoPrincipal.getData().get(0); updateGraficoSecundario(primeiraCategoria.getName(), objeto); }catch(Exception e){ updateGraficoSecundario("", null); } } private void updateGraficoSecundario(String nomeCategoria, Grafico objeto){ if(objeto!=null){ String id_categoria = listaContaCartao.getSelectionModel().getSelectedItem().getIdCategoria(); Integer tipo_categoria = getTipoCategoria(); graficoSecundario.getData().setAll(objeto.getRelatorioMensalBarras(inicio.getValue(), fim.getValue(), nomeCategoria, id_categoria, tipo_categoria)); graficoSecundario.getData().stream().forEach((serie) -> { serie.getData().stream().forEach((item) -> { eventosGrafico(item.getNode(), serie.getName()+" - "+idioma.getMensagem("moeda")+" "+item.getYValue()); }); }); graficoSecundario.setTitle(idioma.getMensagem("itens")+" / "+nomeCategoria+" - "+getValorTotal(graficoSecundario.getData())); }else{ graficoSecundario.getData().clear(); graficoSecundario.setTitle(idioma.getMensagem("itens")+" - "+getValorTotal(graficoSecundario.getData())); } } private void relatorioGraficoLinhas(){ listaCategorias.setEditable(true); if(listaCategorias.getItems().size()<=0){ ObservableList<DespesaCategoria> categorias = new DespesaCategoria().listar(); listaCategorias.setItems(categorias); } listaCategorias.setCellFactory(CheckBoxListCell.forListView((DespesaCategoria param) -> { BooleanProperty observable = param.getSelecao(); observable.addListener((obs, wasSelected, isNowSelected) -> gerarGraficoLinhas() ); return observable; })); ajustarColunas(25,75); tabela.add(listaCategorias, 0, 1); tabela.add(graficoLinhas, 1, 1); gerarGraficoLinhas(); } public void gerarGraficoLinhas(){ List<String> categoriasSelecionadas = new ArrayList<>(); listaCategorias.getItems().stream().forEach((categoria) -> { if(categoria.isSelecionado()){ categoriasSelecionadas.add(categoria.getIdCategoria()); } }); new Despesa().preencherRelatorioMensalLinhas(graficoLinhas, inicio.getValue(), fim.getValue(), categoriasSelecionadas, listaContaCartao.getSelectionModel().getSelectedItem(), tipo.getSelectionModel().getSelectedItem()); graficoLinhas.getData().stream().forEach((serie) -> { serie.getData().stream().forEach((item) -> { eventosGrafico(item.getNode(), serie.getName()+" - "+idioma.getMensagem("moeda")+" "+item.getYValue()); }); }); } private void ajustarColunas(int coluna1, int coluna2){ ColumnConstraints col1 = new ColumnConstraints(); col1.setPercentWidth(coluna1); ColumnConstraints col2 = new ColumnConstraints(); col2.setPercentWidth(coluna2); tabela.getColumnConstraints().setAll(col1,col2); } private void eventosGrafico(Node node, String nome){ Tooltip tooltip = new Tooltip(nome); node.setOnMouseEntered((MouseEvent event) -> { tooltip.show(node, event.getScreenX()+15, event.getScreenY()); }); node.setOnMouseExited((MouseEvent event) -> { tooltip.hide(); }); } @Override public void acaoVoltar() { Kernel.principal.acaoVoltar(); } @Override public void acaoCadastrar(int botao) { System.out.println(idioma.getMensagem("nao_implementado")); } @Override public void acaoAlterar(int tabela) { System.out.println(idioma.getMensagem("nao_implementado")); } @Override public void acaoExcluir(int botao) { System.out.println(idioma.getMensagem("nao_implementado")); } @Override public void acaoGerenciar(int botao) { System.out.println(idioma.getMensagem("nao_implementado")); } @Override public void acaoFiltrar(Boolean animacao) { System.out.println(idioma.getMensagem("nao_implementado")); } @Override public void acaoAjuda() { Ajuda.getInstance().setObjetos(voltar,labelRelatorio,relatorio,labelContaCartao,listaContaCartao,labelInicio,inicio,labelFim,fim,atualizar,graficoPrincipal,graficoSecundario,listaCategorias,graficoLinhas,listaDespesas,listaExtrato); Ajuda.getInstance().capitulo(Posicao.CENTRO, idioma.getMensagem("tuto_relat_1")); Ajuda.getInstance().capitulo(relatorio, Posicao.BAIXO, idioma.getMensagem("tuto_relat_2")); Ajuda.getInstance().capitulo(listaContaCartao, Posicao.BAIXO, idioma.getMensagem("tuto_relat_3")); Ajuda.getInstance().capitulo(inicio, Posicao.BAIXO, idioma.getMensagem("tuto_relat_4")); Ajuda.getInstance().capitulo(fim, Posicao.BAIXO, idioma.getMensagem("tuto_relat_5")); Ajuda.getInstance().capitulo(atualizar, Posicao.BAIXO, idioma.getMensagem("tuto_relat_6")); Ajuda.getInstance().apresentarProximo(); } }