Personalizar Guardado de Actas (Regular, Promoción y Examen)

Se me presentó la necesidad de agregar una “capa” más de seguridad al proceso de confirmación de carga de notas de las actas.

Ya diseñé los algoritmos, tablas y procedimientos involucrados en la generación, asignación al docente, impresión y validación de tarjetas de coordenadas.
Y también tengo el script que me genera las imágenes de cada tarjeta, simil a esta: https://www.dropbox.com/s/s6i3ecbzmxihddq/001%202015%20395.png?dl=0

El SP encargado de hacer la validación tiene esta sintáxis:

CREATE FUNCTION sp817_validar_coordenadas(
p_nroSerie varchar(12)
, p_unidad_academica varchar(5)
, p_nro_inscripcion varchar(10)
, p_coordenada1 char(2)
, p_coordenada2 char(2)
, p_coordenada3 char(2)
, p_valor1 char(2)
, p_valor2 char(2)
, p_valor3 char(2)
)
RETURNING BOOLEAN

Lo que me falta es el 100% de la personalización del abm de cada acta…
Mi idea sería:

  • En 3 variables de sesión del server generar al azar 3 coordenadas, ej: “C3”, “H1” y “F9”
  • Antes de intentar Guardar los cambios mostrar las 3 coordenadas y solicitar se ingresen los correspondientes códigos.
  • Comprobar los datos y Guardar o informar error hasta N veces y luego cerrar la sesión.
  • Adicionalmente se podría imprementar un captcha simil al del login.

Lo que no tengo en claro es como me conviene encarar las personalizaciones de G3W… no quisiera salirme del estándar.
Agregar unos INPUTs al HTML y hacer una llamada AjaX desde el botón Guardar lo hago sin problemas, pero me estaría saltando al framework…

¿Alguien me da una mano?

Hola Diego, con lo que propones vos no estarías saltando el framework, a mi parecer tendrías que hacer lo siguiente:

  1. Agregar los 3 inputs de las coordenadas al HTML, estas 3 coordenadas y el nro de serie de la tarjeta guardarla en la sesión del docente. ej:

kernel::sesion()->set('nro_serie', "123456789");
kernel::sesion()->set('coor1', "C3");
kernel::sesion()->set('coor2', "H1");
kernel::sesion()->set('coor3', "F9");

  1. Luego cuando el docente guarda validas los valores que puso en los inputs junto con los datos en sesión (seria llamar a FUNCTION sp817_validar_coordenadas).

  2. Cada vez que falla la validación le cambias las coordenadas a completar, si falla 3 veces le cerras la sesión.

podes ir subiendo el código al colab así te puedo ayudar en cualquier duda especifica que tengas respecto al codigo.

pregunta, esto para que versión de 3W es?

saludos.

OK gracias por la respuesta… primero te cuento lo que tengo analizado de momento:

En src/siu/operaciones/notas_cursadas/renglones quiero personalizar default.twig y pagelet_renglones.js para hacer lo descrito en mi primer mensaje.

La idea sería en pagelet_renglones.js hacer una llamada ajax en el botón Guardar y antes de hacer el submit obtener y validar las 3 coordenadas

Y modificar default.twig para agregar un DIV tipo ventana “modal true” (inicialmente oculto) que haga las veces de form para cargar las coordenadas y se lo muestre al hacer clic en Guardar.

Lo que no me queda claro es como hacer la personalización… ¿debo copiar los archivos replicando la estructura de carpetas y repetir todo el código?

¿hay personalizaciones de ejemplo para descargarme y ver como se personaliza cada tipo de archivo?

Sobre tu respuesta:

  • ¿Cuándo en tu punto 1) decís que agregue los inputs al html te referis al archivo.twig?

  • El punto 2) viendo las llamadas ajax de pagelet_renglones.js creo que me doy una idea de como hacer la llamada, pero… ¿dónde iría el php que procesa el request ajax?

  • Ya el punto 3) creo que no tendría dudas de como hacerlo… pero no te extrañe que luego pregunte algo más :smiley:

Actualizo: agrego una url a un sitio web de manuales (que estoy empezando a leer) quizás a alguien más le sea útil: http://librosweb.es/libro/symfony_2_4

Pensando en que la validación debo hacerla al menos en 2 sitios (actas de cursada y actas de examen)…

¿Hay manera de en vez de personalizar cada operación por separado hacer usar un pagelet genérico?

