Si me modifican un dato de mi tabla, necesito saberlo al instante……

La capacitadora me ha presentado el siguiente problema: necesita saber exactamente cuándo un aprendiz es cambiado de categoría en la base de datos PostgreSQL (tarea que hace el departamento de personal cuando el instructor lo informa), tener la posibilidad de guardar una traza de su trayectoria y calcular automáticamente los días laborables de que dispone para evaluarse en esa nueva categoría.

La tarea tiene sus complicaciones, pues los instructores no siempre están al tanto de las fechas y tampoco avisan inmediatamente a la capacitadora, que también necesita moverse, hacer gestiones en la calle, etc. Así pues, pensé en preparar un “trigger” que inmediatamente que se cambie el dato de la categoría actualice otra tabla donde se guardará la traza de la trayectoria en la formación del aprendiz, y a partir de cuyas fechas se calculará el período de tiempo asignado para cada etapa de preparación.

Manos a la obra, pues. Acá todo es PHP+PostgreSQL, así que los cambios en la base de datos se visualizarán en una página PHP.

Creemos en nuetra base una tabla etapa_alumno_cambio, con los campos cambiado_por (de tipo texto), cambiado_cuando (de tipo date), numero (de tipo integer), etapa_anterior (de tipo smallint) y etapa_nueva (de tipo smallint).

Esa tabla la creo directamente desde la pizarrita de comandos del PgAdmin3 tecleando:

create table etapa_alumno_cambio (

cambiado_por text default current_user,

cambiado_cuando date default now,

numero integer,

etapa_anterior smallint,

etapa_nueva smallint);

Ya tenemos la tabla nueva que necesitamos,

Sea  generales la tabla donde se guardan los datos de todo el personal, y sea entre 7000 y 9000 el rango de números asignado a los estudiantes.

Como uso PgAdmin3 para manipular la base PostgreSQL, declaro en la pizarrita de comandos una función nueva, que llamaré loguea_cambio_etapa()  mediante:

create or replace function loguea_cambio_etapa() returns trigger as $$

declare el_numero integer;
declare la_etapa_nueva smallint;

BEGIN
IF TG_OP = ‘INSERT’ THEN
select into el_numero numero
from generales where numero=NEW.numero;

select into la_etapa_nueva tipo
from generales where numero=NEW.numero;

if el_numero >=7000 and el_numero <=9000 then
INSERT INTO etapa_alumno_cambio(numero,etapa_nueva)
VALUES (el_numero,la_etapa_nueva);
end if;

ELSIF TG_OP = ‘UPDATE’ THEN
select into el_numero numero
from generales where numero=NEW.numero;

select into la_etapa_nueva tipo
from generales where numero=NEW.numero;

if el_numero >=7000 and el_numero <=9000 then
INSERT INTO etapa_alumno_cambio(numero,etapa_anterior,etapa_nueva)
VALUES (el_numero,OLD.etapa,la_etapa_nueva);
end if;

END IF;
RETURN NEW;
END;

$$ langage plpgsql security definer;

Como se ve, la función monitorea los cambios en la tabla generales que involucren a números que se encuentren en el rango de 7000 a 9000. Se conserva la fecha del cambio, quién lo hizo, y tanto la etapa anterior (si la hay) como la nueva etapa.

Ahora hay que habilitar el “trigger”, el disparador que ejecutará la función cada vez que haya un cambio. Nuevamene voy a mi pizarrita de comandos y declaro:

create trigger loguea_cambio_etapa

after insert or updte or delete on etapa_alumnos

for each row execute procedure logue_cambio_etapa();

Hasta aquí tenemos que la traza de cualquier cambio de la etapa del aprendiz que sea realizado en la tabla principal de datos de personal será reflejada en la nuestra. En consecuencia, si más adelante necesito verifiar la trayectoria de estudiante de alguno, será fácil consultarla.

Ahora pasamos a preparar la página PHP que presentará la información pedida (no es excesivamente complicada, pero sí un poco larga):

<?php
//error_reporting(E_ALL);
require(‘comun.php3’);
//$ano=$_GET[‘ano’];
//@pg_query($mibase,”drop table tabla_calidad_alumnos”);
$consulta=pg_query($mibase,”select nombre,ape1,ape2,numero,tipo, idtrabajador
from generales
where
numero>7000 and numero<9000
and depto=’ENS’
and fechabaja=’2100-01-01′
order by numero”);
$total=pg_num_rows($consulta);
if (!$consulta)
{
echo “Error al conectarse a la base de datos de la galera.<br>”;
exit;
}

$bcolor=’cyan’;

echo “<center><b>”;
echo “Fecha: “;
@setlocale(“LC_TIME”,”es_ES”);
echo strftime(“%A %d de %B del %Y”);
printf(“<br>Estudiantes: %s”,$total);
echo “</center></b>”;

function cabeza($ano)
{
$cadena1=”Porcientos”;
$cadena2=”Control del tiempo del estudiante en cada etapa”.”<br>”;
//$cadena3=”Estudiantes: ” . $total;
require(‘../comun/a_header.php3’);
require(‘../comun/fonts.css’);

echo “<table border=1 class=tabla width=90%>”;
echo “<tr>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>Alumno</b>”;
echo “</td>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>No.</b>”;
echo “</td>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>Etapa</b>”;
echo “</td>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>Duraci&oacute;n</b>”;
echo “</td>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>Inici&oacute; la etapa</b>”;
echo “</td>”;
echo “<td align=center bgcolor=yellow>”;
echo “<font size=2>”;
echo “<b>Fin tentativo de la etapa</b>”;
echo “</td>”;

}
function cola()
{
echo “</tr>”;
echo “</table>”;
}
$inicio=$linea=0;
$actual=0;

