File "AsistenciaModel.php"

Full Path: C:/wamp64/www/Asistencia_Capacitacion/Modelos/AsistenciaModel.php
File size: 12.67 KB
MIME-type: text/x-php
Charset: utf-8

<?php
// File: Modelos/AsistenciaModel.php

require_once 'Database.php';

class AsistenciaModel {
    private $db;

    public function __construct() {
        $this->db = Database::getInstance()->getConnection();
        $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $this->db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
    }
    
    // ---------------------------------------------------------------
    // Obtener capacitaciones filtradas por empresa (case-insensitive)
    // ---------------------------------------------------------------
    public function getCapacitaciones($empresaNombreLogueado) {
        try {
            $sql = "
                SELECT 
                    c.CODIGO, 
                    c.CAPACITACION, 
                    c.empresa_id,
                    e.nombre_empresa
                FROM capacitaciones c
                JOIN empresa e ON c.empresa_id = e.id
                WHERE LOWER(e.nombre_empresa) = LOWER(:nombre_empresa_filtro)
                ORDER BY c.CAPACITACION ASC
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':nombre_empresa_filtro', $empresaNombreLogueado, PDO::PARAM_STR);
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("AsistenciaModel ERROR en getCapacitaciones: " . $e->getMessage());
            return [];
        }
    }

    // ---------------------------------------------------------------
    // Registro de ENTRADA
    // ---------------------------------------------------------------
    public function registrarEntrada($codigo, $capacitacion, $empresaNombreLogueado) {
        try {
            $fecha_actual = date("Y-m-d");

            // Paso 1: Obtener datos del empleado
            $sql = "SELECT CONCAT(nombre, ' ', apellido) as nombre, ccosto, descripcion, cargo, empresa 
                    FROM empleados WHERE cedula = :codigo";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':codigo', $codigo, PDO::PARAM_STR);
            $stmt->execute();
            $empleado = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$empleado) {
                return ['success' => false, 'message' => "Cedula o codigo de barras no existe en la base de datos."];
            }
            
            $empleadoEmpresa = trim($empleado['empresa']);

            // Paso 2: Obtener la empresa de la capacitación
            $sql = "SELECT e.nombre_empresa 
                    FROM capacitaciones c
                    JOIN empresa e ON c.empresa_id = e.id
                    WHERE c.CODIGO = :capacitacion_codigo";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':capacitacion_codigo', $capacitacion, PDO::PARAM_STR);
            $stmt->execute();
            $capacitacionEmpresa = $stmt->fetchColumn();

            if (!$capacitacionEmpresa) {
                return ['success' => false, 'message' => "Capacitación no encontrada o no tiene empresa asignada."];
            }

            $capacitacionEmpresa = trim($capacitacionEmpresa);

            // Validación 1: Empresa del empleado vs empresa de la capacitación
            if (strcasecmp($empleadoEmpresa, $capacitacionEmpresa) !== 0) {
                return ['success' => false, 'message' => "Error de Validación: El empleado de '{$empleadoEmpresa}' no puede registrar asistencia en la capacitación de '{$capacitacionEmpresa}'."];
            }
            
            // Validación 2: Empresa de la capacitación vs empresa del usuario logueado
            if (strcasecmp($capacitacionEmpresa, trim($empresaNombreLogueado)) !== 0) {
                return ['success' => false, 'message' => "Error de Seguridad: La capacitación no pertenece a la empresa '{$empresaNombreLogueado}'. [cap:{$capacitacionEmpresa}]"];
            }
            
            // Paso 3: Verificar duplicados
            $sql = "SELECT id FROM asistencia 
                    WHERE cedula = :codigo 
                    AND capacitacion = :capacitacion 
                    AND DATE(fecha) = :fecha_actual 
                    AND horaSalida IS NULL";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':codigo', $codigo, PDO::PARAM_STR);
            $stmt->bindParam(':capacitacion', $capacitacion, PDO::PARAM_STR);
            $stmt->bindParam(':fecha_actual', $fecha_actual, PDO::PARAM_STR);
            $stmt->execute();

            if ($stmt->rowCount() > 0) {
                return ['success' => false, 'message' => "Ya tiene una ENTRADA pendiente para esta capacitacion hoy."];
            }
            
            // Paso 4: Insertar
            $sql = "INSERT INTO asistencia 
                        (capacitacion, cedula, nombre, ccosto, descripcion, cargo, empresa, fecha, hora, estado) 
                    VALUES 
                        (:capacitacion, :codigo, :nombre, :ccosto, :descripcion, :cargo, :empresa_nombre, CURDATE(), CURTIME(), 0)";
            
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':capacitacion',   $capacitacion,           PDO::PARAM_STR);
            $stmt->bindParam(':codigo',          $codigo,                 PDO::PARAM_STR);
            $stmt->bindParam(':nombre',          $empleado['nombre'],     PDO::PARAM_STR);
            $stmt->bindParam(':ccosto',          $empleado['ccosto'],     PDO::PARAM_STR);
            $stmt->bindParam(':descripcion',     $empleado['descripcion'],PDO::PARAM_STR);
            $stmt->bindParam(':cargo',           $empleado['cargo'],      PDO::PARAM_STR);
            $stmt->bindParam(':empresa_nombre',  $empleado['empresa'],    PDO::PARAM_STR);

            if ($stmt->execute()) {
                return [
                    'success' => true,
                    'message' => "Registro de ENTRADA exitoso para " . $empleado['nombre'],
                    'nombre'  => $empleado['nombre'],
                    'cedula'  => $codigo
                ];
            } else {
                $errorInfo = $stmt->errorInfo();
                return ['success' => false, 'message' => "Error al registrar la asistencia: " . $errorInfo[2]];
            }
        
        } catch (PDOException $e) {
            error_log("PDOException en registrarEntrada: " . $e->getMessage());
            return ['success' => false, 'message' => "Error de Base de Datos: " . $e->getMessage()];
        }
    }

    // ---------------------------------------------------------------
    // Registro de SALIDA
    // ---------------------------------------------------------------
    public function registrarSalida($codigo, $capacitacion, $empresaNombreLogueado) {
        try {
            $fecha_actual = date("Y-m-d");

            // Paso 1: Obtener la empresa de la capacitación
            $sql = "SELECT e.nombre_empresa 
                    FROM capacitaciones c
                    JOIN empresa e ON c.empresa_id = e.id
                    WHERE c.CODIGO = :capacitacion_codigo";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':capacitacion_codigo', $capacitacion, PDO::PARAM_STR);
            $stmt->execute();
            $capacitacionEmpresa = $stmt->fetchColumn();

            if (!$capacitacionEmpresa) {
                return ['success' => false, 'message' => "Capacitación no encontrada o no tiene empresa asignada."];
            }

            $capacitacionEmpresa = trim($capacitacionEmpresa);

            // Validación de seguridad: capacitación debe pertenecer a la empresa logueada
            if (strcasecmp($capacitacionEmpresa, trim($empresaNombreLogueado)) !== 0) {
                return ['success' => false, 'message' => "Error de Seguridad: Esta capacitación pertenece a '{$capacitacionEmpresa}' y no a '{$empresaNombreLogueado}'."];
            }

            // Paso 2: Buscar entrada pendiente
            $sql = "SELECT id, nombre, empresa 
                    FROM asistencia 
                    WHERE cedula = :codigo 
                    AND capacitacion = :capacitacion 
                    AND DATE(fecha) = :fecha_actual 
                    AND horaSalida IS NULL";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':codigo',        $codigo,        PDO::PARAM_STR);
            $stmt->bindParam(':capacitacion',  $capacitacion,  PDO::PARAM_STR);
            $stmt->bindParam(':fecha_actual',  $fecha_actual,  PDO::PARAM_STR);
            $stmt->execute();
            $registro = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$registro) {
                return ['success' => false, 'message' => "No se encontró un registro de ENTRADA pendiente para la cédula $codigo en la capacitación '$capacitacion'."];
            }
            
            // Validación: empleado debe pertenecer a la misma empresa de la capacitación
            if (strcasecmp(trim($registro['empresa']), $capacitacionEmpresa) !== 0) {
                return ['success' => false, 'message' => "Error: El empleado de '{$registro['empresa']}' no pertenece a la empresa '{$capacitacionEmpresa}' de la capacitación."];
            }

            // Paso 3: Registrar salida
            $sql = "UPDATE asistencia SET horaSalida = CURTIME(), estado = 1 WHERE id = :id";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':id', $registro['id'], PDO::PARAM_INT);
            
            if ($stmt->execute()) {
                return [
                    'success' => true,
                    'message' => "Salida registrada correctamente para " . $registro['nombre'],
                    'nombre'  => $registro['nombre'],
                    'cedula'  => $codigo
                ];
            } else {
                $errorInfo = $stmt->errorInfo();
                return ['success' => false, 'message' => "Error al registrar la salida: " . $errorInfo[2]];
            }
        
        } catch (PDOException $e) {
            error_log("PDOException en registrarSalida: " . $e->getMessage());
            return ['success' => false, 'message' => "Error de Base de Datos: " . $e->getMessage()];
        }
    }
    
    // ---------------------------------------------------------------
    // Obtener registros de asistencia para consulta (CON FILTROS)
    // ---------------------------------------------------------------
    // $nombreEmpresa = nombre de la empresa del usuario logueado
    // $verTodos     = boolean para quitar/poner el LIMIT 300
    // $filtros      = array con claves: cedula, capacitacion, fecha_desde, fecha_hasta
    // ---------------------------------------------------------------
    public function getRegistrosAsistencia($nombreEmpresa, $verTodos = false, $filtros = []) {
        try {
            // Construir la consulta base
            $sql = "
                SELECT 
                    id, capacitacion, cedula, nombre, ccosto, 
                    descripcion, cargo, empresa, fecha, hora, horaSalida, estado,
                    CASE 
                        WHEN estado = 0 THEN 'Pendiente por salida'
                        WHEN estado = 1 THEN 'Salida Registrada'
                        ELSE 'Estado desconocido'
                    END as estado_texto
                FROM asistencia 
                WHERE LOWER(empresa) = LOWER(:nombre_empresa_filtro)
            ";

            // --- Agregar filtros dinámicos ---
            $params = [':nombre_empresa_filtro' => $nombreEmpresa];

            // Filtro por Cédula
            if (!empty($filtros['cedula'])) {
                $sql .= " AND cedula LIKE :cedula";
                $params[':cedula'] = '%' . $filtros['cedula'] . '%';
            }

            // Filtro por Capacitación
            if (!empty($filtros['capacitacion'])) {
                $sql .= " AND capacitacion = :capacitacion";
                $params[':capacitacion'] = $filtros['capacitacion'];
            }

            // Filtro por Fecha Desde
            if (!empty($filtros['fecha_desde'])) {
                $sql .= " AND DATE(fecha) >= :fecha_desde";
                $params[':fecha_desde'] = $filtros['fecha_desde'];
            }

            // Filtro por Fecha Hasta
            if (!empty($filtros['fecha_hasta'])) {
                $sql .= " AND DATE(fecha) <= :fecha_hasta";
                $params[':fecha_hasta'] = $filtros['fecha_hasta'];
            }

            // Ordenamiento
            $sql .= " ORDER BY id DESC";

            // Límite
            if (!$verTodos) {
                $sql .= " LIMIT 300";
            }

            // Preparar y ejecutar
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        } catch (PDOException $e) {
            error_log("AsistenciaModel ERROR en getRegistrosAsistencia: " . $e->getMessage());
            return [];
        }
    }
}