Disculpen la cantidad de preguntas pero claramente Synfony y las plantillas Twig no son lo mío (de momento:).

Hola, acá te paso la documentación de como personalizar http://portalguarani.siu.edu.ar/Portal/wiki/NotasTecnicas/esquemaChulupí. Para los twigs y JS se debe copiar el archivo completo en el directorio correspondiente a la personalización, y allí modificar lo que se desea.

en el punto 1) los inputs van en el default.twig

en el punto 2) el PHP que procesa el AJAX es una acción de un controlador, fíjate como hace en src/siu/operaciones/fecha_examen/filtro/pagelet_filtro.js donde dice info.url_buscar_planes, eso lo setea en src/siu/operaciones/fecha_examen/pagelet_filtro.php public function prepare().

Notas: La validación de las 3 coordenadas también la tenes que hacer del lado del servidor antes de guardar las notas, si la haces solamente del lado del cliente corres riesgos de seguridad.

Gracias por el aporte de los manuales, he leído cosas de esa pagina y están muy interesantes.
saludos.

Subo lo que llevo hecho hasta ahora así si ven algo raro lo comentan (de momento no tuve oportunidad de darle run así que puede haber burradas importantes;).

En pers\unlam\extension_kernel\login.php:
(No es un login propiamente dicho pero me pareció que estaba bien ubicado… si se les ocurre una ubicación mejor soy todo ojos)

namespace unlam\extension_kernel;

use siu\errores\error_guarani_login;

class login extends \siu\extension_kernel\login
{
    /**
     * parametros: nroSerie, $coordena1, $coordena2, $coordena3, valor1, valor2, valor3
     * cache: no
     * filas: 1
     */
    function autenticar_tarjeta($nroSerie, $coordena1, $coordena2, $coordena3, $valor1, $valor2, $valor3)
    {
        $ua = guarani::$ua;
        $nro_inscripcion = guarani::persona()->get_nro_inscripcion();

        $parametros = array('nroSerie' => $nroSerie,
                    'unidad_academica' => $ua,
                    'nro_inscripcion' => $nro_inscripcion,
                    'coordenada' => array(
                        array('nombre' => $coordena1, 'valor' => $valor1),
                        array('nombre' => $coordena2, 'valor' => $valor2),
                        array('nombre' => $coordena3, 'valor' => $valor3)
                    )
                );
        $resultado = catalogo::consultar('docente', 'autenticar_tarjeta', $parametros);
        if (empty($resultado)) {
            throw new error_guarani_login('-1');
        }
        return $resultado;
    }
}

Y en pers\unlam\modelo\datos\db\docente.php:

namespace unlam\modelo\datos\db;

use kernel\kernel;
//use siu\errores\error_guarani;
//use siu\guarani;

//use siu\modelo\entidades\persona;
//use siu\modelo\entidades\unidad_academica;

class docente extends \siu\modelo\datos\db\docente
{
	/**
	 * parametros: parametros
	 * cache: no
	 * filas: 1
	 */
	function autenticar_tarjeta($parametros)
	{
		$sql = "execute procedure sp817_validar_coordenadas('"
             . $parametros["nroSerie"] . "', '"
             . $parametros["unidad_academica"] . "', '"
             . $parametros["nro_inscripcion"] . "', '"
             . $parametros["coordenada"][0]["nombre"] . "', '"
             . $parametros["coordenada"][1]["nombre"] . "', '"
             . $parametros["coordenada"][2]["nombre"] . "', '"
             . $parametros["coordenada"][0]["valor"] . "', '"
             . $parametros["coordenada"][1]["valor"] . "', '"
             . $parametros["coordenada"][2]["valor"] . "')";

        $datos = kernel::db()->consultar($sql, db::FETCH_NUM);
		$ok = $datos[0];

		return $ok;
	}    
}

Hola, el método para validar las coordenadas ingresadas me parecería bueno que este en una clase aparte en lugar de la clase docente.php, por ejemplo en pers\unlam\modelo\datos\db\tarjeta_coordenadas.php, ya que se puede dar que mas adelante no solo la quieras usar para los docentes sino también para otros tipos de usuarios en otras operaciones.

