form accion controlador

Hola, estoy diseñando una nueva operación en g3w3 3.16.2 y mi estructura de datos es la sguiente:

Esta es mi estructura y modifiqué los archivos con éxito: …/g3w3/src/pers/personalizacion1/

  •   ../g3w3/src/pers/personalizacion1/conf/acceso/acc_Alumno.php
    
  •   ../g3w3/src/pers/personalizacion1/modelo/datos/db/fac.php
    
  •   ../g3w3/src/pers/personalizacion1/modelo/transacciones/carga_datos.php
    
  •   ../g3w3/src/pers/personalizacion1/operaciones/comprobantes
    

Acá agregué los siguientes directorios y archivos:
/cuadro_comprobantes/default.twig
controlador.php
pagelet_cuadro_comprobantes.php
template.twig
vista.php

Todo funciona perfecto y logré hacer lo que quiero, hasta ahora.
La duda que tengo, en el archivo /cuadro_comprobantes/default.twig escribí una tabla y con un for (twig) recorro los datos y la lleno perfectamente.
Al hacer click en cada fila, se abre un modal con un formulario que también lo escribí en html y lo lleno con datos utilizando el for de twig. (en el mismo default.twig)
La duda es a la hora de hacer click en el submit del form, quiero llamar a una acción del controlador y no puedo.
Cómo debería ser la llamada en el action del form?
Ví un pequeño ejemplo y para registrar el evento del form hay que hacer una serie de pasos que seguí y no me funcionan.
Puedo saltear la registración del form y la validación de cada campo y llamar al controlador desde el action? creo que sería más simple y se aplica bien a lo que quiero hacer.

Si es necesario, comparto el código. Muchas gracias.
Saludos.

Hola Gonzalo,

La duda es a la hora de hacer click en el submit del form, quiero llamar a una acción del controlador y no puedo. 
Cómo debería ser la llamada en el action del form?

Deberías hacer lo siguiente:

  1. Crear la acción en el controlador, las mismas siempre deben tener el prefijo “accion__”, ej:

function accion__guardar()
{
// Código aquí....
}

  1. En el pagelet crear la URL a esta acción para luego ponerla en el formulario, dentro de la función prepare (prepara datos para la vista):

function prepare()
{
.......
$operacion = kernel::ruteador()->get_id_operacion();
$this->data['url_guardar'] = kernel::vinculador()->crear($operacion, 'guardar'); // Si la acción  se llamara "accion__procesar_solicitud", el segundo parámetro seria 'procesar_solicitud' en lugar de 'guardar'.
}

  1. En el twig hacemos uso de esta URL en el action del form:

<form method="post" action="{{ this.data.url_guardar }}">
......
</form>

Espero que te sirva!!!

saludos.

Si, me funcionó perfecto. Muchas gracias.

Te hago otra consulta acerca del catálogo y transacciones.

/**
	 * parametros: id
	 * cache: no
	 */
	function datos_comp($parametros)
	{
		$sql = "SELECT *FROM negocio_pers.comprobantes where id = {$parametros['id']}";
                 return kernel::db()->consultar($sql);
	}

y en las transacciones tengo esto:

function datos__comprobante()
    {
        return catalogo::consultar('comprobantes', 'datos_comp', array('id' => '....'));
    }

Ese parámetro me lo envío del formulario por post y llamo la consulta desde el controlador así:

$comprobante = carga_comprobantes::datos__comp($_POST['id']);

También probé así:

function datos__comprobante()
    {
        return catalogo::consultar('comprobantes', 'datos_comp', array('id' => $id));
    }

Pero no funciona tampoco. Harcodeando los datos va bien.

Seguro es una tontera.
Gracias

