
En este apartado se recogen experiencias concretas que puedan servir para simplificar desarrollo de aplicaciones WEB.
Un programa tiene asociado una tabla, en el apartado de campos asociado a esta tabla, se puede indicar qué campos los formarán. Al definir el campo, podemos indicar su ámbito, fórmula, fila, columna, pestaña, seguridad campo, tipo de campo y descripción (en multidioma).
![]() | ![]() |
Si no se especifica fila, columna en los campos, el valor por defecto 0.0, los campos se distribuyen en modo columna por orden de definición de los campos en la creación de la tabla.
Si se quiere fijar fila.columna se tiene que aportar el valor deseado para orgranizar todos los campos en el orden que se quiera, sin depender de su orden de creación. En el siguiente ejemplo se muestra como los campos de la tabla RM_ACCIONES se distribuyen con fila columna, para que su alta, modificación o consulta siempre sea con un orden fijo.
![]() | ![]() |
Al mostrar los campos de una tabla, GERAPLI, mostrará por defecto el tamaño real de campo. Por ejemplo, un campo se creo con varchar (255), entonces se muestra una solicitud de campo para los 255. Muchas veces. nos interesa cambiar el tamaño del campo solicitado en la pantalla. Esto se hace asociando al campo un ámbito con dicho elemento cambiado. Hay varias formas:
![]() | ![]() |
![]() | ![]() | ![]() |
Por defecto todo campo definido tiene una parte de literal/título y otra de petición del campo. El uso de LITERALES nos permite dar una mejor apariencia a nuestras pantallas, pues no se solicitan campos. A continuación se muestra un ejemplo en el que los títulos: Descripción campo, y Descripción campo corto, están sin campos, y por otro lados los campos DESCRIn y DESCRICORTO están con literal y sin él:
![]() |
Lo primer es situar los campos LITERALES en la fila columna que deseemos, teniendo en cuenta que su ámbito será @LITERAL_PANTALLA. En el primero se añaden blancos para ubicar correctamente el título:
![]() | ![]() |
Los campos DESCRIn y DESCRICORTOn, son campos de tipo IDIOMA, es decir, sólo aparecerán los correspondientes al IDIOMA que se tenga activado en el aplicativo, Se han de situar en la misma fila, columna todos. El campo DESCRIN nos ha de mostrar el literal del idioma que corresponde, pero en cambio, el campo DESCRICORTOn no ha de mostrar literal, pues ya incluímos título inicial.
![]() | ![]() |
Los campos de una tabla se van ubicando en la pantalla asumiendo que el máximo tamaño del literal o del campo se va poniendo homogéneo en todos los campos de las columnas, Sólo si se le hace un RESET, con el atributo @NUEVA_TABLA en programa dentro de características, los campos se vuelve a recalcular. Veamos un ejemplo, se le dice que
![]() | ![]() |
Si la tabla utiliza PESTAÑAS, entonces el formato de @NUEVATABLA sera fila1-pestaña,fila2-pestaña,...; Ejemplo: @NUEVATABLA:5-1,10-1,7-2. Si no tiene pestaña se pondrá solo las filas, ejemplo @NUEVA_TABLA:5,10,15.
La pestaña tiene que coincidir con el número inicial asociado a la pestaña. Por ejemplo, pestaña: 010.General seria @NUEVA_TABLA:5-010,...
En pantalla podemos condicionar que aparezcan dinámicamente unos campos dependiendo del valor que pongamos en otro. Esto nos permite aportar al usuario qué campos tiene que entrar dependiendo de lo que él vaya poniendo. Veamos un ejemplo:
![]() | ![]() |
En la pantalla de APLICACIONES, dentro de la pestaña de FACTURACIÓN, si tenemos el campo Facturas emitidas con valor NO, no se muestran asociados. Pero en cambio, si lo modificamos a SI, entonces dinámicamente nos aparecen nuevos campos: Productos, Albaranes, Servicios, columna código, columna descuento, etc. Para obtener esto en el ámbito asociado a estos nuevos campos a de tener @CAMPO:FACTEMI;@CONDI:FACTEMI='S', donde FACTEMI=Facturas emitidas es el campo inicial al que se condiciona.
De la misma forma, se puede condicionar un campo al valor de varios campos de la pantalla. Siguiendo el ejemplo anterior si tenemos como SI Facturas emitidas y Servicios, entonces nos aparecen los campos Columna código y Columna descuento. Pero si cambiamos a NO el campo Servicios, entonces estos dos últimos desaparecen, por estar condicionados a los dos primeros. Es decir, en el ámbito de los últimos se tiene que indicar lo siguiente: @CAMPO:FACTEMI,FACTSERVI;@CONDI:FACTEMI='S' && FACTSERVI='S', siendo FACTEMI=Facturas emitidas y FACTSERVI=Servicios.
![]() | ![]() |
Cuando un campo de una pantalla corresponde a una tabla distinta, nos puede interesar aportar un buscador, para facilitar al usuario la búsqueda del elemento que quiere asociar. En determinados casos se puede aportar incluso la posibilidad de dar de alta un nuevo elemento, para incorporarlo como asociado. Veamos un ejemplo:
Tenemos una tabla de ORDENES, con un campo ENTIDAD, que corresponde a otra tabla de ENTIDADES, queremos que cuando se dé de alta una ÓRDEN, se pueda seleccionar una ENTIDAD de las existentes. Tras pulsar el botón de búsqueda que está junto a la ENTIDAD, se nos aporta emergente una pantalla con las consulta de las ENTIDADES, simplemente haciendo doble click sobre una ENTIDAD, la traspasaremos a la ORDEN.
![]() | ![]() |
Dentro de la tabla de ORDENES, definimos un campo ENTIDAD, al que le asociamos un ámbito TE-BUSQUEDA-ENTIDAD, en el que le describimos el botón de búsqueda en su apartado de IGUALA (SQL)
![]() | ![]() |
El formato sería el siguiente:
| Clave | Valor | Observaciones |
|---|---|---|
| @TABLA | TE_ENTIDAD | Tabla sobre la que se realiza la búsqueda/mto |
| @RETORNA | ENTIDAD | El valor del campo ENTIDAD seleccionado será retornado |
| @ANEXO | DESCRIPCION | En el programa base se mostrará el campo retornado y este ANEXO. |
| @PG | TE-BUSQUEDA-ENTIDAD | Nombre del programa GENLISTA que proporciona la búsqueda/mto |
| @PGMTO | TE-MTO-ENTIDAD | Si se quiere aportar icono de mantenimiento de ENTIDADES |
| @ENLACE | S | Indica que pulsado doble click sobre cualquier fila de la búsqueda se retornará ese valor |
| @ANCHO-CAMPO | Ancho del campo | Ajustar el tamaño del campo |
La forma de implementarlo sería, primero implementar el programa de búsqueda de ENTIDADES, es decir, el TE-BUSQUEDA-ENTIDAD, indicarle la tabla secundaria, que campos se tendrían en el buscados, que campos mostrar, si le corresponde ponerle filtros adicionales, etc. Con el programa funcionando, entonces se puede crear el ámbito y asociarlo al campo.
Al crear el programa de CONSULTA/MTO se tiene que poner:
| Clave | Valor |
|---|---|
| Operación inical | Consulta |
| Ejecutar clic en línea | Nada |
| Características | @RESETFILTROS:S;@WINFRAME:Gerbuscador; |
En determinadas ocasiones nos puede interesar a un campo de una pantalla asociarle un icono para aportar información adicional. Por ejemplo en las ACCIONES de un circuito, al indicarle el CUERPO de correo, poner un botón para visualizarlo.
![]() | ![]() |
En el campo CUERPOMAIL, en su ámbito XWCUERPOMAIL, se incorpora dentro de condicionado, el valor: @EXTERNO:Visualizar cuerpo,xmrutinas.php?para=VISCUERPO&cpo=CUERPOMAIL,icondownload.gif,S; Donde tras @EXTERNO se indican, separados por comas: Nombre Visualizar cuerpo, rutina xmrutinas.php?para=VISCUERPO&cpo=CUERPOMAIL, image icondownload.gif y Nueva ventana* S.
![]() | ![]() |
Los campos de las pantallas puede variar o bien por que se definen campos de tipo 'ENLACE' que una vez informado hacen que la pantalla se refresque y por tanto aparezca o desaparezca campos, o bien utilizando un campo de con ambito tipo RUTINA que permita tomar el control de dichos campos. En este apartado se explicará este segundo caso. Pasos a seguir:
1 - Definir un ambito de tipo rutina. Ejemplo: M\_TICKET\_RUTINA, se indica que es de tipo ALFANUMERICO, con el resto de campos a blanco o valores por defecto, excepto el campo rutina entrada que se informa: mcamposentrada.inc mticket_rutina
2 - Sobre los campos de la tabla asociada en el programa, incluir un campo con el ambito de tipo rutina. No hace falta posicionalo pues no aparecerá en la pantalla.
Disponemos de una tabla de cuentas y una de extractos. Queremos que 3 campos de una pantalla de cuenta, se puedan modificar o no dependiendo de si para esa cuenta tenemos extractos o no. Es decir, si tenemos una cuenta creada, podremos modificar esos campos si no hay extractos asociados a la cuenta y no dejaremos modificarlos en caso de que si haya extractos.
Para obtener lo anterior en el ÁMBITO de los 3 campos, en el apartado CONDICIONADO hemos de poner:
@NOWE;@SQLCONDIMODI:select COUNT (*) as CONTADOR from MEXTRACTOSMOV where WEB='$WEB$' and EMPRESA='$EMPRESA$' and CUENTA=(SELECT CUENTA FROM MCUENTABANCO WHERE RRN(MCUENTABANCO)=$ROWID$);@PERMITIR_MODI:=0;
En una pantalla de relación de una tabla que tengamos asociado con doble click sobre una fila su modificación, nos puede interesar que sólo se modifiquen los registros, si se dan unas condiciones. Es decir, en la misma pantalla de relación mostramos registros, que al dar doble click se activa la modificación o su consulta.
Un ejemplo práctico sería el siguiente: tenemos una tabla de ORDENES de un BANCO. queremos que las ORDENES se puedan modificar si su fecha es mayor a la fecha de cierre de su BANCO. Es decir, si el BANCO tiene fecha de cierre 31/12/2016, las ORDENES con fecha inferior a esta se muestran en modo CONSULTA (y por tanto no podemos alterar nada), pero si la fecha es superior a la de cierre nos permite la MODIFICACIÓN.
Para conseguir fácilmente lo anterior hemos de incluir en FILTROSQL de programa de ordenes @SOLOCONSU:terutinas.inc ordenesconsu. Sólo al tratarse de la operación de modificar (es decir, al dar doble clik sobre lista de ordenes), entonces se ejecuta la rutina indicada ordenes_consu. En esta rutina se accede a la información de la orden, banco y fecha. Con el banco se accede a la fecha de cierre del banco. Si la fecha cierre es superior a la fecha de la orden entonces se pone la variable $gerreturn='1', indicando que active la consulta.
En las siguiente pantallas se muestra la información del banco, con fecha cierre 31/12/2016, y la pantalla de relación de ORDENES.
![]() | ![]() |
En las siguientes pantallas se muestra el acceso en modo CONSULTA y en modo MODIFICACIÓN, dependiendo que la fecha de la orden sea menor a 31/12/2016 o mayor.
![]() | ![]() |
Independientemente del tamaño de la imagen obtenida, queremos que al mostrarlo en la pantalla de modificación o consulta nos aparezcan acotada para que no vaya cambiando la pantalla en función de la imagen.
En el ámbito de la IMAGEN hemos de poner el parámetro: @MOSTRARANCHO:nnn o bien @MOSTRARALTO:nnn", donde nnn es el valor en PX.
Ejemplo: en el ámbito poner: @ANCHOMIN:90;@ANCHOMAX:300;@MOSTRAR_ALTO:150; Mostrará todos los graficos con un alto de 150 siempre.
Otra forma es: sería @MOSTRARMTO:S;@MOSTRARMTOANCHO:400;@MOSTRARMTOALTO:600; pero en este caso, si es menor iria variando el tamaño del gráfico.
| Campo | tipo | Ambito |
|---|---|---|
| FOTO | IMAGEN | @ANCHO:400;@ANCHOMIN:40;@ANCHOMAX:300;@NOFOTO:SEXO=H,hombre.gif:SEXO=M,mujer.gif;@PESTAÑA:PARTICULAR;@MOSTRAR_ALTO:163; |
| MAPA | GOOGLE MAPS | @TIPO:AUTOMATICO/MANUAL;@ORIGEN:DIRECCIONMAPA,POBLACION,PROVINCIA;@ZOOM:16;@NOMBRE:EMPLEADO;@PESTAÑA:PARTICULAR;@ANCHOMIN:150x150; |
Queremos que tanto la foto como el mapa (reducido) aparezcan con un tamaño máximo de 150 px. A google maps hay que ponerlo en formato nnnxnnn, pero siempre se envia unos 10-13px adicionales, por eso la foto la limitamos con 163. El resultado es que aunque las dimensiones originales de las fotos sean de tamaños distintos estamos forzando a que la pantalla sea homogénea y no varíe con las mismas. Ejemplo:
Tabla de base de datos con un índice de clave única
- En el cuadro de texto "Campo" pondremos el nombre del campo - En el caso que hayamos creado el campo WEB y EMPRESA (ejecución SAAS) : Para el campo WEB utilizaremos siempre el ámbito' XWEB y para el campo EMPRESA utilizaremos siempre el ámbito XEMPRESA.
Las tablas pueden contener WEB/EMPRESA, para que en el programa a poner que es MULTIEMPRESA, automáticamente nos permita gestionar los datos de multiples entornos WEB/EMPRESA con el mismo programa, sin pensar que siempre se informa y filtra por dichos campos.
Si se quiere acceder a los campos WEB/EMPRESA, tendremos que poner que el programa no es MULTIEMPRESA y definir los campos con ambito distinto de XWEB, XEMPRESA o bien crear una formula del tipo: select WEB from GLCAPLICA as A where A.WEB=GLCAPLICA.WEB que nos aporte dicha información.
Protección del software. Se permiten 3 tipos de ejecución dentro de entorno WEB, controlados por el valor WWW_GERPHX dentro \config\entorno.ini. Los posibles tipos son:
WWW_GERPHX=1.
La empresa desarrolladora decide el nivel de protección que aporta a sus clientes en el momento de realizar la instalación del producto.
Todos los programas han de tener los includes U_COMUN y GERWEB.
// ----------------------------------------------- Proteccion sw ----
$xsphx=getenv('WWW_GERPHX');
if ($xsphx=="1") { unlink($nombre); }
$srootns='';
$saux=getenv('WWW_NS');
if ($saux!='') { $srootns='/'.$saux; }
if ($xsphx=="2") {
include_once '../pho/gerweb.ino';
includeonce '../pho/ucomun.ino';
} else {
if ($xsphx=="0") {
include_once '../php/gerweb.inc';
includeonce '../php/ucomun.inc';
} else {
include_once '../phx/gerweb.ino';
includeonce '../phx/ucomun.ino';
}
}
Conexión a la base de datos. Se tiene que hacer una única conexión a la base de datos con una variable global accesible por cualquier rutina.
$conn = new gerdb ('');
if ($conn->ID==-1) { Sin_sesion(); }
Este ejemplo pretende mostrar como grabar un fichero (en principio ilimitado) en un registro de la base de datos, en este caso en XM_MAIL, utilizado de forma regular para envíos de mail desde cualquier aplicación.
Ejemplo grabación registro XM_MAIL
// -----------------------------------------------------------------------------------
// Grabar la entrada de XM_MAIL con estado distinto a PENDIENTE, pues sino el
// servicio inmediatamente lo enviaria como mail
// -----------------------------------------------------------------------------------
$xweb=$xempresa='GERSOFT';
$fecha_alta = date("Y/m/d");
$hora_alta = date("H:i:s");
$tipomail = 'LICENCIA';
$mailfrom=$mailto=$mail_cco='rhidalgo@gerapli.com';
$mail_asunto = 'Prueba envio mail con documento adjunto';
$mail_cuerpo = 'CLAVE';
$mail_campos = 'CODIGO~NOMBRE';
$mail_valores = '0020~Emilio Rodriguez Sanchez';
$mailfiche1 = $mailfile2=$mail_file3='';
$estado = 'Editado';
$fecha = $hora = '';
$buffer = "insert into XMMAIL (WEB,EMPRESA, FECHAALTA, HORAALTA, TIPO, MAILDE, MAILPARA, MAILCCO, ASUNTO, CUERPO, ";
$buffer.= "CUERPOWEB, CUERPOEMPRESA, ADJUNTO1, ADJUNTO2, ADJUNTO3, CAMPOS, VALORES, ESTADO, FECHA, HORA, DOCU_TIPO, ";
$buffer.= "DOCUSIZE, DOCU, ACUSE, NOTIFICA) VALUES ('" . $xweb . "','" . $xempresa . "','" . $fechaalta . "','";
$buffer.= $horaalta . "','".$tipomail."','" .$mailfrom . "','" . $mailto . "','" . $mailcco . "','" . $mail_asunto;
$buffer.= "','".$mailcuerpo."','" . $xweb . "','" . $xempresa . "','" . $mailfiche1 . "','" . $mail_fiche2. "','";
$buffer.= $mailfiche3. "','" . $mailcampos. "','" . $mail_valores ."','" . $estado. "','" . $fecha . "','" . $hora . "','";
$buffer.= $docutipo . "','" . $docusize . "', '0x1', '" . $mailacuse . "', '" . $mailnotifica . "')";
$conn->ger_exec ($cursor1, $buffer);
Leer el registro XM_MAIL antes grabado
// -----------------------------------------------------------------------------------
// Leer el registro anteriormente grabado
// -----------------------------------------------------------------------------------
$tm=array(); $rcm='';
$buffer="select IDENTI from XMMAIL where WEB='GERSOFT' and ESTADO='Editado' and FECHAALTA='$fechaalta' and HORAALTA='$hora_alta'";
$conn->ger_exec ($cursor1, $buffer);
$rc= gerdb_fetch ($cursor1, $tm);
if ($rc=='') {
$identi=$tm['IDENTI'];
Es recomendable que cualquier elemento que se tenga que grabar en disco, exclusivamente se haga en WWW_ROOT\tmp
// -----------------------------------------------------------------------------------
// Grabar un fichero htm ilimitado en disco para luego incorporalo en XM_MAIL.
// -----------------------------------------------------------------------------------
$sroot=getenv('WWW_ROOT'); if (!isset($sroot)) $sroot="c:\\inetpub\\wwwroot";
$fiche=$sroot."\\tmp\\ubicacion.htm";
if (!$fpd = fopen($saux, 'w')) {
echo "No se puede abrir el archivo ($saux)";
return;
}
$saux1.="\n"; fputs($fpd, $saux1);
// ....
fclose($fpd);
El fichero grabado en disco puede ser ilimitado. En base de datos campos image suelen estar limitados a 2 GB (SQLSERVER y ORACLE) o a 16MB (ISERIES). La función filesize nos calcula el tamaño en octetos del fichero.
$tamanyo=filesize($fiche);
$tipo='htm';
// -----------------------------------------------------------------------------------
// Grabar el fichero en XM_MAIL
// -----------------------------------------------------------------------------------
$conn->gergrabagrafico("XM_MAIL", "DOCU", $identi, $fiche, $xrowid);
Actualizar el registro XM_MAIL
Actualizar el registro de XM_MAIL con la longitud real del fichero, su tipo y el nuevo estado, para que pueda ser procesado.
$buffer="update XMMAIL set DOCUTIPO='$tipo', DOCU_SIZE=$tamanyo, ESTADO='Pendiente' where IDENTI=" . $identi;
$conn->ger_exec ($cursor1, $buffer);
(WWWROOT = e:\webpublica)
Comonentes de GERRC
Es necesario instalar los componentes "CRRuntime32bit13_0.msi"
- CRforVSredistinstall32bit13_0.zip
>o
- CRRuntime32bit13_0.msi
Este servicio es el que se usa de forma STANDARD en GERAPLI
Recordemos que el usuario de este servicio debe ser un usuario administrador con el que se pueda iniciar una sesión interactiva para poder realizar en cualquier momento las comprobaciones que se requieran de forma online.
Fichero de configuración del la web de GERAPLI : e:\web_publica\basico\entorno.ini
- WWW_EXSYSTEM -> 1
Indica que se utilizará el servicio GERPDFTK- WWWCRYSTALRPT -> e:\webpublica\CRYSTALREPORTS
Se indica la ruta donde se almacenan los RPT de "Crystal Reports" Los ficheros RPT tienen que usar conectividad ODBC con la BBDD- WWWDSN + WWWUSERBD + WWW_PASSWD
Parametros de la conectividad ODBC con el que el RPT se conectará a la base de datos
Desde la definición de un programa GENLISTA podemos asociar un botón lateral con una llamada a la rutina "gercr.php".
Ejemplo de llamada :
gercr.php?rpt=LISTADO&tablarpt=GIEXPEDIENTES&campo_rpt=TRABAJO &genlista=1
PARAMETROS:
- rpt -> Nombre del archivo RPT (OBLIGATORIO)
- genlista -> Se indica fijo con un 1 siempre cuando la llamada a la rutina se hace desde aquí un programa GENLISTA
- tabla -> Nombre de la tabla del programa GENLISTA
- campo_rpt -> Valor que identifica si debe usar un fichero RPT diferente al que viene marcado en el parámetro rpt.
Ejemplo:
- rpt -> LISTADO
- tablarpt -> GIEXPEDIENTES
- campo_rpt -> TRABAJO
GI_EXPEDIENTES asociado al "rowid" de la fila del programa GENLISTA desde donde se ha ejecuta
Definición parámetros GERAPLI
- RPT -> Nombre del archivo RPT (OBLIGATORIO)
- TABLA_RPT
- CAMPO_RPT
Valor que identifica si debe usar un fichero RPT diferente al que viene marcado en el parámetro rpt.
Ejemplo:
- RPT -> LISTADO
- TABLARPT -> GIEXPEDIENTES
- CAMPO_RPT -> TRABAJO
Parámetros del RPT para que el usuario rellene: Se definirán los mismos que se hayan definido en el RPT pero con el prefijo -> RPT_
Ejemplo:
- Si en el RPT se ha definido el parámetro EXPEDIENTE
- El parámetro GERAPLI se llamará : RPT_EXPEDIENTE
La conectividad con la BBDD se realizará con ODBC. El nombre de los parámetros que queramos llamar desde GENLISTA será equivalente a algún campo de la tabla de GENLISTA.
En el entorno WEB-GERAPLI se requiere borrar periodicamente la carpeta /tmp, pues en ella se van acumulando ficheros de trabajo para la obtención de la ejecución de las páginas de GERAPLI. Utilizaremos una tarea programada que realice esta labor por ejemplo a la 01:00
lsa.bat
call schtasks /delete /TN Copias /F call schtasks /create /TN Copias /RU SYSTEM /SC DAILY /SD 03/11/2014 /ST 01:00 /TR "c:\web_publica\basico\borrar.bat" call SCHTASKS /QUERY /TN COPIAS /V /FO LIST
borrar.bat
Set Fecha=%Date:~0,2%/%Date:~3,2%/%Date:~6,4% Set Hora=%Time:~0,2%:%Time:~3,2% echo Inicio copia %Fecha% %Hora% ---------------------------------------------- >> f:\\copia\\copia.log call del c:\web_publica\tmp\*.* /s /q