NO me parece adecuado que este en login.php, ademas dicha clase NO esta pensada para hacer consultas al modelo (te va a dar error). Acá te propongo un refactoring de lo que me pasaste:


    /**
     * parametros: _ua, nro_serie, nro_inscripcion, coordenada1, coordenada2, coordenada3, valor1, valor2, valor3
     * cache: no
     * filas: 1
     */
    function autenticar_tarjeta($parametros)
    {
        $sql = "execute procedure sp817_validar_coordenadas({$parametros["nro_serie"]}, {$parametros["_ua"]}), {$parametros["nro_inscripcion"]}, {$parametros["coordenada1"]}, {$parametros["coordenada2"]}, {$parametros["coordenada3"]}, {$parametros["valor1"]}, {$parametros["valor2"]}, {$parametros["valor3"]})";

        $datos = kernel::db()->consultar($sql, db::FETCH_NUM);
        $resultado = $datos[0];

        if (empty($resultado)) {
            return false;//Falló autenticación
        }
        else{
            return true;//Autenticación OK
        }

    }

En parametros a $coordena1, $coordena2, $coordena3 le saque el signo pesos $ y los parámetros se los pase entre {} a $sql para no tener que concatenarlos como string.

Luego desde el controlador podes llamarla así:


$parametros['nro_inscripcion'] = kernel::persona()->get_nro_inscripcion();
$resultado = catalogo::consultar('tarjeta_coordenadas', 'autenticar_tarjeta', $parametros);

Pasar el resto de los parámetros menos el parámetro _ua que lo toma automáticamente del sistema.

Una pregunta, esto para que versión de 3W es? me fije en colab y NO veo donde subieron la personalización, pasame la URL del repositorio.

saludos.

OKas primero (antes de olvidarme) gracias por los aportes.

Todavía no lo había subido al SVN porque estaba muy verde… y no me gusta subir cambios que ni siquiera compilen; pero hice una excepción y ya hice commit…

Podés accederlo desde: https://colab.siu.edu.ar/svn/guarani2/nodos/unlam/3w/trunk/2.8.0/
Lo que no sé es si cualquiera puede levantar el proyecto o solo los usuarios de la unlam.

Editado para corregir la url…

Tengo parcialmente hecha la modificación…

Este sería el html que debo recodificar en el twig

<div id="coordenadas" title="Confirme Grabación">
   <div class="borde-coordenadas"><p>Ingrese las coordenadas...</p></div>
   <div class="borde-coordenadas">
      <label for='C1'>B7:</label><input id='C1' type="text" size="1" maxlength="2" /> -
      <label for='C2'>D4:</label><input id='C2' type="text" size="1" maxlength="2" /> -
      <label for='C3'>I2:</label><input id='C3' type="text" size="1" maxlength="2" />
   </div>
</div>

Este el javascript asociado (uso jquery ui para mostrar un diálogo):

$("#coordenadas").dialog({
   modal: true,
   dialogClass: "no-close",
   showText: false,
   buttons: [{
      text: "Cancelar",
      icons: { primary: "ui-icon-cancel" },
      click: function() {
         $(this).dialog("close");
      }
   }, {
      text: "Aceptar",
      icons: { primary: "ui-icon-check" },
      click: function() {
          // acá la llamada ajax para guardar...
      }
   }]
});

Y estos los estilos:

.borde-coordenadas {
   padding: 10px 0 0 0;
}

.no-close .ui-dialog-titlebar-close {
   display: none;
}

te dejo la clase tarjeta_coordenadas con el cambio sugerido:

<?php

namespace unlam\modelo\datos\db;

use kernel\kernel;
use kernel\util\db\db;

class tarjeta_coordenadas
{
    /**
      * parametros: parametros
      * cache: no
      * filas: 1
      */
    function asignar_tarjeta($parametros)
    {
        $sql = "execute procedure sp817_asignar_tarjeta_coordenadas({$parametros["nroSerie"]}, {$parametros["unidad_academica"]}, {$parametros["nro_inscripcion"]})";

        $datos = kernel::db()->consultar($sql, db::FETCH_NUM);

        $ok = $datos[0];

        return $ok;       
    }

    /**
      * parametros: parametros
      * cache: no
      * filas: 1
      */
    function autenticar_tarjeta($parametros)
    {
        $sql = "execute procedure sp817_validar_coordenadas({$parametros["nro_serie"]}, {$parametros["_ua"]}), {$parametros["nro_inscripcion"]}, {$parametros["coordenada1"]}, {$parametros["coordenada2"]}, {$parametros["coordenada3"]}, {$parametros["valor1"]}, {$parametros["valor2"]}, {$parametros["valor3"]})";

        $datos = kernel::db()->consultar($sql, db::FETCH_NUM);

        $ok = $datos[0];

        return $ok;
    }    

}