Hola Gonzalo, observo lo siguiente:

  1. En el catalogo, falta un espacio entre el “*” y el “FROM”, debería ser “SELECT * FROM”. Ademas siempre que agregas o modificas cosas en el catalogo debes correr el comando bin/guarani generar_catalogo en 3W. Luego debes versionar el archivo _info_catalogo.php.

  2. Observo varias cosas en esta linea $comprobante = carga_comprobantes::datos__comp($_POST[‘id’]);:

a) Estas llamando de manera estática una función que no lo es. Tomemos como ejemplo el controlador src/siu/operaciones/solicitud_certificado/controlador.php, vas a ver que tiene una función llamada modelo la cual devuelve una instancia de la clase src/siu/modelo/transacciones/solicitud_certificados.php (singleton), y luego para llamar una función de dicha transacción hace como sigue:

$this->modelo()->nombre_funcion($parametos);

b) No es aconsejable acceder directamente a los datos de $_POST ($_POST[‘id’]). Tenemos funciones que obtienen datos del $_POST o $_GET, pero le aplican un proceso de sanitización previamente:

$id = $this->validate_param('id', 'post', validador::TIPO_INT);

saludos.

Gracias.
Te molesto con algo más, me comunico con un webservice y al obtener la respuesta de éxito o error, quiero mostrar un mensaje con el resumen de la operación.

Para esto, hago un

$this->render_template('response.twig', $resultado); 

$resultado tiene el mensaje y detalles de la operación. El problema que tengo es que no me mantiene los estilos y me muestra una pantalla en blanco con un par de datos que no sé de donde salen, además de mi párrafo mal formateado.

https://i.imgur.com/VIchme0.png

En el .twig solo hago un

del mensaje para probar.

me basé en …operaciones/plan_estudio/

Este archivo lo tengo fuera del cuadro_comprobantes, es decir , así:

  •   ../g3w3/src/pers/personalizacion1/operaciones/comprobantes
    

/cuadro_comprobantes/default.twig
controlador.php
pagelet_cuadro_comprobantes.php
template.twig
vista.php
response.twig (este es el .twig que utilizo para el render_template).

Es correcto hacer esto o existe alguna otra forma ?
Gracias.

Hola Gonzalo, te paso un ejemplo de como se usa el render_template.

Si te fijas en la operación Plan de estudio (perfil alumno), vas a ver que si el alumno tiene correlativas aparece un botón que dice “Ver”. Dicho botón hace un AJAX para mostrar las correlativas de dicha actividad.

El Ajax lo hace en src/siu/operaciones/plan_estudio/info_plan/pagelet_info_plan.js función delegate_correlativas, esto lo termina atajando la función accion__correlativas de src/siu/operaciones/plan_estudio/controlador.php. Si te fijas al final de todo hace lo siguente:


    function accion__correlativas()
    {
        .................
        $this->render_template('correlativas.twig', $resultado);

    }

Esto lo que devuelve es un JSON con la siguiente estructura:


{
    "cod": "1",
    "cont": "<div>Contenido HTML</div>"
}

Lo que deberías hacer es tomar el contenido HTML (paquete.cont) e insertarlo en una parte de la pantalla:

                        
                        kernel.ajax.call(info.url_correlativas, {
                            type: 'post',
                            data: {
                                elemento: $link.data("elemento"),
                                elemento_padre: $link.data("elementoPadre")
                            },
                            success: function(paquete) {
                                $link.data('completo', 'true');
                                $('#'+id_destino).html(paquete.cont);
                            },
                            error: function() {
                                $('#'+id_destino).html(paquete.cont);
                            },
                            complete: function() {
                                $('#'+id_destino).toggle('slow', cambiar_texto($link));
                            }
                        })

saludos.

Gracias, Leo.
El tema es que no mando nada por post, sólo quiero mostrar un mensaje de éxito o error que eso me lo dice el webservice.
Quizás no me expliqué bien, hice una nueva operación donde leo facturas para pagar y me conecto con todopago. Utiliza un webservice soap

https://i.imgur.com/sOfD2IR.png

