34849-vm/hr_evaluaciones.php
2026-06-24 21:44:23 +00:00

332 lines
15 KiB
PHP

<?php
session_start();
$userRole = $_SESSION['user_role'] ?? '';
if (!isset($_SESSION['user_id']) || ($userRole !== 'Administrador' && $userRole !== 'admin')) {
header('Location: dashboard.php');
exit;
}
require_once 'db/config.php';
$pdo = db();
$schemaInitError = null;
require_once 'includes/hr_bootstrap.php';
try {
hr_ensure_schema($pdo);
} catch (Throwable $e) {
$schemaInitError = $e->getMessage();
}
$pageTitle = "Recursos Humanos - Evaluaciones";
$pageDescription = "Registro de evaluaciones internas y seguimiento del desempeño del personal.";
$areasValidas = ['Ventas', 'Almacén', 'Marketing', 'Administración', 'Finanzas', 'Gerencia'];
$resultadosValidos = ['Aprobado', 'En Capacitación', 'Requiere Seguimiento'];
$notice = null;
$noticeType = 'success';
if (!empty($schemaInitError)) {
$notice = 'Error al preparar las tablas de Recursos Humanos.';
$noticeType = 'danger';
error_log('HR schema init error (evaluaciones): ' . $schemaInitError);
}
if (isset($_GET['success']) && $_GET['success'] === '1') {
$notice = 'Evaluación guardada correctamente.';
$noticeType = 'success';
}
// Lista de colaboradores para los selects
$colaboradores = [];
try {
$stmt = $pdo->query('SELECT id, nombre_completo, area FROM hr_colaboradores ORDER BY nombre_completo ASC');
$colaboradores = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$colaboradores = [];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
if ($action === 'add_evaluacion') {
try {
$colaborador_id = (int)($_POST['colaborador_id'] ?? 0);
$fecha = $_POST['fecha'] ?? date('Y-m-d');
$tipo_evaluacion = trim((string)($_POST['tipo_evaluacion'] ?? ''));
$puntaje = (int)($_POST['puntaje'] ?? 0);
$resultado = (string)($_POST['resultado'] ?? '');
$observaciones = trim((string)($_POST['observaciones'] ?? ''));
if ($colaborador_id <= 0) {
throw new RuntimeException('Selecciona un colaborador.');
}
if ($tipo_evaluacion === '') {
throw new RuntimeException('Tipo de evaluación es obligatorio.');
}
if (!in_array($resultado, $resultadosValidos, true)) {
throw new RuntimeException('Resultado inválido.');
}
// Traer área del colaborador para guardarla en el registro
$stmtArea = $pdo->prepare('SELECT area FROM hr_colaboradores WHERE id = ? LIMIT 1');
$stmtArea->execute([$colaborador_id]);
$areaRow = $stmtArea->fetch(PDO::FETCH_ASSOC);
if (!$areaRow || empty($areaRow['area'])) {
throw new RuntimeException('No se encontró el área del colaborador.');
}
$area = (string)$areaRow['area'];
if (!in_array($area, $areasValidas, true)) {
// Seguridad extra
throw new RuntimeException('Área inválida en el colaborador.');
}
$stmt = $pdo->prepare('INSERT INTO hr_evaluaciones (colaborador_id, area, fecha, tipo_evaluacion, puntaje, resultado, observaciones) VALUES (?, ?, ?, ?, ?, ?, ?)');
$stmt->execute([
$colaborador_id,
$area,
$fecha,
$tipo_evaluacion,
$puntaje,
$resultado,
$observaciones,
]);
header('Location: hr_evaluaciones.php?success=1');
exit;
} catch (Throwable $e) {
$notice = 'No se pudo guardar la evaluación: ' . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
$noticeType = 'danger';
}
}
}
// --- Filtros de listado ---
$f_colaborador = (int)($_GET['colaborador_id'] ?? 0);
$f_resultado = (string)($_GET['resultado'] ?? 'Todos');
$f_fecha_desde = trim((string)($_GET['fecha_desde'] ?? ''));
$f_fecha_hasta = trim((string)($_GET['fecha_hasta'] ?? ''));
if ($f_resultado !== 'Todos' && !in_array($f_resultado, $resultadosValidos, true)) {
$f_resultado = 'Todos';
}
$where = [];
$params = [];
if ($f_colaborador > 0) {
$where[] = 'e.colaborador_id = ?';
$params[] = $f_colaborador;
}
if ($f_resultado !== 'Todos') {
$where[] = 'e.resultado = ?';
$params[] = $f_resultado;
}
if ($f_fecha_desde !== '') {
$where[] = 'e.fecha >= ?';
$params[] = $f_fecha_desde;
}
if ($f_fecha_hasta !== '') {
$where[] = 'e.fecha <= ?';
$params[] = $f_fecha_hasta;
}
$sql = 'SELECT e.id, e.fecha, e.tipo_evaluacion, e.puntaje, e.resultado, e.area, e.observaciones, c.nombre_completo, c.dni FROM hr_evaluaciones e LEFT JOIN hr_colaboradores c ON c.id = e.colaborador_id';
if (!empty($where)) {
$sql .= ' WHERE ' . implode(' AND ', $where);
}
$sql .= ' ORDER BY e.fecha DESC, e.id DESC';
$evaluaciones = [];
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$evaluaciones = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log('HR Evaluaciones DB error: ' . $e->getMessage());
$notice = 'No se pudo cargar el listado de evaluaciones.';
$noticeType = 'danger';
}
$fechaHoy = date('Y-m-d');
include 'layout_header.php';
?>
<div class="container-fluid mt-4">
<?php if ($notice): ?>
<div class="alert alert-<?= htmlspecialchars($noticeType, ENT_QUOTES, 'UTF-8'); ?> mb-4" role="alert">
<?= $notice; ?>
</div>
<?php endif; ?>
<div class="row g-4">
<div class="col-lg-4">
<div class="card shadow-sm">
<div class="card-header bg-light">
<h2 class="h5 mb-0">Nueva Evaluación</h2>
</div>
<div class="card-body">
<?php if (empty($colaboradores)): ?>
<div class="alert alert-warning">
Primero agrega colaboradores en <b>Colaboradores</b>.
</div>
<?php else: ?>
<form method="POST">
<input type="hidden" name="action" value="add_evaluacion">
<div class="mb-3">
<label class="form-label">Colaborador</label>
<select name="colaborador_id" class="form-select" required>
<?php foreach ($colaboradores as $c): ?>
<option value="<?= (int)$c['id']; ?>">
<?= htmlspecialchars($c['nombre_completo'] ?? '', ENT_QUOTES, 'UTF-8'); ?>
(<?= htmlspecialchars($c['area'] ?? '', ENT_QUOTES, 'UTF-8'); ?>)
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Fecha</label>
<input type="date" name="fecha" class="form-control" value="<?= htmlspecialchars($fechaHoy, ENT_QUOTES, 'UTF-8'); ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Tipo de Evaluación</label>
<input type="text" name="tipo_evaluacion" class="form-control" placeholder="Ej: Evaluación Mensual" required>
</div>
<div class="mb-3">
<label class="form-label">Puntaje</label>
<input type="number" name="puntaje" class="form-control" value="0" min="0" required>
</div>
<div class="mb-3">
<label class="form-label">Resultado</label>
<select name="resultado" class="form-select" required>
<?php foreach ($resultadosValidos as $r): ?>
<option value="<?= htmlspecialchars($r, ENT_QUOTES, 'UTF-8'); ?>">
<?= htmlspecialchars($r, ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Observaciones</label>
<textarea name="observaciones" class="form-control" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary w-100">
<i class="fas fa-save me-1"></i> Guardar
</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
<div class="col-lg-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<h2 class="h5 mb-0">Evaluaciones</h2>
<span class="badge bg-secondary">Total: <?= count($evaluaciones); ?></span>
</div>
<div class="card-body">
<form method="GET" class="row g-2 align-items-end">
<div class="col-sm-5">
<label class="form-label">Colaborador</label>
<select name="colaborador_id" class="form-select">
<option value="0">Todos</option>
<?php foreach ($colaboradores as $c): ?>
<option value="<?= (int)$c['id']; ?>" <?= $f_colaborador === (int)$c['id'] ? 'selected' : ''; ?>>
<?= htmlspecialchars($c['nombre_completo'] ?? '', ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-sm-3">
<label class="form-label">Resultado</label>
<select name="resultado" class="form-select">
<option value="Todos" <?= $f_resultado === 'Todos' ? 'selected' : ''; ?>>Todos</option>
<?php foreach ($resultadosValidos as $r): ?>
<option value="<?= htmlspecialchars($r, ENT_QUOTES, 'UTF-8'); ?>" <?= $f_resultado === $r ? 'selected' : ''; ?>>
<?= htmlspecialchars($r, ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-sm-2">
<label class="form-label">Desde</label>
<input type="date" name="fecha_desde" class="form-control" value="<?= htmlspecialchars($f_fecha_desde, ENT_QUOTES, 'UTF-8'); ?>">
</div>
<div class="col-sm-2">
<label class="form-label">Hasta</label>
<input type="date" name="fecha_hasta" class="form-control" value="<?= htmlspecialchars($f_fecha_hasta, ENT_QUOTES, 'UTF-8'); ?>">
</div>
<div class="col-12 d-flex justify-content-end gap-2 mt-2">
<a class="btn btn-outline-secondary" href="hr_evaluaciones.php">Limpiar</a>
<button class="btn btn-primary" type="submit">
<i class="fas fa-filter me-1"></i> Filtrar
</button>
</div>
</form>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped align-middle">
<thead class="table-light">
<tr>
<th>ID</th>
<th>Colaborador</th>
<th>Área</th>
<th>Fecha</th>
<th>Tipo</th>
<th>Puntaje</th>
<th>Resultado</th>
<th>Observaciones</th>
</tr>
</thead>
<tbody>
<?php if (empty($evaluaciones)): ?>
<tr>
<td colspan="8" class="text-center py-4 text-muted">No hay evaluaciones para los filtros seleccionados.</td>
</tr>
<?php else: ?>
<?php foreach ($evaluaciones as $e): ?>
<tr>
<td><?= (int)$e['id']; ?></td>
<td>
<?= htmlspecialchars($e['nombre_completo'] ?? '', ENT_QUOTES, 'UTF-8'); ?>
<?php if (!empty($e['dni'])): ?>
<div class="text-muted small">DNI: <?= htmlspecialchars($e['dni'], ENT_QUOTES, 'UTF-8'); ?></div>
<?php endif; ?>
</td>
<td><span class="badge bg-primary"><?= htmlspecialchars($e['area'] ?? '', ENT_QUOTES, 'UTF-8'); ?></span></td>
<td><?= htmlspecialchars($e['fecha'] ?? '', ENT_QUOTES, 'UTF-8'); ?></td>
<td><?= htmlspecialchars($e['tipo_evaluacion'] ?? '', ENT_QUOTES, 'UTF-8'); ?></td>
<td><b><?= (int)($e['puntaje'] ?? 0); ?></b></td>
<td>
<span class="badge bg-info text-dark">
<?= htmlspecialchars($e['resultado'] ?? '', ENT_QUOTES, 'UTF-8'); ?>
</span>
</td>
<td style="max-width: 260px;">
<div style="white-space: pre-wrap;"><?= htmlspecialchars($e['observaciones'] ?? '', ENT_QUOTES, 'UTF-8'); ?></div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php include 'layout_footer.php'; ?>