Lo que no me queda claro es desde dónde proponías hacer la consulta que hago desde \siu\extension_kernel\login…

Hola, lo que te proponía era no meter el código en \siu\extension_kernel\login.php sino en una clase del modelo personalizada (ej: \pers\unlam\modelo\datos\db\tarjeta_coordenadas.php), por lo que me pasaste esta mal la forma en que pasas los parámetros, estas haciendo:


 /**
      * parametros: parametros
      * cache: no
      * filas: 1
      */

cuando deberías hacer como te puse anteriormente:


/**
     * parametros: _ua, nro_serie, nro_inscripcion, coordenada1, coordenada2, coordenada3, valor1, valor2, valor3
     * cache: no
     * filas: 1
     */
    function autenticar_tarjeta($parametros)
    {

sabes que entro acá https://colab.siu.edu.ar/svn/guarani3/nodos/unlam/3w/trunk/3.8.0 y no veo que hayas subido nada, fíjate que por ahí estas haciendo commit a otro repositorio, proba corriendo “svn info” en tu proyecto local así podes ver donde estas apuntando.

Acá encontré un ejemplo de personalizaciones: http://portalguarani.siu.edu.ar/Portal/wiki/NotasTecnicas/tutorialForm

saludos

sip la url que había puesto estaba mal (era del repositorio de Guarani3)… estaba corrigiendo eso… fijate que ya lo corregí.

Originalmente en login.php lo que hacía era armar un array de parametros y en docentes.php al armar la consulta usaba los elementos del array.

Pareciera que algo se nos está pasando… la consulta y acceso a la db la hacia (originalmente) extendiendo del modelo docente.php (ahora acepté tu sugerencia y creé la clase tarjeta_coordenadas).

Y lo que hacía desde login.php era extender al controlador y agregarle una función más (que procesaba los datos obtenidos desde docentes.php)… ¿decís de crear un controlador nuevo solo para esta función?

Hola Diego, ahí puede ver lo que subiste, note un par de cositas (pavadas), si te fijas en esta documentación los archivos .css NO los tenes que copiar todos, solamente deben contener las reglas CSS que vos personalices. También veo que en los archivos de mensajes (mensajes.es.php) usas la nueva notación de php para arrays, me parece bien pero tene en cuenta que esta notación no funciona con versiones viejas de PHP.

Yo lo que se me ocurre que podes hacer es personalizar la acción function accion__guardar() del controlador src/siu/operaciones/notas_examen/controlador.php (es simplemente extender y personalizar dicha clase/metodo) y ahí antes de $this->guardar_folio(kernel::request()->getPost(‘renglones’)); validas las coordenadas ingresadas llamando al modelo tarjeta_coordenadas.php.

Anda avanzando y cualquier duda no dudes preguntar. saludos.

El el default.twig tengo:


    <div id="coordenadas" title="Confirme Grabación">
        <div class="borde-coordenadas"><p>Ingrese las coordenadas...</p></div>
        <div class="borde-coordenadas">
            <label for='C1'>{% app.session.get('coordenada1') %}:</label><input id='C1' type="text" size="1" maxlength="2" /> -
            <label for='C2'>{% app.session.get('coordenada2') %}:</label><input id='C2' type="text" size="1" maxlength="2" /> -
            <label for='C3'>{% app.session.get('coordenada3') %}:</label><input id='C3' type="text" size="1" maxlength="2" />
        </div>
    </div>

No me doy cuenta en qué momento debo generar las coordenadas…
¿En que parte de que controlador iría esto?:

$letras = "ABCDEFGHI";
kernel::sesion()->set('coordenada1', $letras[rand(0,8)] . rand(1,9));
kernel::sesion()->set('coordenada2', $letras[rand(0,8)] . rand(1,9));
kernel::sesion()->set('coordenada3', $letras[rand(0,8)] . rand(1,9));

Hola, tendrías que meterlo en la acción function accion__edicion() (tenes que personalizar el controlador src/siu/operaciones/notas_examen/controlador.php). Yo te diría que el código que genera las 3 coordenadas NO lo pongas en el controlador sino que los pongas en src/pers/unlam/operaciones/_comun/util/tarjeta_coordenadas.php y ademas verifica que las coordenadas NO se repitan:


<?php
namespace unlam\operaciones\_comun\util;

class tarjeta_coordenadas {

    static function obtener_coordenadas()
    {
        $letras = "ABCDEFGHI";

        $coordenada1 = $letras[rand(0,8)] . rand(1,9);

        do {
            $coordenada2 = $letras[rand(0,8)] . rand(1,9);
        } while ($coordenada1 == $coordenada2);

        do {
            $coordenada3 = $letras[rand(0,8)] . rand(1,9);
        } while (($coordenada1 == $coordenada3) || ($coordenada2 == $coordenada3));

        return array ($coordenada1, $coordenada2, $coordenada3);
    }
} 

luego en src/pers/unlam/operaciones/notas_examen/controlador.php:


<?php

namespace unlam\operaciones\notas_examen;

use unlam\operaciones\_comun\util\tarjeta_coordenadas;
use kernel\kernel;

class controlador extends \siu\operaciones\notas_examen\controlador {

    function accion__edicion()
    {
        parent::accion__edicion();

        list ($coordenada1, $coordenada2, $coordenada3) = tarjeta_coordenadas::obtener_coordenadas();
        kernel::sesion()->set('coordenada1', $coordenada1);
        kernel::sesion()->set('coordenada2', $coordenada2);
        kernel::sesion()->set('coordenada3', $coordenada3);

    }
} 

No se si este código {{ app.session.get(‘coordenada1’) }} funciona en los .twig me parece que es propio de Symfony. Después me fijo de como acceder a la sesión desde un twig.

saludos.

Hola, podes hacer lo que te puse en el mensaje anterior y luego:
en src/pers/unlam/operaciones/notas_examen/controlador.php quedaría:


<?php

namespace unlam\operaciones\notas_examen;

use unlam\operaciones\_comun\util\tarjeta_coordenadas;
use kernel\kernel;

class controlador extends \siu\operaciones\notas_examen\controlador {

    protected $coordenadas;

    function accion__edicion()
    {
        parent::accion__edicion();

        $this->generar_coordenadas();
    }

    function generar_coordenadas(){

        $this->coordenadas = tarjeta_coordenadas::obtener_coordenadas();
        $operacion = kernel::ruteador()->get_id_operacion();
        kernel::sesion()->set($operacion.'_coordenadas', $this->coordenadas);

    }

    function get_coordenadas(){

        return $this->coordenadas;

    }
} 

luego vas a tener que personalizar el prepare del pagelet:
src/pers/unlam/operaciones/notas_examen/pagelet_renglones.php


<?php

namespace unlam\operaciones\notas_examen;


class pagelet_renglones extends \siu\operaciones\notas_examen\pagelet_renglones{

    function prepare()
    {
        parent::prepare();
        $coordenadas = $this->controlador->get_coordenadas();
        $this->data['coordenadas'] = $coordenadas;
    }
} 

luego en el twig te quedaría:


<div id="coordenadas" title="Confirme Grabación">
        <div class="borde-coordenadas"><p>Ingrese las coordenadas...</p></div>
        <div class="borde-coordenadas">
            <label for='C1'>{{ this.data.coordenadas.0 }}:</label><input id='C1' type="text" size="1" maxlength="2" /> -
            <label for='C2'>{{ this.data.coordenadas.1 }}:</label><input id='C2' type="text" size="1" maxlength="2" /> -
            <label for='C3'>{{ this.data.coordenadas.2 }}:</label><input id='C3' type="text" size="1" maxlength="2" />
        </div>
    </div>

luego en el controlador para acceder a las coordenadas de la sesion podes hacer:


        $operacion = kernel::ruteador()->get_id_operacion();
        $coordenadas = kernel::sesion()->get($operacion.'_coordenadas');

saludos

OK estoy “procesando” toda la data… cuando aplique todo lo sugerido al código lo subo al svn…

Me da un error feo al intentar abrir la carga de notas (de examen y/o cursada) abrí un nuevo hilo para tratar el tema de ¿cómo se debe debuguear? específicamente.

Dejo aquí el link al otro hilo: http://foro.comunidad.siu.edu.ar/index.php?topic=8763.0

Cualquier consulta relacionada con el tema principal de este hilo la seguimos aquí, pero me pareció que para tratar el tema debug correspondía iniciar un nuevo tópico.

Hola, ahí te respondí en el otro foro. saludos.