El proceso está funcionando completo. Lo único que me falta es mostrar un mensaje de éxito de operación o error (lo marque en rojo donde debería mostrarlo).

En la acción del controlador a la hora de chequear si el pago fue exitoso, hago lo siguiente:


function accion_check()
{
.......
.......
........
........
$optionsGAA = array (
            .....
            .....
            'RequestKey' => $_COOKIE['RequestKey'],
            'AnswerKey' => $_GET['Answer']
        ); 
$http_header = array(..........., 'user_agent' => 'PHPSoapClient');
$connector = new Sdk($http_header, 'test');

$rta = $connector->getAuthorizeAnswer($optionsGAA);
if ($rta['StatusCode'] == -1){
 // significa que fue exitoso y acá debería hacer un redirect y mostrar el mensaje de éxito arriba de la tabla como indiqué en la imagen.
} else {
  // hacer el mismo redirect pero con el mensaje de error
}


 

Lo único que me falta es el proceso del mensaje, después el resto está funcionando bien.
Gracias y perdonen las molestias.

Hola Gonzalo,

Si lo que queres hacer es mostrar un mensaje de éxito/error podes hacer lo siguiente:

Si te fijas en la operación de Mensajes de 3W hace lo siguiente:

  1. Si te fijas en la función accion__enviar_mensaje de la clase src/siu/operaciones/mensajes/controlador.php, vas a ver que guarda un mensaje en la sesión y luego redirige:

				// Al finalizar de enviar el mensaje se lo redirija al inicio de la operación ('index'), ahora a enviados
				$operacion = kernel::ruteador()->get_id_operacion();
				kernel::sesion()->set('mensaje_enviado_ok', true);
				$this->nuevo_request($operacion, 'enviados');

  1. Luego en la función prepare de la clase src/siu/operaciones/mensajes/pagelet_lista_mensajes.php, si el mensaje esta seteado se lo pasa al JS para que lo muestre:

		if(kernel::sesion()->esta_seteada('mensaje_enviado_ok')){
			kernel::sesion()->borrar('mensaje_enviado_ok');
			$this->add_var_js('mensaje_enviado_ok', true);
			$this->add_mensaje_js('mensaje_enviado_ok_msj', ucfirst(kernel::traductor()->trans('mensajes_enviar_exito')));
		}

  1. Luego en el JS muestra el mensaje si esta presente:

			// Si hay mensaje de envío exitoso lo muestro
			if(info.mensaje_enviado_ok){
				
				kernel.ui.show_mensaje(info.mensajes.mensaje_enviado_ok_msj, {
				    tipo: 'alert-success',
				    timeout: 10000
				});
				
			}

saludos.

Hay otra operación (Reasignación de Optativas) que en lugar de mostrarlo con funciones JS, lo muestra directamente en la vista:

  1. En la función accion__guardar de la clase src/siu/operaciones/reasignar_optativa/controlador.php hace:

			kernel::sesion()->set('hubo_error', $hubo_error);

  1. Luego en el pagelet, función prepare de la clase src/siu/operaciones/reasignar_optativa/pagelet_listado.php hace:

		// Si es la vuelta de la confirmación
		if(kernel::sesion()->esta_seteada('hubo_error') && kernel::sesion()->esta_seteada('cant_cambios')){
			
			$this->data['mostrar_mensaje'] = true;
			
			$hubo_error		= kernel::sesion()->get('hubo_error');
			$cant_cambios	= kernel::sesion()->get('cant_cambios');
			
			// Si hubo error
			if($hubo_error){
				$this->data['tipo_mensaje'] = static::TIPO_MENSAJE_ERROR;
				$this->data['mensaje']		= kernel::traductor()->trans('reasignar_optativa.error_confirmar_reasignacion');
			} // si no hubo error y hubo cambios
			else if ($cant_cambios > 0){
				$this->data['tipo_mensaje'] = static::TIPO_MENSAJE_EXITO;
				$this->data['mensaje']		= kernel::traductor()->trans('reasignar_optativa.reasignacion_exitosa');
			} // si no hubo error y tampoco hubo cambios
			else{
				$this->data['tipo_mensaje'] = static::TIPO_MENSAJE_INFO;
				$this->data['mensaje']		= kernel::traductor()->trans('reasignar_optativa.no_has_reasignado_optativas');
			}
			
			kernel::sesion()->borrar('hubo_error');
			kernel::sesion()->borrar('cant_cambios');
		}

  1. Finalmente lo muestra en la pantalla src/siu/operaciones/reasignar_optativa/listado/default.twig:

        {% if this.data.mostrar_mensaje %}
            <div class="alert {{ this.data.tipo_mensaje }}">
                <button type="button" class="close" data-dismiss="alert">&times;</button>
                {{ this.data.mensaje }}
            </div>
        {% endif %}

En caso de error el mensaje debe ser de tipo “alert-error”, en caso de éxito “alert-success” (https://getbootstrap.com/2.3.2/components.html#alerts).

saludos.

Gracias! utilicé la primer opción.

Te hago una última consulta:
Agregué la operación en “Trámites” pero cuando ya estoy en la operación y hago click en los botones del navbar, ningún dropdown funciona (no se despliegan).

https://i.imgur.com/TsiXaFL.png

Estando en la operación pagos, el desplegable no funciona. Debería desplegar así:

https://i.imgur.com/8sKSHkz.png

Hola Gonzalo,

Si estamos hablando de la operación Reasignación de Optativas no es necesario agregarla al menú, ya que la misma ya se encuentra allí:

src/siu/conf/acceso/acc_Alumno.php


<?php
return array(
    'id' => 'Alumno',
    'parametros' => array(
        'index' => 'inicio_alumno'
    ),
    'operaciones' => array(
..................
        'reasignar_optativa' => array(
            'activa' => true,
            'menu' => array(
		'submenu' => 'tramites',
                'visible' => true
            )
        ),
..................
    )
);

¿te esta dando algún error en los logs de Apache o de la aplicación (carpeta instalacion/log)?

saludos.

Para agregar una nueva operación en el menú (perfil Alumno), se debe personalizar de la siguiente manera:

src/pers//conf/acceso/acc_Alumno.php


<?php
return array(

    'operaciones' => array(

        '<NOMBRE-OP>' => array(
            'activa' => true,
            'menu' => array(
                'submenu' => 'tramites', // <===> La agrego dentro de "Trámites"
                'visible' => true
            )
        )

    )

);

Reemplazar:
: por el nombre de la carpeta de personalización dentro de src/pers.
: por el nombre de la carpeta de la operación dentro de src/pers//operaciones

saludos.

Buen día, retomando esta operación, no me arroja ningún error ya que me queda bloqueado el cursos al querer clickear la operación.
Estando en “Trámites → Pagos” el único botón que puedo clickear es “Inscripción a Materias”, el resto no funciona.

https://i.imgur.com/lOHDk7k.jpg

src/pers/todopago/conf/acceso/acc_Alumno.php
Este archivo lo tengo así:

<?php
return array(
    'operaciones' => array(
        'acceso' => array( 'activa' => true, ),

        'pagos' => array(
            'activa' => true, 
            'menu' => array(
                'submenu' => 'tramites',
                'visible' => true
            )
        )
	)
);

?>

También probé dejando completo el archivo como el original y solo agregar mi operación.
El sistema de carpetas es este:
… /g3w3/src/pers/todopago/operaciones/pagos

En el archivo acc_Alumno.php cambio “pagos” por “todopago”, no funciona directamente.

Gracias.
Saludos.

Hola Gonzalo,

Claro, en el archivo src/pers/todopago/conf/acceso/acc_Alumno.php va el nombre de la carpeta de la operación.

Si la carpeta es src/pers/todopago/operaciones/pagos, el archivo acc_Alumno.php debería quedar así:


<?php
return array(

    'operaciones' => array(

        'pagos' => array(
            'activa' => true,
            'menu' => array(
                'submenu' => 'tramites',
                'visible' => true
            )
        )

    )

);

Si queres que en la URL diga “todopago” en lugar de “pagos” hace lo siguiente:


<?php
return array(

    'operaciones' => array(

        'pagos' => array(
            'activa' => true,
            'url' => 'todopago',
            'menu' => array(
                'submenu' => 'tramites',
                'visible' => true
            )
        )

    )

);

saludos.

Hola Leo, lo tengo tal cual me indicas:

https://i.imgur.com/JRZXgyT.png

<?php
return array(
    'operaciones' => array(

        'pagos' => array(
            'activa' => true, 
            'menu' => array(
                'submenu' => 'tramites',
                'visible' => true
            )
        )
	)
);

?>

Por alguna razón, estando en “Trámites->Pagos”, el dropdown de trámites y reportes, dejan de funcionar.
Gracias.
Saludos.

Hola Gonzalo, es extraño!!!

Fíjate en los logs de Apache si muestra algún error, o en su defecto en los logs de la aplicación (carpeta instalacion/log).

¿tenes la personalización subida al colab?, así la puedo ver.

saludos.

Hola Leo,
Revisé los logs y no indican error en el menú.

Ahí subí dos de las personalizaciones que tengo activadas en desarrollo.

src/pers/template
src/pers/todopago

Muchas gracias!

Hola Gonzalo,

Probé las personalizaciones en mi instalación local, y no tengo el problema que me decís de que no despliega el menú.

La personalización parece estar bien, algo que noto a mejorar es que pusieron los mensajes de la personalización todopago dentro de la personalización template, con lo cual la primera es dependiente de la segunda pero el resto esta bien!!!

Te voy a pedir lo siguiente, en el navegador hace un Inspeccionar elemento y anda la solapa Consola, luego trata de desplegar el menú y fíjate si muestra algún error JavaScript en consola.

saludos.

Aparte de lo anterior, tengo unas sugerencias que les pueden servir:

En la función prepare del archivo src/pers/todopago/operaciones/pagos/pagelet_cuadro_pagos.php tenes:


$operacion = kernel::ruteador()->get_id_operacion(); // <==> $operacion toma el valor 'pagos'
$this->data['url_guardar'] = kernel::vinculador()->crear($operacion, 'guardar');
$this->add_var_js('url_guardar', kernel::vinculador()->crear('pagos', 'pagar')); // <==> Acá podes reemplazar 'pagos' por $operacion

En la función accion__guardar del archivo src/pers/todopago/operaciones/pagos/controlador.php tenes:


$optionsSAR_comercio = array (
	            'Security'=>$APIKeys,
	            'EncodingMethod'=>'XML',
	            'Merchant'=>$MerchantID,
	            'URL_OK'=>"http://".$_SERVER['SERVER_NAME']."/g3w3/pagos/exito?operationid=".$input['nro_factura'],
	            'URL_ERROR'=>"http://".$_SERVER['SERVER_NAME']."/g3w3/pagos/error?operationid=".$input['nro_factura'],
	        ); 

las URLs las podes armas como sigue:


$operacion = kernel::ruteador()->get_id_operacion();
'URL_OK' => kernel::vinculador()->crear($operacion, 'exito', ['operationid' => $input['nro_factura']]),
'URL_ERROR' => kernel::vinculador()->crear($operacion, 'error', ['operationid' => $input['nro_factura']]),

También trata de no subir las credenciales de TodoPago en el código, lo mejor es poner “placeholders” y luego cuando haces la instalación se las cambias.

saludos.

Buen día,
Muchas gracias por el análisis. Voy a aplicar esos cambios que me dices y volveré a probar.

Saludos