diff --git a/public/admin/asignaciones.php b/public/admin/asignaciones.php old mode 100755 new mode 100644 index 97d4b60..aef4bd6 --- a/public/admin/asignaciones.php +++ b/public/admin/asignaciones.php @@ -24,6 +24,11 @@ if (isset($_GET['success']) && $_GET['success'] === 'orden_actualizado') { $messageType = 'success'; } +if (isset($_GET['success']) && $_GET['success'] === 'automatica') { + $message = 'Turnos generados automáticamente correctamente.'; + $messageType = 'success'; +} + if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!CSRF::isValidRequest()) { $message = 'Error de validación del formulario'; @@ -31,527 +36,246 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } else { $action = $_POST['action'] ?? ''; - if ($action === 'asignar') { + if ($action === 'asignar_actual') { $userId = $_POST['user_id'] ?? 0; - $semana = $_POST['semana'] ?? ''; - - if ($userId && $semana) { - $asignacionModel->asignar($userId, $semana); - $message = 'Turno asignado correctamente'; - $messageType = 'success'; - } - } elseif ($action === 'rotar') { - $semana = $_POST['semana'] ?? ''; - $asignacionActual = $asignacionModel->getAsignacionPorSemana($semana); - if ($asignacionActual) { - $proximaPersona = $asignacionModel->getProximaPersona($asignacionActual['user_id']); - if ($proximaPersona) { - $asignacionModel->asignar($proximaPersona['id'], $semana); - $message = 'Turno rotado a: ' . htmlspecialchars($proximaPersona['nombre']); - $messageType = 'success'; - } + // Encontrar el domingo actual + $hoy = new DateTime(); + $diaSemana = (int)$hoy->format('w'); + $domingoActual = clone $hoy; + $domingoActual->modify('-' . $diaSemana . ' days'); + $currentWeekStart = $domingoActual->format('Y-m-d'); + + if ($userId) { + $asignacionModel->asignar($userId, $currentWeekStart); + $message = 'Turno actual asignado correctamente'; + $messageType = 'success'; + header("Location: " . $_SERVER['PHP_SELF'] . "?success=actual"); + exit; } - } elseif ($action === 'rotacion_automatica') { + } elseif ($action === 'rotar_automatica') { $resultado = $asignacionModel->asignarSemanasFuturasAutomaticas(12); if ($resultado['success'] > 0) { - $message = "Se generaron {$resultado['success']} semanas futuras correctamente"; - if (!empty($resultado['errors'])) { - $message .= ". Errores: " . implode(', ', $resultado['errors']); - $messageType = 'warning'; - } else { - $messageType = 'success'; - } + header("Location: " . $_SERVER['PHP_SELF'] . "?success=automatica"); + exit; } else { - $message = 'No se pudieron generar asignaciones: ' . implode(', ', $resultado['errors']); - $messageType = 'danger'; - } - } elseif ($action === 'asignar_masivo') { - $userIds = $_POST['user_ids'] ?? []; - $semanaInicio = $_POST['semana_inicio'] ?? ''; - $rotacionAutomatica = isset($_POST['rotacion_automatica']) ? true : false; - - if (!empty($userIds) && $semanaInicio) { - $resultado = $asignacionModel->asignarMasivo($userIds, $semanaInicio, $rotacionAutomatica); - - if ($resultado['success'] > 0) { - $message = "Se asignaron {$resultado['success']} turnos correctamente"; - if ($rotacionAutomatica) { - $message .= " con rotación automática para la siguiente semana"; - } - $messageType = 'success'; - } - - if (!empty($resultado['errors'])) { - $message .= "
Errores: " . implode('
', $resultado['errors']); - $messageType = 'warning'; - } - } else { - $message = 'Debes seleccionar al menos un ayudante y una semana'; + $message = 'No se pudieron generar turnos: ' . implode(', ', $resultado['errors']); $messageType = 'danger'; } } } } -$ayudantes = $userModel->getAyudantesActivos(); -$horarios = $horariosModel->getActivos(); - -// Encontrar el domingo actual +// Obtener datos principales $hoy = new DateTime(); -$diaSemana = (int)$hoy->format('w'); // 0 = domingo, 6 = sábado +$diaSemana = (int)$hoy->format('w'); $domingoActual = clone $hoy; -$domingoActual->modify('-' . $diaSemana . ' days'); // Restar días para llegar al domingo - +$domingoActual->modify('-' . $diaSemana . ' days'); $currentWeekStart = $domingoActual->format('Y-m-d'); + $asignacionActual = $asignacionModel->getAsignacionPorSemana($currentWeekStart); +$ayudantes = $userModel->getAyudantesActivos(); -// Calcular posición en el ciclo (semana X de 4) -function calcularPosicionCiclo($semanaInicio) { - // Empezamos desde el inicio del ciclo: 28 Dic 2025 - $fechaInicioCiclo = new DateTime('2025-12-28'); - $semanaActual = new DateTime($semanaInicio); - - $diasDiferencia = $fechaInicioCiclo->diff($semanaActual)->days; - $semanasDesdeInicio = floor($diasDiferencia / 7); - - // Posición en ciclo de 4 semanas (1-4) - $posicion = ($semanasDesdeInicio % 4) + 1; - - return $posicion; -} - -$posicionCicloActual = calcularPosicionCiclo($currentWeekStart); - -// Generar semanas agrupadas por mes -$mesesEspanol = [ - 'January' => 'Enero', 'February' => 'Febrero', 'March' => 'Marzo', - 'April' => 'Abril', 'May' => 'Mayo', 'June' => 'Junio', - 'July' => 'Julio', 'August' => 'Agosto', 'September' => 'Septiembre', - 'October' => 'Octubre', 'November' => 'Noviembre', 'December' => 'Diciembre' -]; - -$semanasAgrupadas = []; -for ($i = -4; $i <= 12; $i++) { +// Obtener próximos turnos (siguientes 3 semanas) +$proximosTurnos = []; +for ($i = 1; $i <= 3; $i++) { $semanaDomingo = clone $domingoActual; $semanaDomingo->modify("+{$i} weeks"); + $semanaInicio = $semanaDomingo->format('Y-m-d'); + $asignacion = $asignacionModel->getAsignacionPorSemana($semanaInicio); - $key = $semanaDomingo->format('Y-m'); - $mesIngles = $semanaDomingo->format('F'); - $mesEspanol = $mesesEspanol[$mesIngles] ?? $mesIngles; - $anio = $semanaDomingo->format('Y'); - - if (!isset($semanasAgrupadas[$key])) { - $semanasAgrupadas[$key] = [ - 'nombre' => "$mesEspanol $anio", - 'semanas' => [] - ]; - } - $semanasAgrupadas[$key]['semanas'][] = [ - 'fecha' => $semanaDomingo->format('Y-m-d'), - 'posicion' => calcularPosicionCiclo($semanaDomingo->format('Y-m-d')) + $proximosTurnos[] = [ + 'semana' => $semanaInicio, + 'fin' => date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))), + 'asignacion' => $asignacion ]; } $currentPage = 'asignaciones'; -$pageTitle = 'Asignación de Turnos'; +$pageTitle = 'Gestión de Turnos'; ?> - Asignaciones - Contenedor Ibiza + Turnos - Contenedor Ibiza - +
-

Asignación de Turnos

+
+

📅 Gestión de Turnos

+ + ⚙️ Vista Avanzada + +
-
+
+ + +
+
-
-
-
-
Asignación Actual (Semana de 4)
+
+
+
+
📍 Turno Actual
-

- Fecha: (Dom) - (Vie) -

- - -
- Asignado a: +
+
+

+ 📆 Semana: + + al +

+ + +
+
✅ Asignado a:
+ +
+ +
+
⚠️ Sin asignar
+ No hay ayudante asignado esta semana +
+
-
- - - - -
- -
No hay asignación para esta semana
- -
- - - -
- - + + -
- -
- + + + +
+
- -
-
-
-
Historial de Asignaciones
-
-
-
- -
- - -
-
+
- getAsignacionPorSemana($semanaVer); - ?> - - -
- - Semana de 4 (): - + +
+
+
+
+
⚡ Acciones Rápidas
+
+
+
+
+
+
🔄 Generar Turnos Automáticos
+

Crea automáticamente las próximas 12 semanas siguiendo el orden actual

+
+ + + +
+
-
- - - - - -
- -
- -No hay asignación para la semana de 4 () -
- -
- - -
- - -
-
- -
-
-
- - -
-
-
Asignación Masiva
-
-
-
- - - -
-
- - - Debe ser un domingo -
-
- -
- - +
+
+
👥 Gestionar Orden
+

Modifica el orden de rotación de los ayudantes

+ + ⚙️ Orden de Rotación + +
- -
- -
- - - - - - - - - - - - - - - - - - - -
- - NombreEmailUsername
- -
-
-
- -
- - - -
- +
- -
-
-
Rotación Automática
-
-
-
-
-
Orden de Rotación Actual:
-
- getAyudantesPorOrden(); - foreach ($ayudantesOrdenados as $index => $ayudante): - ?> - - . - + +
+
+
+
+
📋 Próximos Turnos
+
+
+
+ $turno): ?> +
+
+
+
+ 📅 - + +
+ + +
+ +
+ +
+ ⚠️ Sin asignar +
+ + + + Modificar + +
+
+
- -
-
-
- - - - - Asigna automáticamente los próximos 12 semanas siguiendo el orden de rotación - -
+
- -
- ℹ️ ¿Cómo funciona?
- • El sistema mantiene un orden cíclico de ayudantes
- • Cada semana (Dom→Vie) asigna automáticamente al siguiente en la lista
- • Al agregar nuevos ayudantes, se integran automáticamente en el ciclo
- • Usa el botón para generar las próximas 12 semanas -
-
-
- - -
-
-
Reordenar Rotación
-
-
-
- - - -

- Arrastra los elementos para cambiar el orden de rotación. - Los cambios afectarán las asignaciones futuras. -

- -
    - getAyudantesPorOrden(); - foreach ($ayudantesOrdenados as $index => $ayudante): - ?> -
  • - - - -
  • - -
- -
- - -
-
- - - $userId) { - $stmt = $asignacionModel->getDb()->prepare(" - UPDATE rotacion_orden - SET orden = ? - WHERE user_id = ? AND activo = 1 - "); - $stmt->execute([$index + 1, $userId]); - } - - // Recalcular asignaciones futuras - $resultado = $asignacionModel->recalcularAsignaciones(20); - - if ($resultado['success'] > 0) { - // Redireccionar para recargar los datos actualizados - header("Location: " . $_SERVER['PHP_SELF'] . "?success=orden_actualizado"); - exit; - } - } - ?> -
- - - - + \ No newline at end of file diff --git a/public/admin/asignaciones_completo.php b/public/admin/asignaciones_completo.php new file mode 100755 index 0000000..97d4b60 --- /dev/null +++ b/public/admin/asignaciones_completo.php @@ -0,0 +1,557 @@ +requireAdmin(); + +$userModel = new User(); +$horariosModel = new DiasHorarios(); +$asignacionModel = new Asignacion(); + +$message = ''; +$messageType = ''; + +if (isset($_GET['success']) && $_GET['success'] === 'orden_actualizado') { + $message = 'Orden actualizado correctamente. Se recalcularon las asignaciones futuras.'; + $messageType = 'success'; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (!CSRF::isValidRequest()) { + $message = 'Error de validación del formulario'; + $messageType = 'danger'; + } else { + $action = $_POST['action'] ?? ''; + + if ($action === 'asignar') { + $userId = $_POST['user_id'] ?? 0; + $semana = $_POST['semana'] ?? ''; + + if ($userId && $semana) { + $asignacionModel->asignar($userId, $semana); + $message = 'Turno asignado correctamente'; + $messageType = 'success'; + } + } elseif ($action === 'rotar') { + $semana = $_POST['semana'] ?? ''; + $asignacionActual = $asignacionModel->getAsignacionPorSemana($semana); + + if ($asignacionActual) { + $proximaPersona = $asignacionModel->getProximaPersona($asignacionActual['user_id']); + if ($proximaPersona) { + $asignacionModel->asignar($proximaPersona['id'], $semana); + $message = 'Turno rotado a: ' . htmlspecialchars($proximaPersona['nombre']); + $messageType = 'success'; + } + } + } elseif ($action === 'rotacion_automatica') { + $resultado = $asignacionModel->asignarSemanasFuturasAutomaticas(12); + + if ($resultado['success'] > 0) { + $message = "Se generaron {$resultado['success']} semanas futuras correctamente"; + if (!empty($resultado['errors'])) { + $message .= ". Errores: " . implode(', ', $resultado['errors']); + $messageType = 'warning'; + } else { + $messageType = 'success'; + } + } else { + $message = 'No se pudieron generar asignaciones: ' . implode(', ', $resultado['errors']); + $messageType = 'danger'; + } + } elseif ($action === 'asignar_masivo') { + $userIds = $_POST['user_ids'] ?? []; + $semanaInicio = $_POST['semana_inicio'] ?? ''; + $rotacionAutomatica = isset($_POST['rotacion_automatica']) ? true : false; + + if (!empty($userIds) && $semanaInicio) { + $resultado = $asignacionModel->asignarMasivo($userIds, $semanaInicio, $rotacionAutomatica); + + if ($resultado['success'] > 0) { + $message = "Se asignaron {$resultado['success']} turnos correctamente"; + if ($rotacionAutomatica) { + $message .= " con rotación automática para la siguiente semana"; + } + $messageType = 'success'; + } + + if (!empty($resultado['errors'])) { + $message .= "
Errores: " . implode('
', $resultado['errors']); + $messageType = 'warning'; + } + } else { + $message = 'Debes seleccionar al menos un ayudante y una semana'; + $messageType = 'danger'; + } + } + } +} + +$ayudantes = $userModel->getAyudantesActivos(); +$horarios = $horariosModel->getActivos(); + +// Encontrar el domingo actual +$hoy = new DateTime(); +$diaSemana = (int)$hoy->format('w'); // 0 = domingo, 6 = sábado +$domingoActual = clone $hoy; +$domingoActual->modify('-' . $diaSemana . ' days'); // Restar días para llegar al domingo + +$currentWeekStart = $domingoActual->format('Y-m-d'); +$asignacionActual = $asignacionModel->getAsignacionPorSemana($currentWeekStart); + +// Calcular posición en el ciclo (semana X de 4) +function calcularPosicionCiclo($semanaInicio) { + // Empezamos desde el inicio del ciclo: 28 Dic 2025 + $fechaInicioCiclo = new DateTime('2025-12-28'); + $semanaActual = new DateTime($semanaInicio); + + $diasDiferencia = $fechaInicioCiclo->diff($semanaActual)->days; + $semanasDesdeInicio = floor($diasDiferencia / 7); + + // Posición en ciclo de 4 semanas (1-4) + $posicion = ($semanasDesdeInicio % 4) + 1; + + return $posicion; +} + +$posicionCicloActual = calcularPosicionCiclo($currentWeekStart); + +// Generar semanas agrupadas por mes +$mesesEspanol = [ + 'January' => 'Enero', 'February' => 'Febrero', 'March' => 'Marzo', + 'April' => 'Abril', 'May' => 'Mayo', 'June' => 'Junio', + 'July' => 'Julio', 'August' => 'Agosto', 'September' => 'Septiembre', + 'October' => 'Octubre', 'November' => 'Noviembre', 'December' => 'Diciembre' +]; + +$semanasAgrupadas = []; +for ($i = -4; $i <= 12; $i++) { + $semanaDomingo = clone $domingoActual; + $semanaDomingo->modify("+{$i} weeks"); + + $key = $semanaDomingo->format('Y-m'); + $mesIngles = $semanaDomingo->format('F'); + $mesEspanol = $mesesEspanol[$mesIngles] ?? $mesIngles; + $anio = $semanaDomingo->format('Y'); + + if (!isset($semanasAgrupadas[$key])) { + $semanasAgrupadas[$key] = [ + 'nombre' => "$mesEspanol $anio", + 'semanas' => [] + ]; + } + $semanasAgrupadas[$key]['semanas'][] = [ + 'fecha' => $semanaDomingo->format('Y-m-d'), + 'posicion' => calcularPosicionCiclo($semanaDomingo->format('Y-m-d')) + ]; +} + +$currentPage = 'asignaciones'; +$pageTitle = 'Asignación de Turnos'; +?> + + + + + + Asignaciones - Contenedor Ibiza + + + + + + +
+

Asignación de Turnos

+ + +
+ + +
+
+
+
+
Asignación Actual (Semana de 4)
+
+
+

+ Fecha: (Dom) - (Vie) +

+ + +
+ Asignado a: +
+ +
+ + + + +
+ +
No hay asignación para esta semana
+ +
+ + + +
+ + +
+ +
+ +
+
+
+ +
+
+
+
Historial de Asignaciones
+
+
+
+ +
+ + +
+
+ + getAsignacionPorSemana($semanaVer); + ?> + + +
+ + Semana de 4 (): + +
+ +
+ + + + + +
+ +
+ +No hay asignación para la semana de 4 () +
+ +
+ + +
+ + +
+
+ +
+
+
+ + +
+
+
Asignación Masiva
+
+
+
+ + + +
+
+ + + Debe ser un domingo +
+
+ +
+ + +
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ + NombreEmailUsername
+ +
+
+
+ +
+ + + +
+
+
+
+ + +
+
+
Rotación Automática
+
+
+
+
+
Orden de Rotación Actual:
+
+ getAyudantesPorOrden(); + foreach ($ayudantesOrdenados as $index => $ayudante): + ?> + + . + + +
+ + +
+
+
+ + + + + Asigna automáticamente los próximos 12 semanas siguiendo el orden de rotación + +
+
+
+ +
+ ℹ️ ¿Cómo funciona?
+ • El sistema mantiene un orden cíclico de ayudantes
+ • Cada semana (Dom→Vie) asigna automáticamente al siguiente en la lista
+ • Al agregar nuevos ayudantes, se integran automáticamente en el ciclo
+ • Usa el botón para generar las próximas 12 semanas +
+
+
+ + +
+
+
Reordenar Rotación
+
+
+
+ + + +

+ Arrastra los elementos para cambiar el orden de rotación. + Los cambios afectarán las asignaciones futuras. +

+ +
    + getAyudantesPorOrden(); + foreach ($ayudantesOrdenados as $index => $ayudante): + ?> +
  • + + + +
  • + +
+ +
+ + +
+
+ + + $userId) { + $stmt = $asignacionModel->getDb()->prepare(" + UPDATE rotacion_orden + SET orden = ? + WHERE user_id = ? AND activo = 1 + "); + $stmt->execute([$index + 1, $userId]); + } + + // Recalcular asignaciones futuras + $resultado = $asignacionModel->recalcularAsignaciones(20); + + if ($resultado['success'] > 0) { + // Redireccionar para recargar los datos actualizados + header("Location: " . $_SERVER['PHP_SELF'] . "?success=orden_actualizado"); + exit; + } + } + ?> + +
+
+
+ + + + + + + diff --git a/public/ayudante.php b/public/ayudante.php index eda60af..977b558 100755 --- a/public/ayudante.php +++ b/public/ayudante.php @@ -1,17 +1,17 @@ requireAuth(); -if ($auth->isAdmin()) { - header('Location: /admin/index.php'); - exit; -} +// Permitir acceso a administradores para que puedan ver la vista de ayudante $user = $auth->getCurrentUser(); $horariosModel = new DiasHorarios(); @@ -72,23 +72,45 @@ $domingo->modify('-' . (int)$domingo->format('w') . ' days'); - + isAdmin()) { + include BASE_PATH . '/public/partials/navbar.php'; + } else { + // Si es ayudante, usar navbar simple + ?> + +
-

Mis Turnos

- - 📄 Exportar PDF - +
+ isAdmin()): ?> +

👥 Vista de Ayudante

+

Viendo la interfaz que ven los ayudantes

+ +

Mis Turnos

+ +
+
Asignaciones +