/* * MIT License * * Copyright (c) 2018 Daniel Cortes * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package danielcortes.xyz.controllers; import danielcortes.xyz.models.caja.Caja; import danielcortes.xyz.models.egreso.Egreso; import danielcortes.xyz.models.egreso.EgresoDAO; import danielcortes.xyz.models.tipo_egreso.TipoEgreso; import danielcortes.xyz.models.tipo_egreso.TipoEgresoDAO; import danielcortes.xyz.views.EgresosView; import danielcortes.xyz.views.components.EgresosTableModel; import javax.swing.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class EgresosController { private EgresosView view; private EgresoDAO egresoDAO; private TipoEgresoDAO tipoEgresoDAO; private Caja caja; private int editingId; private boolean editing; private Egreso editingEgreso; /** * Crea el controlador, el cual esta acoplado con la vista de egresos, controlando el estado y el contenido de esta * Al inicial ejecuta: * - Metodo que genera los eventos para la vista. * - Metodo que llena los tipos de egresos en la vista. * - Actualiza el estado de los botones. */ public EgresosController(EgresosView view, EgresoDAO egresoDAO, TipoEgresoDAO tipoEgresoDAO) { this.view = view; this.egresoDAO = egresoDAO; this.tipoEgresoDAO = tipoEgresoDAO; this.setUpViewEvents(); this.fillTipoEgresoCombo(); this.updateButtonsEnabled(); } /** * Getter! * @return */ public EgresoDAO getEgresoDAO() { return egresoDAO; } /** * Getter * @return */ public TipoEgresoDAO getTipoEgresoDAO() { return tipoEgresoDAO; } /** * Guarda la caja entregada y actualiza los datos de la tabla de egresos y actualiza el field con el total de egresos. */ public void updateCaja(Caja caja){ this.caja = caja; this.fillEgresosTable(); this.updateTotalEgresos(); } /** * Rellena el ComboBox con los tipos de egresos disponibles */ private void fillTipoEgresoCombo() { JComboBox tipoCombo = view.getTipoCombo(); for (TipoEgreso tipoEgreso : this.tipoEgresoDAO.findAll()) { tipoCombo.addItem(tipoEgreso); } } /** * Rellena la tabla de egresos con los egresos correspondientes a la caja seleccionada */ private void fillEgresosTable() { EgresosTableModel egresosTableModel = view.getEgresosTableModel(); egresosTableModel.removeRows(); for (Egreso egreso : this.egresoDAO.findByCaja(this.caja)) { egresosTableModel.addRow(egreso); } } /** * Asigna todos los eventos para la vista de egresos. * - Cuando se apreta el boton de guardar o se apreta enter en los fields de descripcion, nro, valor y tipo * Se llama al metodo guardarActionListener. * - Cuando se apreta el boton de eliminar se llama al metodos eliminarActionListener * - Cuando se presiona editar o se realizan 2 clicks en la tabla de egresos se llama a editarActionListener * - Cuando se selecciona una fila en la tabla se llama a updateButtonsEnabled */ private void setUpViewEvents() { this.view.getEgresosTable().getSelectionModel().addListSelectionListener(e -> updateButtonsEnabled()); this.view.getGuardarButton().addActionListener(e -> guardarActionListener()); this.view.getEliminarButton().addActionListener(e -> eliminarActionListener()); this.view.getEditarButton().addActionListener(e -> editarActionListener()); this.view.getDescripcionField().addActionListener(e -> guardarActionListener()); this.view.getNroField().addActionListener(e -> guardarActionListener()); this.view.getValorField().addActionListener(e -> guardarActionListener()); this.view.getTipoCombo().addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { guardarActionListener(); } } }); this.view.getEgresosTable().addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent mouseEvent) { JTable table = (JTable) mouseEvent.getSource(); if (mouseEvent.getClickCount() == 2 && table.getSelectedRow() != -1) { EgresosController.this.editarActionListener(); } } }); } /** * Realiza las preparaciones previas a guardar un egreso * Primero llama a normalizar los inputs y a ocultar los mensajes de error * Luego si es que esta colocada la flag de editing se llama al metodo editarEgreso y si no, se llama a guardarEgreso * Al terminar esto, se llama a resetear el focus en los inputs y a actualizar el total de egresos * */ private void guardarActionListener() { this.normalizeInputs(); this.hideErrorMessages(); String nro = this.view.getNroField().getText(); String descripcion = this.view.getDescripcionField().getText(); String valor = this.view.getValorField().getText(); TipoEgreso tipo = (TipoEgreso) this.view.getTipoCombo().getSelectedItem(); if(editing){ this.editarEgreso(nro, descripcion, valor, tipo, this.caja); }else { this.guardarEgreso(nro, descripcion, valor, tipo, this.caja); } this.resetFocus(); } /** * Realiza las acciones necesarias para eliminar un egreso * Obtiene el egreso seleccionado y lo elimina, luego llama a actualizar el total de egresos y a actualizar el estado de los botones. */ private void eliminarActionListener() { int selectedID = this.view.getEgresosTable().getSelectedRow(); if (selectedID >= 0) { Egreso egreso = this.view.getEgresosTableModel().getEgreso(selectedID); this.view.getEgresosTableModel().removeRow(selectedID); this.egresoDAO.deleteEgreso(egreso); this.updateTotalEgresos(); this.updateButtonsEnabled(); } } /** * Realiza lo necesario para comenzar a editar un egreso * Llama a esconder los mensajes de error. * Guarda globalmente en la clase el egreso que se esta editando, su id y una flag indicando que se esta en modo editar. * Ademas rellena los campos de input con los valores del egreso que se esta editando. */ private void editarActionListener() { this.hideErrorMessages(); int selectedID = this.view.getEgresosTable().getSelectedRow(); if (selectedID >= 0) { Egreso egreso = this.view.getEgresosTableModel().getEgreso(selectedID); this.editingId = selectedID; this.editingEgreso = egreso; this.editing = true; this.view.getNroField().setText(egreso.getNro()); this.view.getDescripcionField().setText(egreso.getDescripcion()); this.view.getValorField().setText(String.valueOf(egreso.getValor())); this.view.getTipoCombo().setSelectedItem(egreso.getTipoEgreso()); } } /** * Obtiene el total de egresos y los coloca en el campo de totalEgresosField. */ private void updateTotalEgresos() { int total = this.egresoDAO.getTotalEgreso(this.caja); this.view.getTotalEgresosField().setText(String.valueOf(total)); } /** * Cuando se tiene seleccionada una fila de la tabla activa los botones de eliminar y editar * Si no esta seleccionada los desactiva */ private void updateButtonsEnabled() { if (this.view.getEgresosTable().getSelectedRow() >= 0) { this.view.getEliminarButton().setEnabled(true); this.view.getEditarButton().setEnabled(true); } else { this.view.getEliminarButton().setEnabled(false); this.view.getEditarButton().setEnabled(false); } } /** * Guarda un egreso tras llamar a validar su input * Luego de guardar, agrega el egreso a la tabla, llama a actualizar el total de egresos y llama a limpiar a los inputs */ private void guardarEgreso(String nro, String descripcion, String valor, TipoEgreso tipo, Caja caja) { if (this.validateInput(nro, descripcion, valor, tipo, caja)) { Egreso egreso = new Egreso(); egreso.setValor(Integer.valueOf(valor)); egreso.setDescripcion(descripcion); egreso.setNro(nro); egreso.setTipoEgreso(tipo); egreso.setCaja(caja); egresoDAO.insertEgreso(egreso); this.view.getEgresosTableModel().addRow(egreso); this.updateTotalEgresos(); this.clearInputs(); } } /** * Actualiza un egreso tras llamar a validar su input * Tras esto actualiza el egreso en la tabla, llama a actualizar el total de egresos y a limpiar los inputs * Finalmente setea la flag editing a false */ private void editarEgreso(String nro, String descripcion, String valor, TipoEgreso tipo, Caja caja) { if (this.validateInput(nro, descripcion, valor, tipo, caja)) { this.editingEgreso.setValor(Integer.valueOf(valor)); this.editingEgreso.setDescripcion(descripcion); this.editingEgreso.setNro(nro); this.editingEgreso.setTipoEgreso(tipo); egresoDAO.updateEgreso(this.editingEgreso); this.view.getEgresosTableModel().setEgreso(this.editingId, this.editingEgreso); this.updateTotalEgresos(); this.clearInputs(); this.editing = false; } } /** * llama a los metodos necesarios para validar los inputs entregados * @return true cuando todas las validaciones retoran true, si no, false */ private boolean validateInput(String nro, String descripcion, String valor, TipoEgreso tipoEgreso, Caja caja) { boolean nroValidation = this.validateNro(nro); boolean descripcionValidation = this.validateDescripcion(descripcion); boolean valorValidation = this.validateValor(valor); boolean tipoEgresoValidation = this.validateTipoEgreso(tipoEgreso); boolean cajaValidation = this.validateCaja(caja); return nroValidation && descripcionValidation && valorValidation && tipoEgresoValidation; } /** * Valida la variable nro contra los casos * - Es null * - Esta vacio * Cuando el primer caso sea true, colocara un mensaje de error correspondiente en el jlabel correspondiente * @return Si cualquiera de estos casos son true se retornara false, si no, se retorna true */ private boolean validateNro(String nro) { if (nro == null) { this.view.getErrorNumero().setText("Hubo un problema con los datos"); this.view.getErrorNumero().setVisible(true); return false; } nro = nro.trim(); if (nro.isEmpty()) { this.view.getErrorNumero().setText("El campo esta vacio"); this.view.getErrorNumero().setVisible(true); return false; } return true; } /** * Valida la variable descripcion contra los casos * - Es null * - Esta vacio * Cuando el primer caso sea true, colocara un mensaje de error correspondiente en el jlabel correspondiente * @return Si cualquiera de estos casos son true se retornara false, si no, se retorna true */ private boolean validateDescripcion(String descripcion) { if (descripcion == null) { this.view.getErrorDescripcion().setText("Hubo un problema con los datos"); this.view.getErrorDescripcion().setVisible(true); return false; } if (descripcion.isEmpty()) { this.view.getErrorDescripcion().setText("El campo esta vacio"); this.view.getErrorDescripcion().setVisible(true); return false; } return true; } /** * Valida la variable valor contra los casos * - Es null * - Esta vacio * - Los caracteres no son todos digitos * - El largo del string es mayot a 10 * Cuando el primer caso sea true, colocara un mensaje de error correspondiente en el jlabel correspondiente * @return Si cualquiera de estos casos son true se retornara false, si no, se retorna true */ private boolean validateValor(String valor) { if (valor == null) { this.view.getErrorValor().setText("Hubo un problema con los datos"); this.view.getErrorValor().setVisible(true); return false; } if (valor.isEmpty()) { this.view.getErrorValor().setText("El campo esta vacio"); this.view.getErrorValor().setVisible(true); return false; } if (!valor.chars().allMatch(Character::isDigit)) { this.view.getErrorValor().setText("Deben ser numeros"); this.view.getErrorValor().setVisible(true); return false; } if (valor.length() > 10) { this.view.getErrorValor().setText("El numero ingresado es demasiado largo"); this.view.getErrorValor().setVisible(true); return false; } return true; } /** * Valida la variable tipoEgreso contra los casos * - Es null * Cuando este caso sea true, colocara un mensaje de error correspondiente en el jlabel correspondiente * @return Si este caso es true se retornara false, si no, se retorna true */ private boolean validateTipoEgreso(TipoEgreso tipoEgreso) { if (tipoEgreso == null) { this.view.getErrorTipoEgreso().setText("Hubo un problema con los datos"); this.view.getErrorTipoEgreso().setVisible(true); return false; } return true; } /** * Valida la variable caja contra los casos * - Es null * @return Si este caso es true se retornara false, si no, se retorna true */ private boolean validateCaja(Caja caja){ return caja != null; } /** * Esconde los mensajes de error en la ventana de egresos */ private void hideErrorMessages() { this.view.getErrorTipoEgreso().setVisible(false); this.view.getErrorValor().setVisible(false); this.view.getErrorDescripcion().setVisible(false); this.view.getErrorNumero().setVisible(false); } /** * Vacia los campos de texto y selecciona la primera opcion en el jcombobox */ private void clearInputs() { this.view.getTipoCombo().setSelectedIndex(0); this.view.getNroField().setText(""); this.view.getValorField().setText(""); this.view.getDescripcionField().setText(""); } /** * Ejecuta trim sobre todos los campos de texto */ private void normalizeInputs(){ this.view.getValorField().setText(this.view.getValorField().getText().trim()); this.view.getNroField().setText(this.view.getNroField().getText().trim()); this.view.getDescripcionField().setText(this.view.getDescripcionField().getText().trim()); } /** * Setea el focus en el campo nroField */ private void resetFocus() { this.view.getNroField().requestFocus(); } }