while ($actual<$total)
{
$este=pg_fetch_row($consulta,$actual);

if ($linea==0) cabeza($ano);
echo “<tr>”;
switch ($este[4])
{
case 4: $colorcito=”cyan”;
break;
case 5: $colorcito=”dodgerblue”;
break;
case 6: $colorcito=”green”;
break;
case 7: $colorcito=”yellow”;
break;
case 8: $colorcito=”magenta”;
break;
case 9: $colorcito=”grey”;//No se cuantos dias
break;
}
echo “<td align=left nowrap bgcolor=$colorcito>”; /* Nombre */
echo “<font class=textg>&nbsp;”;
echo $este[0] .” “. $este[1]. ” ” .$este[2];
echo “</td>”;
echo “<td align=left nowrap bgcolor=$colorcito>”; /* Numero */
echo “<font class=textg>&nbsp;”;
echo $este[3];
echo “</td>”;
echo “<td align=left nowrap bgcolor=$colorcito>”; /* Etapa */
echo “<font class=textg>&nbsp;”;
$etapa=pg_query($mibase,”select calificador from distrib where tipo=$este[4]”);
$dime_etapa=pg_fetch_row($etapa);
echo $dime_etapa[0];

echo “</td>”;
echo “<td align=center nowrap bgcolor=$colorcito>”; /* Duracion */
echo “<font class=textg>&nbsp;”;
switch ($este[4])
{
case 4: $duracion=48;
break;
case 5: $duracion=48;
break;
case 6: $duracion=36;
break;
case 7: $duracion=36;
break;
case 8: $duracion=36;
break;
case 9: $duracion=3600;//No se cuantos dias
break;
}

echo $duracion;
echo “</td>”;
echo “<td align=left nowrap bgcolor=$colorcito>”;
$fechacambio=pg_query($mibase,”select cambiado_cuando,
cambiado_cuando+$duracion,
extract(dow from cambiado_cuando)
from etapa_alumno_cambio where numero=$este[3]”);
$dimefechacambio=pg_fetch_row($fechacambio);
echo $dimefechacambio[0];

/* Calcular cuantos sabados y domingos hay entre las dos fechas extremas */
$diadelasemana=$dimefechacambio[2];
$vesumando=0;

for ($cuenta=1;$cuenta<$duracion;$cuenta++)
{
$diadelasemana++;
if ($diadelasemana>=6){
$vesumando++;
}
if ($diadelasemana>6) {$diadelasemana=0;}
}
//echo ” fines de semana ->” .$vesumando;/* Dias que hay que sumarle a la duracion */

echo “</td>”;
echo “<td align=left nowrap bgcolor=$colorcito>”;
if ($dimefechacambio[1])
{
/*echo $dimefechacambio[1];*/ /*Si lo descomento tengo la fecha tentativa sin descontar sabados y domingos*/
$incrementa=$vesumando*24*60*60;
$xx=strtotime($dimefechacambio[1]);
$xx=$xx+$incrementa;
echo ” ” .date(‘Y-n-j’,$xx);
$vesumando=0;
}
echo “</td>”;
echo “</tr>”;
$linea++;
if ($inicio==0){$dato=38;} else {$dato=43;}
if ($linea>$dato or $actual+1>=$total)
{
$linea=0;
$inicio=1;
cola();
?>
<div style=”page-break-after:always”></div>
<?php
}
$actual++;
}
echo “</table>”;
echo “<br>”;
require(‘../comun/atras.php3’);
echo “</center>”;
?>

Como se ve, hay ficheros incluidos y hojas de estilo para declarar cómo quiero que luzca la página (las cuestiones cosméticas).el rejuego con

<div style=”page-break-after:always”></div>

es para que haga el equivalente a un salto de página en pantalla, pues esto se imprime y debe lucir aceptablemente.

La consulta (el query) a la base PostgreSQL ya trae como resultado una fecha tentativa de fin de etapa, calculada sumándole a la fecha de la modificación (cuándo se anunció el último cambio) los días que correspondan a cada etapa. Como me han pedido que no se les cuenten los sábados ni domingos, pues uso las funciones dow (day of week), strtotime (convertir una cadena a fecha) y date (fecha) para averiguar cuántos de esos hay en el intervalo de fechas, y guardar ese número como un valor a sumar a la fecha tentativa de fin del período.

Y bien, es todo. Fue más difícil pensar cómo que programarlo.

Si a alguien le es útil esta información, hágamelo saber.

Esta entrada fue publicada en Debian, Linux, Programación, Software Libre, Ubuntu. Guarda el enlace permanente.

Una respuesta a Si me modifican un dato de mi tabla, necesito saberlo al instante……

  1. AdrianFagales dijo:

    Hermano existe algun linux, que simplemente tu le des clic al sofware que desas instalar , este se instale y lista, no importa el distro, solo que descargue el programa de internet, luego le de doble clic y este se instale. o hay q tener siempre un repo enorme a mano.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *