Update code with changes from git diff
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,7 +10,6 @@ composer.phar
|
||||
/concept/
|
||||
/backup/
|
||||
/.vscode/
|
||||
/export/
|
||||
/log/
|
||||
|
||||
/include/.env
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#input $_GET['id_espacio_sgu']
|
||||
#output rutas: [ ...ruta, salones: [{...salon}] ]
|
||||
header('Content-Type: application/json charset=utf-8');
|
||||
ini_set('memory_limit', '256M');
|
||||
ini_set('post_max_size', '256M');
|
||||
ini_set('memory_limit', '500M');
|
||||
ini_set('post_max_size', '500M');
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
@@ -39,16 +39,18 @@ try {
|
||||
PERIODO.periodo_fecha_inicio,
|
||||
PERIODO.periodo_fecha_fin,
|
||||
salon,
|
||||
materia_nombre as materia,
|
||||
COALESCE(materia_nombre, materia_asignacion_materia) as materia,
|
||||
carrera_nombre as carrera,
|
||||
facultad_nombre as facultad,
|
||||
nivel_nombre as nivel,
|
||||
horario_fin
|
||||
FROM horario
|
||||
left JOIN materia USING (materia_id)
|
||||
JOIN carrera USING (carrera_id)
|
||||
LEFT JOIN carrera USING (carrera_id)
|
||||
left join materia_asignacion using (horario_id)
|
||||
-- JOIN carrera USING (carrera_id) but if carrera_id is null then 0
|
||||
JOIN nivel USING (nivel_id)
|
||||
JOIN facultad ON facultad.facultad_id = carrera.facultad_id
|
||||
JOIN facultad ON facultad.facultad_id = COALESCE(carrera.facultad_id, 0)
|
||||
JOIN PERIODO USING (periodo_id)
|
||||
JOIN SALON USING (salon_id)
|
||||
WHERE (PERIODO.periodo_id, facultad.facultad_id) = (:periodo_id, COALESCE(:facultad_id, facultad.facultad_id))
|
||||
@@ -97,12 +99,14 @@ try {
|
||||
LEFT JOIN ROL on ROL.rol_id = justificador.rol_id
|
||||
left join facultad on facultad.facultad_id = justificador.facultad_id
|
||||
WHERE (fechas.registro_fecha_ideal + HORARIO_HORA) BETWEEN
|
||||
GREATEST(HORARIO_FECHA_INICIO, PERIODO_FECHA_INICIO, :fecha_inicio) AND LEAST(:fecha_fin, PERIODO_FECHA_FIN, HORARIO_FECHA_FIN)
|
||||
GREATEST(HORARIO_FECHA_INICIO, PERIODO_FECHA_INICIO, :fecha_inicio) AND LEAST(PERIODO_FECHA_FIN, HORARIO_FECHA_FIN, :fecha_fin)
|
||||
ORDER BY fechas.registro_fecha_ideal DESC, horarios.horario_id, profesor_nombre",
|
||||
$params
|
||||
);
|
||||
|
||||
// $user->print_to_log(json_encode($params));
|
||||
$db->delete('general_log');
|
||||
$db->insert('general_log', [
|
||||
'general_log_json' => json_encode($params, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
|
||||
]);
|
||||
echo json_encode(array_merge($data), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
http_response_code(405);
|
||||
|
||||
@@ -25,37 +25,50 @@ try {
|
||||
echo json_encode(['error' => 'No hay clases pendientes']);
|
||||
exit;
|
||||
}
|
||||
if (!(isset($post_data['fecha'], $post_data['bloques'], $post_data['justificacion']))) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Faltan parametros']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = $db->querySingle(
|
||||
'INSERT INTO registro (profesor_id, horario_id, registro_fecha_ideal, registro_justificada, justificador_id, registro_fecha_justificacion, justificacion)
|
||||
VALUES (:profesor_id, :horario_id, :registro_fecha_ideal, :registro_justificada, :justificador_id, NOW(), :justificacion)
|
||||
ON CONFLICT (profesor_id, horario_id, registro_fecha_ideal)
|
||||
DO UPDATE SET registro_justificada = :registro_justificada, justificador_id = :justificador_id, registro_fecha_justificacion = NOW(), justificacion = :justificacion
|
||||
RETURNING *',
|
||||
$bloques = $db
|
||||
->where('id', $post_data['bloques'])
|
||||
->orderBy('hora_inicio')
|
||||
->get('bloque_horario', null, 'hora_inicio, hora_fin');
|
||||
|
||||
$min_hora_inicio = $bloques[0]['hora_inicio'];
|
||||
$max_hora_fin = $bloques[count($bloques) - 1]['hora_fin'];
|
||||
|
||||
$pdo->beginTransaction();
|
||||
$data = $db->query(
|
||||
"INSERT INTO registro (horario_id, registro_fecha_ideal, profesor_id, justificador_id, justificacion, registro_fecha_justificacion, registro_justificada)
|
||||
SELECT DISTINCT
|
||||
horario_id, :fecha::DATE, profesor_id, :justificador_id::INT, :justificacion, NOW(), true
|
||||
from horario_view
|
||||
join horario_profesor using (horario_id)
|
||||
where
|
||||
(:hora_inicio::TIME, :hora_fin::TIME) OVERLAPS (horario_hora, horario_fin) AND
|
||||
horario_dia = EXTRACT(DOW FROM :fecha::DATE) AND
|
||||
periodo_id = :periodo_id AND
|
||||
(horario_view.facultad_id = :facultad_id OR :facultad_id IS NULL)
|
||||
ON CONFLICT (horario_id, registro_fecha_ideal, profesor_id) DO UPDATE SET
|
||||
justificador_id = :justificador_id,
|
||||
justificacion = :justificacion,
|
||||
registro_fecha_justificacion = NOW(),
|
||||
registro_justificada = true
|
||||
RETURNING *;",
|
||||
array(
|
||||
'profesor_id' => $post_data['profesor_id'],
|
||||
'horario_id' => $post_data['horario_id'],
|
||||
'registro_fecha_ideal' => $post_data['registro_fecha_ideal'],
|
||||
'registro_justificada' => $post_data['registro_justificada'],
|
||||
'justificador_id' => $user->user['id'],
|
||||
'justificacion' => empty($post_data['justificacion']) ? null : $post_data['justificacion'],
|
||||
'fecha' => $post_data['fecha'],
|
||||
'periodo_id' => $user->periodo_id,
|
||||
'facultad_id' => $user->facultad['facultad_id'],
|
||||
'hora_inicio' => $min_hora_inicio,
|
||||
'hora_fin' => $max_hora_fin,
|
||||
)
|
||||
);
|
||||
|
||||
$data_justificador = $db->querySingle(
|
||||
"SELECT justificador.usuario_nombre as justificador_nombre,
|
||||
justificador.usuario_clave as justificador_clave,
|
||||
facultad.facultad_nombre as justificador_facultad, rol.rol_titulo as justificador_rol
|
||||
|
||||
FROM USUARIO JUSTIFICADOR
|
||||
JOIN ROL on ROL.rol_id = justificador.rol_id
|
||||
LEFT JOIN facultad on facultad.facultad_id = justificador.facultad_id
|
||||
where justificador.usuario_id = :justificador_id",
|
||||
array(
|
||||
'justificador_id' => $user->user['id'],
|
||||
)
|
||||
);
|
||||
echo json_encode(array_merge($data, $data_justificador), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
$pdo->commit();
|
||||
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'method not allowed']);
|
||||
@@ -70,6 +83,7 @@ try {
|
||||
'query' => $db->getLastQuery(),
|
||||
'post_data' => $post_data,
|
||||
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
$pdo->rollBack();
|
||||
exit;
|
||||
} catch (Exception $th) {
|
||||
http_response_code(500);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
$ruta = "../";
|
||||
require_once "../include/bd_pdo.php";
|
||||
global $pdo;
|
||||
$sql="SELECT * FROM materia WHERE materia_id = :idMateria";
|
||||
$params = ['idMateria' => $_POST['idmateria']];
|
||||
echo json_encode(query($sql, $params, false));
|
||||
$ruta = "../";
|
||||
require_once "../include/bd_pdo.php";
|
||||
global $pdo;
|
||||
$sql = "SELECT * FROM materia
|
||||
JOIN carrera using (carrera_id)
|
||||
WHERE materia_id = :idMateria";
|
||||
$params = ['idMateria' => $_POST['idmateria']];
|
||||
echo json_encode(query($sql, $params, false));
|
||||
?>
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
$ruta = "../";
|
||||
require_once "../include/bd_pdo.php";
|
||||
global $pdo;
|
||||
$ruta = "../";
|
||||
require_once "../include/bd_pdo.php";
|
||||
global $pdo;
|
||||
|
||||
$sql = "UPDATE materia SET materia_nombre = :nombre WHERE materia_id = :id";
|
||||
$params = array(':nombre' => mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"]);
|
||||
$hecho = query($sql, $params, false);
|
||||
header("Location: ../materias.php");
|
||||
exit();
|
||||
$sql = "UPDATE materia SET materia_nombre = :nombre, carrera_id = :carrera WHERE materia_id = :id";
|
||||
$params = array(':nombre' => mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"], ':carrera' => $_POST["carrera"]);
|
||||
$hecho = query($sql, $params, false);
|
||||
header("Location: ../materias.php");
|
||||
exit();
|
||||
?>
|
||||
20
action/correo.php
Normal file
20
action/correo.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
require_once '../class/mailer.php';
|
||||
require_once('../include/phpmailer/PHPMailerAutoload.php');
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if(!isset($_GET["correo"])){
|
||||
echo "Debes especificar la dirección a la que se enviará el correo <strong>?correo=</strong>";
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
$to = $_GET["correo"];
|
||||
$texto = "<h1>Esto es una prueba automatizada</h1><p>El correo se envió atutomáticamente, no debes hacer nada más.</p>";
|
||||
$asunto="Prueba";
|
||||
Mailer::enviarCorreo($to, $asunto, $texto, true);
|
||||
echo "Enviado!".date("H:i:s");
|
||||
|
||||
?>
|
||||
76
action/justificar.php
Normal file
76
action/justificar.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
require_once "{$_SERVER['DOCUMENT_ROOT']}/class/c_login.php";
|
||||
header('Content-Type: application/json');
|
||||
if (!Login::is_logged()) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
echo json_encode(['error' => 'No se ha iniciado sesión']);
|
||||
exit();
|
||||
}
|
||||
$user = Login::get_user();
|
||||
|
||||
try {
|
||||
switch ($_SERVER['REQUEST_METHOD']) {
|
||||
case 'POST':
|
||||
// check parameters
|
||||
|
||||
$raw = file_get_contents('php://input');
|
||||
$post_data = json_decode($raw, true);
|
||||
|
||||
$data = $db->querySingle(
|
||||
'WITH HORARIOS AS (
|
||||
SELECT *
|
||||
FROM horario
|
||||
JOIN horario_profesor USING (horario_id)
|
||||
WHERE horario.periodo_id = :periodo_id
|
||||
)
|
||||
INSERT INTO registro (profesor_id, horario_id, registro_fecha_ideal, registro_justificada, justificador_id, registro_fecha_justificacion, justificacion)
|
||||
VALUES (:profesor_id, :horario_id, :registro_fecha_ideal, :registro_justificada, :justificador_id, NOW(), :justificacion)
|
||||
ON CONFLICT (profesor_id, horario_id, registro_fecha_ideal)
|
||||
DO UPDATE SET registro_justificada = :registro_justificada, justificador_id = :justificador_id, registro_fecha_justificacion = NOW(), justificacion = :justificacion
|
||||
RETURNING *',
|
||||
array(
|
||||
'periodo_id' => $user->periodo_id,
|
||||
'profesor_id' => $post_data['profesor_id'],
|
||||
'horario_id' => $post_data['horario_id'],
|
||||
'registro_fecha_ideal' => $post_data['registro_fecha_ideal'],
|
||||
'registro_justificada' => $post_data['registro_justificada'],
|
||||
'justificador_id' => $user->user['id'],
|
||||
'justificacion' => empty($post_data['justificacion']) ? null : $post_data['justificacion'],
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$data_justificador = $db->querySingle(
|
||||
"SELECT justificador.usuario_nombre as justificador_nombre,
|
||||
justificador.usuario_clave as justificador_clave,
|
||||
facultad.facultad_nombre as justificador_facultad, rol.rol_titulo as justificador_rol
|
||||
|
||||
FROM USUARIO JUSTIFICADOR
|
||||
JOIN ROL on ROL.rol_id = justificador.rol_id
|
||||
LEFT JOIN facultad on facultad.facultad_id = justificador.facultad_id
|
||||
where justificador.usuario_id = :justificador_id",
|
||||
array(
|
||||
'justificador_id' => $user->user['id'],
|
||||
)
|
||||
);
|
||||
// exit('exit');
|
||||
|
||||
echo json_encode(array_merge($data, $data_justificador), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
break;
|
||||
|
||||
default:
|
||||
header('HTTP/1.1 405 Method Not Allowed');
|
||||
echo json_encode(['error' => 'Método no permitido']);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
echo json_encode([
|
||||
'error' => $e->getMessage(),
|
||||
'query' => $db->getLastQuery(),
|
||||
'exception' => $e->getTraceAsString()
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'error' => $e->getMessage(),
|
||||
'exception' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
204
action/periodos.php
Normal file
204
action/periodos.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
require_once "{$_SERVER['DOCUMENT_ROOT']}/class/c_login.php";
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!Login::is_logged()) {
|
||||
header('HTTP/1.1 401 Unauthorized');
|
||||
echo json_encode(['error' => 'No se ha iniciado sesión']);
|
||||
exit();
|
||||
}
|
||||
$user = Login::get_user();
|
||||
|
||||
try {
|
||||
switch ($_SERVER['REQUEST_METHOD']) {
|
||||
case 'GET':
|
||||
// Fetch all puestos
|
||||
$periodo_id = $user->periodo_id;
|
||||
if (is_null($user->facultad['facultad_id'])) {
|
||||
$periodos = $db
|
||||
->where('CURRENT_DATE BETWEEN periodo_fecha_inicio AND periodo_fecha_fin')
|
||||
->join('nivel', 'nivel.nivel_id = periodo.nivel_id')
|
||||
->orderBy('periodo_id')
|
||||
->get('periodo', null, 'periodo.*, nivel_nombre as nivel');
|
||||
} else {
|
||||
$periodos = $db->query(
|
||||
"SELECT DISTINCT periodo.*, nivel_nombre as nivel FROM periodo
|
||||
JOIN horario_view USING (periodo_id)
|
||||
JOIN nivel ON nivel.nivel_id = periodo.nivel_id
|
||||
WHERE CURRENT_DATE BETWEEN periodo.periodo_fecha_inicio AND periodo.periodo_fecha_fin
|
||||
AND facultad_id = :facultad_id
|
||||
ORDER BY periodo_id
|
||||
",
|
||||
['facultad_id' => $user->facultad['facultad_id']]
|
||||
);
|
||||
}
|
||||
echo json_encode($periodos);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
// Update nivel_id of a periodo
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
if (!isset($data['action'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Falta la acción a realizar']);
|
||||
exit();
|
||||
}
|
||||
|
||||
switch ($data['action']) {
|
||||
case 'changeNivel':
|
||||
if (!isset($data['periodo_id'], $data['nivel_id'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Falta el id del periodo o el nivel']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$periodo_id = $data['periodo_id'];
|
||||
$nivel_id = $data['nivel_id'];
|
||||
$db->where('periodo_id', $periodo_id)->update('periodo', ['nivel_id' => $nivel_id]);
|
||||
|
||||
$periodo_nombre = $db->where('periodo_id', $periodo_id)->getOne('periodo', 'periodo_nombre')['periodo_nombre'];
|
||||
$nivel_nombre = $db->where('nivel_id', $nivel_id)->getOne('nivel', 'nivel_nombre')['nivel_nombre'];
|
||||
|
||||
echo json_encode([
|
||||
'success' =>
|
||||
"El nivel del periodo $periodo_nombre ha sido cambiado a $nivel_nombre"
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'changeFechaInicio':
|
||||
if (!isset($data['periodo_id'], $data['periodo_fecha_inicio'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Falta el id del periodo o la fecha de inicio']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$periodo_id = $data['periodo_id'];
|
||||
$periodo_fecha_inicio = $data['periodo_fecha_inicio'];
|
||||
$db->where('periodo_id', $periodo_id)->update('periodo', ['periodo_fecha_inicio' => $periodo_fecha_inicio]);
|
||||
|
||||
$periodo_nombre = $db->where('periodo_id', $periodo_id)->getOne('periodo', 'periodo_nombre')['periodo_nombre'];
|
||||
|
||||
echo json_encode([
|
||||
'success' =>
|
||||
"La fecha de inicio del periodo $periodo_nombre ha sido cambiada a $periodo_fecha_inicio"
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'changeFechaFin':
|
||||
if (!isset($data['periodo_id'], $data['periodo_fecha_fin'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Falta el id del periodo o la fecha de fin']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$periodo_id = $data['periodo_id'];
|
||||
$periodo_fecha_fin = $data['periodo_fecha_fin'];
|
||||
$db->where('periodo_id', $periodo_id)->update('periodo', ['periodo_fecha_fin' => $periodo_fecha_fin]);
|
||||
|
||||
$periodo_nombre = $db->where('periodo_id', $periodo_id)->getOne('periodo', 'periodo_nombre')['periodo_nombre'];
|
||||
|
||||
echo json_encode([
|
||||
'success' =>
|
||||
"La fecha de fin del periodo $periodo_nombre ha sido cambiada a $periodo_fecha_fin"
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'updatePeriodo':
|
||||
if (!isset($data['periodo_id'], $data['periodo_nombre'], $data['id_periodo_sgu'], $data['periodo_clave'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Faltan datos para actualizar el periodo']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$periodo_id = $data['periodo_id'];
|
||||
|
||||
$db->where('periodo_id', $periodo_id)->update('periodo', array_filter($data, fn($key) => in_array($key, [
|
||||
'periodo_nombre',
|
||||
'id_periodo_sgu',
|
||||
'periodo_clave',
|
||||
]), ARRAY_FILTER_USE_KEY));
|
||||
|
||||
$periodo_nombre = $db->where('periodo_id', $periodo_id)->getOne('periodo', 'periodo_nombre')['periodo_nombre'];
|
||||
|
||||
echo json_encode([
|
||||
'success' =>
|
||||
"El periodo $periodo_nombre ha sido actualizado"
|
||||
]);
|
||||
break;
|
||||
|
||||
default:
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Acción no válida']);
|
||||
exit();
|
||||
}
|
||||
|
||||
break;
|
||||
case 'POST':
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
if (!isset($data['periodo_nombre'], $data['nivel_id'], $data['periodo_fecha_inicio'], $data['periodo_fecha_fin'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Faltan datos para crear el periodo']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$newPeriodo = $db->insert(
|
||||
'periodo',
|
||||
array_filter($data, fn($key) => in_array($key, [
|
||||
'periodo_nombre',
|
||||
'nivel_id',
|
||||
'periodo_fecha_inicio',
|
||||
'periodo_fecha_fin',
|
||||
'periodo_clave',
|
||||
'id_periodo_sgu',
|
||||
]), ARRAY_FILTER_USE_KEY)
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'El periodo ha sido creado',
|
||||
'periodo' => $newPeriodo
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
// Delete a periodo
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
if (!isset($data['periodo_id'])) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
echo json_encode(['error' => 'Falta el id del periodo']);
|
||||
exit();
|
||||
}
|
||||
|
||||
$periodo_id = $data['periodo_id'];
|
||||
$periodo_nombre = $db->where('periodo_id', $periodo_id)->getOne('periodo', 'periodo_nombre')['periodo_nombre'];
|
||||
|
||||
$db->where('periodo_id', $periodo_id)->delete('periodo');
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => "El periodo $periodo_nombre ha sido eliminado"
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
header('HTTP/1.1 405 Method Not Allowed');
|
||||
echo json_encode(['error' => 'Método no permitido']);
|
||||
break;
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
echo json_encode([
|
||||
'error' => $e->getMessage(),
|
||||
'query' => $db->getLastQuery(),
|
||||
'exception' => $e->getTraceAsString()
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'error' => $e->getMessage(),
|
||||
'exception' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
@@ -5,6 +5,11 @@ Cambia de estado la reposición
|
||||
$pag = "../reposiciones_crear.php";
|
||||
$ruta = "../";
|
||||
require_once "../class/c_login.php";
|
||||
require_once "../class/mailer.php";
|
||||
|
||||
define("COORDINADOR", 9);
|
||||
define("SUPERVISOR", 7);
|
||||
define("ENVIO_CORREOS", true);
|
||||
|
||||
// check if the session is started
|
||||
if (!isset($_SESSION['user']))
|
||||
@@ -24,6 +29,71 @@ $id_repo = filter_input(INPUT_POST, "id", FILTER_SANITIZE_NUMBER_INT);//limpia t
|
||||
$edo = filter_input(INPUT_POST, "edo", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
if(isset($_POST["salon"]) && $_POST["salon"] != "")
|
||||
$salon = filter_input(INPUT_POST, "salon", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
//--------------
|
||||
|
||||
//--------------
|
||||
//Obtiene datos reposición
|
||||
//TODO , SALÓN SALIÓ PENDIENTE Y FALTA REVISAR LISTA DE CORREOS TO
|
||||
$reposicion_rs = $db->querySingle('SELECT h.materia, r.fecha_nueva, r.hora_nueva, r.fecha_clase, h.horario_hora, h.facultad_id, h.facultad, f.clave_dependencia, s.salon_id, s.salon_array, r.motivo_cancelacion, ta.tipoaula_supervisor , ta.tipoaula_nombre
|
||||
from reposicion_solicitud r
|
||||
inner join horario_view h on h.horario_id = r.horario_id
|
||||
inner join facultad f on f.facultad_id = h.facultad_id
|
||||
inner join tipoaula ta on ta.tipoaula_id = r.tipoaula_id
|
||||
left join salon_view s on r.salon_id = s.salon_id
|
||||
where r.reposicion_solicitud_id = :id_repo',
|
||||
[':id_repo' => $id_repo]
|
||||
);
|
||||
|
||||
if($reposicion_rs["salon_id"] == "" || $reposicion_rs["salon_id"] == NULL){
|
||||
$salon_desc = "Pendiente";
|
||||
}else{
|
||||
$salon_json = json_decode($reposicion_rs["salon_array"], true);
|
||||
if($salon_json[0]== "UNIVERSIDAD LA SALLE"){
|
||||
unset($salon_json[0]);
|
||||
}
|
||||
$salon_desc = join(" / ",$salon_json);
|
||||
}
|
||||
//Obtiene correos
|
||||
$correos_rs = $db->query('SELECT p.profesor_nombre, p.profesor_correo, u.usuario_nombre as jefe_nombre, u.usuario_correo as jefe_correo,
|
||||
coor.usuario_nombre as coordinador_nombre, coor.usuario_correo as coordinador_correo
|
||||
from reposicion_solicitud rs
|
||||
inner join profesor p on rs.profesor_id =p.profesor_id
|
||||
inner join usuario u on u.usuario_id = rs.usuario_id
|
||||
inner join horario_view hv on hv.horario_id = rs.horario_id
|
||||
inner join usuario coor on hv.facultad_id = coor.facultad_id and coor.rol_id = :rol_coord
|
||||
where rs.reposicion_solicitud_id = :id_repo',
|
||||
[':rol_coord' => COORDINADOR, ':id_repo' => $id_repo]
|
||||
);
|
||||
//print_r($correos_rs); exit();
|
||||
|
||||
$prof_correos=array();
|
||||
$jefe_correos=[];
|
||||
$coord_correos=[];
|
||||
|
||||
foreach($correos_rs as $correo){
|
||||
if( count($prof_correos)==0 && $correo["profesor_correo"]!=""){
|
||||
if( !isset($prof_correos["correo"]) || !in_array($correo["profesor_correo"], $prof_correos["correo"]) ){
|
||||
array_push($prof_correos, $correo["profesor_correo"]);
|
||||
}
|
||||
}
|
||||
if( count($jefe_correos)==0 && $correo["jefe_correo"]!=""){
|
||||
if(!isset($jefe_correos["correo"]) || !in_array($correo["jefe_correo"], $jefe_correos["correo"])){
|
||||
array_push($jefe_correos, $correo["jefe_correo"]);
|
||||
}
|
||||
}
|
||||
if( count($coord_correos)==0 && $correo["coordinador_correo"]!=""){
|
||||
if(!isset($coord_correos["correo"]) || !in_array($correo["coordinador_correo"], $coord_correos["correo"])){
|
||||
array_push($coord_correos, $correo["coordinador_correo"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$correosSup_rs = $db->querySingle("SELECT DISTINCT sup.usuario_correo as coordinador_correo
|
||||
FROM horario_supervisor hs
|
||||
inner join usuario sup on sup.usuario_id =hs.usuario_id
|
||||
where :facultad = ANY(hs.facultad_id_array)
|
||||
and hs.turno_inicio <= :hora and hs.turno_fin >= :hora",
|
||||
[':facultad'=>$reposicion_rs["facultad_id"], ':hora'=>$reposicion_rs["hora_nueva"]] );
|
||||
|
||||
|
||||
if($edo == 4){//cancelación
|
||||
@@ -45,52 +115,63 @@ if($edo == 4){//cancelación
|
||||
}
|
||||
}
|
||||
|
||||
//Obtener datos del usuario que creó la reposición y mandar correo
|
||||
/*$stmt = $pdo->prepare('Select * from
|
||||
:id, :periodo, NULL, NULL, NULL, NULL, NULL, 0, 1)');
|
||||
$stmt->bindParam(":id", $id_repo);
|
||||
$stmt->bindParam(":periodo", $_SESSION["periodo_id"]);
|
||||
if(!$stmt->execute()){
|
||||
header("Location:".$pag."?error=1");
|
||||
exit();
|
||||
}
|
||||
$rs = $stmt->fetch();
|
||||
$stmt->closeCursor();
|
||||
$stmt = null;
|
||||
|
||||
$stmt = $pdo->prepare('Select * from fs_contacto(:usr, 3, NULL)');//3 = correo
|
||||
$stmt->bindParam(":usr", $rs["Usuario_id"]);
|
||||
if(!$stmt->execute()){
|
||||
header("Location:".$pag."?error=1");
|
||||
exit();
|
||||
}
|
||||
$correos_rs = $stmt->fetchAll();
|
||||
$stmt->closeCursor();
|
||||
$stmt = null;
|
||||
$fecha_clase = date('d/m/Y', strtotime($reposicion_rs["fecha_clase"]));
|
||||
$fecha_nueva = date('d/m/Y', strtotime($reposicion_rs["fecha_nueva"]));
|
||||
$hora_tmp = explode(":",$reposicion_rs["horario_hora"]);
|
||||
$hora_clase = $hora_tmp[0].":".$hora_tmp[1];
|
||||
$hora_tmp = explode(":",$reposicion_rs["hora_nueva"]);
|
||||
$hora_nueva = $hora_tmp[0].":".$hora_tmp[1];
|
||||
|
||||
$correoList = "";
|
||||
foreach($correos_rs as $c){
|
||||
if($c.substr("lasallistas.org,mx",0) || $c.substr("lasalle.mx",0)){
|
||||
$correoList .= $c.";";
|
||||
$asunto = "";
|
||||
$texto = "";
|
||||
$to = "";
|
||||
switch($edo){
|
||||
case 2://Correo a supervisor
|
||||
$asunto = "Reposición nueva - ".$reposicion_rs["clave_dependencia"]." ".$reposicion_rs["facultad"];
|
||||
//crear plantilla
|
||||
$texto = "<p>Se creó una reposición nueva para: <b>".$reposicion_rs["clave_dependencia"]." ".$reposicion_rs["facultad"]."</b>.</p>";
|
||||
$texto .= "<p><b>".mb_strtoupper($reposicion_rs["materia"])."</b> del día <b>".$fecha_clase." a las ".$hora_clase." hrs. </b> se propone reponer el <b>".$fecha_nueva." a las ".$hora_nueva." hrs.</b>";
|
||||
if(!$reposicion_rs["tipoaula_supervisor"]){
|
||||
$texto .= " en el salón: <b>".$salon_desc."</b></p>";
|
||||
}else{
|
||||
$texto .= " en un salón de tipo: <b>".$reposicion_rs["tipoaula_nombre"]."</b></p>";
|
||||
}
|
||||
}
|
||||
|
||||
//$correoHTML = "<p>Se aprobó la reposición para el <b> a las </b> en el salón <b></b>.</p>";
|
||||
*/
|
||||
/*
|
||||
$log = new LogActividad();
|
||||
if($edo == 4){
|
||||
$desc_log = "Cancela reposición ID[".$id_repo."] edo[".$edo."]";
|
||||
$ok = 2;
|
||||
}else{
|
||||
$desc_log = "Autoriza reposición ID[".$id_repo."] edo[".$edo."] Salon[".(empty($salon)?"":$salon)."]";
|
||||
$texto .= "<p>Ingresa al <a href='https://paad.lci.ulsa.mx'>sistema PAAD</a> para autorizarla.</p>";
|
||||
$to = join(",", $correosSup_rs);
|
||||
$ok = 0;
|
||||
if($edo == 3){
|
||||
break;
|
||||
case 3://Correo a coordinador, profesor y jefe
|
||||
$asunto = "Reposición autorizada - ".$reposicion_rs["materia"];
|
||||
$texto = "<p>La resposición de la clase de <b>".$reposicion_rs["materia"]."</b> del día <b>".$fecha_clase." a las ".$hora_clase." hrs. </b> está autorizada para realizarse el día <b>".$fecha_nueva." a las ".$hora_nueva." hrs. en: $salon_desc</b></p>";
|
||||
$to = join(",", $coord_correos).",".join(",", $prof_correos).",".join(",", $jefe_correos);
|
||||
$ok = 0;
|
||||
break;
|
||||
case 4://Correo a coordinador, profesor y jefe
|
||||
$asunto = "Reposición declinada - ".$reposicion_rs["materia"];
|
||||
$texto = "<p>La resposición de la clase de <b>".$reposicion_rs["materia"]." planeada para el día ".$fecha_nueva." a las ".$hora_nueva." hrs.</b> ha sido declinada por el siguiente motivo:</p>";
|
||||
$texto .= "<p style='font-style:italic; padding-left:25px'>".$reposicion_rs["motivo_cancelacion"]."</p>";
|
||||
$to = join(",", $coord_correos).",".join(",", $prof_correos).",".join(",", $jefe_correos);
|
||||
$ok = 1;
|
||||
//if($correoList!= "")
|
||||
//Mailer::enviarCorreo($correoList , "Reposición autorizada", $correoHTML);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if($to!= "" && ENVIO_CORREOS){
|
||||
$texto = '<body >
|
||||
<img src="https://paad.lci.ulsa.mx/imagenes/logo_lasalle.png" alt="La Salle" style="margin-bottom:60px">
|
||||
'.$texto.'
|
||||
</body>';
|
||||
|
||||
require_once('../include/phpmailer/PHPMailerAutoload.php');
|
||||
/*if(DB_NAME == "poad_pruebas"){
|
||||
$asunto = "PRUEBAS-".$asunto;
|
||||
Mailer::enviarCorreo("alejandro.lara@lasalle.mx", $asunto, $texto, true);
|
||||
}else{*/
|
||||
Mailer::enviarCorreo($to, $asunto, $texto, true);
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
$log->appendLog($_SESSION["usuario_id"], $_SESSION["usuario_nombre"]." ".$_SESSION["usuario_apellidos"], $desc_log);
|
||||
*/
|
||||
header("Location: ".$pag."?ok=".$ok);
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
$pag = "../reposiciones_crear.php";
|
||||
$ruta = "../";
|
||||
require_once "../class/c_login.php";
|
||||
require_once "../class/mailer.php";
|
||||
|
||||
define("COORDINADOR", 9);
|
||||
define("ENVIO_CORREOS", true);
|
||||
|
||||
// check if the session is started
|
||||
if (!isset($_SESSION['user']))
|
||||
@@ -13,64 +17,71 @@ if (!isset($_SESSION['user']))
|
||||
$user = unserialize($_SESSION['user']);
|
||||
//$user->access();
|
||||
|
||||
$duracion_id = filter_input(INPUT_POST, "duracion", FILTER_SANITIZE_NUMBER_INT); //Id reposicion
|
||||
$bloque = filter_input(INPUT_POST, "bloque", FILTER_SANITIZE_NUMBER_INT); //
|
||||
$ciclo = filter_input(INPUT_POST, "ciclo", FILTER_SANITIZE_NUMBER_INT); //
|
||||
$fecha_falta = trim(htmlspecialchars($_POST["fecha_falta"], ENT_QUOTES, "UTF-8")); //limpia texto
|
||||
$fecha = trim(htmlspecialchars($_POST["fecha_inicial"], ENT_QUOTES, "UTF-8")); //limpia texto
|
||||
$fecha_cambio = trim(htmlspecialchars($_POST["fecha_cambio"], ENT_QUOTES, "UTF-8")); //limpia texto
|
||||
$hora_ini = filter_input(INPUT_POST, "hora_ini", FILTER_SANITIZE_NUMBER_INT); //limpia texto
|
||||
$min_ini = filter_input(INPUT_POST, "min_ini", FILTER_SANITIZE_NUMBER_INT); //limpia texto
|
||||
$hor = filter_input(INPUT_POST, "horario", FILTER_SANITIZE_NUMBER_INT); //limpia texto
|
||||
$alumnos = filter_input(INPUT_POST, "alumnos", FILTER_SANITIZE_NUMBER_INT); //limpia texto
|
||||
$tipo = filter_input(INPUT_POST, "tipo", FILTER_SANITIZE_NUMBER_INT); //1 Repo , 0 Cambio
|
||||
$aula = filter_input(INPUT_POST, "aula", FILTER_SANITIZE_NUMBER_INT); //1 regular , 2 sala computo, 3 otro facultad
|
||||
$duracion_id = filter_input(INPUT_POST, "duracion", FILTER_SANITIZE_NUMBER_INT);//Id reposicion
|
||||
$bloque = filter_input(INPUT_POST, "bloque", FILTER_SANITIZE_NUMBER_INT);//
|
||||
$ciclo = filter_input(INPUT_POST, "ciclo", FILTER_SANITIZE_NUMBER_INT);//
|
||||
$fecha_falta = trim(htmlspecialchars($_POST["fecha_falta"], ENT_QUOTES, "UTF-8"));//limpia texto
|
||||
$fecha = trim(htmlspecialchars($_POST["fecha_inicial"], ENT_QUOTES, "UTF-8"));//limpia texto
|
||||
$fecha_cambio = trim(htmlspecialchars($_POST["fecha_cambio"], ENT_QUOTES, "UTF-8"));//limpia texto
|
||||
$hora_ini = filter_input(INPUT_POST, "hora_ini", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
$min_ini = filter_input(INPUT_POST, "min_ini", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
$hor = filter_input(INPUT_POST, "horario", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
$alumnos = filter_input(INPUT_POST, "alumnos", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
$tipo = filter_input(INPUT_POST, "tipo", FILTER_SANITIZE_NUMBER_INT);//1 Repo , 0 Cambio
|
||||
$aula = filter_input(INPUT_POST, "aula", FILTER_SANITIZE_NUMBER_INT);//1 regular , 2 sala computo, 3 otro facultad
|
||||
|
||||
if (empty($_POST["prof"]))
|
||||
if(empty($_POST["prof"]))
|
||||
$prof = $user["id"];
|
||||
else
|
||||
$prof = filter_input(INPUT_POST, "prof", FILTER_SANITIZE_NUMBER_INT); //limpia texto
|
||||
$prof = filter_input(INPUT_POST, "prof", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
//if(isset($_POST["salon"]) && $_POST["salon"] != "")
|
||||
//$salon = trim(filter_input(INPUT_POST, "salon", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW)));//limpia texto
|
||||
$comentario = trim(htmlspecialchars($_POST["comentario"], ENT_QUOTES, "UTF-8")); //limpia texto
|
||||
$comentario = trim(htmlspecialchars($_POST["comentario"], ENT_QUOTES, "UTF-8"));//limpia texto
|
||||
|
||||
|
||||
$duracion_rs = $db->querySingle("select * from duracion where duracion_id = :id", [":id" => $duracion_id]);
|
||||
$duracion_rs = $db->querySingle("select * from duracion where duracion_id = :id", [":id"=>$duracion_id]);
|
||||
$duracion_tiempo = $duracion_rs["duracion_interval"];
|
||||
|
||||
//-- Obtiene datos de horario regular de clase
|
||||
$horario_rs = $db->querySingle(
|
||||
'SELECT * from horario_view where horario_id = :hor',
|
||||
$horario_rs = $db->querySingle('SELECT * from horario_view where horario_id = :hor',
|
||||
[':hor' => $hor]
|
||||
);
|
||||
);
|
||||
|
||||
$materia = $horario_rs["materia_id"];
|
||||
$dia = $horario_rs["horario_dia"];
|
||||
|
||||
$hora = $hora_ini . ":" . $min_ini . ":00";
|
||||
$fecha_new = DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d') . " " . $hora;
|
||||
$fecha_fin_new = date("Y-m-d", strtotime($fecha_new)) . " " . $duracion_tiempo;
|
||||
$hora = $hora_ini.":".$min_ini.":00";
|
||||
$fecha_new = DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d')." ".$hora;
|
||||
$fecha_fin_new = date("Y-m-d", strtotime($fecha_new))." ".$duracion_tiempo;
|
||||
$dia_new = date('w', strtotime($fecha_new));
|
||||
|
||||
if ($tipo == 1) { //Reposición
|
||||
if($tipo == 1){//Reposición
|
||||
$fecha_falta = DateTime::createFromFormat('d/m/Y', $fecha_falta)->format('Y-m-d');
|
||||
$dia_falta = date('w', strtotime($fecha_falta));
|
||||
} else {
|
||||
}else{
|
||||
$fecha_cambio = DateTime::createFromFormat('d/m/Y', $fecha_cambio)->format('Y-m-d');
|
||||
$dia_falta = date('w', strtotime($fecha_cambio));
|
||||
}
|
||||
|
||||
|
||||
//Valida que tenga clase en la fecha de falta
|
||||
if (intval($dia) != intval($dia_falta)) {
|
||||
header("Location:" . $pag . "?error=11");
|
||||
if(intval($dia) != intval($dia_falta)){
|
||||
header("Location:".$pag."?error=11");
|
||||
/*print_r($_POST);
|
||||
echo 'SELECT * from horario_view where horario_id = '.$hor;
|
||||
echo intval($dia)." != ".intval($dia_falta);*/
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($tipo == 1) { //Reposición
|
||||
//Obtiene correo
|
||||
$correos_rs = $db->querySingle('SELECT coor.usuario_correo, coor.usuario_nombre from usuario coor where rol_id = :rol_coord and facultad_id = (
|
||||
select coalesce(facultad_id,0) from usuario u where u.usuario_id = :id_usr)',[':rol_coord' => COORDINADOR, ':id_usr' => $user->user["id"]]
|
||||
);
|
||||
if( count($correos_rs) > 0 ){
|
||||
$to = $correos_rs["usuario_correo"];
|
||||
}
|
||||
|
||||
if($tipo == 1){//Reposición
|
||||
// Valida que grupo no tenga clases
|
||||
/*$result = validaConflictoHoras($pdo, $gpo, $dia_new, $hora, $materia, "-", $fecha_new, $fecha_fin_new, $duracion);
|
||||
if($result != ""){//error
|
||||
@@ -81,71 +92,54 @@ if ($tipo == 1) { //Reposición
|
||||
*/
|
||||
//Valida que profesor no este en 2 reposiciones al mismo tiempo en la fecha nueva
|
||||
|
||||
$traslape = $db->querySingle(
|
||||
'SELECT * from traslape_profesor_reposicion(:prof, :fecha, :hora, :dur)',
|
||||
[':prof' => $prof, ':fecha' => DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d'), ':hora' => $hora, ':dur' => $duracion_tiempo]
|
||||
$traslape = $db->querySingle('SELECT * from traslape_profesor_reposicion(:prof, :fecha, :hora, :dur)',
|
||||
[':prof' => $prof, ':fecha'=>DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d'), ':hora'=>$hora, ':dur'=>$duracion_tiempo]
|
||||
)["traslape_profesor_reposicion"];
|
||||
if ($traslape) {
|
||||
if($traslape){
|
||||
//print_r($_POST);
|
||||
//echo "SELECT * from traslape_profesor_reposicion($prof,'".DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d')."' , '$hora', $duracion)";
|
||||
header("Location:" . $pag . "?error=9");
|
||||
header("Location:".$pag."?error=9");
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
$db->query(
|
||||
'SELECT * from fi_reposicion_solicitud(:f_falta, :f_nueva, :hora_nueva, :hor, :prof, 1, :desc, :alumnos, true, :aula, :duracion, :usr, :bloque, :ciclo)',
|
||||
[
|
||||
':f_falta' => $fecha_falta,
|
||||
':f_nueva' => $fecha_new,
|
||||
':hora_nueva' => $hora,
|
||||
':hor' => $hor,
|
||||
':prof' => $prof,
|
||||
':desc' => $comentario,
|
||||
':alumnos' => $alumnos,
|
||||
':aula' => $aula,
|
||||
':duracion' => $duracion_tiempo,
|
||||
':usr' => $user->user["id"],
|
||||
':bloque' => $bloque,
|
||||
':ciclo' => $ciclo
|
||||
try{
|
||||
$db->query('SELECT * from fi_reposicion_solicitud(:f_falta, :f_nueva, :hora_nueva, :hor, :prof, 1, :desc, :alumnos, true, :aula, :duracion, :usr, :bloque, :ciclo)',
|
||||
[':f_falta' => $fecha_falta, ':f_nueva' => $fecha_new, ':hora_nueva' => $hora, ':hor' => $hor,
|
||||
':prof' => $prof, ':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion' => $duracion_tiempo, ':usr'=>$user->user["id"],
|
||||
':bloque' => $bloque, ':ciclo' => $ciclo
|
||||
]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
}catch(Exception $e){
|
||||
echo $e->getMessage();
|
||||
//header("Location: ".$pag."?error=1");
|
||||
exit();
|
||||
}
|
||||
$texto = "<p>Se creó una reposición nueva.</p>";
|
||||
$texto .= "<p><b>".mb_strtoupper($reposicion_rs["materia"])."</b> del día <b>".$fecha_falta." a las ".$hor." hrs. </b> se propone reponer el <b>".$fecha_new." a las ".$hora." hrs.</b>";
|
||||
$texto .= "<p>Ingresa al <a href='https://paad.lci.ulsa.mx'>sistema PAAD</a> para autorizarla.</p>";
|
||||
|
||||
/*
|
||||
/*
|
||||
$log = new LogActividad();
|
||||
$desc_log = "Inserta reposición nueva ID[".$rs["fi_reposicion"]."] Fechas[".$fecha_falta.">".$fecha_new."] Periodo[".$_SESSION["periodo_id"]."] Materia[".$materia."] Profesor[".$prof."] Salon[".$salon."] Horario[".$hor."] Alumnos[".$alumnos."]";
|
||||
$log->appendLog($_SESSION["usuario_id"], $_SESSION["usuario_nombre"]." ".$_SESSION["usuario_apellidos"], $desc_log);*/
|
||||
|
||||
|
||||
} else { //Cambio salón / hora
|
||||
}else{//Cambio salón / hora
|
||||
|
||||
try {
|
||||
$db->query(
|
||||
'SELECT * from fi_reposicion_solicitud(:f_falta, :f_nueva, :hora_nueva, :hor, :prof, 1, :desc, :alumnos, true, :aula, :duracion, :usr, :bloque, :ciclo)',
|
||||
[
|
||||
':f_falta' => $fecha_falta,
|
||||
':f_nueva' => $fecha_cambio,
|
||||
':hora_nueva' => $hora,
|
||||
':hor' => $hor,
|
||||
':prof' => $prof,
|
||||
':desc' => $comentario,
|
||||
':alumnos' => $alumnos,
|
||||
':aula' => $aula,
|
||||
':duracion' => $duracion_tiempo,
|
||||
':usr' => $user->user["id"],
|
||||
':bloque' => $bloque,
|
||||
':ciclo' => $ciclo
|
||||
try{
|
||||
$db->query('SELECT * from fi_reposicion_solicitud(:f_falta, :f_nueva, :hora_nueva, :hor, :prof, 1, :desc, :alumnos, true, :aula, :duracion, :usr, :bloque, :ciclo)',
|
||||
[':f_falta' => $fecha_falta, ':f_nueva' => $fecha_cambio, ':hora_nueva' => $hora, ':hor' => $hor,
|
||||
':prof' => $prof, ':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion' => $duracion_tiempo, ':usr'=>$user->user["id"],
|
||||
':bloque' => $bloque, ':ciclo' => $ciclo
|
||||
]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
header("Location: " . $pag . "?error=1");
|
||||
}catch(Exception $e){
|
||||
header("Location: ".$pag."?error=1");
|
||||
exit();
|
||||
}
|
||||
$texto = "<p>Se creó un cambio de salón nuevo.</p>";
|
||||
$texto .= "<p><b>".mb_strtoupper($reposicion_rs["materia"])."</b> del día <b>".$fecha_falta." a las ".$hora." hrs. </b> se propone reponer el <b>".$fecha_nueva." a las ".$hora_nueva." hrs.</b>";
|
||||
$texto .= "<p>Ingresa al <a href='https://paad.lci.ulsa.mx'>sistema PAAD</a> para autorizarlo.</p>";
|
||||
|
||||
/*
|
||||
$log = new LogActividad();
|
||||
@@ -155,6 +149,24 @@ if ($tipo == 1) { //Reposición
|
||||
|
||||
}
|
||||
|
||||
header("Location: " . $pag . "?ok=0");
|
||||
|
||||
if($to!= "" && ENVIO_CORREOS){
|
||||
$asunto = "Reposición nueva - solicitud";
|
||||
//crear plantilla
|
||||
$texto = '<body >
|
||||
<img src="https://paad.lci.ulsa.mx/imagenes/logo_lasalle.png" alt="La Salle" style="margin-bottom:60px">
|
||||
'.$texto.'
|
||||
</body>';
|
||||
|
||||
require_once('../include/phpmailer/PHPMailerAutoload.php');
|
||||
/*if(DB_NAME == "poad_pruebas"){
|
||||
$asunto = "PRUEBAS-".$asunto;
|
||||
Mailer::enviarCorreo("alejandro.lara@lasalle.mx", $asunto, $texto, true);
|
||||
}else{*/
|
||||
Mailer::enviarCorreo($to, $asunto, $texto, true);
|
||||
//}
|
||||
}
|
||||
|
||||
header("Location: ".$pag."?ok=0");
|
||||
exit();
|
||||
?>
|
||||
@@ -23,13 +23,13 @@ $user = unserialize($_SESSION['user']);
|
||||
|
||||
|
||||
try{
|
||||
if($user->rol["rol_id"] == 9){//es coordinador
|
||||
$rs = $db->querySingle('SELECT * from fs_reposicion(:id, NULL, :fac, NULL, NULL, NULL, NULL, NULL, NULL)',
|
||||
[':id' => $id, ":fac"=>$user->facultad["facultad_id"] ]
|
||||
if($user->rol["rol_id"] == 7){//es supervisor
|
||||
$rs = $db->querySingle('SELECT * from fs_reposicion_solicitud(:id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, :sup)',
|
||||
[':id' => $id, ':sup'=>$user->user["id"]]
|
||||
);
|
||||
}else{//supervisor
|
||||
$rs = $db->querySingle('SELECT * from fs_reposicion(:id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)',
|
||||
[':id' => $id]
|
||||
}else{//coordinador
|
||||
$rs = $db->querySingle('SELECT * from fs_reposicion_solicitud(:id, :fac, NULL, NULL, NULL, NULL, NULL, NULL, null)',
|
||||
[':id' => $id, ":fac"=>$user->facultad["facultad_id"] ]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,18 +104,18 @@ if($tipo == 1){//Reposición
|
||||
}
|
||||
|
||||
try{
|
||||
$db->query('SELECT * from fu_reposicion_solicitud(:id, :f_falta, :f_nueva, :hora_nueva, NULL, 1, :desc, :alumnos, :aula, :duracion_id, NULL)',
|
||||
$db->query('SELECT * from fu_reposicion_solicitud(:id, :f_falta, :f_nueva, :hora_nueva, NULL, 1, :desc, :alumnos, :aula, :duracion, NULL)',
|
||||
[':id'=> $id, ':f_falta' => $fecha_falta, ':f_nueva' => $fecha_new, ':hora_nueva' => $hora,
|
||||
':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion_id' => $duracion_id
|
||||
':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion' => $duracion_tiempo
|
||||
]
|
||||
);
|
||||
}catch(Exception $e){
|
||||
//header("Location: ".$pag."?error=2");
|
||||
print_r($e->getMessage());
|
||||
echo "SELECT * from fu_reposicion_solicitud(:id, :f_falta, :f_nueva, :hora_nueva, NULL, 1, :desc, :alumnos, :aula, :duracion_id, NULL)'";
|
||||
echo "SELECT * from fu_reposicion_solicitud(:id, :f_falta, :f_nueva, :hora_nueva, NULL, 1, :desc, :alumnos, :aula, :duracion, NULL)'";
|
||||
print_r(
|
||||
[':id'=> $id, ':f_falta' => $fecha_falta, ':f_nueva' => $fecha_new, ':hora_nueva' => $hora,
|
||||
':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion_id' => $duracion_id
|
||||
':desc' => $comentario, ':alumnos' => $alumnos, ':aula' => $aula, ':duracion' => $duracion_tiempo
|
||||
]);
|
||||
exit();
|
||||
}
|
||||
|
||||
104
auditoria.php
104
auditoria.php
@@ -57,10 +57,11 @@
|
||||
<? exit;
|
||||
} ?>
|
||||
|
||||
<main class="container-fluid px-4 mt-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 60vh;">
|
||||
<!-- {{ store.current }} -->
|
||||
<main class="container-fluid px-4 mt-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 60vh;"
|
||||
v-scope="">
|
||||
<!-- {{ store.filters }} -->
|
||||
<?php include "import/periodo.php" ?>
|
||||
<div class="form-box">
|
||||
<div class="form-box marco">
|
||||
<div class="form-group row">
|
||||
<? if (!$user->facultad['facultad_id']) { ?>
|
||||
<label for="dlFacultad" class="col-4 col-form-label">Facultad</label>
|
||||
@@ -71,7 +72,7 @@
|
||||
</div>
|
||||
<span class="icono ing-buscar"></span>
|
||||
<ul style="display:none">
|
||||
<li class="datalist-option" data-id="0"
|
||||
<li class="datalist-option" data-id="-1"
|
||||
@click="store.filters.facultad_id = null; store.current.page = 1;">
|
||||
Todas las facultades
|
||||
</li>
|
||||
@@ -217,15 +218,19 @@
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex justify-content-between flex-wrap align-items-center">
|
||||
<!-- botón descargar -->
|
||||
<? if ($user->acceso == 'w') { ?>
|
||||
<!-- botón justificar profesores -->
|
||||
<div class="col-md-2 col-12 text-center">
|
||||
<div class="btn-group my-3">
|
||||
<button type="button" class="btn btn-outline-primary mr-3">
|
||||
<button type="button" class="btn btn-outline-primary mr-3" data-toggle="modal"
|
||||
data-target="#justificar-profesores">
|
||||
Justificar profesores
|
||||
<i class="ing-justificar"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<? } ?>
|
||||
|
||||
<!-- botón descargar -->
|
||||
<div class="col-md-2 col-12 text-center">
|
||||
<div class="btn-group my-3" v-if="store.registros.relevant.length > 0">
|
||||
@@ -556,7 +561,8 @@
|
||||
<div class="col-12 text-center">
|
||||
Esta clase se reprogramó para el día
|
||||
{{ clase_vista.reposicion_fecha }} a las
|
||||
{{ clase_vista.reposicion_hora?.slice(0, 5) }} - {{clase_vista.reposicion_hora_fin?.slice(0, 5) }}
|
||||
{{ clase_vista.reposicion_hora?.slice(0, 5) }} -
|
||||
{{clase_vista.reposicion_hora_fin?.slice(0, 5) }}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -641,10 +647,92 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" tabindex="-1" id="justificar-profesores" data-backdrop="static" data-keyboard="false"
|
||||
v-scope="{
|
||||
justificacion: {
|
||||
fecha: null,
|
||||
bloques: [],
|
||||
observaciones: null
|
||||
}
|
||||
}">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
Justificación de profesores
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="lead">
|
||||
Selecciona los bloques que deseas justificar, puedes seleccionar varios bloques
|
||||
<small>
|
||||
Todos los profesores que tengan clases en los bloques seleccionados serán justificados
|
||||
</small>
|
||||
</p>
|
||||
<form>
|
||||
<div class="form-group row" v-if="store.periodo">
|
||||
<label for="fecha-justificación" class="col-sm-4 col-form-label barra-right">Fecha de la
|
||||
justificación</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="date" class="form-control" id="fecha-justificación"
|
||||
:min="store.periodo.periodo_fecha_inicio" :max="store.periodo.periodo_fecha_fin"
|
||||
v-model="justificacion.fecha">
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="form-group row">
|
||||
<legend class="col-form-label col-sm-4 float-sm-left pt-0 barra-right">
|
||||
Bloques horario
|
||||
</legend>
|
||||
<div class="col-sm-8">
|
||||
<select class="custom-select" multiple v-model="justificacion.bloques">
|
||||
<option selected disabled>Seleccione los bloques</option>
|
||||
<option disabled><strong>Mañana</strong></option>
|
||||
<option
|
||||
v-for="bloque in store.bloques_horario.data.filter(bloque => bloque.hora_inicio < '13:00:00')"
|
||||
:key="bloque.id" :value="bloque.id" class="text-center">
|
||||
{{bloque.hora_inicio.substr(0,5)}} - {{bloque.hora_fin.substr(0,5)}}
|
||||
</option>
|
||||
<option disabled><strong>Tarde</strong></option>
|
||||
<option
|
||||
v-for="bloque in store.bloques_horario.data.filter(bloque => bloque.hora_inicio >= '13:00:00')"
|
||||
:key="bloque.id" :value="bloque.id" class="text-center">
|
||||
{{bloque.hora_inicio.substr(0,5)}} - {{bloque.hora_fin.substr(0,5)}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-group row">
|
||||
<label for="observaciones" class="col-sm-4 col-form-label barra-right">
|
||||
Observaciones
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea class="form-control" id="observaciones" rows="3"
|
||||
v-model="justificacion.observaciones"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-danger" data-dismiss="modal">Cancelar</button>
|
||||
<button type="button" class="btn btn-primary"
|
||||
:disabled="Object.keys(justificacion).some(key => !justificacion[key])" @click="
|
||||
store.justificarBloque(justificacion.fecha, justificacion.bloques, justificacion.observaciones);
|
||||
Object.keys(justificacion).forEach(key => justificacion[key] = null);
|
||||
">
|
||||
Justificar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<? } ?>
|
||||
</main>
|
||||
|
||||
<!-- <script src="js/datalist.js"></script> -->
|
||||
<!-- <script src=" js/datalist.js"></script> -->
|
||||
<script src="js/datepicker-es.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
|
||||
<script src="js/auditoría.js?<?= rand(0, 2) ?>" type="module"></script>
|
||||
|
||||
82
class/mailer.php
Normal file
82
class/mailer.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
//https://github.com/PHPMailer/PHPMailer
|
||||
//require_once('../include/phpmailer/PHPMailerAutoload.php');
|
||||
|
||||
class Mailer{
|
||||
private const FROM = "academia@lasalle.mx";
|
||||
private const FROM_NAME = "Vicerrectoría Académica";
|
||||
private const FROM_PASS = "Foy25193";
|
||||
private const FOOTER = "<p style='margin-top:5em; color:#aaa;font-style:italics'><small>Este es un correo automatizado, esta cuenta no recibe correos.<small></p>";
|
||||
//private $lista_to, $asunto, $texto;
|
||||
|
||||
/**
|
||||
* Función estática para mandar correos. Los destinatarios pueden ser arreglo o cadena separada por ; incluir: include/phpmailer/PHPMailerAutoload.php
|
||||
*
|
||||
* @param array|string $lista_to El destinatario o lista de destinatarios. Puede ser un arreglo de direcciones de correo electrónico o una cadena de texto con direcciones de correo separadas por ;.
|
||||
* @param string $asunto El asunto del correo.
|
||||
* @param string $texto El cuerpo del mensaje del correo en HTML.
|
||||
* @param bool $bcc Indica si se debe enviar el correo como copia oculta (true) o no (false). Valor por defecto: false.
|
||||
*
|
||||
* @return bool True si el correo se envió exitosamente, false en caso contrario.
|
||||
*/
|
||||
public static function enviarCorreo($lista_to, $asunto, $texto, $bcc = false){
|
||||
try{
|
||||
//SMTP Settings
|
||||
$mail = new PHPMailer();
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->SMTPDebug = 0;
|
||||
$mail->isSMTP();
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->SMTPSecure = 'TLS';
|
||||
$mail->Host = "smtp.office365.com";
|
||||
$mail->Port = 587;
|
||||
$mail->Username = self::FROM;
|
||||
$mail->Password = self::FROM_PASS;
|
||||
|
||||
$mail->SetFrom(self::FROM, self::FROM_NAME); //from (verified email address)
|
||||
$mail->Subject = $asunto; //subject
|
||||
|
||||
$mail->IsHTML(true);
|
||||
$mail->MsgHTML($texto.self::FOOTER);//adjunta footer
|
||||
//recipient
|
||||
if(is_array($lista_to)){
|
||||
foreach($lista_to as $correo){
|
||||
if(trim($correo)!="")
|
||||
if($bcc)
|
||||
$mail->addBCC($correo);
|
||||
else
|
||||
$mail->AddAddress($correo);
|
||||
}
|
||||
}else{//cadena de texto separada por ;
|
||||
if(strpos($lista_to, ";")!==false){
|
||||
$toArr = explode(";", $lista_to);
|
||||
}elseif(strpos($lista_to, ",")!==false){
|
||||
$toArr = explode(",", $lista_to);
|
||||
}else{
|
||||
echo "Cadena de correos inválida";
|
||||
return false;
|
||||
}
|
||||
foreach($toArr as $correo){
|
||||
if(trim($correo)!=""){
|
||||
if($bcc)
|
||||
$mail->addBCC($correo);
|
||||
else
|
||||
$mail->AddAddress($correo);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Success
|
||||
if ($mail->Send()) {
|
||||
return true;
|
||||
}
|
||||
}catch(phpmailerException $e){
|
||||
echo $mail->ErrorInfo;
|
||||
return false;
|
||||
}catch(Exception $e2){
|
||||
echo $mail->ErrorInfo;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +1,115 @@
|
||||
<?php
|
||||
require_once 'class/c_login.php';
|
||||
require_once 'include/bd_pdo.php';
|
||||
if (!isset($_SESSION['user'])){
|
||||
die(header('Location: index.php'));
|
||||
}
|
||||
|
||||
//$user = unserialize($_SESSION['user']);
|
||||
$user = Login::get_user();
|
||||
|
||||
$user->access();
|
||||
if($user->acceso == null){
|
||||
header('Location: main.php?error=1');
|
||||
}else{
|
||||
$user->print_to_log('Dias_festivos');
|
||||
if ($user->acceso === null && !$user->admin){
|
||||
die(header('Location: index.php'));
|
||||
exit();
|
||||
}
|
||||
if(isset($_GET['facultad'])){
|
||||
$fac = $_GET['facultad'];
|
||||
}else if($user->admin){
|
||||
$fac = null;
|
||||
}else{
|
||||
$fac = $user->facultad['facultad_id'];
|
||||
|
||||
$fs_dias_festivos = $db->query("SELECT d.diasfestivos_id, d.diasfestivos_dia , p.periodo_id , p.periodo_nombre, extract(dow from diasfestivos_dia) AS dia_id from diasfestivos d
|
||||
join periodo p on p.periodo_id = any (d.periodos_id)
|
||||
order by d.diasfestivos_dia DESC");
|
||||
|
||||
|
||||
|
||||
$dias_arr = array();
|
||||
foreach ($fs_dias_festivos as $dia){
|
||||
if(isset($dias_arr[$dia["diasfestivos_id"]])){
|
||||
$dias_arr[$dia["diasfestivos_id"]]["periodos"][] = array("periodo_id"=>$dia["periodo_id"], "periodo_nombre"=>$dia["periodo_nombre"]);
|
||||
}else{
|
||||
$dias_arr[$dia["diasfestivos_id"]] = array("diasfestivos_id"=>$dia["diasfestivos_id"], "diasfestivos_dia"=>$dia["diasfestivos_dia"], "dia_id"=>$dia["dia_id"],
|
||||
"periodos"=>array(array("periodo_id"=>$dia["periodo_id"], "periodo_nombre"=>$dia["periodo_nombre"]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$dias_nombres=array("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado");
|
||||
|
||||
$write = true;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Días Festivos</title>
|
||||
<link rel="stylesheet" href="css/jquery-ui.css">
|
||||
<link rel="stylesheet" href="css/calendar.css">
|
||||
<link rel="stylesheet" href="css/toggle.css" type="text/css">
|
||||
<title>Días festivos</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="content-type" content="text/plain; charset=UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<?php
|
||||
include 'import/html_css_files.php';
|
||||
?>
|
||||
<link rel="stylesheet" href="css/jquery-ui.css">
|
||||
<link rel="stylesheet" href="css/calendar.css">
|
||||
<link rel="stylesheet" href="css/toggle.css" type="text/css">
|
||||
<script src="js/scrollables.js" defer></script>
|
||||
<script>
|
||||
const write = <?= $write ? 'true' : 'false' ?>;
|
||||
</script>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/bootstrap/popper.min.js"></script>
|
||||
<script src="js/bootstrap/bootstrap.min.js"></script>
|
||||
<script src="js/jquery-ui.js"></script>
|
||||
<script src="js/datepicker-es.js"></script>
|
||||
<script src="js/messages.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body style="display: block;">
|
||||
<?php
|
||||
include "import/html_header.php";
|
||||
html_header(
|
||||
"DÍAS FESTIVOS",
|
||||
"Gestión de Checador "
|
||||
);
|
||||
$user->access();
|
||||
$fs_dias_festivos = query("SELECT * FROM fs_diasfestivos(:facultad, null, null, null) ORDER BY diasfestivos_dia", [':facultad' => $fac], false);
|
||||
$fs_periodos = query("SELECT * FROM fs_periodos(null, null) WHERE estado = 'Activo'", null, false);
|
||||
$fs_dias_festivos_generales = query("SELECT * FROM fs_diasfestivos(null, null) ORDER BY diasfestivos_dia", null, false);
|
||||
include('include/constantes.php');
|
||||
include("import/html_header.php");
|
||||
html_header("Días festivos", "Sistema de gestión de checador");
|
||||
?>
|
||||
<main class="content marco">
|
||||
<?= "<!-- $user -->" ?>
|
||||
<main class="container content marco content-margin" id="local-app">
|
||||
|
||||
<section id="message"></section>
|
||||
|
||||
<?php if($user->admin){ ?>
|
||||
<div class="col-12 text-right">
|
||||
<button type="button" class="btn btn-outline-secondary" data-toggle="modal" data-target="#modal" data-tipo="1"><span class="ing-mas ing-fw"></span> Agregar Día Festivo</button>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div id="message"></div>
|
||||
<form action="dias_festivos.php" method="post" class="">
|
||||
<div class="form-box">
|
||||
<div class="form-group row">
|
||||
<label for="filter_fecha_ini" class="col-4 col-form-label">Fecha inicial</label>
|
||||
<div class="col-8 col-sm-4">
|
||||
<input id="filter_fecha_ini" name="fecha_ini" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="" value="<?php echo $fecha_ini;?>">
|
||||
<div class="invalid-feedback">No es una fecha válida.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="filter_fecha_fin" class="col-4 col-form-label">Fecha final</label>
|
||||
<div class="col-8 col-sm-4">
|
||||
<input id="filter_fecha_fin" name="fecha_fin" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="" value="<?php echo $fecha_fin;?>">
|
||||
<div class="invalid-feedback">No es una fecha válida.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 text-center">
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<span class="ing-buscar ing-fw"></span>
|
||||
Filtrar
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-reset">
|
||||
<span class="ing-borrar ing-fw"></span>
|
||||
Limpiar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!-- Tabla -->
|
||||
<?php if($fs_dias_festivos || $fs_dias_festivos_generales){ ?>
|
||||
<?php
|
||||
if(count($dias_arr) > 0){ ?>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 table-responsive">
|
||||
<table class="table table-sm table-striped table-white">
|
||||
@@ -61,46 +117,37 @@ if(isset($_GET['facultad'])){
|
||||
<tr>
|
||||
<th>Día</th>
|
||||
<th>Periodo</th>
|
||||
<th>Nivel</th>
|
||||
<?php if($user->admin){ ?>
|
||||
<th>Facultad</th>
|
||||
<th>Acciones</th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($fs_dias_festivos as $dia){ ?>
|
||||
<?php foreach($dias_arr as $dia){ ?>
|
||||
<tr data-id="<?= $dia['diasfestivos_id'] ?>" id="<?= $dia['diasfestivos_id'] ?>" data-periodo="1">
|
||||
<td class="text-center"><?php $day = explode("-", $dia['diasfestivos_dia']);
|
||||
echo $day['2']."-".$day['1']."-".$day['0'];
|
||||
<td class="text-center text-nowrap align-middle">
|
||||
<?php $day = explode("-", $dia['diasfestivos_dia']);
|
||||
echo $dias_nombres[$dia["dia_id"]]."<br>";
|
||||
echo $day[2]."/".$day[1]."/".$day[0];
|
||||
?></td>
|
||||
<td class="text-center"><?= $dia['periodo_nombre'] ?></td>
|
||||
<td class="text-center"><?= $dia['nivel_nombre'] ?></td>
|
||||
<td>
|
||||
<ul class="mb-0">
|
||||
<?
|
||||
foreach($dia["periodos"] as $per){
|
||||
echo "<li>".$per['periodo_nombre']."</li>";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</td>
|
||||
<?php if($user->admin){ ?>
|
||||
<td class="text-center"><?= $dia['facultad_nombre'] ?></td>
|
||||
<td class="text-center icono-acciones">
|
||||
<a href="#" data-toggle="modal" data-target="#modal" data-tipo="2" title="Editar"><span class="ing-editar ing-fw"></span></a>
|
||||
<a href="#" data-toggle="modal" data-target="#modal_confirm" title="Borrar"><span class="ing-basura ing-fw"></span></a>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<?php foreach($fs_dias_festivos_generales as $dia){ ?>
|
||||
<tr data-id="<?= $dia['diasfestivos_id'] ?>" id="<?= $dia['diasfestivos_id'] ?>" data-periodo="0">
|
||||
<td class="text-center"><?php $day = explode("-", $dia['diasfestivos_dia']);
|
||||
echo $day['2']."-".$day['1']."-".$day['0'];
|
||||
?></td>
|
||||
<td class="text-center">Todos</td>
|
||||
<td class="text-center">Todos</td>
|
||||
<?php if($user->admin){ ?>
|
||||
<td class="text-center">Todas</td>
|
||||
<td class="text-center icono-acciones">
|
||||
<td class="text-center icono-acciones align-middle">
|
||||
<a href="#" data-toggle="modal" data-target="#modal" data-tipo="2" title="Editar"><span class="ing-editar ing-fw"></span></a>
|
||||
<a href="#" data-toggle="modal" data-target="#modal_confirm" title="Borrar"><span class="ing-basura ing-fw"></span></a>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -129,22 +176,6 @@ if(isset($_GET['facultad'])){
|
||||
<form action="" method="post" id="formaModal" onsubmit="return valida_campos()">
|
||||
<input type="hidden" name="id" id="id">
|
||||
<div class="form-box">
|
||||
<div class="form-group row">
|
||||
<label for="periodo" class="col-3 col-form-label">Periodo *</label>
|
||||
<div class="col-8">
|
||||
<div class="datalist datalist-select mb-1 w-100">
|
||||
<div class="datalist-input" id="fac">Mostrar todos</div>
|
||||
<span class="ing-buscar icono"></span>
|
||||
<ul style="display:none">
|
||||
<li data-id="0" class="pl4-">Todos</li>
|
||||
<?php foreach($fs_periodos as $periodo){ ?>
|
||||
<li data-id="<?= $periodo['id'] ?>" class="pl4-"> <?php echo $periodo['periodo']." ".$periodo['facultad']." - ".$periodo['nivel']; ?></li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
<input type="hidden" id="periodo" name="periodo" value="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row" id="rangoDiv">
|
||||
<label for="rango" class="col-3 col-form-label">Rango</label>
|
||||
<div class="col-8">
|
||||
@@ -157,13 +188,26 @@ if(isset($_GET['facultad'])){
|
||||
<input id="diaFestivo" name="diaFestivo" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="">
|
||||
</div>
|
||||
<div class="col-1 diaFestivoRango">
|
||||
-
|
||||
<span class="ing-menos"></span>
|
||||
</div>
|
||||
<div class="col-4 diaFestivoRango" id="diaFestivoRango">
|
||||
<input id="diaFestivoFin" name="diaFestivoFin" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="">
|
||||
</div>
|
||||
<div class="invalid-feedback">Debe seleccionar una fecha</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row" id="periodos">
|
||||
<label for="periodos" class="col-3 col-form-label">Periodos</label>
|
||||
<div class="col-7">
|
||||
<select multiple="multiple" size="4" class="form-control">
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<button class="btn btn-outline-primary"><span class="ing-mas"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="offset-4 col-8">
|
||||
<button type="submit" class="btn btn-outline-primary" id="submitBtn" data-tipo="1">
|
||||
@@ -203,7 +247,7 @@ if(isset($_GET['facultad'])){
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/jquery-ui.js"></script>
|
||||
<script src="js/bootstrap/bootstrap.min.js"></script>
|
||||
<script src="js/datalist.js"></script>
|
||||
|
||||
<script src="js/datepicker-es.js"></script>
|
||||
<script src="js/toggle.js"></script>
|
||||
<?php
|
||||
@@ -251,7 +295,7 @@ if(isset($_GET['facultad'])){
|
||||
changeMonth: true,
|
||||
});
|
||||
|
||||
<?php if(!$fs_dias_festivos && !$fs_dias_festivos_generales){ ?>
|
||||
<?php if(count($dias_arr) == 0){ ?>
|
||||
triggerMessage("No se encontraron días festivos", "Error");
|
||||
<?php } ?>
|
||||
|
||||
|
||||
65
export/control.php
Normal file
65
export/control.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<button onclick="getExcel()">
|
||||
Get excel
|
||||
</button>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
|
||||
<script>
|
||||
async function getExcel() {
|
||||
const res = await fetch('supervisor_excel.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify([
|
||||
{
|
||||
"profesor_id": 1089,
|
||||
"estado_supervisor_id": 1,
|
||||
"horario_id": 3538,
|
||||
"registro_id": 1,
|
||||
"registro_fecha": null,
|
||||
"registro_retardo": null,
|
||||
"registro_justificada": null,
|
||||
"registro_fecha_ideal": "2023-08-03",
|
||||
"comentario": "Hola mundo",
|
||||
"registro_fecha_supervisor": "2023-08-03 12:21:38.336147",
|
||||
"supervisor_id": 6,
|
||||
"justificacion": null,
|
||||
"fecha_justificacion": null,
|
||||
"horario_hora": "12:00:00",
|
||||
"horario_fin": "13:30:00",
|
||||
"horario_grupo": "MG 45030102",
|
||||
"horario_dia": 4,
|
||||
"dia": "jueves",
|
||||
"duracion_id": 2,
|
||||
"duracion": "01:30:00",
|
||||
"carrera_id": 439,
|
||||
"carrera": "LICENCIATURA EN INGENIERÍA ELECTRÓNICA PARA SISTEMAS INTELIGENTES",
|
||||
"facultad_id": 28,
|
||||
"facultad": "FACULTAD DE INGENIERÍA",
|
||||
"periodo_id": null,
|
||||
"periodo": "LICENCIATURA: agosto - noviembre 2023",
|
||||
"materia_id": 191,
|
||||
"materia": "Dinámica",
|
||||
"nivel_id": 1,
|
||||
"nivel": "Licenciatura",
|
||||
"salon_id": 1245,
|
||||
"salon": "ING MM 208",
|
||||
"nombre": "Asistencia",
|
||||
"estado_color": "success",
|
||||
"estado_icon": "ing-autorizar",
|
||||
"profesor_nombre": "ISRAEL WOOD CANO",
|
||||
"profesor_clave": "008999",
|
||||
"profesor_correo": "israel.wood@lasallistas.org.mx",
|
||||
"profesor_grado": null,
|
||||
"usuario_id": 6,
|
||||
"usuario_nombre": "Francisco Javier Garrido Alfaro",
|
||||
"usuario_correo": null,
|
||||
"usuario_admin": false,
|
||||
"usuario_clave": "ad011538",
|
||||
"rol_id": 7
|
||||
}
|
||||
])
|
||||
});
|
||||
const blob = await res.blob();
|
||||
saveAs(blob, 'excel.xlsx');
|
||||
}
|
||||
</script>
|
||||
139
export/horario_excel.php
Normal file
139
export/horario_excel.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
$ruta = "../";
|
||||
require_once "../vendor/autoload.php";
|
||||
require_once "../class/c_login.php";
|
||||
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
//crea imagen
|
||||
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
||||
$drawing->setName('La Salle');
|
||||
$drawing->setDescription('La Salle');
|
||||
$drawing->setPath('../imagenes/logo.png'); // put your path and image here
|
||||
$drawing->setCoordinates('A1');
|
||||
$drawing->setHeight(100);
|
||||
$drawing->setOffsetX(10);
|
||||
//agrega imagen
|
||||
$drawing->setWorksheet($spreadsheet->getActiveSheet());
|
||||
|
||||
|
||||
extract($_POST);
|
||||
$row = 6;
|
||||
$sábado = $sábado == 'true';
|
||||
$sheet->setCellValue("A$row", 'Hora');
|
||||
$sheet->setCellValue("B$row", 'Lunes');
|
||||
$sheet->setCellValue("C$row", 'Martes');
|
||||
$sheet->setCellValue("D$row", 'Miércoles');
|
||||
$sheet->setCellValue("E$row", 'Jueves');
|
||||
$sheet->setCellValue("F$row", 'Viernes');
|
||||
if ($sábado)
|
||||
$sheet->setCellValue("G$row", 'Sábado');
|
||||
|
||||
// to this row set bold, font size 12 and Indivisa Sans, and center the text, bg color to #101097, color to white,
|
||||
$until = $sábado ? 'G' : 'F';
|
||||
|
||||
$sheet->getStyle("A$row:$until$row")->getFont()->setBold(true);
|
||||
$sheet->getStyle("A$row:$until$row")->getFont()->setSize(15);
|
||||
$sheet->getStyle("A$row:$until$row")->getFont()->setName('Indivisa Display Sans');
|
||||
$sheet->getStyle("A$row:$until$row")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle("A$row:$until$row")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
||||
$sheet->getStyle("A$row:$until$row")->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$sheet->getStyle("A$row:$until$row")->getFill()->getStartColor()->setARGB('001d68');
|
||||
$sheet->getStyle("A$row:$until$row")->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
|
||||
|
||||
# the first column is the hour of the day merged with 4 rows each
|
||||
$row++;
|
||||
foreach (range($min, $max) as $hour) {
|
||||
$sheet->setCellValue("A$row", "$hour:00");
|
||||
$sheet->mergeCells("A$row:A" . ($row + 3));
|
||||
|
||||
for ($i = 0; $i < 4; $i++)
|
||||
$sheet->getRowDimension($row + $i)->setRowHeight(25);
|
||||
|
||||
|
||||
// align to center
|
||||
$sheet->getStyle("A$row")->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle("A$row")->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
||||
|
||||
$sheet->getStyle("A$row")->getFont()->setBold(true);
|
||||
$sheet->getStyle("A$row")->getFont()->setName('Indivisa Text Sans');
|
||||
$sheet->getStyle("A$row")->getFont()->setSize(12);
|
||||
|
||||
|
||||
$row += 4;
|
||||
}
|
||||
|
||||
|
||||
# Size columns to 30
|
||||
foreach (range('A', 'G') as $column) {
|
||||
if ($column == 'G' && !$sábado)
|
||||
continue;
|
||||
$sheet->getColumnDimension($column)->setWidth(($column == 'A' ? 10 : 30));
|
||||
}
|
||||
|
||||
# foreach horarios
|
||||
$row = 7;
|
||||
$días = ['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'];
|
||||
$lista_minutos = ['00', '15', '30', '45'];
|
||||
foreach (json_decode($horarios) as $horario) {
|
||||
[$hora, $minutos] = array_map(fn($x) => intval($x), explode(':', $horario->hora));
|
||||
$rowHora = $row + ($hora - $min) * 4;
|
||||
$rowHora += array_search($minutos, $lista_minutos);
|
||||
|
||||
$colHora = array_search($horario->dia, $días) + 2;
|
||||
$content = new \PhpOffice\PhpSpreadsheet\RichText\RichText();
|
||||
$content->createText("$horario->hora");
|
||||
// $content = "$horario->hora $horario->materia\n$horario->salon\n$horario->profesor";
|
||||
$content->createTextRun(" $horario->materia\n")->getFont()->setBold(true)->setName('Indivisa Text Sans')->setSize(12);
|
||||
$content->createTextRun("Salón: $horario->salon\n")->getFont()->setBold(true);
|
||||
foreach ($horario->profesores as $profesor) $content->createTextRun("🎓 $profesor->profesor\n")->getFont()->setBold(true);
|
||||
// APPLY THE FONT FAMILY
|
||||
$sheet->setCellValueByColumnAndRow($colHora, $rowHora, $content);
|
||||
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
|
||||
|
||||
// merge cells
|
||||
$sheet->mergeCellsByColumnAndRow($colHora, $rowHora, $colHora, $rowHora + $horario->bloques - 1);
|
||||
// set border white
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getBorders()->getOutline()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getBorders()->getOutline()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
|
||||
// set bg color d4d9dd
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID);
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getFill()->getStartColor()->setARGB('d4d9dd');
|
||||
|
||||
// set font size 12
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getFont()->setSize(12);
|
||||
// set font name Indivisa Text Sans
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getFont()->setName('Indivisa Text Sans');
|
||||
// set font color 001d68z
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getFont()->getColor()->setARGB('001d68');
|
||||
|
||||
// wrap text
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getAlignment()->setWrapText(true);
|
||||
// border white
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getBorders()->getOutline()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
$sheet->getStyleByColumnAndRow($colHora, $rowHora)->getBorders()->getOutline()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
|
||||
}
|
||||
|
||||
|
||||
#$writer = new Xlsx($spreadsheet);
|
||||
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||
# $writer->save('asistencias.xlsx');
|
||||
|
||||
// download
|
||||
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
header('Content-Disposition: attachment;filename="asistencias.xlsx"');
|
||||
header('Cache-Control: max-age=0');
|
||||
|
||||
// cache expires in 60 seconds (1 minute)
|
||||
header('Expires: mon 26 jul 1997 05:00:00 gmt');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
header('Cache-Control: cache, must-revalidate');
|
||||
header('Pragma: public');
|
||||
|
||||
$writer->save('php://output');
|
||||
179
export/supervisor_excel.php
Normal file
179
export/supervisor_excel.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
$fecha = date('d_m_Y');
|
||||
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
header("Content-Disposition: attachment;filename=horario_$fecha.xlsx");
|
||||
header("Cache-Control: max-age=0");
|
||||
|
||||
require_once "../vendor/autoload.php";
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
// Image settings
|
||||
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
||||
$drawing->setName('La Salle')
|
||||
->setDescription('La Salle')
|
||||
->setPath('../imagenes/logo.png')
|
||||
->setCoordinates('B1')
|
||||
->setHeight(100)
|
||||
->setOffsetX(10)
|
||||
->setWorksheet($spreadsheet->getActiveSheet());
|
||||
|
||||
$json = file_get_contents('php://input');
|
||||
$data = json_decode($json, true);
|
||||
|
||||
empty($data) and die(json_encode(['error' => 'No se recibieron datos', 'data' => $data]));
|
||||
|
||||
$data_excel = array(
|
||||
"FECHA" => 'registro_fecha_ideal',
|
||||
"CLAVE" => 'profesor_clave',
|
||||
"PROFESOR" => 'profesor_nombre',
|
||||
"CORREO" => 'profesor_correo',
|
||||
"FACULTAD" => 'facultad',
|
||||
"MATERIA" => 'materia',
|
||||
"CARRERA / PROGRAMA" => 'carrera',
|
||||
"GRUPO" => 'horario_grupo',
|
||||
"HORARIO" => 'horario_hora_completa',
|
||||
"SALÓN" => 'salon',
|
||||
"REGISTRO PROFESOR" => 'asistencia',
|
||||
"HORA DE REGISTRO" => 'registro_fecha',
|
||||
"NOMBRE SUPERVISOR" => 'usuario_nombre',
|
||||
"REGISTRO SUPERVISOR" => 'nombre',
|
||||
"HORA DE SUPERVISIÓN" => 'registro_fecha_supervisor',
|
||||
"OBSERVACIONES" => 'comentario',
|
||||
"JUSTIFICACIÓN" => 'justificacion',
|
||||
); // Same as before
|
||||
|
||||
|
||||
|
||||
const ROW = 6;
|
||||
// Merge cells from A1 to C+ ROW
|
||||
$sheet->mergeCells('A1:C' . (ROW - 1));
|
||||
// Merge cells from D1 to size of $data_excel + 1
|
||||
$sheet->mergeCells('D1:' . chr(65 + count($data_excel) - 1) . (ROW - 1));
|
||||
|
||||
// Set the title in D1 Sistema de Auditoría de Asistencia
|
||||
$sheet->setCellValue('D1', 'Sistema de Auditoría de Asistencia');
|
||||
$sheet->getStyle('D1')->applyFromArray([
|
||||
'font' => [
|
||||
'bold' => true,
|
||||
'size' => 30,
|
||||
'name' => 'Indivisa Text Sans',
|
||||
'color' => ['argb' => '001d68'],
|
||||
],
|
||||
'alignment' => [
|
||||
'vertical' => Alignment::VERTICAL_CENTER,
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
$lastColumnLetter = chr(65 + count($data_excel) - 1);
|
||||
$headers_range = 'A' . ROW . ':' . $lastColumnLetter . ROW;
|
||||
|
||||
$keys = array_keys($data_excel);
|
||||
array_walk($keys, function ($key, $index) use ($sheet) {
|
||||
$sheet->setCellValue(chr(65 + $index) . ROW, $key);
|
||||
});
|
||||
// Apply the header styles
|
||||
$sheet->getStyle($headers_range)->applyFromArray([
|
||||
'font' => [
|
||||
'bold' => true,
|
||||
'size' => 15,
|
||||
'name' => 'Indivisa Text Sans',
|
||||
'color' => ['argb' => Color::COLOR_WHITE],
|
||||
],
|
||||
'alignment' => [
|
||||
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
||||
'vertical' => Alignment::VERTICAL_CENTER,
|
||||
],
|
||||
'fill' => [
|
||||
'fillType' => Fill::FILL_SOLID,
|
||||
'startColor' => ['argb' => '001d68'],
|
||||
]
|
||||
]);
|
||||
|
||||
// set filters
|
||||
$sheet->setAutoFilter($headers_range);
|
||||
|
||||
|
||||
|
||||
// Styles that are common for all rows can be set outside the loop
|
||||
|
||||
const DEFAULT_FONT = [
|
||||
'size' => 12,
|
||||
'name' => 'Indivisa Text Sans',
|
||||
'color' => ['argb' => '001d68']
|
||||
];
|
||||
|
||||
const DEFAULT_STYLE = [
|
||||
'alignment' => [
|
||||
'vertical' => Alignment::VERTICAL_CENTER,
|
||||
'wrapText' => true,
|
||||
],
|
||||
'font' => DEFAULT_FONT,
|
||||
'borders' => [
|
||||
'outline' => [
|
||||
'borderStyle' => Border::BORDER_THIN,
|
||||
'color' => ['argb' => Color::COLOR_WHITE],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
function getFormattedValue($key, $registro)
|
||||
{
|
||||
return match ($key) {
|
||||
'asistencia' => is_null($registro['registro_fecha'])
|
||||
? "Sin registro"
|
||||
: ($registro['registro_retardo'] ? "Retardo " : "Asistencia "),
|
||||
'registro_fecha', 'registro_fecha_supervisor' =>
|
||||
is_null($registro[$key])
|
||||
? 'Sin registro'
|
||||
: date('H:i', strtotime($registro[$key])),
|
||||
'nombre' => $registro[$key] ?? "Sin registro",
|
||||
'horario_hora_completa' => "{$registro['horario_hora']} - {$registro['horario_fin']}",
|
||||
'usuario_nombre', 'justificacion', 'comentario' =>
|
||||
$registro[$key] ?? "Sin registro",
|
||||
default => $registro[$key]
|
||||
};
|
||||
}
|
||||
|
||||
foreach ($data as $index => $registro) {
|
||||
$pair = $index % 2 == 0;
|
||||
$cellRange = 'A' . (ROW + $index + 1) . ':' . $lastColumnLetter . (ROW + $index + 1);
|
||||
$styleArray = DEFAULT_STYLE;
|
||||
$styleArray['fill'] = [
|
||||
'fillType' => Fill::FILL_SOLID,
|
||||
'startColor' => ['argb' => $pair ? 'd4d9dd' : 'f6f7f8'],
|
||||
];
|
||||
|
||||
$sheet->getStyle($cellRange)->applyFromArray($styleArray);
|
||||
|
||||
$values = array_values($data_excel);
|
||||
|
||||
array_walk($values, function ($row, $column_index) use ($sheet, $index, $registro) {
|
||||
$value = getFormattedValue($row, $registro);
|
||||
$cellLocation = chr(65 + $column_index) . (ROW + $index + 1);
|
||||
|
||||
$sheet->setCellValue($cellLocation, $value);
|
||||
|
||||
if ($value == "Sin registro") {
|
||||
$sheet->getStyle($cellLocation)->applyFromArray(['font' => ['color' => ['argb' => 'ea0029']]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
foreach ($sheet->getColumnIterator() as $column) {
|
||||
$sheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
|
||||
}
|
||||
|
||||
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||
$writer->save('php://output');
|
||||
@@ -2,7 +2,7 @@
|
||||
<?
|
||||
$user or die("Error: no se pudo cargar el usuario");
|
||||
?>
|
||||
<form action="action/action_periodousuario_update.php" method="post" id="formaPeriodo">
|
||||
<form action="action/action_periodousuario_update.php" method="post" id="formaPeriodo" class="marco">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<?php
|
||||
|
||||
50
include/phpmailer/PHPMailerAutoload.php
Normal file
50
include/phpmailer/PHPMailerAutoload.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPMailer SPL autoloader.
|
||||
* PHP Version 5
|
||||
* @package PHPMailer
|
||||
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2012 - 2014 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHPMailer SPL autoloader.
|
||||
* @param string $classname The name of the class to load
|
||||
*/
|
||||
function PHPMailerAutoload($classname)
|
||||
{
|
||||
//Can't use __DIR__ as it's only in PHP 5.3+
|
||||
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
|
||||
if (is_readable($filename)) {
|
||||
require $filename;
|
||||
}
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
|
||||
//SPL autoloading was introduced in PHP 5.1.2
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
spl_autoload_register('PHPMailerAutoload', true, true);
|
||||
} else {
|
||||
spl_autoload_register('PHPMailerAutoload');
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Fall back to traditional autoload for old PHP versions
|
||||
* @param string $classname The name of the class to load
|
||||
*/
|
||||
spl_autoload_register($classname);
|
||||
/*function __autoload($classname)
|
||||
{
|
||||
PHPMailerAutoload($classname);
|
||||
}*/
|
||||
}
|
||||
3884
include/phpmailer/class.phpmailer.php
Normal file
3884
include/phpmailer/class.phpmailer.php
Normal file
File diff suppressed because it is too large
Load Diff
1181
include/phpmailer/class.smtp.php
Normal file
1181
include/phpmailer/class.smtp.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@ $('div.modal#cargando').modal({
|
||||
});
|
||||
const store = reactive({
|
||||
loading: false,
|
||||
perido: null,
|
||||
current: {
|
||||
comentario: '',
|
||||
clase_vista: null,
|
||||
@@ -132,8 +133,8 @@ const store = reactive({
|
||||
store.current.justificada.registro_justificada = true;
|
||||
let data;
|
||||
try {
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
const res = await fetch('action/justificar.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
@@ -154,6 +155,43 @@ const store = reactive({
|
||||
store.current.justificada.justificador_rol = data.justificador_rol;
|
||||
store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion;
|
||||
},
|
||||
async justificarBloque(fecha, bloques, justificacion) {
|
||||
if (bloques.length === 0) {
|
||||
alert('No se ha seleccionado ningún bloque');
|
||||
return;
|
||||
}
|
||||
if (!justificacion) {
|
||||
alert('No se ha ingresado ninguna observación');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fecha,
|
||||
bloques,
|
||||
justificacion,
|
||||
})
|
||||
});
|
||||
const resData = await res.json();
|
||||
if (resData.status === 'success') {
|
||||
alert('Se ha justificado el bloque');
|
||||
store.current.modal_state = 'Cargando datos...';
|
||||
$('div.modal#cargando').modal('show');
|
||||
await store.registros.fetch();
|
||||
$('div.modal#cargando').modal('hide');
|
||||
}
|
||||
else {
|
||||
alert('No se ha podido justificar el bloque');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
alert('Error al justificar');
|
||||
}
|
||||
},
|
||||
registros: {
|
||||
data: [],
|
||||
async fetch(fecha, fecha_inicio, fecha_fin) {
|
||||
@@ -203,7 +241,7 @@ const store = reactive({
|
||||
if one of the filters is null, then it is not relevant
|
||||
|
||||
*/
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] || store.filters[filtro]?.length > 0);
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0);
|
||||
return this.data.filter((registro) => {
|
||||
return filters.every((filtro) => {
|
||||
switch (filtro) {
|
||||
@@ -279,6 +317,7 @@ const store = reactive({
|
||||
});
|
||||
createApp({
|
||||
store,
|
||||
messages: [],
|
||||
get clase_vista() {
|
||||
return store.current.clase_vista;
|
||||
},
|
||||
@@ -294,12 +333,21 @@ createApp({
|
||||
profesores: [],
|
||||
async mounted() {
|
||||
$('div.modal#cargando').modal('show');
|
||||
try {
|
||||
// await store.registros.fetch()
|
||||
await store.facultades.fetch();
|
||||
await store.estados.fetch();
|
||||
await store.bloques_horario.fetch();
|
||||
await store.filters.switchFechas();
|
||||
store.periodo = await fetch('action/periodo_datos.php').then(res => res.json());
|
||||
this.profesores = await (await fetch('action/action_profesor.php')).json();
|
||||
this.messages.push({ title: 'Datos cargados', text: 'Los datos se han cargado correctamente', type: 'success', timestamp: new Date() });
|
||||
}
|
||||
catch (error) {
|
||||
this.messages.push({ title: 'Error al cargar datos', text: 'No se pudieron cargar los datos', type: 'danger', timestamp: new Date() });
|
||||
}
|
||||
finally {
|
||||
$('div.modal#cargando').modal('hide');
|
||||
}
|
||||
}
|
||||
}).mount('#app');
|
||||
|
||||
133
js/periodos.js
133
js/periodos.js
@@ -1,44 +1,115 @@
|
||||
import { createApp } from 'https://unpkg.com/petite-vue?module';
|
||||
const app = createApp({
|
||||
carreras: [],
|
||||
periodos: [],
|
||||
niveles: [],
|
||||
message: {},
|
||||
async setNivel(carrera, nivel) {
|
||||
if (carrera.nivel_id === nivel.nivel_id) {
|
||||
messages: [],
|
||||
addMessage(title, text, type) {
|
||||
this.messages.push({ title, text, type, timestamp: new Date() });
|
||||
},
|
||||
async sendRequest(action, periodo_id, data) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
action: action,
|
||||
periodo_id: periodo_id,
|
||||
...data
|
||||
})
|
||||
});
|
||||
return await response.json();
|
||||
},
|
||||
async changeNivel(periodo, nivel_id) {
|
||||
if (periodo.nivel_id === nivel_id)
|
||||
return;
|
||||
const result = await this.sendRequest('changeNivel', periodo.periodo_id, { nivel_id: nivel_id });
|
||||
if (result.success) {
|
||||
this.addMessage('Nivel cambiado', `El nivel del periodo ${periodo.periodo_nombre} ha sido cambiado a ${this.niveles.find((nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre}`, 'success');
|
||||
periodo.nivel_id = nivel_id;
|
||||
periodo.nivel = this.niveles.find((nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre || '';
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al cambiar nivel', `No se pudo cambiar el nivel del periodo ${periodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async changeFechaInicio(periodo, fecha_inicio) {
|
||||
const result = await this.sendRequest('changeFechaInicio', periodo.periodo_id, { periodo_fecha_inicio: fecha_inicio });
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de inicio cambiada', `La fecha de inicio del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_inicio}`, 'success');
|
||||
periodo.periodo_fecha_inicio = fecha_inicio;
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al cambiar fecha de inicio', `No se pudo cambiar la fecha de inicio del periodo ${periodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async changeFechaFin(periodo, fecha_fin) {
|
||||
const result = await this.sendRequest('changeFechaFin', periodo.periodo_id, { periodo_fecha_fin: fecha_fin });
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de fin cambiada', `La fecha de fin del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_fin}`, 'success');
|
||||
periodo.periodo_fecha_fin = fecha_fin;
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al cambiar fecha de fin', `No se pudo cambiar la fecha de fin del periodo ${periodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async updatePeriodo(periodo) {
|
||||
const result = await this.sendRequest('updatePeriodo', periodo.periodo_id, {
|
||||
periodo_nombre: periodo.periodo_nombre,
|
||||
id_periodo_sgu: periodo.id_periodo_sgu,
|
||||
periodo_clave: periodo.periodo_clave,
|
||||
});
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo actualizado', `El periodo ${periodo.periodo_nombre} ha sido actualizado`, 'success');
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al actualizar periodo', `No se pudo actualizar el periodo ${periodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async createPeriodo(newPeriodo) {
|
||||
if (newPeriodo.periodo_nombre === null || newPeriodo.nivel_id === null || newPeriodo.periodo_fecha_inicio === null || newPeriodo.periodo_fecha_fin === null) {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger');
|
||||
return;
|
||||
}
|
||||
carrera.nivel_id = nivel.nivel_id;
|
||||
carrera.nivel_nombre = nivel.nivel_nombre;
|
||||
await fetch('action/carrera.php', {
|
||||
method: 'PUT',
|
||||
const result = await fetch('action/periodos.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(newPeriodo)
|
||||
}).then(res => res.json());
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo creado', `El periodo ${newPeriodo.periodo_nombre} ha sido creado`, 'success');
|
||||
this.periodos;
|
||||
Object.keys(newPeriodo).forEach(key => newPeriodo[key] = null);
|
||||
newPeriodo.nivel_id = '';
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json());
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async deletePeriodo(periodo) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
carrera_id: carrera.carrera_id,
|
||||
nivel_id: nivel.nivel_id
|
||||
periodo_id: periodo.periodo_id,
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.message.title = "Actualización";
|
||||
this.message.text = res.error ?? res.success;
|
||||
this.message.type = res.error ? 'danger' : 'success';
|
||||
this.message.timestamp = new Date().toLocaleTimeString();
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo eliminado', `El periodo ${periodo.periodo_nombre} ha sido eliminado`, 'success');
|
||||
this.periodos = this.periodos.filter((p) => p.periodo_id !== periodo.periodo_id);
|
||||
}
|
||||
else {
|
||||
this.addMessage('Error al eliminar periodo', `No se pudo eliminar el periodo ${periodo.periodo_nombre}`, 'danger');
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.carreras = await fetch('action/carrera.php').then(res => res.json());
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json());
|
||||
this.niveles = await fetch('action/nivel.php').then(res => res.json());
|
||||
// group by facultad_id
|
||||
const carreras = this.carreras.reduce((acc, cur) => {
|
||||
const { facultad_nombre } = cur;
|
||||
if (!acc[facultad_nombre]) {
|
||||
acc[facultad_nombre] = [];
|
||||
}
|
||||
acc[facultad_nombre].push(cur);
|
||||
return acc;
|
||||
}, {});
|
||||
this.carreras = Object.entries(carreras).map(([facultad_nombre, carreras]) => ({
|
||||
facultad_nombre: facultad_nombre,
|
||||
carreras
|
||||
}));
|
||||
}
|
||||
}).mount('#app');
|
||||
|
||||
@@ -29,3 +29,12 @@ const check = () => {
|
||||
}
|
||||
|
||||
['scroll', 'resize'].forEach(e => window.addEventListener(e, check))
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const links = document.querySelectorAll('a');
|
||||
links.forEach(function (link) {
|
||||
link.addEventListener('click', function (event) {
|
||||
// event.preventDefault();
|
||||
});
|
||||
});
|
||||
});
|
||||
42
materias.php
42
materias.php
@@ -63,7 +63,7 @@ if ($user->admin) {
|
||||
single: false
|
||||
);
|
||||
$fs_carreras = query(
|
||||
"SELECT * FROM fs_carreras(:facultad, null, null)",
|
||||
"SELECT * FROM fs_carreras(:facultad, null, null) ORDER BY unaccent(carrera_nombre)",
|
||||
array(":facultad" => $facultad),
|
||||
single: false
|
||||
);
|
||||
@@ -102,14 +102,15 @@ if ($user->admin) {
|
||||
$nivel_ac = $carrera["nivel_id"];
|
||||
?>
|
||||
<li data-id="" class="not-selectable">
|
||||
<?php echo $carrera["nivel_nombre"]; ?>
|
||||
<?= $carrera["nivel_nombre"]; ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<li data-id="<?php echo $carrera["carrera_nombre"]; ?>"
|
||||
<li data-id="<?= $carrera["carrera_nombre"]; ?>"
|
||||
class="pl-4 <?= !(isset($filter_carrera) && $carrera["carrera_nombre"] == $filter_carrera) ?: 'selected'; ?>">
|
||||
<?= $carrera["carrera_nombre"] ?></li>
|
||||
<?= $carrera["carrera_nombre"] ?>
|
||||
</li>
|
||||
<?php
|
||||
|
||||
}
|
||||
@@ -143,7 +144,7 @@ if ($user->admin) {
|
||||
if ($pcarrera == "") {
|
||||
?>
|
||||
<p> Se muestran los primeros <strong>
|
||||
<?php echo $max_count; ?>
|
||||
<?= $max_count; ?>
|
||||
</strong> resultados. Utiliza los filtros para encontrar la materia que buscas.</p>
|
||||
<?php } ?>
|
||||
<table class="table table-sm table-striped table-white">
|
||||
@@ -151,6 +152,7 @@ if ($user->admin) {
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Carrera</th>
|
||||
<th>Editar</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -159,12 +161,18 @@ if ($user->admin) {
|
||||
foreach ($fs_materias as $materia) {
|
||||
|
||||
?>
|
||||
<tr data-id="<?php echo $materia["materia_id"]; ?>" id="<?php echo $materia["materia_id"]; ?>">
|
||||
<tr data-id="<?= $materia["materia_id"]; ?>" id="<?= $materia["materia_id"]; ?>">
|
||||
<td class="text-primary">
|
||||
<?php echo $materia["materia_nombre"]; ?>
|
||||
<?= $materia["materia_nombre"]; ?>
|
||||
</td>
|
||||
<td class="text-primary">
|
||||
<?php echo $materia["carrera_nombre"]; ?>
|
||||
<?= $materia["carrera_nombre"]; ?>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-outline-primary" data-toggle="modal"
|
||||
data-target="#modal">
|
||||
<span class="ing-editar ing-fw"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
@@ -204,9 +212,23 @@ if ($user->admin) {
|
||||
<div class="form-group row">
|
||||
<label for="nombre" class="col-4 col-form-label">Nombre *</label>
|
||||
<div class="col-8">
|
||||
<input id="nombre" name="nombre" type="text" class="form-control" maxlength="100">
|
||||
<input id="nombre" name="nombre" type="text" class="form-control" maxlength="100"
|
||||
readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="carrera" class="col-4 col-form-label">Carrera *</label>
|
||||
<div class="col-8">
|
||||
<select id="carrera" name="carrera" class="form-control">
|
||||
<?php
|
||||
foreach ($fs_carreras as $carrera) {
|
||||
echo '<option value="' . $carrera["carrera_id"] . '">' . $carrera["carrera_nombre"] . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="offset-4 col-8">
|
||||
<button type="submit" class="btn btn-outline-primary" id="submitBtn" data-tipo="1">
|
||||
@@ -268,6 +290,7 @@ if ($user->admin) {
|
||||
},
|
||||
success: function (result) {
|
||||
$("#nombre").val(result[0]["materia_nombre"]);
|
||||
$("#carrera").val(result[0]["carrera_id"]); // establecer el valor de la carrera
|
||||
$("#id").val(result[0]["materia_id"]);
|
||||
},
|
||||
error: function () {
|
||||
@@ -275,6 +298,7 @@ if ($user->admin) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
301
periodos.php
301
periodos.php
@@ -8,15 +8,11 @@
|
||||
<?php
|
||||
include 'import/html_css_files.php';
|
||||
?>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.0.0/dist/trix.css">
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/jquery-ui.js"></script>
|
||||
<script src="js/bootstrap/bootstrap.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -25,182 +21,178 @@
|
||||
include "import/html_header.php";
|
||||
global $user;
|
||||
|
||||
html_header("Periodos", "Sistema de gestión de checador");
|
||||
html_header("Periodos");
|
||||
?>
|
||||
<main class="container-fluid px-4 my-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 70vh;">
|
||||
<section class="row mt-4">
|
||||
<div class="col-12 position-relative">
|
||||
<main class="container-fluid px-4 my-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 70vh;"
|
||||
v-scope="">
|
||||
<div aria-live="polite" aria-atomic="true" style="position: relative">
|
||||
<div style="position: fixed; bottom: 2%; right: 2%; z-index: 9999; min-width: 300px;">
|
||||
|
||||
<!-- Loop for messages -->
|
||||
<div class="toast show shadow-sm mb-3 bg-white"
|
||||
style="position: fixed; top: 15%; right: 1%; max-width: 300px;" role="alert" aria-live="assertive"
|
||||
aria-atomic="true"
|
||||
@vue:mounted="$('.toast').toast({delay: 5000}).toast('show').on('hidden.bs.toast', () => { message.text = '' })"
|
||||
v-if="message.text">
|
||||
<div class="toast-header">
|
||||
<strong class="mr-auto text-primary text-uppercase text-center w-100 px-4">
|
||||
<div class="toast show shadow-sm mb-3 bg-white shadow-sm" role="alert" aria-live="assertive"
|
||||
aria-atomic="true" v-for="(message, index) in messages"
|
||||
@vue:mounted="$(`#toast-${message.timestamp.getTime()}`).toast({delay: 5000}).toast('show').on('hidden.bs.toast', () => messages.splice(index, 1))" " :key="
|
||||
message.timestamp.getTime()" :id="`toast-${message.timestamp.getTime()}`">
|
||||
<div class="toast-header" :class="`bg-primary text-white`">
|
||||
<strong class="mr-auto text-uppercase text-center w-100 px-4">
|
||||
<i
|
||||
:class="`text-${message.type} fas fa-${message.type === 'danger' ? 'exclamation-triangle' : message.type === 'success' ? 'check-circle' : 'info-circle'} mr-2`"></i>
|
||||
{{ message.title }}
|
||||
</strong>
|
||||
<small class="text-muted">{{ message.timestamp }}</small>
|
||||
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close"
|
||||
@click="message.text = ''">
|
||||
<small class="text-light">{{ message.timestamp.toLocaleString() }}</small>
|
||||
<button type="button" class="ml-2 mb-1 close text-light" aria-label="Close"
|
||||
@click="$(`#toast-${message.timestamp.getTime()}`).toast('hide')">
|
||||
<span aria-hidden="true">
|
||||
<i class="fas fa-times"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
<div :class="message.type == 'success' ? 'text-success' : 'text-danger'"><i
|
||||
:class="message.type == 'success' ? 'fas fa-check-circle' : 'fas fa-times-circle'"></i>
|
||||
{{ message.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="container">
|
||||
<div class="d-flex flex-wrap justify-content-around">
|
||||
<div class="accordion col-8 mb-4" id="puestos"
|
||||
v-scope="{selected_carrera_id: -1, current_materia: null, current_encargado: null}"
|
||||
v-if="puestos.length">
|
||||
<div class="card" v-for="(puesto, index) in puestos" :key="puesto.puesto_id">
|
||||
<div class="card-header bg-primary" :id="`puesto-${puesto.nombre}`">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left text-light" type="button"
|
||||
data-toggle="collapse" :data-target="`#puesto-${puesto.puesto_id}`" aria-expanded="true"
|
||||
:aria-controls="`puesto-${puesto.puesto_id}`">
|
||||
{{puesto.nombre}}
|
||||
|
||||
<button type="button" class="btn btn-outline-danger float-right"
|
||||
data-target="#eliminar-puesto" data-toggle="modal" @click="to_delete = puesto">
|
||||
<span class="icono ing-basura"></span>
|
||||
</button>
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div :id="`puesto-${puesto.puesto_id}`" class="collapse" :class="{'show': index == 0}"
|
||||
:aria-labelledby="`puesto-${puesto.nombre}`" data-parent="#puestos">
|
||||
<div class="card-body">
|
||||
<!-- Encargado -->
|
||||
<div class="form-row justify-content-around align-items-center mb-2">
|
||||
<label :for="`encargado-${puesto.puesto_id}`" class="col-3">
|
||||
Encargado del área
|
||||
</label>
|
||||
<div id="encargados" class="datalist datalist-select mb-1 col-9">
|
||||
<div class="datalist-input" v-if="puesto.encargado">
|
||||
({{puesto.encargado.usuario_clave}}) {{ puesto.encargado.usuario_nombre }}
|
||||
</div>
|
||||
<div class="datalist-input" v-else>
|
||||
Selecciona un encargado
|
||||
</div>
|
||||
<span class="icono ing-buscar"></span>
|
||||
<ul style="display:none">
|
||||
<li class="datalist-option" v-for="usuario in usuarios"
|
||||
:key="usuario.usuario_id" :data-id="usuario.usuario_id"
|
||||
style=" white-space: nowrap;" @click="puesto.encargado = usuario"
|
||||
:class="{'selected': puesto.encargado?.usuario_id == usuario.usuario_id}">
|
||||
(<small> {{usuario.usuario_clave}} </small>) {{ usuario.usuario_nombre }}
|
||||
</li>
|
||||
</ul>
|
||||
<input type="hidden" id="encargado_id" name="id">
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div class="form-row justify-content-around align-items-center mb-2"
|
||||
v-show="carreras.length">
|
||||
<label :for="`carrera-${puesto.puesto_id}`" class="col-3">
|
||||
Carrera
|
||||
</label>
|
||||
<div id="dlCarreras" class="datalist datalist-select mb-1 col-9">
|
||||
<div class="datalist-input">
|
||||
Selecciona una carrera
|
||||
</div>
|
||||
<span class="icono ing-buscar"></span>
|
||||
<ul style="display:none">
|
||||
<li class="datalist-option" data-id="0" @click="selected_carrera_id = 0">
|
||||
Todas las carreras
|
||||
</li>
|
||||
<li class="datalist-option" v-for="carrera in carreras"
|
||||
:key="carrera.carrera_id" :data-id="carrera.carrera_id"
|
||||
style=" white-space: nowrap;"
|
||||
@click="selected_carrera_id = carrera.carrera_id">
|
||||
(<small> {{carrera.clave_carrera}} </small>) {{ carrera.carrera_nombre }}
|
||||
</li>
|
||||
</ul>
|
||||
<input type="hidden" id="carrera_id" name="id">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row justify-content-around align-items-center"
|
||||
v-scope="{to_add_materia: null}">
|
||||
<label :for="`materias-${puesto.puesto_id}`" class="col-3">
|
||||
Materias
|
||||
</label>
|
||||
<input name="materia" placeholder="Seleccione una materia" list="datalist-materias"
|
||||
class="form-control col-9 " v-model="current_materia" @input="to_add_materia = materias.find(m => current_materia == `${m.clave_materia} - ${m.materia_nombre}`);
|
||||
if (to_add_materia) {
|
||||
if (puesto.materias.find(p => p.materia_id == to_add_materia.materia_id)) {
|
||||
console.log('La materia ya está asignada');
|
||||
current_materia = null;
|
||||
return;
|
||||
}
|
||||
puesto.materias.push(to_add_materia);
|
||||
materias.splice(materias.indexOf(to_add_materia), 1);
|
||||
current_materia = null;
|
||||
}" :disabled="selected_carrera_id == -1" v-model="current_materia"
|
||||
:id="`materias-${puesto.puesto_id}`" autocomplete="off">
|
||||
</div>
|
||||
<datalist id="datalist-materias">
|
||||
<option
|
||||
v-for="materia in materias.filter(m => selected_carrera_id == 0 || m.carrera_id == selected_carrera_id).filter(m => !puesto.materias.find(p => p.materia_id == m.materia_id))"
|
||||
:value="`${materia.clave_materia} - ${materia.materia_nombre}`">
|
||||
</datalist>
|
||||
|
||||
<hr>
|
||||
<fieldset class="container d-flex flex-column justify-content-center align-items-center">
|
||||
<legend>Materias Asignadas <span
|
||||
class="badge badge-secondary">{{puesto.materias.length}}</span></legend>
|
||||
<ul class="list-group overflow-auto col-10" v-if="puesto.materias.length"
|
||||
style="max-height: 200px; overflow-y: auto;">
|
||||
<li class="list-group-item list-group-item-action"
|
||||
v-for="materia in puesto.materias" :key="materia.materia_id"
|
||||
@click="puesto.materias.splice(puesto.materias.indexOf(materia), 1); materias.push(materia)"
|
||||
style="cursor: pointer;">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="col-2 text-center">
|
||||
<span class="icono ing-borrar text-danger"></span>
|
||||
</div>
|
||||
<div class="col-10 text-left">
|
||||
{{materia.clave_materia}} - {{materia.materia_nombre}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="alert alert-light" role="alert" v-else>
|
||||
No hay materias asignadas
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
<div class="card-footer text-muted">
|
||||
<!-- scroll to top -->
|
||||
<button type="button" class="btn btn-outline-primary btn-lg btn-block"
|
||||
@click="actualizarPuesto(puesto.puesto_id, puesto.materias, puesto.encargado?.usuario_id)"
|
||||
onclick="window.scrollTo(0, 0);">
|
||||
{{ puesto.encargado ? 'Guardar cambios' : 'Guardar sin encargado' }}
|
||||
<div class="d-flex flex-wrap flex-row-reverse align-items-center mb-3">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#createPeriodoModal">
|
||||
<div class="ing-mas"></div>
|
||||
Crear periodo
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="periodos.length">
|
||||
<table class="table table-sm table-hover table-striped table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr class="text-center text-uppercase">
|
||||
<th scope="col" class="align-middle" style="width: 8%;">SGU</th>
|
||||
<th scope="col" class="align-middle" style="width: 7%;">Clave</th>
|
||||
<th scope="col" class="align-middle" style="width: 25%;">Nombre</th>
|
||||
<th scope="col" class="align-middle" style="width: 20%;">Nivel</th>
|
||||
<th scope="col" class="align-middle" style="width: 15%;">Fecha de inicio</th>
|
||||
<th scope="col" class="align-middle" style="width: 15%;">Fecha de fin</th>
|
||||
<th scope="col" class="align-middle" style="width: 10%;">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(periodo, index) in periodos" :key="periodo.periodo_id">
|
||||
<td class="text-center align-middle">
|
||||
{{ periodo.id_periodo_sgu }}
|
||||
</td>
|
||||
<td class="text-center align-middle">
|
||||
{{ periodo.periodo_clave }}
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<input type="text" name="periodo_nombre" id="" v-model="periodo.periodo_nombre" class="form-control"
|
||||
required>
|
||||
</td>
|
||||
<td class="align-middle text-center">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button"
|
||||
id="nivelDropdown" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
{{ periodo.nivel }}
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu" aria-labelledby="nivelDropdown">
|
||||
<a class="dropdown-item" v-for="nivel in niveles" :key="nivel.nivel_id"
|
||||
href="#/" @vue:mounted="$('.dropdown-toggle').dropdown()"
|
||||
@click="changeNivel(periodo, nivel.nivel_id)"
|
||||
:class="{'active': nivel.nivel_id === periodo.nivel_id}">{{nivel.nivel_nombre}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<input type="date" class="form-control" v-model="periodo.periodo_fecha_inicio" required
|
||||
:max="periodo.periodo_fecha_fin"
|
||||
@change="changeFechaInicio(periodo, periodo.periodo_fecha_inicio)">
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<input type="date" class="form-control" v-model="periodo.periodo_fecha_fin" required
|
||||
:min="periodo.periodo_fecha_inicio"
|
||||
@change="changeFechaFin(periodo, periodo.periodo_fecha_fin)">
|
||||
</td>
|
||||
<td class="align-middle text-center">
|
||||
<button type="button" class="btn btn-outline-primary" @click="updatePeriodo(periodo)"
|
||||
:disabled="[periodo.id_periodo_sgu, periodo.periodo_clave, periodo.periodo_nombre].some(value => !value)">
|
||||
<i class="ing-guardar"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger" @click="deletePeriodo(periodo)">
|
||||
<i class="ing-basura"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="alert alert-dark" role="alert">
|
||||
No hay puestos registrados
|
||||
|
||||
<div class="alert alert-info" role="alert" v-else>
|
||||
No hay periodos registrados
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal to create periodo -->
|
||||
<div class="modal fade" id="createPeriodoModal" tabindex="-1" role="dialog"
|
||||
aria-labelledby="createPeriodoModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content"
|
||||
v-scope="{newPeriodo: { periodo_nombre: null, nivel_id: '', periodo_fecha_inicio: null, periodo_fecha_fin: null, id_periodo_sgu: null, periodo_clave: null }}">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="createPeriodoModalLabel">Crear periodo</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Form to create periodo -->
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="periodo_nombre">Nombre del periodo</label>
|
||||
<input type="text" class="form-control" id="periodo_nombre" required
|
||||
v-model="newPeriodo.periodo_nombre">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nivel_id">Nivel</label>
|
||||
<select class="form-control" id="nivel_id" required v-model="newPeriodo.nivel_id">
|
||||
<option value="" selected disabled>Selecciona un nivel</option>
|
||||
<option v-for="nivel in niveles" :key="nivel.nivel_id" :value="nivel.nivel_id">
|
||||
{{ nivel.nivel_nombre }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="periodo_fecha_inicio">Fecha de inicio</label>
|
||||
<input type="date" class="form-control" id="periodo_fecha_inicio" required
|
||||
v-model="newPeriodo.periodo_fecha_inicio" :max="newPeriodo.periodo_fecha_fin">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="periodo_fecha_fin">Fecha de fin</label>
|
||||
<input type="date" class="form-control" id="periodo_fecha_fin" required
|
||||
v-model="newPeriodo.periodo_fecha_fin" :min="newPeriodo.periodo_fecha_inicio">
|
||||
</div>
|
||||
<!-- Newly added fields -->
|
||||
<div class="form-group">
|
||||
<label for="id_periodo_sgu">ID Periodo SGU</label>
|
||||
<input type="text" class="form-control" id="id_periodo_sgu" required
|
||||
v-model="newPeriodo.id_periodo_sgu" inputmode="numeric" pattern="[0-9]*" min="0">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="periodo_id">Periodo Clave</label>
|
||||
<input type="text" class="form-control" id="periodo_clave" required
|
||||
v-model="newPeriodo.periodo_clave" inputmode="numeric" pattern="[0-9]*" min="0">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-danger" data-dismiss="modal"
|
||||
@click="Object.keys(newPeriodo).forEach(key => newPeriodo[key] = null); newPeriodo.nivel_id = ''">Cerrar</button>
|
||||
<button type="button" class="btn btn-primary" @click="createPeriodo(newPeriodo)">Crear
|
||||
periodo</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?
|
||||
include "import/html_footer.php"; ?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
||||
@@ -212,7 +204,6 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js"
|
||||
integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="js/datalist.js"></script>
|
||||
<script src="js/periodos.js?<?= rand(0, 2) ?>" type="module"></script>
|
||||
<script src="js/scrollables.js"></script>
|
||||
</body>
|
||||
|
||||
91
puestos.php
91
puestos.php
@@ -42,7 +42,7 @@
|
||||
<?
|
||||
if ($user->acceso == 'w') {
|
||||
?>
|
||||
<div class="justify-content-between align-items-center d-flex mb-4">
|
||||
<div class="marco text-right">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#nuevo-puesto">
|
||||
<span class="ing-mas"></span>
|
||||
Agregar puesto
|
||||
@@ -53,32 +53,31 @@
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="d-flex flex-wrap justify-content-around">
|
||||
<div class="accordion col-8 mb-4" id="puestos"
|
||||
<div class="d-flex flex-wrap marco justify-content-around">
|
||||
<div class="accordion col-10 mx-auto my-5" id="puestos"
|
||||
v-scope="{selected_carrera_id: -1, current_materia: null, current_encargado: null}"
|
||||
v-if="puestos.length">
|
||||
<div class="card" v-for="(puesto, index) in puestos" :key="puesto.puesto_id">
|
||||
<div class="card-header bg-primary" :id="`puesto-${puesto.nombre}`">
|
||||
<h2 class="mb-0">
|
||||
<button class="btn btn-link btn-block text-left text-light" type="button"
|
||||
|
||||
<div class="card mb-3 shadow-lg" v-for="(puesto, index) in puestos" :key="puesto.puesto_id">
|
||||
<!-- Card Header -->
|
||||
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
||||
<button class="btn btn-link text-white flex-grow-1 text-left" type="button"
|
||||
data-toggle="collapse" :data-target="`#puesto-${puesto.puesto_id}`" aria-expanded="true"
|
||||
:aria-controls="`puesto-${puesto.puesto_id}`">
|
||||
{{puesto.nombre}}
|
||||
|
||||
<button type="button" class="btn btn-outline-danger float-right"
|
||||
data-target="#eliminar-puesto" data-toggle="modal" @click="to_delete = puesto">
|
||||
<span class="icono ing-basura"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-light" data-target="#eliminar-puesto"
|
||||
data-toggle="modal" @click="to_delete = puesto">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div :id="`puesto-${puesto.puesto_id}`" class="collapse" :class="{'show': index == 0}"
|
||||
<div :id="`puesto-${puesto.puesto_id}`" class="collapse"
|
||||
:aria-labelledby="`puesto-${puesto.nombre}`" data-parent="#puestos">
|
||||
<div class="card-body">
|
||||
<!-- Encargado -->
|
||||
<div class="form-row justify-content-around align-items-center mb-2">
|
||||
<label :for="`encargado-${puesto.puesto_id}`" class="col-3">
|
||||
<label :for="`encargado-${puesto.puesto_id}`" class="col-2 barra-right">
|
||||
Encargado del área
|
||||
</label>
|
||||
<div id="encargados" class="datalist datalist-select mb-1 col-9">
|
||||
@@ -104,7 +103,7 @@
|
||||
|
||||
<div class="form-row justify-content-around align-items-center mb-2"
|
||||
v-show="carreras.length">
|
||||
<label :for="`carrera-${puesto.puesto_id}`" class="col-3">
|
||||
<label :for="`carrera-${puesto.puesto_id}`" class="col-2 barra-right">
|
||||
Carrera
|
||||
</label>
|
||||
<div id="dlCarreras" class="datalist datalist-select mb-1 col-9">
|
||||
@@ -128,7 +127,7 @@
|
||||
</div>
|
||||
<div class="form-row justify-content-around align-items-center"
|
||||
v-scope="{to_add_materia: null}">
|
||||
<label :for="`materias-${puesto.puesto_id}`" class="col-3">
|
||||
<label :for="`materias-${puesto.puesto_id}`" class="col-2 barra-right">
|
||||
Materias
|
||||
</label>
|
||||
<input name="materia" placeholder="Seleccione una materia" list="datalist-materias"
|
||||
@@ -152,36 +151,51 @@
|
||||
</datalist>
|
||||
|
||||
<hr>
|
||||
<fieldset class="container d-flex flex-column justify-content-center align-items-center">
|
||||
<legend>Materias Asignadas <span
|
||||
class="badge badge-secondary">{{puesto.materias.length}}</span></legend>
|
||||
<ul class="list-group overflow-auto col-10" v-if="puesto.materias.length"
|
||||
style="max-height: 200px; overflow-y: auto;">
|
||||
<li class="list-group-item list-group-item-action"
|
||||
<style>
|
||||
.list-group-item-action:hover {
|
||||
background-color: rgba(255, 0, 0, 0.1);
|
||||
/* Light red tint on hover for better feedback */
|
||||
}
|
||||
|
||||
.list-group-item-action:active {
|
||||
background-color: rgba(255, 0, 0, 0.2);
|
||||
/* Slightly darker red tint when active */
|
||||
}
|
||||
</style>
|
||||
<fieldset class="container mt-4">
|
||||
<legend class="text-center mb-3">
|
||||
Materias Asignadas <span class="badge badge-info">{{puesto.materias.length}}</span>
|
||||
</legend>
|
||||
|
||||
<!-- Assigned Subjects List -->
|
||||
<ul class="list-group shadow-sm" v-if="puesto.materias.length"
|
||||
style="max-height: 250px; overflow-y: auto;">
|
||||
<li class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"
|
||||
v-for="materia in puesto.materias" :key="materia.materia_id"
|
||||
@click="puesto.materias.splice(puesto.materias.indexOf(materia), 1); materias.push(materia)"
|
||||
style="cursor: pointer;">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="col-2 text-center">
|
||||
<span class="icono ing-borrar text-danger"></span>
|
||||
</div>
|
||||
<div class="col-10 text-left">
|
||||
style="cursor: pointer; transition: background-color 0.3s ease;">
|
||||
|
||||
<span class="flex-grow-1">
|
||||
{{materia.clave_materia}} - {{materia.materia_nombre}}
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<!-- Delete icon - assuming using FontAwesome, replace with your icon system if different -->
|
||||
<i class="fas fa-trash-alt text-danger ml-3" style="cursor: pointer;"></i>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="alert alert-light" role="alert" v-else>
|
||||
|
||||
<!-- Empty State Alert -->
|
||||
<div class="alert alert-light text-center" role="alert" v-else>
|
||||
No hay materias asignadas
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="card-footer text-muted">
|
||||
<!-- scroll to top -->
|
||||
<button type="button" class="btn btn-outline-primary btn-lg btn-block"
|
||||
@click="actualizarPuesto(puesto.puesto_id, puesto.materias, puesto.encargado?.usuario_id)"
|
||||
onclick="window.scrollTo(0, 0);">
|
||||
<div class="card-footer d-flex justify-content-between align-items-center">
|
||||
<!-- <small class="text-muted">Última actualización: {{ puesto.lastUpdate | formatDate }}</small> -->
|
||||
<button type="button" class="btn btn-primary"
|
||||
@click="actualizarPuesto(puesto.puesto_id, puesto.materias, puesto.encargado?.usuario_id)">
|
||||
{{ puesto.encargado ? 'Guardar cambios' : 'Guardar sin encargado' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -278,6 +292,11 @@
|
||||
<script src="js/datalist.js"></script>
|
||||
<script src="js/puestos.js?<?= rand(0, 2) ?>" type="module"></script>
|
||||
<script src="js/scrollables.js"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.collapse').collapse
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
require_once 'class/mailer.php';
|
||||
require_once 'class/c_login.php';
|
||||
if (!isset($_SESSION['user'])){
|
||||
die(header('Location: index.php'));
|
||||
@@ -83,27 +83,21 @@ if($user->periodo_id!= ""){
|
||||
else
|
||||
$fecha_fin = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_fin"]));
|
||||
|
||||
|
||||
//Reposiciones
|
||||
$repEdo_rs = $db->query('SELECT * FROM fs_estado_reposicion' );
|
||||
|
||||
$repoParams = array();
|
||||
$query = "NULL,";//jefe carrera
|
||||
/*if($user->jefe_carrera){
|
||||
$query .= ":jefe, ";
|
||||
$repoParams[":jefe"] = $user->user["id"];
|
||||
}else{
|
||||
$query .= "NULL, ";
|
||||
}*/
|
||||
$query = "";
|
||||
if($user->rol["rol_id"] == 9){//es coordinador
|
||||
$query .= ":facultad, ";
|
||||
$repoParams[":facultad"] = $user->facultad["facultad_id"];
|
||||
}else{//supervisor
|
||||
$query .= "NULL, ";
|
||||
}
|
||||
if((isset($_POST["prof"]) && is_numeric($_POST["prof"])) ){
|
||||
if(isset($_POST["prof"]) ){
|
||||
$query .= ":prof,";
|
||||
$repoParams[":prof"] = filter_input(INPUT_POST, "prof", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||
$profesor = trim($_POST["prof"]);//limpia texto
|
||||
$repoParams[":prof"] = $profesor;
|
||||
}else{
|
||||
$query .= "NULL,";
|
||||
}
|
||||
@@ -167,7 +161,7 @@ if($user->periodo_id!= ""){
|
||||
<?php require('import/periodo.php') ?>
|
||||
|
||||
<?php if($user->periodo_id!= ""){ ?>
|
||||
<form id="asistencia" method="post" onsubmit="return validaFechas()">
|
||||
<form action="reposiciones_autorizar.php" id="asistencia" method="post" onsubmit="return validaFechas()">
|
||||
<div class="form-box">
|
||||
<input type="hidden" name="facultad" value="5">
|
||||
|
||||
@@ -186,27 +180,9 @@ if($user->periodo_id!= ""){
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="filtro_prof" class="col-4 col-form-label">Profesor</label>
|
||||
<label class="col-4 col-form-label" for="prof">Profesor</label>
|
||||
<div class="col-8 col-sm-4">
|
||||
<input list="lista_profesores" name="dlProfesor" id="dlProfesor" class="form-control" placeholder="Profesor">
|
||||
<div class="valid-feedback">
|
||||
Profesor encontrado
|
||||
</div>
|
||||
<div class="invalid-feedback">
|
||||
Profesor no encontrado
|
||||
</div>
|
||||
<datalist id="lista_profesores">
|
||||
<?php
|
||||
foreach ($profesores_rs as $profesor) {
|
||||
extract($profesor);
|
||||
?>
|
||||
<option data-clave="<?= $profesor_clave ?>" data-profesor="<?= $profesor_nombre ?>" data-id="<?= $profesor_id; ?>" value="<?= "$profesor_clave | $profesor_nombre" ?>"></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</datalist>
|
||||
<ul class="list-group" id="profesores"></ul>
|
||||
<input type="hidden" id="editor_profesor" name="profesor" value="">
|
||||
<input type="text" name="prof" id="prof" class="form-control" placeholder="Profesor" value="<?php if(isset($profesor)) echo $profesor; ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -237,7 +213,12 @@ if($user->periodo_id!= ""){
|
||||
<div class="tab-pane fade" id="tab<?php echo $i;?>" role="tabpanel" aria-labelledby="tab<?php echo $i;?>-tab">
|
||||
<?php
|
||||
$repoParams[":edo"]=$redo["estado_reposicion_id"];
|
||||
$reposiciones_rs = $db->query('SELECT * FROM fs_reposicion(NULL, '.$query.'0, NULL) ', $repoParams );
|
||||
if($user->rol["rol_id"] == 7){//es supervisor
|
||||
$repoParams[":sup"] = $user->user["id"];
|
||||
$reposiciones_rs = $db->query('SELECT * FROM fs_reposicion_solicitud(NULL, '.$query.'0, NULL, :sup) ', $repoParams );
|
||||
}else{
|
||||
$reposiciones_rs = $db->query('SELECT * FROM fs_reposicion_solicitud(NULL, '.$query.'0, NULL) ', $repoParams );
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -510,7 +491,7 @@ if($user->periodo_id!= ""){
|
||||
|
||||
<p class="aprobar-block">Una vez realizada la acción no se puede deshacer.</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-primary btn-enviar aprobar-block" id="submitBtn" data-edo="<?php echo $edo_new; ?>" ><?php echo $ICO["aceptar"];?> Aprobar</button>
|
||||
<button type="button" class="btn btn-primary btn-enviar aprobar-block" id="submitBtn" ><?php echo $ICO["aceptar"];?> Aprobar</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal" aria-label="Close">Cerrar</button>
|
||||
</p>
|
||||
|
||||
@@ -582,8 +563,8 @@ if($user->periodo_id!= ""){
|
||||
}
|
||||
if(isset($_GET["ok"]) && is_numeric($_GET["ok"])){
|
||||
switch ($_GET["ok"]){
|
||||
case 0: $successDesc = "La reposición se guardó correctamente."; break;
|
||||
case 1: $successDesc = "La reposición se actualizó correctamente."; break;
|
||||
case 0: $successDesc = "La reposición se actualizó correctamente."; break;
|
||||
case 1: $successDesc = "La reposición fue declinada."; break;
|
||||
}
|
||||
}
|
||||
require_once 'js/messages.php';
|
||||
|
||||
@@ -129,7 +129,8 @@ if(!is_null($user->periodo_id)){
|
||||
?>
|
||||
|
||||
<main class="container content marco content-margin" id="local-app">
|
||||
<?php if($write==true && isset($prof_rs) && count($prof_rs)>0) {?>
|
||||
<?php
|
||||
if($write==true && isset($prof_rs) && count($prof_rs)>0) {?>
|
||||
<!-- Botón para abrir el modal -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12 text-right">
|
||||
|
||||
4
test.php
4
test.php
@@ -19,8 +19,10 @@
|
||||
|
||||
html_header("test.php");
|
||||
?>
|
||||
<?= "<!-- $user -->" ?>
|
||||
<main class="container content content-margin" id="local-app">
|
||||
<pre>
|
||||
<?= $user ?>
|
||||
</pre>
|
||||
|
||||
</main>
|
||||
<?
|
||||
|
||||
@@ -77,6 +77,7 @@ $('div.modal#cargando').modal({
|
||||
|
||||
const store = reactive({
|
||||
loading: false,
|
||||
perido: null as Periodo | null,
|
||||
current: {
|
||||
comentario: '',
|
||||
clase_vista: null,
|
||||
@@ -216,8 +217,8 @@ const store = reactive({
|
||||
registro_fecha_justificacion: Date;
|
||||
};
|
||||
try {
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
const res = await fetch('action/justificar.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
@@ -237,6 +238,41 @@ const store = reactive({
|
||||
store.current.justificada.justificador_rol = data.justificador_rol
|
||||
store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion
|
||||
},
|
||||
async justificarBloque(fecha: Date, bloques: Array<number>, justificacion: string) {
|
||||
if (bloques.length === 0) {
|
||||
alert('No se ha seleccionado ningún bloque');
|
||||
return;
|
||||
}
|
||||
if (!justificacion) {
|
||||
alert('No se ha ingresado ninguna observación');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fecha,
|
||||
bloques,
|
||||
justificacion,
|
||||
})
|
||||
})
|
||||
const resData = await res.json();
|
||||
if (resData.status === 'success') {
|
||||
alert('Se ha justificado el bloque');
|
||||
store.current.modal_state = 'Cargando datos...';
|
||||
$('div.modal#cargando').modal('show');
|
||||
await store.registros.fetch();
|
||||
$('div.modal#cargando').modal('hide');
|
||||
} else {
|
||||
alert('No se ha podido justificar el bloque');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Error al justificar');
|
||||
}
|
||||
},
|
||||
registros: {
|
||||
data: [] as Registro[],
|
||||
async fetch(fecha?: Date, fecha_inicio?: Date, fecha_fin?: Date) {
|
||||
@@ -284,7 +320,7 @@ const store = reactive({
|
||||
if one of the filters is null, then it is not relevant
|
||||
|
||||
*/
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] || store.filters[filtro]?.length > 0)
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0)
|
||||
return this.data.filter((registro: Registro) => {
|
||||
return filters.every((filtro) => {
|
||||
switch (filtro) {
|
||||
@@ -306,6 +342,7 @@ const store = reactive({
|
||||
return nombre.includes(textoFiltro);
|
||||
}
|
||||
case 'facultad_id':
|
||||
|
||||
return registro.facultad_id === store.filters[filtro];
|
||||
case 'estados':
|
||||
if (store.filters[filtro].length === 0) return true;
|
||||
@@ -364,6 +401,7 @@ type Profesor = {
|
||||
}
|
||||
createApp({
|
||||
store,
|
||||
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||
get clase_vista() {
|
||||
return store.current.clase_vista
|
||||
},
|
||||
@@ -380,14 +418,22 @@ createApp({
|
||||
profesores: [] as Profesor[],
|
||||
async mounted() {
|
||||
$('div.modal#cargando').modal('show');
|
||||
try {
|
||||
|
||||
// await store.registros.fetch()
|
||||
await store.facultades.fetch()
|
||||
await store.estados.fetch()
|
||||
await store.bloques_horario.fetch()
|
||||
await store.filters.switchFechas()
|
||||
await store.filters.switchFechas();
|
||||
store.periodo = await fetch('action/periodo_datos.php').then(res => res.json()) as Periodo;
|
||||
this.profesores = await (await fetch('action/action_profesor.php')).json() as Profesor[];
|
||||
|
||||
this.messages.push({ title: 'Datos cargados', text: 'Los datos se han cargado correctamente', type: 'success', timestamp: new Date() })
|
||||
} catch (error) {
|
||||
this.messages.push({ title: 'Error al cargar datos', text: 'No se pudieron cargar los datos', type: 'danger', timestamp: new Date() })
|
||||
}
|
||||
finally {
|
||||
$('div.modal#cargando').modal('hide');
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
|
||||
176
ts/periodos.ts
176
ts/periodos.ts
@@ -1,63 +1,145 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
type Carrera = {
|
||||
carrera_id: number;
|
||||
carrera_nombre: string;
|
||||
clave_carrera: string;
|
||||
facultad_id: number;
|
||||
facultad_nombre: string;
|
||||
nivel_id: number;
|
||||
nivel_nombre: string;
|
||||
interface Periodo {
|
||||
created_at: Date;
|
||||
estado_id: number;
|
||||
id_periodo_sgu: number;
|
||||
nivel: string;
|
||||
nivel_id: number | '';
|
||||
periodo_clave: string;
|
||||
periodo_fecha_fin: Date;
|
||||
periodo_fecha_inicio: Date;
|
||||
periodo_id: number;
|
||||
periodo_nombre: string;
|
||||
}
|
||||
|
||||
type Nivel = {
|
||||
interface Nivel {
|
||||
nivel_id: number;
|
||||
nivel_nombre: string;
|
||||
}
|
||||
|
||||
const app = createApp({
|
||||
carreras: [] as Carrera[],
|
||||
niveles: [] as Nivel[],
|
||||
message: {} as Record<string, string>,
|
||||
async setNivel(carrera: Carrera, nivel: Nivel) {
|
||||
if (carrera.nivel_id === nivel.nivel_id) {
|
||||
periodos: [] as Array<Periodo>,
|
||||
niveles: [] as Array<Nivel>,
|
||||
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||
|
||||
addMessage(title: string, text: string, type: string) {
|
||||
this.messages.push({ title, text, type, timestamp: new Date() });
|
||||
},
|
||||
|
||||
async sendRequest(action: string, periodo_id: number, data: any) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
action: action,
|
||||
periodo_id: periodo_id,
|
||||
...data
|
||||
})
|
||||
})
|
||||
return await response.json()
|
||||
},
|
||||
|
||||
async changeNivel(periodo: Periodo, nivel_id: number) {
|
||||
if (periodo.nivel_id === nivel_id) return
|
||||
|
||||
const result = await this.sendRequest('changeNivel', periodo.periodo_id, { nivel_id: nivel_id })
|
||||
if (result.success) {
|
||||
this.addMessage('Nivel cambiado', `El nivel del periodo ${periodo.periodo_nombre} ha sido cambiado a ${this.niveles.find((nivel: Nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre}`, 'success')
|
||||
periodo.nivel_id = nivel_id
|
||||
periodo.nivel = this.niveles.find((nivel: Nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre || ''
|
||||
} else {
|
||||
this.addMessage('Error al cambiar nivel', `No se pudo cambiar el nivel del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async changeFechaInicio(periodo: Periodo, fecha_inicio: Date) {
|
||||
const result = await this.sendRequest('changeFechaInicio', periodo.periodo_id, { periodo_fecha_inicio: fecha_inicio })
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de inicio cambiada', `La fecha de inicio del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_inicio}`, 'success')
|
||||
|
||||
periodo.periodo_fecha_inicio = fecha_inicio
|
||||
} else {
|
||||
this.addMessage('Error al cambiar fecha de inicio', `No se pudo cambiar la fecha de inicio del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async changeFechaFin(periodo: Periodo, fecha_fin: Date) {
|
||||
const result = await this.sendRequest('changeFechaFin', periodo.periodo_id, { periodo_fecha_fin: fecha_fin })
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de fin cambiada', `La fecha de fin del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_fin}`, 'success')
|
||||
periodo.periodo_fecha_fin = fecha_fin
|
||||
} else {
|
||||
this.addMessage('Error al cambiar fecha de fin', `No se pudo cambiar la fecha de fin del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async updatePeriodo(periodo: Periodo) {
|
||||
const result = await this.sendRequest('updatePeriodo', periodo.periodo_id, {
|
||||
periodo_nombre: periodo.periodo_nombre,
|
||||
id_periodo_sgu: periodo.id_periodo_sgu,
|
||||
periodo_clave: periodo.periodo_clave,
|
||||
})
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo actualizado', `El periodo ${periodo.periodo_nombre} ha sido actualizado`, 'success')
|
||||
} else {
|
||||
this.addMessage('Error al actualizar periodo', `No se pudo actualizar el periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async createPeriodo(newPeriodo: Periodo) {
|
||||
|
||||
if (newPeriodo.periodo_nombre === null || newPeriodo.nivel_id === null || newPeriodo.periodo_fecha_inicio === null || newPeriodo.periodo_fecha_fin === null) {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger')
|
||||
return
|
||||
}
|
||||
carrera.nivel_id = nivel.nivel_id
|
||||
carrera.nivel_nombre = nivel.nivel_nombre
|
||||
|
||||
await fetch('action/carrera.php', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
carrera_id: carrera.carrera_id,
|
||||
nivel_id: nivel.nivel_id
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.message.title = "Actualización"
|
||||
this.message.text = res.error ?? res.success
|
||||
this.message.type = res.error ? 'danger' : 'success'
|
||||
this.message.timestamp = new Date().toLocaleTimeString()
|
||||
})
|
||||
|
||||
|
||||
const result = await fetch('action/periodos.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
async mounted() {
|
||||
this.carreras = await fetch('action/carrera.php').then(res => res.json())
|
||||
this.niveles = await fetch('action/nivel.php').then(res => res.json())
|
||||
// group by facultad_id
|
||||
const carreras = this.carreras.reduce((acc, cur) => {
|
||||
const { facultad_nombre } = cur
|
||||
if (!acc[facultad_nombre]) {
|
||||
acc[facultad_nombre] = []
|
||||
body: JSON.stringify(newPeriodo)
|
||||
}).then(res => res.json())
|
||||
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo creado', `El periodo ${newPeriodo.periodo_nombre} ha sido creado`, 'success')
|
||||
|
||||
this.periodos
|
||||
Object.keys(newPeriodo).forEach(key => newPeriodo[key] = null);
|
||||
newPeriodo.nivel_id = '';
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json())
|
||||
} else {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
acc[facultad_nombre].push(cur)
|
||||
return acc
|
||||
}, {} as Record<number, Carrera[]>)
|
||||
this.carreras = Object.entries(carreras).map(([facultad_nombre, carreras]) => ({
|
||||
facultad_nombre: facultad_nombre,
|
||||
carreras
|
||||
}))
|
||||
},
|
||||
|
||||
async deletePeriodo(periodo: Periodo) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
periodo_id: periodo.periodo_id,
|
||||
})
|
||||
})
|
||||
const result = await response.json()
|
||||
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo eliminado', `El periodo ${periodo.periodo_nombre} ha sido eliminado`, 'success')
|
||||
this.periodos = this.periodos.filter((p: Periodo) => p.periodo_id !== periodo.periodo_id)
|
||||
} else {
|
||||
this.addMessage('Error al eliminar periodo', `No se pudo eliminar el periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json())
|
||||
this.niveles = await fetch('action/nivel.php').then(res => res.json())
|
||||
}
|
||||
}).mount('#app')
|
||||
Reference in New Issue
Block a user