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/
|
/concept/
|
||||||
/backup/
|
/backup/
|
||||||
/.vscode/
|
/.vscode/
|
||||||
/export/
|
|
||||||
/log/
|
/log/
|
||||||
|
|
||||||
/include/.env
|
/include/.env
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
#input $_GET['id_espacio_sgu']
|
#input $_GET['id_espacio_sgu']
|
||||||
#output rutas: [ ...ruta, salones: [{...salon}] ]
|
#output rutas: [ ...ruta, salones: [{...salon}] ]
|
||||||
header('Content-Type: application/json charset=utf-8');
|
header('Content-Type: application/json charset=utf-8');
|
||||||
ini_set('memory_limit', '256M');
|
ini_set('memory_limit', '500M');
|
||||||
ini_set('post_max_size', '256M');
|
ini_set('post_max_size', '500M');
|
||||||
ini_set('display_errors', 1);
|
ini_set('display_errors', 1);
|
||||||
ini_set('display_startup_errors', 1);
|
ini_set('display_startup_errors', 1);
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
@@ -39,16 +39,18 @@ try {
|
|||||||
PERIODO.periodo_fecha_inicio,
|
PERIODO.periodo_fecha_inicio,
|
||||||
PERIODO.periodo_fecha_fin,
|
PERIODO.periodo_fecha_fin,
|
||||||
salon,
|
salon,
|
||||||
materia_nombre as materia,
|
COALESCE(materia_nombre, materia_asignacion_materia) as materia,
|
||||||
carrera_nombre as carrera,
|
carrera_nombre as carrera,
|
||||||
facultad_nombre as facultad,
|
facultad_nombre as facultad,
|
||||||
nivel_nombre as nivel,
|
nivel_nombre as nivel,
|
||||||
horario_fin
|
horario_fin
|
||||||
FROM horario
|
FROM horario
|
||||||
left JOIN materia USING (materia_id)
|
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 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 PERIODO USING (periodo_id)
|
||||||
JOIN SALON USING (salon_id)
|
JOIN SALON USING (salon_id)
|
||||||
WHERE (PERIODO.periodo_id, facultad.facultad_id) = (:periodo_id, COALESCE(:facultad_id, facultad.facultad_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 ROL on ROL.rol_id = justificador.rol_id
|
||||||
left join facultad on facultad.facultad_id = justificador.facultad_id
|
left join facultad on facultad.facultad_id = justificador.facultad_id
|
||||||
WHERE (fechas.registro_fecha_ideal + HORARIO_HORA) BETWEEN
|
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",
|
ORDER BY fechas.registro_fecha_ideal DESC, horarios.horario_id, profesor_nombre",
|
||||||
$params
|
$params
|
||||||
);
|
);
|
||||||
|
$db->delete('general_log');
|
||||||
// $user->print_to_log(json_encode($params));
|
$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);
|
echo json_encode(array_merge($data), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
} else {
|
} else {
|
||||||
http_response_code(405);
|
http_response_code(405);
|
||||||
|
|||||||
@@ -25,37 +25,50 @@ try {
|
|||||||
echo json_encode(['error' => 'No hay clases pendientes']);
|
echo json_encode(['error' => 'No hay clases pendientes']);
|
||||||
exit;
|
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(
|
$bloques = $db
|
||||||
'INSERT INTO registro (profesor_id, horario_id, registro_fecha_ideal, registro_justificada, justificador_id, registro_fecha_justificacion, justificacion)
|
->where('id', $post_data['bloques'])
|
||||||
VALUES (:profesor_id, :horario_id, :registro_fecha_ideal, :registro_justificada, :justificador_id, NOW(), :justificacion)
|
->orderBy('hora_inicio')
|
||||||
ON CONFLICT (profesor_id, horario_id, registro_fecha_ideal)
|
->get('bloque_horario', null, 'hora_inicio, hora_fin');
|
||||||
DO UPDATE SET registro_justificada = :registro_justificada, justificador_id = :justificador_id, registro_fecha_justificacion = NOW(), justificacion = :justificacion
|
|
||||||
RETURNING *',
|
$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(
|
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'],
|
'justificador_id' => $user->user['id'],
|
||||||
'justificacion' => empty($post_data['justificacion']) ? null : $post_data['justificacion'],
|
'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,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
$pdo->commit();
|
||||||
$data_justificador = $db->querySingle(
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
"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);
|
|
||||||
} else {
|
} else {
|
||||||
http_response_code(405);
|
http_response_code(405);
|
||||||
echo json_encode(['error' => 'method not allowed']);
|
echo json_encode(['error' => 'method not allowed']);
|
||||||
@@ -70,6 +83,7 @@ try {
|
|||||||
'query' => $db->getLastQuery(),
|
'query' => $db->getLastQuery(),
|
||||||
'post_data' => $post_data,
|
'post_data' => $post_data,
|
||||||
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
|
$pdo->rollBack();
|
||||||
exit;
|
exit;
|
||||||
} catch (Exception $th) {
|
} catch (Exception $th) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
$ruta = "../";
|
$ruta = "../";
|
||||||
require_once "../include/bd_pdo.php";
|
require_once "../include/bd_pdo.php";
|
||||||
global $pdo;
|
global $pdo;
|
||||||
$sql="SELECT * FROM materia WHERE materia_id = :idMateria";
|
$sql = "SELECT * FROM materia
|
||||||
$params = ['idMateria' => $_POST['idmateria']];
|
JOIN carrera using (carrera_id)
|
||||||
echo json_encode(query($sql, $params, false));
|
WHERE materia_id = :idMateria";
|
||||||
|
$params = ['idMateria' => $_POST['idmateria']];
|
||||||
|
echo json_encode(query($sql, $params, false));
|
||||||
?>
|
?>
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
$ruta = "../";
|
$ruta = "../";
|
||||||
require_once "../include/bd_pdo.php";
|
require_once "../include/bd_pdo.php";
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$sql = "UPDATE materia SET materia_nombre = :nombre WHERE materia_id = :id";
|
$sql = "UPDATE materia SET materia_nombre = :nombre, carrera_id = :carrera WHERE materia_id = :id";
|
||||||
$params = array(':nombre' => mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"]);
|
$params = array(':nombre' => mb_strtoupper($_POST["nombre"]), ':id' => $_POST["id"], ':carrera' => $_POST["carrera"]);
|
||||||
$hecho = query($sql, $params, false);
|
$hecho = query($sql, $params, false);
|
||||||
header("Location: ../materias.php");
|
header("Location: ../materias.php");
|
||||||
exit();
|
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";
|
$pag = "../reposiciones_crear.php";
|
||||||
$ruta = "../";
|
$ruta = "../";
|
||||||
require_once "../class/c_login.php";
|
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
|
// check if the session is started
|
||||||
if (!isset($_SESSION['user']))
|
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
|
$edo = filter_input(INPUT_POST, "edo", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||||
if(isset($_POST["salon"]) && $_POST["salon"] != "")
|
if(isset($_POST["salon"]) && $_POST["salon"] != "")
|
||||||
$salon = filter_input(INPUT_POST, "salon", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
$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
|
if($edo == 4){//cancelación
|
||||||
@@ -42,55 +112,66 @@ if($edo == 4){//cancelación
|
|||||||
$db->querySingle('SELECT fu_reposicion_solicitud(:id, NULL, NULL, NULL, NULL, :edo, NULL, NULL, NULL, NULL)',
|
$db->querySingle('SELECT fu_reposicion_solicitud(:id, NULL, NULL, NULL, NULL, :edo, NULL, NULL, NULL, NULL)',
|
||||||
[':id' => $id_repo, ':edo' => $edo]
|
[':id' => $id_repo, ':edo' => $edo]
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
|
||||||
|
|
||||||
$correoList = "";
|
|
||||||
foreach($correos_rs as $c){
|
|
||||||
if($c.substr("lasallistas.org,mx",0) || $c.substr("lasalle.mx",0)){
|
|
||||||
$correoList .= $c.";";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//$correoHTML = "<p>Se aprobó la reposición para el <b> a las </b> en el salón <b></b>.</p>";
|
|
||||||
*/
|
$fecha_clase = date('d/m/Y', strtotime($reposicion_rs["fecha_clase"]));
|
||||||
/*
|
$fecha_nueva = date('d/m/Y', strtotime($reposicion_rs["fecha_nueva"]));
|
||||||
$log = new LogActividad();
|
$hora_tmp = explode(":",$reposicion_rs["horario_hora"]);
|
||||||
if($edo == 4){
|
$hora_clase = $hora_tmp[0].":".$hora_tmp[1];
|
||||||
$desc_log = "Cancela reposición ID[".$id_repo."] edo[".$edo."]";
|
$hora_tmp = explode(":",$reposicion_rs["hora_nueva"]);
|
||||||
$ok = 2;
|
$hora_nueva = $hora_tmp[0].":".$hora_tmp[1];
|
||||||
}else{
|
|
||||||
$desc_log = "Autoriza reposición ID[".$id_repo."] edo[".$edo."] Salon[".(empty($salon)?"":$salon)."]";
|
$asunto = "";
|
||||||
$ok = 0;
|
$texto = "";
|
||||||
if($edo == 3){
|
$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>";
|
||||||
|
}
|
||||||
|
$texto .= "<p>Ingresa al <a href='https://paad.lci.ulsa.mx'>sistema PAAD</a> para autorizarla.</p>";
|
||||||
|
$to = join(",", $correosSup_rs);
|
||||||
|
$ok = 0;
|
||||||
|
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;
|
$ok = 1;
|
||||||
//if($correoList!= "")
|
break;
|
||||||
//Mailer::enviarCorreo($correoList , "Reposición autorizada", $correoHTML);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
$log->appendLog($_SESSION["usuario_id"], $_SESSION["usuario_nombre"]." ".$_SESSION["usuario_apellidos"], $desc_log);
|
||||||
*/
|
*/
|
||||||
header("Location: ".$pag."?ok=".$ok);
|
header("Location: ".$pag."?ok=".$ok);
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
$pag = "../reposiciones_crear.php";
|
$pag = "../reposiciones_crear.php";
|
||||||
$ruta = "../";
|
$ruta = "../";
|
||||||
require_once "../class/c_login.php";
|
require_once "../class/c_login.php";
|
||||||
|
require_once "../class/mailer.php";
|
||||||
|
|
||||||
|
define("COORDINADOR", 9);
|
||||||
|
define("ENVIO_CORREOS", true);
|
||||||
|
|
||||||
// check if the session is started
|
// check if the session is started
|
||||||
if (!isset($_SESSION['user']))
|
if (!isset($_SESSION['user']))
|
||||||
@@ -13,64 +17,71 @@ if (!isset($_SESSION['user']))
|
|||||||
$user = unserialize($_SESSION['user']);
|
$user = unserialize($_SESSION['user']);
|
||||||
//$user->access();
|
//$user->access();
|
||||||
|
|
||||||
$duracion_id = filter_input(INPUT_POST, "duracion", FILTER_SANITIZE_NUMBER_INT); //Id reposicion
|
$duracion_id = filter_input(INPUT_POST, "duracion", FILTER_SANITIZE_NUMBER_INT);//Id reposicion
|
||||||
$bloque = filter_input(INPUT_POST, "bloque", FILTER_SANITIZE_NUMBER_INT); //
|
$bloque = filter_input(INPUT_POST, "bloque", FILTER_SANITIZE_NUMBER_INT);//
|
||||||
$ciclo = filter_input(INPUT_POST, "ciclo", 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_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 = trim(htmlspecialchars($_POST["fecha_inicial"], ENT_QUOTES, "UTF-8"));//limpia texto
|
||||||
$fecha_cambio = trim(htmlspecialchars($_POST["fecha_cambio"], 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
|
$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
|
$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
|
$hor = filter_input(INPUT_POST, "horario", FILTER_SANITIZE_NUMBER_INT);//limpia texto
|
||||||
$alumnos = filter_input(INPUT_POST, "alumnos", 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
|
$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
|
$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"];
|
$prof = $user["id"];
|
||||||
else
|
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"] != "")
|
//if(isset($_POST["salon"]) && $_POST["salon"] != "")
|
||||||
//$salon = trim(filter_input(INPUT_POST, "salon", FILTER_SANITIZE_STRING,array('flags' => FILTER_FLAG_STRIP_LOW)));//limpia texto
|
//$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"];
|
$duracion_tiempo = $duracion_rs["duracion_interval"];
|
||||||
|
|
||||||
//-- Obtiene datos de horario regular de clase
|
//-- Obtiene datos de horario regular de clase
|
||||||
$horario_rs = $db->querySingle(
|
$horario_rs = $db->querySingle('SELECT * from horario_view where horario_id = :hor',
|
||||||
'SELECT * from horario_view where horario_id = :hor',
|
[':hor' => $hor]
|
||||||
[':hor' => $hor]
|
);
|
||||||
);
|
|
||||||
|
|
||||||
$materia = $horario_rs["materia_id"];
|
$materia = $horario_rs["materia_id"];
|
||||||
$dia = $horario_rs["horario_dia"];
|
$dia = $horario_rs["horario_dia"];
|
||||||
|
|
||||||
$hora = $hora_ini . ":" . $min_ini . ":00";
|
$hora = $hora_ini.":".$min_ini.":00";
|
||||||
$fecha_new = DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d') . " " . $hora;
|
$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;
|
$fecha_fin_new = date("Y-m-d", strtotime($fecha_new))." ".$duracion_tiempo;
|
||||||
$dia_new = date('w', strtotime($fecha_new));
|
$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');
|
$fecha_falta = DateTime::createFromFormat('d/m/Y', $fecha_falta)->format('Y-m-d');
|
||||||
$dia_falta = date('w', strtotime($fecha_falta));
|
$dia_falta = date('w', strtotime($fecha_falta));
|
||||||
} else {
|
}else{
|
||||||
$fecha_cambio = DateTime::createFromFormat('d/m/Y', $fecha_cambio)->format('Y-m-d');
|
$fecha_cambio = DateTime::createFromFormat('d/m/Y', $fecha_cambio)->format('Y-m-d');
|
||||||
$dia_falta = date('w', strtotime($fecha_cambio));
|
$dia_falta = date('w', strtotime($fecha_cambio));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Valida que tenga clase en la fecha de falta
|
//Valida que tenga clase en la fecha de falta
|
||||||
if (intval($dia) != intval($dia_falta)) {
|
if(intval($dia) != intval($dia_falta)){
|
||||||
header("Location:" . $pag . "?error=11");
|
header("Location:".$pag."?error=11");
|
||||||
/*print_r($_POST);
|
/*print_r($_POST);
|
||||||
echo 'SELECT * from horario_view where horario_id = '.$hor;
|
echo 'SELECT * from horario_view where horario_id = '.$hor;
|
||||||
echo intval($dia)." != ".intval($dia_falta);*/
|
echo intval($dia)." != ".intval($dia_falta);*/
|
||||||
exit();
|
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
|
// Valida que grupo no tenga clases
|
||||||
/*$result = validaConflictoHoras($pdo, $gpo, $dia_new, $hora, $materia, "-", $fecha_new, $fecha_fin_new, $duracion);
|
/*$result = validaConflictoHoras($pdo, $gpo, $dia_new, $hora, $materia, "-", $fecha_new, $fecha_fin_new, $duracion);
|
||||||
if($result != ""){//error
|
if($result != ""){//error
|
||||||
@@ -80,81 +91,82 @@ if ($tipo == 1) { //Reposición
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//Valida que profesor no este en 2 reposiciones al mismo tiempo en la fecha nueva
|
//Valida que profesor no este en 2 reposiciones al mismo tiempo en la fecha nueva
|
||||||
|
|
||||||
$traslape = $db->querySingle(
|
$traslape = $db->querySingle('SELECT * from traslape_profesor_reposicion(:prof, :fecha, :hora, :dur)',
|
||||||
'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]
|
||||||
[':prof' => $prof, ':fecha' => DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d'), ':hora' => $hora, ':dur' => $duracion_tiempo]
|
|
||||||
)["traslape_profesor_reposicion"];
|
)["traslape_profesor_reposicion"];
|
||||||
if ($traslape) {
|
if($traslape){
|
||||||
//print_r($_POST);
|
//print_r($_POST);
|
||||||
//echo "SELECT * from traslape_profesor_reposicion($prof,'".DateTime::createFromFormat('d/m/Y', $fecha)->format('Y-m-d')."' , '$hora', $duracion)";
|
//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();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try{
|
||||||
$db->query(
|
$db->query('SELECT * from fi_reposicion_solicitud(:f_falta, :f_nueva, :hora_nueva, :hor, :prof, 1, :desc, :alumnos, true, :aula, :duracion, :usr, :bloque, :ciclo)',
|
||||||
'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"],
|
||||||
':f_falta' => $fecha_falta,
|
':bloque' => $bloque, ':ciclo' => $ciclo
|
||||||
':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();
|
echo $e->getMessage();
|
||||||
//header("Location: ".$pag."?error=1");
|
//header("Location: ".$pag."?error=1");
|
||||||
exit();
|
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);*/
|
||||||
|
|
||||||
/*
|
|
||||||
$log = new LogActividad();
|
}else{//Cambio salón / hora
|
||||||
$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);*/
|
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,
|
||||||
} else { //Cambio salón / hora
|
':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) {
|
}catch(Exception $e){
|
||||||
header("Location: " . $pag . "?error=1");
|
header("Location: ".$pag."?error=1");
|
||||||
exit();
|
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();
|
$log = new LogActividad();
|
||||||
$desc_log = "Inserta reposición nueva ID[".$rs["fi_reposicion"]."] Fechas[".$fecha_cambio.">".$fecha_cambio_nueva."] Periodo[".$_SESSION["periodo_id"]."] Materia[".$materia."] Profesor[".$prof."] Salon[".$salon."] Horario[".$hor."] Alumnos[".$alumnos."]";
|
$desc_log = "Inserta reposición nueva ID[".$rs["fi_reposicion"]."] Fechas[".$fecha_cambio.">".$fecha_cambio_nueva."] 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);
|
$log->appendLog($_SESSION["usuario_id"], $_SESSION["usuario_nombre"]." ".$_SESSION["usuario_apellidos"], $desc_log);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
exit();
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ $user = unserialize($_SESSION['user']);
|
|||||||
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
if($user->rol["rol_id"] == 9){//es coordinador
|
if($user->rol["rol_id"] == 7){//es supervisor
|
||||||
$rs = $db->querySingle('SELECT * from fs_reposicion(:id, NULL, :fac, NULL, NULL, NULL, NULL, NULL, NULL)',
|
$rs = $db->querySingle('SELECT * from fs_reposicion_solicitud(:id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, :sup)',
|
||||||
[':id' => $id, ":fac"=>$user->facultad["facultad_id"] ]
|
[':id' => $id, ':sup'=>$user->user["id"]]
|
||||||
);
|
);
|
||||||
}else{//supervisor
|
}else{//coordinador
|
||||||
$rs = $db->querySingle('SELECT * from fs_reposicion(:id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)',
|
$rs = $db->querySingle('SELECT * from fs_reposicion_solicitud(:id, :fac, NULL, NULL, NULL, NULL, NULL, NULL, null)',
|
||||||
[':id' => $id]
|
[':id' => $id, ":fac"=>$user->facultad["facultad_id"] ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,18 +104,18 @@ if($tipo == 1){//Reposición
|
|||||||
}
|
}
|
||||||
|
|
||||||
try{
|
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,
|
[':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){
|
}catch(Exception $e){
|
||||||
//header("Location: ".$pag."?error=2");
|
//header("Location: ".$pag."?error=2");
|
||||||
print_r($e->getMessage());
|
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(
|
print_r(
|
||||||
[':id'=> $id, ':f_falta' => $fecha_falta, ':f_nueva' => $fecha_new, ':hora_nueva' => $hora,
|
[':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();
|
exit();
|
||||||
}
|
}
|
||||||
|
|||||||
116
auditoria.php
116
auditoria.php
@@ -57,10 +57,11 @@
|
|||||||
<? exit;
|
<? exit;
|
||||||
} ?>
|
} ?>
|
||||||
|
|
||||||
<main class="container-fluid px-4 mt-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 60vh;">
|
<main class="container-fluid px-4 mt-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 60vh;"
|
||||||
<!-- {{ store.current }} -->
|
v-scope="">
|
||||||
|
<!-- {{ store.filters }} -->
|
||||||
<?php include "import/periodo.php" ?>
|
<?php include "import/periodo.php" ?>
|
||||||
<div class="form-box">
|
<div class="form-box marco">
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<? if (!$user->facultad['facultad_id']) { ?>
|
<? if (!$user->facultad['facultad_id']) { ?>
|
||||||
<label for="dlFacultad" class="col-4 col-form-label">Facultad</label>
|
<label for="dlFacultad" class="col-4 col-form-label">Facultad</label>
|
||||||
@@ -71,7 +72,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="icono ing-buscar"></span>
|
<span class="icono ing-buscar"></span>
|
||||||
<ul style="display:none">
|
<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;">
|
@click="store.filters.facultad_id = null; store.current.page = 1;">
|
||||||
Todas las facultades
|
Todas las facultades
|
||||||
</li>
|
</li>
|
||||||
@@ -217,15 +218,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 d-flex justify-content-between flex-wrap align-items-center">
|
<div class="mt-3 d-flex justify-content-between flex-wrap align-items-center">
|
||||||
<!-- botón descargar -->
|
<? if ($user->acceso == 'w') { ?>
|
||||||
<div class="col-md-2 col-12 text-center">
|
<!-- botón justificar profesores -->
|
||||||
<div class="btn-group my-3">
|
<div class="col-md-2 col-12 text-center">
|
||||||
<button type="button" class="btn btn-outline-primary mr-3">
|
<div class="btn-group my-3">
|
||||||
Justificar profesores
|
<button type="button" class="btn btn-outline-primary mr-3" data-toggle="modal"
|
||||||
<i class="ing-justificar"></i>
|
data-target="#justificar-profesores">
|
||||||
</button>
|
Justificar profesores
|
||||||
|
<i class="ing-justificar"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<? } ?>
|
||||||
|
|
||||||
<!-- botón descargar -->
|
<!-- botón descargar -->
|
||||||
<div class="col-md-2 col-12 text-center">
|
<div class="col-md-2 col-12 text-center">
|
||||||
<div class="btn-group my-3" v-if="store.registros.relevant.length > 0">
|
<div class="btn-group my-3" v-if="store.registros.relevant.length > 0">
|
||||||
@@ -556,7 +561,8 @@
|
|||||||
<div class="col-12 text-center">
|
<div class="col-12 text-center">
|
||||||
Esta clase se reprogramó para el día
|
Esta clase se reprogramó para el día
|
||||||
{{ clase_vista.reposicion_fecha }} a las
|
{{ 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>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -641,10 +647,92 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
</main>
|
||||||
|
|
||||||
<!-- <script src="js/datalist.js"></script> -->
|
<!-- <script src=" js/datalist.js"></script> -->
|
||||||
<script src="js/datepicker-es.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="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>
|
<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
|
<?php
|
||||||
require_once 'class/c_login.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 = Login::get_user();
|
||||||
|
|
||||||
$user->access();
|
$user->access();
|
||||||
if($user->acceso == null){
|
if ($user->acceso === null && !$user->admin){
|
||||||
header('Location: main.php?error=1');
|
die(header('Location: index.php'));
|
||||||
}else{
|
exit();
|
||||||
$user->print_to_log('Dias_festivos');
|
|
||||||
}
|
}
|
||||||
if(isset($_GET['facultad'])){
|
|
||||||
$fac = $_GET['facultad'];
|
$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
|
||||||
}else if($user->admin){
|
join periodo p on p.periodo_id = any (d.periodos_id)
|
||||||
$fac = null;
|
order by d.diasfestivos_dia DESC");
|
||||||
}else{
|
|
||||||
$fac = $user->facultad['facultad_id'];
|
|
||||||
|
|
||||||
|
$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>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<title>Días festivos</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Días Festivos</title>
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" href="css/jquery-ui.css">
|
<meta http-equiv="content-type" content="text/plain; charset=UTF-8" />
|
||||||
<link rel="stylesheet" href="css/calendar.css">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet" href="css/toggle.css" type="text/css">
|
|
||||||
<?php
|
<?php
|
||||||
include 'import/html_css_files.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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body style="display: block;">
|
||||||
<?php
|
<?php
|
||||||
include "import/html_header.php";
|
include('include/constantes.php');
|
||||||
html_header(
|
include("import/html_header.php");
|
||||||
"DÍAS FESTIVOS",
|
html_header("Días festivos", "Sistema de gestión de checador");
|
||||||
"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);
|
|
||||||
?>
|
?>
|
||||||
<main class="content marco">
|
<?= "<!-- $user -->" ?>
|
||||||
|
<main class="container content marco content-margin" id="local-app">
|
||||||
|
|
||||||
|
<section id="message"></section>
|
||||||
|
|
||||||
<?php if($user->admin){ ?>
|
<?php if($user->admin){ ?>
|
||||||
<div class="col-12 text-right">
|
<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>
|
<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>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<div id="message"></div>
|
<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 -->
|
<!-- Tabla -->
|
||||||
<?php if($fs_dias_festivos || $fs_dias_festivos_generales){ ?>
|
<?php
|
||||||
|
if(count($dias_arr) > 0){ ?>
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-12 table-responsive">
|
<div class="col-12 table-responsive">
|
||||||
<table class="table table-sm table-striped table-white">
|
<table class="table table-sm table-striped table-white">
|
||||||
@@ -61,46 +117,37 @@ if(isset($_GET['facultad'])){
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Día</th>
|
<th>Día</th>
|
||||||
<th>Periodo</th>
|
<th>Periodo</th>
|
||||||
<th>Nivel</th>
|
|
||||||
<?php if($user->admin){ ?>
|
<?php if($user->admin){ ?>
|
||||||
<th>Facultad</th>
|
|
||||||
<th>Acciones</th>
|
<th>Acciones</th>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<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">
|
<tr data-id="<?= $dia['diasfestivos_id'] ?>" id="<?= $dia['diasfestivos_id'] ?>" data-periodo="1">
|
||||||
<td class="text-center"><?php $day = explode("-", $dia['diasfestivos_dia']);
|
<td class="text-center text-nowrap align-middle">
|
||||||
echo $day['2']."-".$day['1']."-".$day['0'];
|
<?php $day = explode("-", $dia['diasfestivos_dia']);
|
||||||
?></td>
|
echo $dias_nombres[$dia["dia_id"]]."<br>";
|
||||||
<td class="text-center"><?= $dia['periodo_nombre'] ?></td>
|
echo $day[2]."/".$day[1]."/".$day[0];
|
||||||
<td class="text-center"><?= $dia['nivel_nombre'] ?></td>
|
?></td>
|
||||||
|
<td>
|
||||||
|
<ul class="mb-0">
|
||||||
|
<?
|
||||||
|
foreach($dia["periodos"] as $per){
|
||||||
|
echo "<li>".$per['periodo_nombre']."</li>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
<?php if($user->admin){ ?>
|
<?php if($user->admin){ ?>
|
||||||
<td class="text-center"><?= $dia['facultad_nombre'] ?></td>
|
<td class="text-center icono-acciones align-middle">
|
||||||
<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" 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>
|
<a href="#" data-toggle="modal" data-target="#modal_confirm" title="Borrar"><span class="ing-basura ing-fw"></span></a>
|
||||||
</td>
|
</td>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</tr>
|
</tr>
|
||||||
<?php } ?>
|
<?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">
|
|
||||||
<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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,22 +176,6 @@ if(isset($_GET['facultad'])){
|
|||||||
<form action="" method="post" id="formaModal" onsubmit="return valida_campos()">
|
<form action="" method="post" id="formaModal" onsubmit="return valida_campos()">
|
||||||
<input type="hidden" name="id" id="id">
|
<input type="hidden" name="id" id="id">
|
||||||
<div class="form-box">
|
<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">
|
<div class="form-group row" id="rangoDiv">
|
||||||
<label for="rango" class="col-3 col-form-label">Rango</label>
|
<label for="rango" class="col-3 col-form-label">Rango</label>
|
||||||
<div class="col-8">
|
<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="">
|
<input id="diaFestivo" name="diaFestivo" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-1 diaFestivoRango">
|
<div class="col-1 diaFestivoRango">
|
||||||
-
|
<span class="ing-menos"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4 diaFestivoRango" id="diaFestivoRango">
|
<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="">
|
<input id="diaFestivoFin" name="diaFestivoFin" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="">
|
||||||
</div>
|
</div>
|
||||||
<div class="invalid-feedback">Debe seleccionar una fecha</div>
|
<div class="invalid-feedback">Debe seleccionar una fecha</div>
|
||||||
</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="form-group row">
|
||||||
<div class="offset-4 col-8">
|
<div class="offset-4 col-8">
|
||||||
<button type="submit" class="btn btn-outline-primary" id="submitBtn" data-tipo="1">
|
<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.min.js"></script>
|
||||||
<script src="js/jquery-ui.js"></script>
|
<script src="js/jquery-ui.js"></script>
|
||||||
<script src="js/bootstrap/bootstrap.min.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/datepicker-es.js"></script>
|
||||||
<script src="js/toggle.js"></script>
|
<script src="js/toggle.js"></script>
|
||||||
<?php
|
<?php
|
||||||
@@ -251,7 +295,7 @@ if(isset($_GET['facultad'])){
|
|||||||
changeMonth: true,
|
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");
|
triggerMessage("No se encontraron días festivos", "Error");
|
||||||
<?php } ?>
|
<?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");
|
$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="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<?php
|
<?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({
|
const store = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
perido: null,
|
||||||
current: {
|
current: {
|
||||||
comentario: '',
|
comentario: '',
|
||||||
clase_vista: null,
|
clase_vista: null,
|
||||||
@@ -132,8 +133,8 @@ const store = reactive({
|
|||||||
store.current.justificada.registro_justificada = true;
|
store.current.justificada.registro_justificada = true;
|
||||||
let data;
|
let data;
|
||||||
try {
|
try {
|
||||||
const res = await fetch('action/action_justificar.php', {
|
const res = await fetch('action/justificar.php', {
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
@@ -154,6 +155,43 @@ const store = reactive({
|
|||||||
store.current.justificada.justificador_rol = data.justificador_rol;
|
store.current.justificada.justificador_rol = data.justificador_rol;
|
||||||
store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion;
|
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: {
|
registros: {
|
||||||
data: [],
|
data: [],
|
||||||
async fetch(fecha, fecha_inicio, fecha_fin) {
|
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
|
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 this.data.filter((registro) => {
|
||||||
return filters.every((filtro) => {
|
return filters.every((filtro) => {
|
||||||
switch (filtro) {
|
switch (filtro) {
|
||||||
@@ -279,6 +317,7 @@ const store = reactive({
|
|||||||
});
|
});
|
||||||
createApp({
|
createApp({
|
||||||
store,
|
store,
|
||||||
|
messages: [],
|
||||||
get clase_vista() {
|
get clase_vista() {
|
||||||
return store.current.clase_vista;
|
return store.current.clase_vista;
|
||||||
},
|
},
|
||||||
@@ -294,12 +333,21 @@ createApp({
|
|||||||
profesores: [],
|
profesores: [],
|
||||||
async mounted() {
|
async mounted() {
|
||||||
$('div.modal#cargando').modal('show');
|
$('div.modal#cargando').modal('show');
|
||||||
// await store.registros.fetch()
|
try {
|
||||||
await store.facultades.fetch();
|
// await store.registros.fetch()
|
||||||
await store.estados.fetch();
|
await store.facultades.fetch();
|
||||||
await store.bloques_horario.fetch();
|
await store.estados.fetch();
|
||||||
await store.filters.switchFechas();
|
await store.bloques_horario.fetch();
|
||||||
this.profesores = await (await fetch('action/action_profesor.php')).json();
|
await store.filters.switchFechas();
|
||||||
$('div.modal#cargando').modal('hide');
|
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');
|
}).mount('#app');
|
||||||
|
|||||||
133
js/periodos.js
133
js/periodos.js
@@ -1,44 +1,115 @@
|
|||||||
import { createApp } from 'https://unpkg.com/petite-vue?module';
|
import { createApp } from 'https://unpkg.com/petite-vue?module';
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
carreras: [],
|
periodos: [],
|
||||||
niveles: [],
|
niveles: [],
|
||||||
message: {},
|
messages: [],
|
||||||
async setNivel(carrera, nivel) {
|
addMessage(title, text, type) {
|
||||||
if (carrera.nivel_id === nivel.nivel_id) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
carrera.nivel_id = nivel.nivel_id;
|
const result = await fetch('action/periodos.php', {
|
||||||
carrera.nivel_nombre = nivel.nivel_nombre;
|
method: 'POST',
|
||||||
await fetch('action/carrera.php', {
|
headers: {
|
||||||
method: 'PUT',
|
'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({
|
body: JSON.stringify({
|
||||||
carrera_id: carrera.carrera_id,
|
periodo_id: periodo.periodo_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 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() {
|
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());
|
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');
|
}).mount('#app');
|
||||||
|
|||||||
@@ -29,3 +29,12 @@ const check = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
['scroll', 'resize'].forEach(e => window.addEventListener(e, 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
|
single: false
|
||||||
);
|
);
|
||||||
$fs_carreras = query(
|
$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),
|
array(":facultad" => $facultad),
|
||||||
single: false
|
single: false
|
||||||
);
|
);
|
||||||
@@ -102,14 +102,15 @@ if ($user->admin) {
|
|||||||
$nivel_ac = $carrera["nivel_id"];
|
$nivel_ac = $carrera["nivel_id"];
|
||||||
?>
|
?>
|
||||||
<li data-id="" class="not-selectable">
|
<li data-id="" class="not-selectable">
|
||||||
<?php echo $carrera["nivel_nombre"]; ?>
|
<?= $carrera["nivel_nombre"]; ?>
|
||||||
</li>
|
</li>
|
||||||
<?php
|
<?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'; ?>">
|
class="pl-4 <?= !(isset($filter_carrera) && $carrera["carrera_nombre"] == $filter_carrera) ?: 'selected'; ?>">
|
||||||
<?= $carrera["carrera_nombre"] ?></li>
|
<?= $carrera["carrera_nombre"] ?>
|
||||||
|
</li>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -143,7 +144,7 @@ if ($user->admin) {
|
|||||||
if ($pcarrera == "") {
|
if ($pcarrera == "") {
|
||||||
?>
|
?>
|
||||||
<p> Se muestran los primeros <strong>
|
<p> Se muestran los primeros <strong>
|
||||||
<?php echo $max_count; ?>
|
<?= $max_count; ?>
|
||||||
</strong> resultados. Utiliza los filtros para encontrar la materia que buscas.</p>
|
</strong> resultados. Utiliza los filtros para encontrar la materia que buscas.</p>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<table class="table table-sm table-striped table-white">
|
<table class="table table-sm table-striped table-white">
|
||||||
@@ -151,6 +152,7 @@ if ($user->admin) {
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Nombre</th>
|
<th>Nombre</th>
|
||||||
<th>Carrera</th>
|
<th>Carrera</th>
|
||||||
|
<th>Editar</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -159,12 +161,18 @@ if ($user->admin) {
|
|||||||
foreach ($fs_materias as $materia) {
|
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">
|
<td class="text-primary">
|
||||||
<?php echo $materia["materia_nombre"]; ?>
|
<?= $materia["materia_nombre"]; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-primary">
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
@@ -204,9 +212,23 @@ if ($user->admin) {
|
|||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="nombre" class="col-4 col-form-label">Nombre *</label>
|
<label for="nombre" class="col-4 col-form-label">Nombre *</label>
|
||||||
<div class="col-8">
|
<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>
|
</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="form-group row">
|
||||||
<div class="offset-4 col-8">
|
<div class="offset-4 col-8">
|
||||||
<button type="submit" class="btn btn-outline-primary" id="submitBtn" data-tipo="1">
|
<button type="submit" class="btn btn-outline-primary" id="submitBtn" data-tipo="1">
|
||||||
@@ -268,6 +290,7 @@ if ($user->admin) {
|
|||||||
},
|
},
|
||||||
success: function (result) {
|
success: function (result) {
|
||||||
$("#nombre").val(result[0]["materia_nombre"]);
|
$("#nombre").val(result[0]["materia_nombre"]);
|
||||||
|
$("#carrera").val(result[0]["carrera_id"]); // establecer el valor de la carrera
|
||||||
$("#id").val(result[0]["materia_id"]);
|
$("#id").val(result[0]["materia_id"]);
|
||||||
},
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
@@ -275,6 +298,7 @@ if ($user->admin) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
307
periodos.php
307
periodos.php
@@ -8,15 +8,11 @@
|
|||||||
<?php
|
<?php
|
||||||
include 'import/html_css_files.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>
|
<style>
|
||||||
[v-cloak] {
|
[v-cloak] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="js/jquery.min.js"></script>
|
|
||||||
<script src="js/jquery-ui.js"></script>
|
|
||||||
<script src="js/bootstrap/bootstrap.min.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -25,182 +21,178 @@
|
|||||||
include "import/html_header.php";
|
include "import/html_header.php";
|
||||||
global $user;
|
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;">
|
<main class="container-fluid px-4 my-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 70vh;"
|
||||||
<section class="row mt-4">
|
v-scope="">
|
||||||
<div class="col-12 position-relative">
|
<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 -->
|
<!-- Loop for messages -->
|
||||||
<div class="toast show shadow-sm mb-3 bg-white"
|
<div class="toast show shadow-sm mb-3 bg-white shadow-sm" role="alert" aria-live="assertive"
|
||||||
style="position: fixed; top: 15%; right: 1%; max-width: 300px;" role="alert" aria-live="assertive"
|
aria-atomic="true" v-for="(message, index) in messages"
|
||||||
aria-atomic="true"
|
@vue:mounted="$(`#toast-${message.timestamp.getTime()}`).toast({delay: 5000}).toast('show').on('hidden.bs.toast', () => messages.splice(index, 1))" " :key="
|
||||||
@vue:mounted="$('.toast').toast({delay: 5000}).toast('show').on('hidden.bs.toast', () => { message.text = '' })"
|
message.timestamp.getTime()" :id="`toast-${message.timestamp.getTime()}`">
|
||||||
v-if="message.text">
|
<div class="toast-header" :class="`bg-primary text-white`">
|
||||||
<div class="toast-header">
|
<strong class="mr-auto text-uppercase text-center w-100 px-4">
|
||||||
<strong class="mr-auto text-primary 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 }}
|
{{ message.title }}
|
||||||
</strong>
|
</strong>
|
||||||
<small class="text-muted">{{ message.timestamp }}</small>
|
<small class="text-light">{{ message.timestamp.toLocaleString() }}</small>
|
||||||
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close"
|
<button type="button" class="ml-2 mb-1 close text-light" aria-label="Close"
|
||||||
@click="message.text = ''">
|
@click="$(`#toast-${message.timestamp.getTime()}`).toast('hide')">
|
||||||
<span aria-hidden="true">
|
<span aria-hidden="true">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
<div :class="message.type == 'success' ? 'text-success' : 'text-danger'"><i
|
{{ message.text }}
|
||||||
:class="message.type == 'success' ? 'fas fa-check-circle' : 'fas fa-times-circle'"></i>
|
|
||||||
{{ message.text }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="d-flex flex-wrap justify-content-around">
|
<div class="d-flex flex-wrap flex-row-reverse align-items-center mb-3">
|
||||||
<div class="accordion col-8 mb-4" id="puestos"
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#createPeriodoModal">
|
||||||
v-scope="{selected_carrera_id: -1, current_materia: null, current_encargado: null}"
|
<div class="ing-mas"></div>
|
||||||
v-if="puestos.length">
|
Crear periodo
|
||||||
<div class="card" v-for="(puesto, index) in puestos" :key="puesto.puesto_id">
|
</button>
|
||||||
<div class="card-header bg-primary" :id="`puesto-${puesto.nombre}`">
|
</div>
|
||||||
<h2 class="mb-0">
|
<div v-if="periodos.length">
|
||||||
<button class="btn btn-link btn-block text-left text-light" type="button"
|
<table class="table table-sm table-hover table-striped table-bordered">
|
||||||
data-toggle="collapse" :data-target="`#puesto-${puesto.puesto_id}`" aria-expanded="true"
|
<thead class="thead-dark">
|
||||||
:aria-controls="`puesto-${puesto.puesto_id}`">
|
<tr class="text-center text-uppercase">
|
||||||
{{puesto.nombre}}
|
<th scope="col" class="align-middle" style="width: 8%;">SGU</th>
|
||||||
|
<th scope="col" class="align-middle" style="width: 7%;">Clave</th>
|
||||||
<button type="button" class="btn btn-outline-danger float-right"
|
<th scope="col" class="align-middle" style="width: 25%;">Nombre</th>
|
||||||
data-target="#eliminar-puesto" data-toggle="modal" @click="to_delete = puesto">
|
<th scope="col" class="align-middle" style="width: 20%;">Nivel</th>
|
||||||
<span class="icono ing-basura"></span>
|
<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>
|
</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>
|
||||||
</h2>
|
<button type="button" class="btn btn-outline-danger" @click="deletePeriodo(periodo)">
|
||||||
</div>
|
<i class="ing-basura"></i>
|
||||||
|
|
||||||
<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' }}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</td>
|
||||||
</div>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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>
|
||||||
</div>
|
<div class="modal-body">
|
||||||
<div v-else>
|
<!-- Form to create periodo -->
|
||||||
<div class="alert alert-dark" role="alert">
|
<form>
|
||||||
No hay puestos registrados
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<?
|
<?
|
||||||
include "import/html_footer.php"; ?>
|
include "import/html_footer.php"; ?>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
|
<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"
|
<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+"
|
integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
<script src="js/datalist.js"></script>
|
|
||||||
<script src="js/periodos.js?<?= rand(0, 2) ?>" type="module"></script>
|
<script src="js/periodos.js?<?= rand(0, 2) ?>" type="module"></script>
|
||||||
<script src="js/scrollables.js"></script>
|
<script src="js/scrollables.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
101
puestos.php
101
puestos.php
@@ -42,7 +42,7 @@
|
|||||||
<?
|
<?
|
||||||
if ($user->acceso == 'w') {
|
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">
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#nuevo-puesto">
|
||||||
<span class="ing-mas"></span>
|
<span class="ing-mas"></span>
|
||||||
Agregar puesto
|
Agregar puesto
|
||||||
@@ -53,32 +53,31 @@
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="d-flex flex-wrap justify-content-around">
|
<div class="d-flex flex-wrap marco justify-content-around">
|
||||||
<div class="accordion col-8 mb-4" id="puestos"
|
<div class="accordion col-10 mx-auto my-5" id="puestos"
|
||||||
v-scope="{selected_carrera_id: -1, current_materia: null, current_encargado: null}"
|
v-scope="{selected_carrera_id: -1, current_materia: null, current_encargado: null}"
|
||||||
v-if="puestos.length">
|
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"
|
<div class="card mb-3 shadow-lg" v-for="(puesto, index) in puestos" :key="puesto.puesto_id">
|
||||||
data-target="#eliminar-puesto" data-toggle="modal" @click="to_delete = puesto">
|
<!-- Card Header -->
|
||||||
<span class="icono ing-basura"></span>
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
||||||
</button>
|
<button class="btn btn-link text-white flex-grow-1 text-left" type="button"
|
||||||
</button>
|
data-toggle="collapse" :data-target="`#puesto-${puesto.puesto_id}`" aria-expanded="true"
|
||||||
</h2>
|
:aria-controls="`puesto-${puesto.puesto_id}`">
|
||||||
|
{{puesto.nombre}}
|
||||||
|
</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>
|
||||||
</div>
|
</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">
|
:aria-labelledby="`puesto-${puesto.nombre}`" data-parent="#puestos">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<!-- Encargado -->
|
<!-- Encargado -->
|
||||||
<div class="form-row justify-content-around align-items-center mb-2">
|
<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
|
Encargado del área
|
||||||
</label>
|
</label>
|
||||||
<div id="encargados" class="datalist datalist-select mb-1 col-9">
|
<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"
|
<div class="form-row justify-content-around align-items-center mb-2"
|
||||||
v-show="carreras.length">
|
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
|
Carrera
|
||||||
</label>
|
</label>
|
||||||
<div id="dlCarreras" class="datalist datalist-select mb-1 col-9">
|
<div id="dlCarreras" class="datalist datalist-select mb-1 col-9">
|
||||||
@@ -128,7 +127,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-row justify-content-around align-items-center"
|
<div class="form-row justify-content-around align-items-center"
|
||||||
v-scope="{to_add_materia: null}">
|
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
|
Materias
|
||||||
</label>
|
</label>
|
||||||
<input name="materia" placeholder="Seleccione una materia" list="datalist-materias"
|
<input name="materia" placeholder="Seleccione una materia" list="datalist-materias"
|
||||||
@@ -152,36 +151,51 @@
|
|||||||
</datalist>
|
</datalist>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<fieldset class="container d-flex flex-column justify-content-center align-items-center">
|
<style>
|
||||||
<legend>Materias Asignadas <span
|
.list-group-item-action:hover {
|
||||||
class="badge badge-secondary">{{puesto.materias.length}}</span></legend>
|
background-color: rgba(255, 0, 0, 0.1);
|
||||||
<ul class="list-group overflow-auto col-10" v-if="puesto.materias.length"
|
/* Light red tint on hover for better feedback */
|
||||||
style="max-height: 200px; overflow-y: auto;">
|
}
|
||||||
<li class="list-group-item list-group-item-action"
|
|
||||||
|
.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"
|
v-for="materia in puesto.materias" :key="materia.materia_id"
|
||||||
@click="puesto.materias.splice(puesto.materias.indexOf(materia), 1); materias.push(materia)"
|
@click="puesto.materias.splice(puesto.materias.indexOf(materia), 1); materias.push(materia)"
|
||||||
style="cursor: pointer;">
|
style="cursor: pointer; transition: background-color 0.3s ease;">
|
||||||
<div class="d-flex justify-content-center">
|
|
||||||
<div class="col-2 text-center">
|
<span class="flex-grow-1">
|
||||||
<span class="icono ing-borrar text-danger"></span>
|
{{materia.clave_materia}} - {{materia.materia_nombre}}
|
||||||
</div>
|
</span>
|
||||||
<div class="col-10 text-left">
|
|
||||||
{{materia.clave_materia}} - {{materia.materia_nombre}}
|
<!-- Delete icon - assuming using FontAwesome, replace with your icon system if different -->
|
||||||
</div>
|
<i class="fas fa-trash-alt text-danger ml-3" style="cursor: pointer;"></i>
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</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
|
No hay materias asignadas
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer text-muted">
|
<div class="card-footer d-flex justify-content-between align-items-center">
|
||||||
<!-- scroll to top -->
|
<!-- <small class="text-muted">Última actualización: {{ puesto.lastUpdate | formatDate }}</small> -->
|
||||||
<button type="button" class="btn btn-outline-primary btn-lg btn-block"
|
<button type="button" class="btn btn-primary"
|
||||||
@click="actualizarPuesto(puesto.puesto_id, puesto.materias, puesto.encargado?.usuario_id)"
|
@click="actualizarPuesto(puesto.puesto_id, puesto.materias, puesto.encargado?.usuario_id)">
|
||||||
onclick="window.scrollTo(0, 0);">
|
|
||||||
{{ puesto.encargado ? 'Guardar cambios' : 'Guardar sin encargado' }}
|
{{ puesto.encargado ? 'Guardar cambios' : 'Guardar sin encargado' }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -278,6 +292,11 @@
|
|||||||
<script src="js/datalist.js"></script>
|
<script src="js/datalist.js"></script>
|
||||||
<script src="js/puestos.js?<?= rand(0, 2) ?>" type="module"></script>
|
<script src="js/puestos.js?<?= rand(0, 2) ?>" type="module"></script>
|
||||||
<script src="js/scrollables.js"></script>
|
<script src="js/scrollables.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('.collapse').collapse
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
require_once 'class/mailer.php';
|
||||||
require_once 'class/c_login.php';
|
require_once 'class/c_login.php';
|
||||||
if (!isset($_SESSION['user'])){
|
if (!isset($_SESSION['user'])){
|
||||||
die(header('Location: index.php'));
|
die(header('Location: index.php'));
|
||||||
@@ -83,27 +83,21 @@ if($user->periodo_id!= ""){
|
|||||||
else
|
else
|
||||||
$fecha_fin = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_fin"]));
|
$fecha_fin = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_fin"]));
|
||||||
|
|
||||||
|
|
||||||
//Reposiciones
|
//Reposiciones
|
||||||
$repEdo_rs = $db->query('SELECT * FROM fs_estado_reposicion' );
|
$repEdo_rs = $db->query('SELECT * FROM fs_estado_reposicion' );
|
||||||
|
|
||||||
$repoParams = array();
|
$repoParams = array();
|
||||||
$query = "NULL,";//jefe carrera
|
$query = "";
|
||||||
/*if($user->jefe_carrera){
|
|
||||||
$query .= ":jefe, ";
|
|
||||||
$repoParams[":jefe"] = $user->user["id"];
|
|
||||||
}else{
|
|
||||||
$query .= "NULL, ";
|
|
||||||
}*/
|
|
||||||
if($user->rol["rol_id"] == 9){//es coordinador
|
if($user->rol["rol_id"] == 9){//es coordinador
|
||||||
$query .= ":facultad, ";
|
$query .= ":facultad, ";
|
||||||
$repoParams[":facultad"] = $user->facultad["facultad_id"];
|
$repoParams[":facultad"] = $user->facultad["facultad_id"];
|
||||||
}else{//supervisor
|
}else{//supervisor
|
||||||
$query .= "NULL, ";
|
$query .= "NULL, ";
|
||||||
}
|
}
|
||||||
if((isset($_POST["prof"]) && is_numeric($_POST["prof"])) ){
|
if(isset($_POST["prof"]) ){
|
||||||
$query .= ":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{
|
}else{
|
||||||
$query .= "NULL,";
|
$query .= "NULL,";
|
||||||
}
|
}
|
||||||
@@ -167,7 +161,7 @@ if($user->periodo_id!= ""){
|
|||||||
<?php require('import/periodo.php') ?>
|
<?php require('import/periodo.php') ?>
|
||||||
|
|
||||||
<?php if($user->periodo_id!= ""){ ?>
|
<?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">
|
<div class="form-box">
|
||||||
<input type="hidden" name="facultad" value="5">
|
<input type="hidden" name="facultad" value="5">
|
||||||
|
|
||||||
@@ -186,27 +180,9 @@ if($user->periodo_id!= ""){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<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">
|
<div class="col-8 col-sm-4">
|
||||||
<input list="lista_profesores" name="dlProfesor" id="dlProfesor" class="form-control" placeholder="Profesor">
|
<input type="text" name="prof" id="prof" class="form-control" placeholder="Profesor" value="<?php if(isset($profesor)) echo $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="">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
<div class="tab-pane fade" id="tab<?php echo $i;?>" role="tabpanel" aria-labelledby="tab<?php echo $i;?>-tab">
|
||||||
<?php
|
<?php
|
||||||
$repoParams[":edo"]=$redo["estado_reposicion_id"];
|
$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 class="aprobar-block">Una vez realizada la acción no se puede deshacer.</p>
|
||||||
<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>
|
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal" aria-label="Close">Cerrar</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -582,8 +563,8 @@ if($user->periodo_id!= ""){
|
|||||||
}
|
}
|
||||||
if(isset($_GET["ok"]) && is_numeric($_GET["ok"])){
|
if(isset($_GET["ok"]) && is_numeric($_GET["ok"])){
|
||||||
switch ($_GET["ok"]){
|
switch ($_GET["ok"]){
|
||||||
case 0: $successDesc = "La reposición se guardó correctamente."; break;
|
case 0: $successDesc = "La reposición se actualizó correctamente."; break;
|
||||||
case 1: $successDesc = "La reposición se actualizó correctamente."; break;
|
case 1: $successDesc = "La reposición fue declinada."; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
require_once 'js/messages.php';
|
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">
|
<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 -->
|
<!-- Botón para abrir el modal -->
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12 text-right">
|
<div class="col-12 text-right">
|
||||||
|
|||||||
6
test.php
6
test.php
@@ -19,9 +19,11 @@
|
|||||||
|
|
||||||
html_header("test.php");
|
html_header("test.php");
|
||||||
?>
|
?>
|
||||||
<?= "<!-- $user -->" ?>
|
|
||||||
<main class="container content content-margin" id="local-app">
|
<main class="container content content-margin" id="local-app">
|
||||||
|
<pre>
|
||||||
|
<?= $user ?>
|
||||||
|
</pre>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
<?
|
<?
|
||||||
include "import/html_footer.php";
|
include "import/html_footer.php";
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ $('div.modal#cargando').modal({
|
|||||||
|
|
||||||
const store = reactive({
|
const store = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
perido: null as Periodo | null,
|
||||||
current: {
|
current: {
|
||||||
comentario: '',
|
comentario: '',
|
||||||
clase_vista: null,
|
clase_vista: null,
|
||||||
@@ -216,8 +217,8 @@ const store = reactive({
|
|||||||
registro_fecha_justificacion: Date;
|
registro_fecha_justificacion: Date;
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const res = await fetch('action/action_justificar.php', {
|
const res = await fetch('action/justificar.php', {
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
@@ -237,6 +238,41 @@ const store = reactive({
|
|||||||
store.current.justificada.justificador_rol = data.justificador_rol
|
store.current.justificada.justificador_rol = data.justificador_rol
|
||||||
store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion
|
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: {
|
registros: {
|
||||||
data: [] as Registro[],
|
data: [] as Registro[],
|
||||||
async fetch(fecha?: Date, fecha_inicio?: Date, fecha_fin?: Date) {
|
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
|
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 this.data.filter((registro: Registro) => {
|
||||||
return filters.every((filtro) => {
|
return filters.every((filtro) => {
|
||||||
switch (filtro) {
|
switch (filtro) {
|
||||||
@@ -306,6 +342,7 @@ const store = reactive({
|
|||||||
return nombre.includes(textoFiltro);
|
return nombre.includes(textoFiltro);
|
||||||
}
|
}
|
||||||
case 'facultad_id':
|
case 'facultad_id':
|
||||||
|
|
||||||
return registro.facultad_id === store.filters[filtro];
|
return registro.facultad_id === store.filters[filtro];
|
||||||
case 'estados':
|
case 'estados':
|
||||||
if (store.filters[filtro].length === 0) return true;
|
if (store.filters[filtro].length === 0) return true;
|
||||||
@@ -364,6 +401,7 @@ type Profesor = {
|
|||||||
}
|
}
|
||||||
createApp({
|
createApp({
|
||||||
store,
|
store,
|
||||||
|
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||||
get clase_vista() {
|
get clase_vista() {
|
||||||
return store.current.clase_vista
|
return store.current.clase_vista
|
||||||
},
|
},
|
||||||
@@ -380,14 +418,22 @@ createApp({
|
|||||||
profesores: [] as Profesor[],
|
profesores: [] as Profesor[],
|
||||||
async mounted() {
|
async mounted() {
|
||||||
$('div.modal#cargando').modal('show');
|
$('div.modal#cargando').modal('show');
|
||||||
|
try {
|
||||||
|
|
||||||
// await store.registros.fetch()
|
// await store.registros.fetch()
|
||||||
await store.facultades.fetch()
|
await store.facultades.fetch()
|
||||||
await store.estados.fetch()
|
await store.estados.fetch()
|
||||||
await store.bloques_horario.fetch()
|
await store.bloques_horario.fetch()
|
||||||
await store.filters.switchFechas()
|
await store.filters.switchFechas();
|
||||||
this.profesores = await (await fetch('action/action_profesor.php')).json() as Profesor[];
|
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[];
|
||||||
$('div.modal#cargando').modal('hide');
|
|
||||||
|
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')
|
}).mount('#app')
|
||||||
|
|||||||
170
ts/periodos.ts
170
ts/periodos.ts
@@ -1,63 +1,145 @@
|
|||||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||||
|
|
||||||
type Carrera = {
|
interface Periodo {
|
||||||
carrera_id: number;
|
created_at: Date;
|
||||||
carrera_nombre: string;
|
estado_id: number;
|
||||||
clave_carrera: string;
|
id_periodo_sgu: number;
|
||||||
facultad_id: number;
|
nivel: string;
|
||||||
facultad_nombre: string;
|
nivel_id: number | '';
|
||||||
nivel_id: number;
|
periodo_clave: string;
|
||||||
nivel_nombre: string;
|
periodo_fecha_fin: Date;
|
||||||
|
periodo_fecha_inicio: Date;
|
||||||
|
periodo_id: number;
|
||||||
|
periodo_nombre: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Nivel = {
|
interface Nivel {
|
||||||
nivel_id: number;
|
nivel_id: number;
|
||||||
nivel_nombre: string;
|
nivel_nombre: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
carreras: [] as Carrera[],
|
periodos: [] as Array<Periodo>,
|
||||||
niveles: [] as Nivel[],
|
niveles: [] as Array<Nivel>,
|
||||||
message: {} as Record<string, string>,
|
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||||
async setNivel(carrera: Carrera, nivel: Nivel) {
|
|
||||||
if (carrera.nivel_id === nivel.nivel_id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
carrera.nivel_id = nivel.nivel_id
|
|
||||||
carrera.nivel_nombre = nivel.nivel_nombre
|
|
||||||
|
|
||||||
await fetch('action/carrera.php', {
|
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',
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
carrera_id: carrera.carrera_id,
|
action: action,
|
||||||
nivel_id: nivel.nivel_id
|
periodo_id: periodo_id,
|
||||||
|
...data
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(res => res.json())
|
return await response.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()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 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() {
|
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())
|
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
|
|
||||||
}, {} as Record<number, Carrera[]>)
|
|
||||||
this.carreras = Object.entries(carreras).map(([facultad_nombre, carreras]) => ({
|
|
||||||
facultad_nombre: facultad_nombre,
|
|
||||||
carreras
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}).mount('#app')
|
}).mount('#app')
|
||||||
Reference in New Issue
Block a user