vista_profesor.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <?php
  2. # print_r($_POST); exit;
  3. require_once 'class/c_login.php';
  4. $user = Login::get_user();
  5. $user->access('reporte_de_asistencias');
  6. if ($user->acceso == null)
  7. die(header('Location: main.php?error=1'));
  8. $user->print_to_log('Consultar: Reporte de asistencias de profesor');
  9. #$required_post = ['id', 'fecha_inicial', 'fecha_final', 'periodo'];
  10. #if (array_diff($required_post, array_keys($_POST)))
  11. #header('Location: s.php');
  12. extract($_POST);
  13. $post_keys = array_keys($_POST);
  14. if (
  15. !in_array('fecha_inicial', $post_keys) ||
  16. !in_array('fecha_final', $post_keys)
  17. ) {
  18. header('Location: reporte_de_asistencias.php');
  19. exit;
  20. }
  21. # date validation
  22. $fecha_inicial = date_create_from_format("d/m/Y", $fecha_inicial);
  23. $fecha_final = date_create_from_format("d/m/Y", $fecha_final);
  24. // Nombre del profesor es opcional
  25. $reporte = queryAll("SELECT * FROM fs_asistencia_profesorreporte(:carrera, :periodo, :id, :initial_date, :final_date)
  26. WHERE materia_id = COALESCE(:materia, materia_id)",
  27. array(
  28. ":carrera" => empty($carrera) ? null : $carrera,
  29. ":periodo" => $user->periodo_id,
  30. ":id" => $id,
  31. ":initial_date" => $fecha_inicial->format("Y-m-d"),
  32. ":final_date" => $fecha_final->format("Y-m-d"),
  33. ":materia" => empty($materia) ? null : $materia
  34. )
  35. );
  36. $profesor = query(
  37. "SELECT * FROM FS_PROFESOR WHERE id = :id",
  38. array(":id" => $id)
  39. );
  40. $asistencias = query(
  41. "SELECT total, asistencias, retardos, justificaciones FROM fs_asistencia_reporte(:carrera, :periodo, :clave, :nombre, :facultad, :initial_date, :final_date)",
  42. array(
  43. ":carrera" => empty($carrera) ? null : $carrera,
  44. ":periodo" => $user->periodo_id,
  45. ":clave" => $profesor['clave'],
  46. ":nombre" => $profesor['profesor'],
  47. ":facultad" => $user->facultad['facultad_id'],
  48. ":initial_date" => $fecha_inicial->format("Y-m-d"),
  49. ":final_date" => $fecha_final->format("Y-m-d"),
  50. ),
  51. );
  52. // die(var_dump($asistencias));
  53. $retardos = query("SELECT FS_HAS_RETARDO(:facultad) AS retardo", array(":facultad" => $user->facultad['facultad_id']))['retardo']; ?>
  54. <!DOCTYPE html>
  55. <head>
  56. <title>Reporte asistencias</title>
  57. <meta charset="utf-8">
  58. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  59. <?php
  60. include_once "import/html_css_files.php";
  61. ?>
  62. </head>
  63. <body style="display: block;">
  64. <?php
  65. include("import/html_header.php");
  66. html_header("Reporte de asistencias", "Sistema de gestión de checador");
  67. ?>
  68. <main class="container content marco content-margin">
  69. <div class="container ml-4">
  70. <div class="row my-3">
  71. <h3 class="ml-4 text-left">
  72. <?= $profesor['profesor'] ?>
  73. </h3>
  74. </div>
  75. <div class="row my-3">
  76. <h4 class="ml-4 text-left text-danger"><b>Clave:</b>
  77. <?= $profesor['clave'] ?>
  78. </h4>
  79. </div>
  80. </div>
  81. <div class="row">
  82. <div class="col-12 text-right">
  83. <button type="button" class="btn btn-outline-secondary"
  84. onclick="submit('reporte_de_asistencias.php', {clave: <?= $profesor['clave'] ?>, periodo: <?= $user->periodo_id ?>, nombre: '<?= $profesor['profesor'] ?>', fecha_inicial: '<?= $fecha_inicial->format('Y-m-d') ?>', fecha_final: '<?= $fecha_final->format('Y-m-d') ?>'})">
  85. <span class="ing-regresar ing-fw"></span>
  86. Regresar
  87. </button>
  88. </div>
  89. </div>
  90. <?php
  91. require_once "import/html_forms_vista.php";
  92. ?>
  93. <section id="message"></section>
  94. <!-- Space -->
  95. <div class="row">
  96. <div class="col-12">
  97. <hr>
  98. </div>
  99. </div>
  100. <div id="barra-profesor"></div>
  101. <div class="row">
  102. <div class="col-12">
  103. <hr>
  104. </div>
  105. </div>
  106. <div class="row">
  107. <div class="col-12">
  108. <?php
  109. if (!empty($reporte)) {
  110. ?>
  111. <!-- legend check (Asistencia) x | (sin registro) | * (Justificada) -->
  112. <div class="row text-right">
  113. <div class="col-12">
  114. <i class='ing-aceptar' style='color:green'></i><span class="text-success"> Asistencia</span> |
  115. <?php if ($retardos) { ?>
  116. <i class='ing-retardo' style='color:orange'></i><span style="color:orange"> Retardo</span> |
  117. <?php } ?>
  118. <i class='ing-cancelar text-danger'></i><span class="text-danger"> Sin registro</span> | <i
  119. class='ing-justificar azul'></i><span class="azul"> Justificada</span>
  120. </div>
  121. </div>
  122. <table class="table table-striped table-hover table-white mt-4 table-sm">
  123. <thead class="thead-dark">
  124. <tr>
  125. <th>Grupo</th>
  126. <th>Salón</th>
  127. <th>Materia</th>
  128. <th>Fecha</th>
  129. <th>Hora de clase</th>
  130. <th>Checado</th> <!-- 3 -->
  131. <th></th>
  132. </tr>
  133. </thead>
  134. <tbody>
  135. <?php
  136. $días = array("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado");
  137. //red icon cross
  138. $cross_icon = "<i class='ing-cancelar text-danger'></i>";
  139. $check_icon = "<i class='ing-aceptar text-success'></i>";
  140. $retardo_icon = "<i class='ing-retardo' style='color:orange'></i>";
  141. $justificado_icon = "<i class='ing-justificar azul'></i>";
  142. # print_r($reporte);
  143. foreach ($reporte as $row) {
  144. # print_r($row);
  145. $justificable = false;
  146. if ($row["checado"] == 1)
  147. if ($row["justificada"] == 1)
  148. $checado = $justificado_icon;
  149. else if ($row["retardo"] == 1)
  150. $checado = $retardo_icon;
  151. else
  152. $checado = $check_icon;
  153. else {
  154. $checado = $cross_icon;
  155. $justificable = true;
  156. }
  157. $fecha = date("d/m/Y", strtotime($row["fecha"]));
  158. $hora = date("H:i", strtotime($row['hora']));
  159. $hora_checado = is_null($row["hora_checado"]) ? '-' : date("H:i:s", strtotime($row["hora_checado"]));
  160. $horario = $db->getOne("fget_horario({$row['id']})");
  161. ?>
  162. <tr class="text-nowrap" id="<?= $row["id"] ?>">
  163. <!-- <td class="complete"><pre><?= print_r($row, true) ?></pre></td> -->
  164. <td class="text-center">
  165. <?= $row["grupo"] ?>
  166. </td>
  167. <td class="text-center">
  168. <?= $horario["salon"] ?>
  169. </td>
  170. <td id="<?= $row["materia_id"] ?>"><?= $row["materia"] ?></td>
  171. <td class="text-center text-nowrap">
  172. <?= $fecha ?> |
  173. <?= $días[date("w", strtotime($row["fecha"]))] ?>
  174. </td>
  175. <!-- "hh:mm:ss" -> "hh:mm" -->
  176. <td class="text-center text-nowrap">
  177. <?= $hora ?> -
  178. <?= join(":", array_slice(explode(":", $horario["hora_final"]), 0, 2)) ?>
  179. </td>
  180. <td class="text-center">
  181. <?= $checado ?>
  182. </td>
  183. <td class="text-center">
  184. <?php if ($justificable) { ?>
  185. <button class='btn btn-sm btn-outline-primary'
  186. onclick="justificar(<?= $row['id'] ?>, '<?= $fecha ?>', ' <?= $hora ?>')">Justificar</button>
  187. <?php } else { ?>
  188. <?= !$row["justificada"] ? $hora_checado : "<b>Justificada</b>" ?>
  189. <?php } ?>
  190. </td>
  191. </tr>
  192. <?php
  193. }
  194. ?>
  195. </tbody>
  196. </table>
  197. <?php
  198. } else { ?>
  199. <div class='alert alert-warning'>No hay registros para mostrar</div>
  200. <?php
  201. }
  202. ?>
  203. </div>
  204. </div>
  205. <?php
  206. include_once "import/html_scroll.php";
  207. ?>
  208. </main>
  209. <?php
  210. include("import/html_footer.php");
  211. ?>
  212. <template id="messages_tmp">
  213. <div class="alert alert-{{type}} alert-dismissible fade show" role="alert">
  214. {{message}}
  215. <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  216. <span aria-hidden="true">&times;</span>
  217. </button>
  218. </div>
  219. </template>
  220. <div class="modal fade" id="modal_confirm" tabindez="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">
  221. <div class="modal-dialog modal-dialog-centered" role="document">
  222. <div class="modal-content">
  223. <div class="modal-body">
  224. <div class="row">
  225. <div class="col">
  226. <p class="font-weight-bold">
  227. ¿Estás seguro de justificar esta falta?
  228. <hr>
  229. <section>
  230. <b>Fecha:</b> <span class="modal-fecha"></span> <br>
  231. <b>Hora:</b> <span class="modal-hora"></span>
  232. </section>
  233. </p>
  234. </div>
  235. </div>
  236. </div>
  237. <div class="modal-footer">
  238. <input type="hidden" id="id_borrar" value="">
  239. <input type="hidden" id="facultad_borrar" value="">
  240. <button type="button" class="btn btn-outline-primary btn-aceptar"><span
  241. class="ing-aceptar ing-fw"></span> Justificar</button>
  242. <button type="button" class="btn btn-outline-danger" data-dismiss="modal" aria-label="Close"><span
  243. class="ing-cancelar ing-fw"></span> Cancelar</button>
  244. </div>
  245. </div>
  246. </div>
  247. </div>
  248. <script src="js/bootstrap/popper.min.js"></script>
  249. <script src="js/bootstrap/bootstrap.min.js"></script>
  250. <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.0/mustache.min.js"></script>
  251. <script src="js/fetchlib.js"></script>
  252. <script src="js/barra.js"></script>
  253. <script>
  254. var profesor = <?= json_encode($asistencias) ?>;
  255. // modal_confirm -> bool
  256. function modal_confirm(fecha, hora) {
  257. return new Promise((resolve, reject) => {
  258. $("#modal_confirm").modal("show");
  259. $(".modal-fecha").html(fecha);
  260. $(".modal-hora").html(hora);
  261. $(".btn-aceptar").click(() => {
  262. $("#modal_confirm").modal("hide");
  263. resolve(true);
  264. });
  265. $("#modal_confirm").on("hidden.bs.modal", () => {
  266. resolve(false);
  267. });
  268. });
  269. }
  270. function show_message(message, type) {
  271. var template = $("#messages_tmp").html();
  272. var html = Mustache.render(template, {
  273. message: message,
  274. type: type
  275. });
  276. var clone = $(html);
  277. // append html to message section
  278. clone.appendTo("#message");
  279. // remove after 4 seconds
  280. setTimeout(function () {
  281. clone.alert("close");
  282. }, 4000);
  283. }
  284. $(document).ready(function () {
  285. $("#reporte").hide();
  286. $("#reporte").click(function (e) {
  287. $("#form_reporte").submit();
  288. });
  289. var periodo_inicio = '<?= $periodo["inicio"] ?>';
  290. var periodo_fin = '<?= $periodo["fin"] ?>';
  291. var previous_date;
  292. $('#initial_date_src').focus(function () {
  293. previous_date = $(this).val();
  294. }).change(function () {
  295. // console.log("Periodo inicio: ", periodo_inicio);
  296. // console.log("this < Periodo inicio: ", $(this).val() < periodo_inicio);
  297. if ($(this).val() > $('#final_date_src').val()) {
  298. show_message("La fecha inicial no puede ser mayor a la fecha final", "danger");
  299. $(this).val(previous_date);
  300. } else if ($(this).val() < periodo_inicio) {
  301. show_message("La fecha inicial no puede ser menor a la fecha inicial del período", "danger");
  302. $(this).val(previous_date);
  303. } else {
  304. $("#reporte").show();
  305. var initial_date = $("#initial_date_src").val();
  306. $("#initial_date_dst").val(initial_date);
  307. }
  308. });
  309. $('#final_date_src').focus(function () {
  310. previous_date = $(this).val();
  311. }).change(function () {
  312. console.log("Periodo fin: ", periodo_fin);
  313. console.log("this > Periodo fin: ", $(this).val() > periodo_fin);
  314. if ($(this).val() < $('#initial_date_src').val()) {
  315. show_message("La fecha final no puede ser menor a la fecha inicial", "danger");
  316. $(this).val(previous_date);
  317. } else if ($(this).val() > periodo_fin) {
  318. show_message("La fecha final no puede ser mayor a la fecha final del período", "danger");
  319. $(this).val(previous_date);
  320. } else {
  321. $("#reporte").show();
  322. var final_date = $("#final_date_src").val();
  323. $("#final_date_dst").val(final_date);
  324. }
  325. });
  326. /*
  327. $("#submit-form").click(function(e) {
  328. var form = $("#form_reporte");
  329. // change action of form
  330. form.attr("action", "consultar_asistencias.php");
  331. form.submit();
  332. });
  333. */
  334. $("#barra-profesor").html(barra(profesor, <?= $retardos ? "true" : "false" ?>));
  335. });
  336. function justificar(id, fecha, hora) {
  337. modal_confirm(fecha, hora).then(async (result) => {
  338. if (result) {
  339. var resultado = await fetchPHP("action/action_justificar.php", {
  340. clave: "<?= $id ?>",
  341. fecha: fecha,
  342. hora: hora,
  343. id: id
  344. });
  345. if (resultado.success) {
  346. show_message("Asistencia justificada", "success");
  347. // Change button to justificada and the icon
  348. // to only javascript
  349. const cell = document.querySelector(`button[onclick="justificar(${id}, '${fecha}', '${hora}')"]`).parentElement;
  350. // the previous td
  351. cell.innerHTML = "<b>Justificada</b>";
  352. profesor.justificaciones++;
  353. profesor.faltas--;
  354. document.getElementById("barra-profesor").innerHTML = barra(profesor, <?= $retardos ? "true" : "false" ?>);
  355. // previous cell, change icon
  356. cell.previousElementSibling.innerHTML = `<?= $justificado_icon ?>`;
  357. } else {
  358. show_message("Error al justificar asistencia", "danger");
  359. }
  360. }
  361. });
  362. }
  363. async function carreras(id_carrera) {
  364. // enable datalist carreras
  365. disableDatalist("#filter_materia", false);
  366. var materias = await fetchPHP("action/action_materias.php", {
  367. carrera: id_carrera,
  368. profesor_id: <?= $id ?>
  369. });
  370. if (materias.error) {
  371. show_message("Error al obtener las materias", "danger");
  372. return
  373. }
  374. // clear datalist
  375. $("#dlmateria ul").html("<li data-id=''>Todas las materias</li>");
  376. // add options to datalist
  377. materias.forEach(materia => {
  378. $("#dlmateria ul").append(`<li data-id="${materia.id}">${materia.nombre}</option>`);
  379. });
  380. setDatalistFirst("#filter_materia");
  381. }
  382. function validateForm() {
  383. var initial_date = $("#initial_date_src").val();
  384. var final_date = $("#final_date_src").val();
  385. if (initial_date == "" || final_date == "") {
  386. show_message("Debe seleccionar un rango de fechas", "Error al generar reporte");
  387. return false;
  388. }
  389. return true;
  390. }
  391. </script>
  392. </body>
  393. </html>