Primer subida completa
This commit is contained in:
384
src/Asignacion.php
Executable file
384
src/Asignacion.php
Executable file
@@ -0,0 +1,384 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/Database.php';
|
||||
|
||||
class Asignacion {
|
||||
private $db;
|
||||
|
||||
public function __construct() {
|
||||
$this->db = Database::getInstance()->getConnection();
|
||||
}
|
||||
|
||||
public function getAsignacionActual() {
|
||||
$currentWeekStart = date('Y-m-d', strtotime('monday this week'));
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT u.*, a.semana_inicio
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
WHERE a.semana_inicio = ?
|
||||
");
|
||||
$stmt->execute([$currentWeekStart]);
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
public function getAsignacionPorSemana($semanaInicio) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT u.*, a.semana_inicio, a.semana_fin, a.id as asignacion_id
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
WHERE a.semana_inicio = ?
|
||||
ORDER BY a.orden_turno ASC
|
||||
LIMIT 1
|
||||
");
|
||||
$stmt->execute([$semanaInicio]);
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
public function getTodasAsignaciones() {
|
||||
$stmt = $this->db->query("
|
||||
SELECT u.nombre, a.*
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
ORDER BY a.semana_inicio DESC
|
||||
LIMIT 20
|
||||
");
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
public function asignar($userId, $semanaInicio) {
|
||||
$semanaFin = date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))); // Domingo a viernes
|
||||
$ordenTurno = $this->getOrdenTurno($userId);
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO asignaciones_turnos (user_id, semana_inicio, semana_fin, orden_turno)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), semana_fin = VALUES(semana_fin), orden_turno = VALUES(orden_turno)
|
||||
");
|
||||
return $stmt->execute([$userId, $semanaInicio, $semanaFin, $ordenTurno]);
|
||||
}
|
||||
|
||||
private function getOrdenTurno($userId) {
|
||||
$stmt = $this->db->prepare("SELECT orden FROM rotacion_orden WHERE user_id = ? AND activo = 1");
|
||||
$stmt->execute([$userId]);
|
||||
$result = $stmt->fetch();
|
||||
return $result ? $result['orden'] : 999;
|
||||
}
|
||||
|
||||
public function getProximaPersona($userIdActual = null) {
|
||||
$sql = "SELECT * FROM users WHERE rol = 'ayudante' AND activo = 1 ORDER BY id";
|
||||
if ($userIdActual) {
|
||||
$stmt = $this->db->query($sql);
|
||||
$ayudantes = $stmt->fetchAll();
|
||||
|
||||
$encontrado = false;
|
||||
foreach ($ayudantes as $a) {
|
||||
if ($encontrado) return $a;
|
||||
if ($a['id'] == $userIdActual) $encontrado = true;
|
||||
}
|
||||
return $ayudantes[0] ?? null;
|
||||
}
|
||||
$stmt = $this->db->query($sql);
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
public function asignarMasivo($userIds, $semanaInicio, $rotacionAutomatica = false) {
|
||||
$resultados = [];
|
||||
$errores = [];
|
||||
|
||||
foreach ($userIds as $index => $userId) {
|
||||
try {
|
||||
$semanaFin = date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))); // Domingo a viernes
|
||||
$ordenTurno = $this->getOrdenTurno($userId);
|
||||
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO asignaciones_turnos (user_id, semana_inicio, semana_fin, orden_turno)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), semana_fin = VALUES(semana_fin), orden_turno = VALUES(orden_turno)
|
||||
");
|
||||
|
||||
$success = $stmt->execute([$userId, $semanaInicio, $semanaFin, $ordenTurno]);
|
||||
|
||||
if ($success) {
|
||||
$resultados[] = [
|
||||
'user_id' => $userId,
|
||||
'semana' => $semanaInicio,
|
||||
'rotar_siguiente' => $rotacionAutomatica && $index === count($userIds) - 1
|
||||
];
|
||||
|
||||
// Si es el último usuario y se activó rotación automática
|
||||
if ($rotacionAutomatica && $index === count($userIds) - 1) {
|
||||
$this->asignarSiguienteSemana($userId, $semanaInicio);
|
||||
}
|
||||
} else {
|
||||
$errores[] = "Error al asignar usuario ID: $userId";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errores[] = "Error usuario ID $userId: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => count($resultados),
|
||||
'errors' => $errores,
|
||||
'resultados' => $resultados
|
||||
];
|
||||
}
|
||||
|
||||
private function asignarSiguienteSemana($ultimoUserId, $semanaActual) {
|
||||
$siguienteSemana = date('Y-m-d', strtotime('+1 week', strtotime($semanaActual)));
|
||||
$siguientePersona = $this->getProximaPersona($ultimoUserId);
|
||||
|
||||
if ($siguientePersona) {
|
||||
$semanaFin = date('Y-m-d', strtotime('+5 days', strtotime($siguienteSemana))); // Domingo a viernes
|
||||
$ordenTurno = $this->getOrdenTurno($siguientePersona['id']);
|
||||
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO asignaciones_turnos (user_id, semana_inicio, semana_fin, orden_turno)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), semana_fin = VALUES(semana_fin), orden_turno = VALUES(orden_turno)
|
||||
");
|
||||
|
||||
return $stmt->execute([$siguientePersona['id'], $siguienteSemana, $semanaFin, $ordenTurno]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function asignarSemanasFuturasAutomaticas($semanasFuturas = 12) {
|
||||
$resultados = [];
|
||||
$errores = [];
|
||||
|
||||
// Obtener todos los ayudantes en orden de rotación
|
||||
$ayudantesOrdenados = $this->getAyudantesPorOrden();
|
||||
|
||||
if (empty($ayudantesOrdenados)) {
|
||||
return ['success' => 0, 'errors' => ['No hay ayudantes configurados'], 'resultados' => []];
|
||||
}
|
||||
|
||||
// Encontrar la última semana asignada
|
||||
$ultimaAsignacion = $this->getUltimaAsignacion();
|
||||
$semanaActual = $ultimaAsignacion
|
||||
? date('Y-m-d', strtotime('+1 week', strtotime($ultimaAsignacion['semana_inicio'])))
|
||||
: date('Y-m-d', strtotime('last sunday', strtotime('today'))); // Empezar desde domingo
|
||||
|
||||
// Determinar el siguiente ayudante en el ciclo
|
||||
$indiceActual = 0;
|
||||
if ($ultimaAsignacion) {
|
||||
$indiceActual = $this->findIndiceSiguiente($ultimaAsignacion['user_id'], $ayudantesOrdenados);
|
||||
}
|
||||
|
||||
// Asignar semanas futuras
|
||||
for ($i = 0; $i < $semanasFuturas; $i++) {
|
||||
$semanaInicio = date('Y-m-d', strtotime("+$i weeks", strtotime($semanaActual)));
|
||||
$semanaFin = date('Y-m-d', strtotime('+5 days', strtotime($semanaInicio))); // Domingo a viernes
|
||||
|
||||
// Seleccionar ayudante usando ciclo cíclico
|
||||
$ayudanteIndex = ($indiceActual + $i) % count($ayudantesOrdenados);
|
||||
$ayudante = $ayudantesOrdenados[$ayudanteIndex];
|
||||
|
||||
try {
|
||||
$ordenTurno = $this->getOrdenTurno($ayudante['id']);
|
||||
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO asignaciones_turnos (user_id, semana_inicio, semana_fin, orden_turno)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), semana_fin = VALUES(semana_fin), orden_turno = VALUES(orden_turno)
|
||||
");
|
||||
|
||||
$success = $stmt->execute([$ayudante['id'], $semanaInicio, $semanaFin, $ordenTurno]);
|
||||
|
||||
if ($success) {
|
||||
$resultados[] = [
|
||||
'semana' => $semanaInicio,
|
||||
'usuario' => $ayudante['nombre'],
|
||||
'orden' => $ordenTurno
|
||||
];
|
||||
} else {
|
||||
$errores[] = "Error al asignar semana $semanaInicio a {$ayudante['nombre']}";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errores[] = "Error semana $semanaInicio: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => count($resultados),
|
||||
'errors' => $errores,
|
||||
'resultados' => $resultados
|
||||
];
|
||||
}
|
||||
|
||||
public function getAyudantesPorOrden() {
|
||||
$stmt = $this->db->query("
|
||||
SELECT u.*, ro.orden
|
||||
FROM users u
|
||||
LEFT JOIN rotacion_orden ro ON u.id = ro.user_id AND ro.activo = 1
|
||||
WHERE u.rol = 'ayudante' AND u.activo = 1
|
||||
ORDER BY COALESCE(ro.orden, 999), u.nombre
|
||||
");
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
private function getUltimaAsignacion() {
|
||||
$stmt = $this->db->query("
|
||||
SELECT a.*, u.nombre
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
WHERE a.semana_inicio <= CURDATE()
|
||||
ORDER BY a.semana_inicio DESC
|
||||
LIMIT 1
|
||||
");
|
||||
return $stmt->fetch();
|
||||
}
|
||||
|
||||
private function findIndiceSiguiente($ultimoUserId, $ayudantesOrdenados) {
|
||||
foreach ($ayudantesOrdenados as $index => $ayudante) {
|
||||
if ($ayudante['id'] == $ultimoUserId) {
|
||||
return ($index + 1) % count($ayudantesOrdenados);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function recalcularAsignaciones($semanasFuturas = 20) {
|
||||
$resultados = [];
|
||||
$errores = [];
|
||||
|
||||
// Obtener todos los ayudantes en orden de rotación
|
||||
$ayudantesOrdenados = $this->getAyudantesPorOrden();
|
||||
|
||||
if (empty($ayudantesOrdenados)) {
|
||||
return ['success' => 0, 'errors' => ['No hay ayudantes configurados'], 'resultados' => []];
|
||||
}
|
||||
|
||||
// Encontrar la última asignación existente (histórica)
|
||||
$stmt = $this->db->query("
|
||||
SELECT a.*, u.nombre
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
ORDER BY a.semana_inicio DESC
|
||||
LIMIT 1
|
||||
");
|
||||
$ultimaAsignacion = $stmt->fetch();
|
||||
|
||||
// Determinar desde dónde empezar a recalcular
|
||||
if ($ultimaAsignacion) {
|
||||
$semanaInicio = date('Y-m-d', strtotime('+1 week', strtotime($ultimaAsignacion['semana_inicio'])));
|
||||
|
||||
// Encontrar posición del último usuario en el nuevo orden
|
||||
$indiceInicial = 0;
|
||||
foreach ($ayudantesOrdenados as $index => $ayudante) {
|
||||
if ($ayudante['id'] == $ultimaAsignacion['user_id']) {
|
||||
$indiceInicial = ($index + 1) % count($ayudantesOrdenados);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No hay asignaciones, empezar desde el próximo domingo
|
||||
$hoy = new DateTime();
|
||||
$diaSemana = (int)$hoy->format('w');
|
||||
$domingo = clone $hoy;
|
||||
$domingo->modify('-' . $diaSemana . ' days');
|
||||
$semanaInicio = $domingo->format('Y-m-d');
|
||||
$indiceInicial = 0;
|
||||
}
|
||||
|
||||
// Eliminar asignaciones futuras
|
||||
$stmt = $this->db->prepare("DELETE FROM asignaciones_turnos WHERE semana_inicio >= ?");
|
||||
$stmt->execute([$semanaInicio]);
|
||||
|
||||
// Generar nuevas asignaciones
|
||||
for ($i = 0; $i < $semanasFuturas; $i++) {
|
||||
$siguienteDomingo = new DateTime($semanaInicio);
|
||||
$siguienteDomingo->modify("+{$i} weeks");
|
||||
|
||||
$fechaInicio = $siguienteDomingo->format('Y-m-d');
|
||||
$fechaFin = $siguienteDomingo->modify('+5 days')->format('Y-m-d');
|
||||
|
||||
$ayudanteIndex = ($indiceInicial + $i) % count($ayudantesOrdenados);
|
||||
$ayudante = $ayudantesOrdenados[$ayudanteIndex];
|
||||
|
||||
try {
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO asignaciones_turnos (user_id, semana_inicio, semana_fin, orden_turno)
|
||||
VALUES (?, ?, ?, ?)
|
||||
");
|
||||
|
||||
$success = $stmt->execute([
|
||||
$ayudante['id'],
|
||||
$fechaInicio,
|
||||
$fechaFin,
|
||||
$ayudante['orden']
|
||||
]);
|
||||
|
||||
if ($success) {
|
||||
$resultados[] = [
|
||||
'semana' => $fechaInicio,
|
||||
'usuario' => $ayudante['nombre'],
|
||||
'orden' => $ayudante['orden']
|
||||
];
|
||||
} else {
|
||||
$errores[] = "Error al asignar semana $fechaInicio a {$ayudante['nombre']}";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errores[] = "Error semana $fechaInicio: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => count($resultados),
|
||||
'errors' => $errores,
|
||||
'resultados' => $resultados
|
||||
];
|
||||
}
|
||||
|
||||
public function inicializarOrdenRotacion() {
|
||||
$ayudantes = $this->getAyudantesPorOrden();
|
||||
$errores = [];
|
||||
$actualizados = 0;
|
||||
|
||||
foreach ($ayudantes as $index => $ayudante) {
|
||||
if ($ayudante['orden'] === null) {
|
||||
try {
|
||||
$stmt = $this->db->prepare("
|
||||
INSERT INTO rotacion_orden (user_id, orden, activo)
|
||||
VALUES (?, ?, 1)
|
||||
ON DUPLICATE KEY UPDATE orden = VALUES(orden), activo = 1
|
||||
");
|
||||
$stmt->execute([$ayudante['id'], $index + 1]);
|
||||
$actualizados++;
|
||||
} catch (Exception $e) {
|
||||
$errores[] = "Error con {$ayudante['nombre']}: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'actualizados' => $actualizados,
|
||||
'errores' => $errores
|
||||
];
|
||||
}
|
||||
|
||||
public function getAsignacionesPorRango($semanaInicio, $semanaFin) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT u.*, a.semana_inicio, a.semana_fin, a.orden_turno
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
WHERE a.semana_inicio >= ? AND a.semana_inicio <= ?
|
||||
ORDER BY a.semana_inicio, u.nombre
|
||||
");
|
||||
$stmt->execute([$semanaInicio, $semanaFin]);
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
|
||||
public function getTodasAsignacionesPorSemana($semanaInicio) {
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT u.*, a.semana_inicio, a.orden_turno
|
||||
FROM asignaciones_turnos a
|
||||
JOIN users u ON a.user_id = u.id
|
||||
WHERE a.semana_inicio = ?
|
||||
ORDER BY a.orden_turno
|
||||
");
|
||||
$stmt->execute([$semanaInicio]);
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user