diff --git a/src/main/java/dev/danipraivet/controlador/ControladorAdmin.java b/src/main/java/dev/danipraivet/controlador/ControladorAdmin.java index 721f331..fb1400f 100644 --- a/src/main/java/dev/danipraivet/controlador/ControladorAdmin.java +++ b/src/main/java/dev/danipraivet/controlador/ControladorAdmin.java @@ -28,6 +28,9 @@ import java.time.format.DateTimeFormatter; import java.util.List; import java.util.ResourceBundle; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class ControladorAdmin implements Initializable { @@ -110,6 +113,7 @@ public void initialize(URL url, ResourceBundle rb) { configurarTablaFichajes(); configurarTablaEmpleados(); Platform.runLater(this::cargarDatos); + Aplicacion.iniciarScheduler(() -> Platform.runLater(this::actualizarDashboard), 60); } @FXML @@ -236,7 +240,11 @@ private void cargarEmpleados() { private void actualizarDashboard() { lblNombreAdmin.setText("Admin: " + GestorSesion.getNombreCompleto()); - lblTotalEmpleados.setText(String.valueOf(empleados.size())); + + long activos = empleados.stream().filter(Empleado::isActivo).count(); + lblTotalEmpleados.setText(String.valueOf(activos)); + + lblFichadosHoy.setText(String.valueOf(servicioFichaje.contarFichadosHoy())); boolean fichado = servicioFichaje.estaFichadoHoy(); if (fichado) { diff --git a/src/main/java/dev/danipraivet/modelo/repositorio/contratos/IRepositorioFichaje.java b/src/main/java/dev/danipraivet/modelo/repositorio/contratos/IRepositorioFichaje.java index abe04ef..1a4aa91 100644 --- a/src/main/java/dev/danipraivet/modelo/repositorio/contratos/IRepositorioFichaje.java +++ b/src/main/java/dev/danipraivet/modelo/repositorio/contratos/IRepositorioFichaje.java @@ -27,4 +27,5 @@ public interface IRepositorioFichaje { // Comprueba si el empleado tiene un fichaje abierto hoy (sin salida registrada) boolean estaFichadoHoy(int codEmpleado); + int contarFichadosHoy(); } diff --git a/src/main/java/dev/danipraivet/modelo/repositorio/implementacion/RepositorioFichaje.java b/src/main/java/dev/danipraivet/modelo/repositorio/implementacion/RepositorioFichaje.java index a58d5cc..5a96376 100644 --- a/src/main/java/dev/danipraivet/modelo/repositorio/implementacion/RepositorioFichaje.java +++ b/src/main/java/dev/danipraivet/modelo/repositorio/implementacion/RepositorioFichaje.java @@ -30,6 +30,7 @@ public class RepositorioFichaje implements IRepositorioFichaje { // Stored procedure de MySQL para registrar fichaje private static final String SQL_REGISTRAR_FICHAJE = "CALL registrar_fichaje(?, @p_mensaje, @p_tipo)"; private static final String SQL_GET_OUT_PARAMS = "SELECT @p_mensaje AS mensaje, @p_tipo AS tipo"; + private static final String SQL_FICHADOS_HOY = "SELECT COUNT(*) FROM dias WHERE fecha = CURRENT_DATE AND entrada_hora IS NOT NULL AND salida_hora IS NULL"; private final Rol rolConexion; public RepositorioFichaje(Rol rolConexion) { this.rolConexion = rolConexion; @@ -233,4 +234,19 @@ private Fichaje mapear(ResultSet rs) throws SQLException { return f; } + + + public int contarFichadosHoy() { + Connection con = null; + try { + con = GestorConexiones.getConexion(rolConexion); + ResultSet rs = con.createStatement().executeQuery(SQL_FICHADOS_HOY); + if (rs.next()) return rs.getInt(1); + } catch (SQLException e) { + log.error("Error en contarFichadosHoy: {}", e.getMessage()); + } finally { + GestorConexiones.liberarConexion(rolConexion, con); + } + return 0; + } } diff --git a/src/main/java/dev/danipraivet/modelo/servicio/ServicioFichaje.java b/src/main/java/dev/danipraivet/modelo/servicio/ServicioFichaje.java index 065a582..cf6b7ce 100644 --- a/src/main/java/dev/danipraivet/modelo/servicio/ServicioFichaje.java +++ b/src/main/java/dev/danipraivet/modelo/servicio/ServicioFichaje.java @@ -75,4 +75,7 @@ public boolean actualizar(Fichaje fichaje) { public boolean eliminar(int id) { return repo.eliminar(id); } + public int contarFichadosHoy() { + return repo.contarFichadosHoy(); + } } diff --git a/src/main/java/dev/danipraivet/vista/Aplicacion.java b/src/main/java/dev/danipraivet/vista/Aplicacion.java index f56eb90..8484404 100644 --- a/src/main/java/dev/danipraivet/vista/Aplicacion.java +++ b/src/main/java/dev/danipraivet/vista/Aplicacion.java @@ -1,5 +1,6 @@ package dev.danipraivet.vista; +import dev.danipraivet.controlador.ControladorAdmin; import dev.danipraivet.modelo.datos.GestorConexiones; import io.github.palexdev.materialfx.theming.JavaFXThemes; import io.github.palexdev.materialfx.theming.MaterialFXStylesheets; @@ -17,6 +18,9 @@ import java.io.IOException; import java.net.URL; import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class Aplicacion extends Application { @@ -24,6 +28,7 @@ public class Aplicacion extends Application { private static final double ANCHO = 1100; private static final double ALTO = 700; private static Stage escenarioPrincipal; + private static ScheduledExecutorService scheduler; public static void navegarA(String vista) { try { @@ -86,6 +91,9 @@ public void start(Stage stage) { public void stop() { log.info("Cerrando aplicacion y liberando conexiones..."); GestorConexiones.cerrarPool(); + if (scheduler != null && !scheduler.isShutdown()) { + scheduler.shutdown(); + } } private void mostrarErrorConexion() { @@ -96,4 +104,9 @@ private void mostrarErrorConexion() { alert.showAndWait(); escenarioPrincipal.show(); } + + public static void iniciarScheduler(Runnable tarea, int intervaloSegundos) { + scheduler = Executors.newSingleThreadScheduledExecutor(); + scheduler.scheduleAtFixedRate(tarea, intervaloSegundos, intervaloSegundos, TimeUnit.SECONDS); + } }