Planos de ejecución en Velneo V7

BUENAS PRACTICAS – 5 CONCEPTOS BASICO

El objetivo del manual Planos de ejecución en Velneo V7 es explicar conceptos cuyo conocimiento se puede considerar imprescindible conocer y comprender para desarrollar aplicaciones con Velneo V7 de forma rápida y eficaz. Estos conceptos te ayudan a comprender la filosofía de programación de Velneo V7.

Con el objetivo de ayudarte a comprender mejor algunos de ellos he creado este documento denominado “Planos de ejecución en Velneo V7″, en el que se tratan temas importantes relacionados con la arquitectura cliente-servidor así como el uso de diferentes objetos de la plataforma y, sobre todo, la descripción de los planos de ejecución y como utilizarlos para optimizar nuestras aplicaciones.

Descarga el documento Planos de ejecución en Velneo V7

Portada planos de ejecución en Velneo V

Haz clic en la imagen superior o en el siguiente enlace Planos de ejecución en Velneo V7 para descargar el manual en formato PDF.

Espero que te resulte útil.

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Planos de ejecución en Velneo V7 appeared first on Lógica mente Velneo V7.

Control de edición de etiquetas en Velneo V7

VITAMINA – 11

Las posibilidades que ofrece Velneo V7 para el desarrollo de la interfaz de tus aplicaciones es muy elevado. Si además de todo lo que trae la plataforma le unimos las posibilidades que ofrece la integración de QML y el control visor HTML, nos encontramos que los límites se disipan entre tantas posibilidades. En este artículos veremos como implementar un control de edición de etiquetas en Velneo V7.

Es cierto que los controles que la plataforma trae por defecto son mucho más Life is Soft que crear controles QML o con HTML, pero no es menos cierto que en Internet podemos encontrar controles, plantillas y recursos que nos ayudan a mejorar la interfaz de nuestras aplicaciones de forma más cómoda y rápida.

Ejemplo de formulario con control de edición de etiquetas

Control de edición de etiquetas en Velneo V7

Esta vitamina es un ejemplo de las posibilidades que ofrece el control visor HTML para añadir a nuestros formularios controles que Velneo V7 no incluye en su galería de objetos o controles.

Vídeo que explica como incluir un control de edición de etiquetas en Velneo V7

Para los amantes de Life is Soft

Te dejo el enlace de descarga de la instalación de la solución controlTag que contiene todos los objetos explicados en esta vitamina totalmente operativos para que los pruebes o uses directamente heredándolo en tus aplicaciones.

Por razones de seguridad, el fichero de instalación .vin lo descargarás comprimido en formato zip. Debes descomprimirlo para obtener el fichero con extensión “.vin”.

Recuerda que este fichero de instalación está creado con la versión 7.14, por lo que necesitas instalarlo en un vServer que tenga esa versión o una superior.

icono descarga 32 Descargar controlTag_1_1_714_vin

Actualizado

Cuando publiqué la versión 1.0 comentaba que esta vitamina funcionaba bien en Windows, pero no en Linux y Mac. La versión 1.1 ya funciona correctamente en todas las plataformas. El motivo por el que no funcionaba correctamente era que el controlHtml usa ficheros externos que van adjuntos en la aplicación y en el segundo parámetro de la función setSourceCode con la que se añade el HTML al control se especifica el directorio de caché de la aplicación, sin embargo, eso funcionaba bien Windows pero no el resto de sistemas. Para garantizar la compatibilidad multiplataforma es necesario añadir el prefijo “file:///” (con tres barras) tal y como se muestra en el siguiente código.

// Cambiar el HTML del control
control.setSourceCode( html, "file:///" + theApp.clientCachePath() );

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Control de edición de etiquetas en Velneo V7 appeared first on Lógica mente Velneo V7.

Importación automática de datos con Velneo V7

VITAMINA – 10

Una de las actividades más habituales con la que nos encontramos los desarrolladores es la importación de datos. Tanto por razones operativas de la aplicación, como por la migración de aplicaciones hacia nuevas versiones. En este artículo aprenderás a desarrollar la importación automática de datos con Velneo V7.

En el desarrollo de aplicaciones a medida la migración de datos es un capítulo importante y que debemos resolver desde el primer momento para contar con información real tanto para hacer pruebas como para preparar la migración definitiva el día de la puesta en producción.

Gracias al uso del API para JavaScript, en Velneo V7, es realmente sencillo y automático el proceso de migración de información de datos desde otros sistemas hacia Velneo V7, a través de ficheros de texto.

En esta píldora vamos a ver los realmente sencillo y práctico que puede ser realizar la importación de datos en tablas V7 a través de un proceso automatizado JavaScript.

1º Un proceso principal V7 que dirige la importación

Para conseguir preparar una importación automática de datos en múltiples tablas V7, lo primero que debemos hacer es preparar un proceso V7 que se encargará de solicitar el directorio de importación, donde encontraremos los diferentes ficheros que vamos a procesar para proceder a la importación de sus datos. En la siguiente imagen podemos ver el contenido de este proceso V7 estándar para la importación.

Importación automática de datos con Velneo V7

2º Un formulario para solicitar la senda de importación

Como vemos en la imagen, lo primero que hace es solicitar mediante un formulario la senda del directorio donde encontraremos todos los ficheros ASCII a importar.

Selección directorio de importación

Este formulario será el que utilizará el usuario para seleccionar el directorio de importación donde previamente a la importación habremos almacenado los ficheros que contienen los datos a importar. Contiene un control de tipo selección de directorio para la localización y selección del directorio de disco donde estarán almacenados los ficheros a importar.

Una vez seleccionado el directorio donde encontraremos los ficheros a procesar para su importación. El proceso V7 se encarga de ejecutar el proceso JavaScript. En la imagen vemos que el proceso se ejecuta mediante los comandos de manejador de objeto y disparar objeto. El proceso se ejecuta en primer plano (cliente), pero se podría optimizar ejecutándolo en tercer plano (servidor), en este último caso los ficheros a importar deberían estar almacenados en una subcarpeta del servidor y, probablemente en lugar de seleccionar el usuario final la senda del directorio de importación, podría ser un directorio configurado.

Podemos observar que el proceso V7 pasa valores al proceso JavaScript mediante el uso de variables locales, en concreto le pasa 2 valores: SENDA (senda del directorio donde se encuentran los ficheros a importar) y SEPARADOR, variable donde identificamos el carácter de separación entre valores de campos. Por defecto se asume el valor de separación de campos “\t” (el tabulador), salvo que le pasemos un caracter específico en la variable SEPARADOR.

3º Un proceso JavaScript que se encargará de la importación

// --------------------------------------------------------------------------------
// Devuelve el idRef de una tabla a partir de su Id
// --------------------------------------------------------------------------------
var tablaIdRef = function ( tablaId )
{
    // ----------------------------
    // Se lee el proyecto principal
    // ----------------------------
    var proyecto = theApp.mainProjectInfo();
    
    // ----------------------------------------------------------------
    // Se repasan todas las tablas buscando la recibida en el parámetro
    // ----------------------------------------------------------------
    for ( var numTabla = 0; numTabla < proyecto.allTableCount(); numTabla++ )
    {
        if ( proyecto.allTableInfo( numTabla ).id() == tablaId )
        {
            return proyecto.allTableInfo( numTabla ).idRef();
        };
    };

    // ---------------------------------------
    // Si no se ha encontrado se devuelve null
    // ---------------------------------------
    return null;
};

// --------------------------------------------------------------------------------
// Importación de registros en una tabla a partir los datos contenidos en un fichero ASCII
// --------------------------------------------------------------------------------
importClass("VDir");
importClass("VFile");
importClass("VTextFile");

// -------------------------
// Se recorre el direoctorio
// -------------------------
var dir = new VDir();
dir.cd( theRoot.varToString( "SENDA" ) );
dir.load();

// ---------------------------------------
// Se recorren los ficheros del directorio
// ---------------------------------------
for ( var numFichero = 0; numFichero < dir.count(); numFichero++ )
{
    // ---------------------------------------------------------------------
    // Se lee el fichero del directorio y se prepara su nombre sin extensión
    // ---------------------------------------------------------------------
    var fichero = dir.entryAt( numFichero );
    var ficheroNombre = fichero.baseName();

    // ---------------------------------------------------------
    // Se prepara el idRef de la tabla destino de la importación
    // ---------------------------------------------------------
    var ficheroIdRef = tablaIdRef( ficheroNombre );
    
    var registro = new VRegister( theRoot );
    if ( registro.setTable( ficheroIdRef ) )
    {
        // -------------------------------------------
        // Se prepara el valor del separador de campos
        // -------------------------------------------
        var separador = ( theRoot.varToString( "SEPARADOR" ) != null ) ? theRoot.varToString( "SEPARADOR" ) : "\t";
        
        // --------------------------------
        // Se abre transacción si no existe
        // --------------------------------
        bTransCurso = theRoot.existTrans();
        if ( bTransCurso == false )
        {
        bTransNueva = theRoot.beginTrans( "Importando: " + fichero );
        };
        
        if ( bTransCurso || bTransNueva )
        {
            // ------------------------------------------
            // Se abre el fichero en modo de sólo lectura
            // ------------------------------------------
            var ficheroTxt = new VTextFile( fichero.filePath() );
        
            if ( ficheroTxt.open( VFile.OpenModeReadOnly ) )
            {                   
                // ------------------------------------------------------------------------------
                // Se leen los nombres de los campos en la primera línea y se guardan en un array
                // ------------------------------------------------------------------------------
                var linea = ficheroTxt.readLine();
                var aCampos = linea.split( separador );
                            
                // ----------------------------------------------------------
                // Recorremos el fichero línea a línea guardando su contenido
                // ----------------------------------------------------------
                var aValores = new Array();
                var nNumRegistro = 0;
                theRoot.initProgressBar();
                theRoot.setProgress( 100 );

                while ( ficheroTxt.atEnd() == false )
                {   
                    // -----------------------------------------
                    // Leer la línea y los valores de los campos
                    // -----------------------------------------
                    linea = ficheroTxt.readLine();
                    aValores = linea.split( separador );
                    for ( var nCampo = 0; nCampo < aValores.length; nCampo++ )
                    {
                        registro.setField( aCampos[ nCampo ], aValores[ nCampo ] );
                    };
                    registro.addRegister();
            
                    // -----------------
                    // Mostrar el avance
                    // -----------------    
                    theRoot.setTitle( "Importando registro nº " + nNumRegistro++ + " de la tabla " + ficheroNombre );
                };

                // --------------------
                // Se cierra el fichero
                // --------------------
                ficheroTxt.close();
                theRoot.endProgressBar();
            };

            // ---------------------------------------------
            // Se cierra la transacción si se creó una nueva
            // ---------------------------------------------
            if ( bTransNueva )
            {
                theRoot.commitTrans();
            };
        };
    };
};

En la primera función tablaIdRef() podemos observar como a partir del identificador de la tabla destino se devuelve el idRef o identificador completo de la tabla (alias/identificador). Esta función parte del principio de que en nuestra aplicación no existen tablas duplicadas con el mismo identificador (algo que deberíamos evitar siempre). En caso de que hubiese un identificador de tabla repetido, nos devolvería el idRef de la primera tabla encontrada.

Esta función es llamada por el proceso JavaScript principal para calcular el idRef de la tabla destino a partir del identificador de la tabla. El proceso asume que el nombre de la tabla se corresponde con el nombre del fichero en disco (sin la extensión).

Por lo tanto los ficheros a importar deben tener las siguientes características:

  • El nombre del fichero a importar deben corresponderse con el identificador de la tabla de destino.
  • En la primera línea del fichero deberán aparecer separados (por el carácter de separación) los identificadores de los campos de destino de cada dato/columna.
  • El campo código debe tener el identificador ID.
  • El campo nombre debe tener el identificador NAME.
  • Los campos de tipo fecha deben exportarse en formato ISO AAAA-MM-DD para que se importen correctamente.

fichero a importar

¿Cómo implementarlo?

Una vez que hemos visto las piezas, vamos a enlazarlas para implementar esta importación de datos:

  1. Crear un proceso V7, por ejemplo con el nombre IMP_TXT_SEL_DIR, que contenga los comandos que vemos en la primera imagen de este artículo.
  2. Debes crear un formulario para solicitar al usuario final el directorio de importación, por ejemplo con el identificador IMP_TXT_SEL_DIR.
  3. En el directorio de scripts crea un fichero JavaScript e incluye el script de JavaScript con la función tablaIdRef y el código que realiza la importación.
  4. Crea un proceso JavaScript, por ejemplo con el nombre IMP_TXT que tenga asignado como fichero script el creado en el punto anterior.
  5. Crea una acción, por ejemplo IMP_TXT, que se encargue de ejecutar el proceso V7 IMP_TXT_SEL_DIR que lanzará el formulario y luego el proceso JavaScript de importación.

Implentación de importación ASCII mediante JavaScript

Para los amantes de Life is Soft

Te dejo el enlace de descarga de la instalación de la solución importaDatosJS que contiene todos los objetos explicados en esta píldora totalmente operativos para que los pruebes o uses directamente heredándolo en tus aplicaciones.

Por razones de seguridad, el fichero de instalación .vin lo descargarás comprimido en formato zip. Debes descomprimirlo para obtener el fichero con extensión “.vin”.

Recuerda que este fichero de instalación está creado con la versión 7.14, por lo que necesitas instalarlo en un vServer que tenga esa versión o una superior.

icono descarga 32 Descargar importaDatosJS_1_0_714.vin

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Importación automática de datos con Velneo V7 appeared first on Lógica mente Velneo V7.

Deshabilitar controles de formulario con CSS en Velneo V7

VITAMINA – 9

Como continuación de la vitamina 8 en la que deshabilitamos y habilitamos los controles de un formulario con el API de Velneo V7 y JavaScript, en esta vitamina lo haremos también de forma sencilla y aprenderemos a deshabilitar controles de formulario con CSS en Velneo V7.

Podemos utilizar el comando de instrucción de procesos V7 “Interfaz: Establecer hoja de estilo CSS” en un manejador de evento del formulario que se ejecute, por ejemplo, al dispararse la señal “Post-inicializado” del formulario, o en cualquier momento que consideremos oportuno.

Deshabilitar controles de formulario con CSS en Velneo V7

Deshabilitar controles de formulario con CSS en Velneo V7

El siguiente script CSS se puede usar para deshabilitar todos los controles del formulario que sean del tipo (edición alfabética, edición fecha, edición fecha/hora, edición hora, edición numérica, edición de maestro, combobox, listbox y botones:

VLineEdit, VDateEdit, VDateTime, VTimeEdit, VDateTimeEdit, 
VNumberSpinBox, VLineEditBrowser, VBoundFieldEdit, VBoundFieldComboBox,
VBoundFieldListBox, VComboBox, VListBox, VPushButton
{
    qproperty-enabled: false
}

VPushButton#BTN_HAB_CTL_CSS
{
    qproperty-enabled: true
}

Si nos fijamos en el CSS podemos observar como tras deshabilitar los controles, y en concreto todos los botones VPushButton, a continuación se habilita de nuevo el botón cuyo identificador es BTN_HAB_CTL_CSS.

Es decir, que podemos habilitar individualmente cualquier control de cualquier tipo indicando primero el tipo de control (VPushButton, VLineEdit, VDateEdit, etc.) el símbolo “#” y el identificador del control. Incluso se puede especificar varios controles a la vez.

Habilita controles del formulario

El siguiente script CSS se puede usar para deshabilitar todos los controles del formulario que sean del tipo (edición alfabética, edición fecha, edición fecha/hora, edición hora, edición numérica, edición de maestro, combobox, listbox y botones:

VLineEdit, QTextEdit, VDateEdit, VDateTime, VTimeEdit, VDateTimeEdit,
VNumberSpinBox, VLineEditBrowser, VBoundFieldEdit, VBoundFieldComboBox,
VBoundFieldListBox, VComboBox, VListBox, VPushButton
{
    qproperty-enabled: true
}

Ventajas y desventajas del CSS respecto al API de Velneo V7 y JavaScript

Esta píldora demuestra que deshabilitar y habilitar opciones con CSS es realmente sencillo, a continuación identifico algunas ventajas de hacerlo mediante CSS o con el API de Velneo V7 y JavaScript:

Ventajas de hacerlo con CSS:

  • Más sencillo de aplicar.
  • Se aplica en cascada a todos los formularios que se abran desde aquel en el que se haya aplicado el estilo.
  • Permite individualizar el estilo de múltiples controles a la vez.

Ventajas de hacerlo con el API de Velneo V7 y JavaScript:

  • Muy configurable y personalizable mediante programación.
  • Muy potente al permitir aplicarlo a todas las propiedades y funciones.
  • Código muy reutilizable y de aplicación directa, no en cascada.

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Deshabilitar controles de formulario con CSS en Velneo V7 appeared first on Lógica mente Velneo V7.

Deshabilitar controles de formulario con el API de Velneo V7

VITAMINA – 8

En cualquier aplicación empresarial donde se maneja información y permisos de lectura y escritura de la misma es necesario gestionar de forma sencilla los controles de los formularios y su estado de edición, es decir que estén habilitados o deshabilitados según los criterios de configuración, usuario o circunstancias que se produzcan durante la ejecución. En esta vitamina vamos a aprender a deshabilitar controles de formulario con el API de Velneo V7.

La solución propuesta en esta vitamina permite con una sola instrucción habilitar o deshabilitar todos los controles de un formulario, teniendo en cuenta aspectos importantes como que cuando deshabilitamos los controles no lo haremos a las vistas de datos (rejillas, casilleros, árboles, etc.) pues muestran información por la que debemos dejar al usuario moverse y cuyo control de permisos de edición se hará en el propio objeto.

Para que el usuario puede consultar toda la información del formulario tampoco debemos deshabilitar los separadores de pestañas (subformularios), ni las pilas ni cajas de formularios, tampoco los splitter ni las cajas de grupo. Si quieres cambiar alguno de estos criterios sólo tienes que revisar el array de tiposEnabled de la función deshabilitarControles() añadiendo o quitando los que te interesen. En la documentación de la clase VMainWindow encontrarás el enum de tipos de controles.

Deshabilitar controles de formulario con el API de Velneo V7

Deshabilitar todos los controles con una instrucción Velneo V7

Para implementar esta vitamina sólo tienes que hacer lo siguiente. Añade el código de las funciones deshabilitaControles() y habilitaControles() en un fichero JavaScript en el directorio de scripts. Es conveniente que tengas un repositorio de funciones JavaScript en el proyecto de datos o aplicación más bajo en el árbol de herencia, para que pueda ser usado desde todos los formularios de tus aplicaciones.

En cada formulario puedes ejecutar el siguiente código en el manejador de evento Post-inicializado o en el punto de ejecución donde te interese ya que al ejecutar la función deshabilitaControles( formulario ) estarás haciéndolo con una sola instrucción a todos los controles del formulario sean del tipo que sean.

#include "3b3uk7ol.vca/js/controlesFormulario.js"

// ----------------------------------------------------------------------
// Deshabilita los controles del formulario
// ----------------------------------------
var formulario = theRoot.dataView();
deshabilitaControles( formulario );

// Se habilita individualmente el botón Habilitar controles
var botonHabilita = formulario.control( "BTN_HAB_CTL" );
botonHabilita.enabled = true;

Recuerda que la primera línea con el #include debes sustituirla por la del fichero JavaScript que hayas añadido en tu repositorio con las funciones deshabilitaControles() y habilitaControles(). Esto puedes hacerlo usando el botón “#i” Asistente: #include otro JavaScript de la toolbar del editor de scripts.

En ese manejador de evento, tras deshabilitar todos los controles, habilito el botón habilitar controles. Es decir, que tras ejecutar ese función genérica siempre podemos habilitar individualmente los controles que nos interesen.

Para habilitar los controles de un formulario, tan sólo tienes que ejecutar este código.

#include "3b3uk7ol.vca/js/controlesFormulario.js"

// ----------------------------------------------------------------------
// Habilita los controles del formulario
// -------------------------------------
var formulario = theRoot.dataView();
habilitaControles( formulario );

Formulario cnotroles habilitados

A continuación está el código de las funciones deshabilitaControles() y habilitaControles() que debes añadir en un fichero JavaScript del directorio de scripts de tu proyecto de datos o aplicación.

// --------------------------------------------------------------------------------
// Deshabilita los controles del formulario
//
// Parámetros:
//     - formulario: Objeto de la clase VFormDataView con el formulario a procesar
// --------------------------------------------------------------------------------
var deshabilitaControles = function ( formulario )
{
    if ( formulario )
    {       
        var tiposEnabled = [ VMainWindow.WTypeDataView, VMainWindow.WTypeMdiView, 
                             VMainWindow.WTypeWebView, VMainWindow.WTypeTabWidget,
                             VMainWindow.WTypeStackedWidget, VMainWindow.WTypeToolBox,
                             VMainWindow.WTypeSplitter, VMainWindow.WTypeGroupBox ];

        var numControles = formulario.controlCount();
        for ( var numControl = 0; numControl < numControles ; numControl++ )
        {
            // Si el control es del tipo de adecuado se deshabilita
            var control = formulario.control( numControl );
            if ( control )
            {
                tipo = theMainWindow.widgetType( control );
                if ( tiposEnabled.indexOf( tipo ) === -1 )
                {
                    control.enabled = false;
                };
            };
        };
    };
};

// --------------------------------------------------------------------------------
// Habilita los controles del formulario
//
// Parámetros:
//     - formulario: Objeto de la clase VFormDataView con el formulario a procesar
// --------------------------------------------------------------------------------
var habilitaControles = function ( formulario )
{
    if ( formulario )
    {    
        var numControles = formulario.controlCount();
        for ( var numControl = 0; numControl < numControles; numControl ++ )
        {
            var control = formulario.control( numControl );
            
            if ( control )
            {
                control.enabled = false;
            };
        };
    };
};

Funciones configurales o personalizadas

Estas funciones que hemos visto son genéricas, pero a partir de ellas podemos crear nuestras propias funciones que habiliten o deshabiliten controles en base a una configuración que puede estar guardada en una tabla o a criterios personalizados en base al usuario, sus grupos de usuario, etc.

Es decir, que la función puede leer información de los identificadores de controles a deshabilitar o habilitar en un momento dado y aplicarlos de forma automática. Por este motivo es tan importante que seamos estrictos a la hora de poner los identificadores de los controles en los formularios de nuestras aplicaciones.

Ventajas y desventajas del API de Velneo V7 respecto al CSS

Esta vitamina demuestra que deshabilitar y habilitar opciones con el API de Velneo V7 y JavaScript es muy potente. En la próxima vitamina 9 veremos lo sencillo que resulta deshabilitar y habilitar controles mediante CSS. A continuación identifico algunas ventajas de hacerlo mediante el API de Velneo V7 y JavaScript o con CSS:

Ventajas de hacerlo con el API de Velneo V7 JavaScript:

  • Muy configurable y personalizable mediante programación.
  • Muy potente al permitir aplicarlo a todas las propiedades y funciones.
  • Código muy reutilizable y de aplicación directa, no en cascada.

Ventajas de hacerlo con CSS:

  • Más sencillo de aplicar.
  • Se aplica en cascada a todos los formularios que se abran desde aquel en el que se haya aplicado el estilo.
  • Permite individualizar el estilo de múltiples controles a la vez

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Deshabilitar controles de formulario con el API de Velneo V7 appeared first on Lógica mente Velneo V7.

Desactivar ordenación en rejillas con CSS en Velneo V7

VITAMINA – 7

En esta vitamina aprenderás a desactivar ordenación en rejillas con CSS en Velneo V7.

Desactivar ordenación en rejillas con CSS en Velneo V7

Si necesitas evitar que el usuario pueda cambiar el orden de los registros visualizados en una rejilla, necesitas conseguir que el usuario:

  1. No tenga acceso a la opción ordenar en el menú contextual ni en el menú lista.
  2. Al hacer clic en la cabecera de una columna no se ordene la rejilla.

El primer punto lo lograrás desactivando el menú contextual por defecto de la rejilla y no dando acceso al usuario al menú de lista en el que se encuentra la opción ordenar.

Para conseguir desactivar la ordenación de los registros mostrados en una rejilla haciendo clic en la cabecera sólo tienes que hacer lo siguiente:

  1. Declara una conexión de evento en la rejilla para atrapar la señal Pre inicializado
  2. Asigna a la conexión de evento pre inicializado un manejador de evento que contenga el siguiente código:

Código para desactivar la ordenación haciendo clic en la cabecera de rejilla

QTableView
{
    qproperty-sortingEnabled: false
}

Observarás que la línea de código aplica un estilo CSS en el que pone a false la propiedad de rejilla sortingEnabled, consiguiendo de esta forma que cuando el usuario haga clic en cualquier cabecera de columna la rejilla no se ordene y siga con los registros visualizados en el orden en el que fueron cargados.

La vitamina no sólo es sencilla de programar, además es muy potente ya que si lo deseas puedes aplicar el CSS a nivel general para que todas las rejillas de la aplicación se comporten de la misma forma sin permitir la ordenación. Particularmente puedes aplicar un CSS específico a cualquier rejilla.

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Desactivar ordenación en rejillas con CSS en Velneo V7 appeared first on Lógica mente Velneo V7.

Desarrolla aplicaciones a medida con éxito

Ejemplo de Kanbanpad

El desarrollo de software a medida tiene características específicas que lo diferencian del desarrollo de aplicaciones estándar, sin embargo la metodología a seguir en ambos casos es muy similar. En este artículo quiero comentarte 7 aspectos que considero fundamental cuidar desde el principio, para tener éxito en un proyecto de desarrollo de una aplicación a medida.

1. Gestiona tus expectativas y las del cliente

No pienses que te vas a hacer rico con un proyecto a medida. Los clientes no son PaPá Noel, no regalan nada, y tampoco tienen por qué hacerlo, de la misma forma que tú debes hacer valorar tu trabajo. Si consigues un proyecto importante vete pensando que si vas a ganar mucho dinero es porque vas a tener que trabajar mucho. Esfuerzo y facturación suelen ser proporcionales.

El éxito profesional y económico en este tipo de proyectos se consigue a través de una larga relación con tu cliente, basada en la confianza que deberás obtener en base a hacer un buen trabajo cumpliendo plazos y calidad.

2. Sin jefe de proyecto no hay organización

En cualquier proyecto siempre hay como mínimo 2 personas, tu cliente y tú. A medida que el tamaño del proyecto crece también lo hacen las personas que están implicadas en el proyecto. Gestionar un equipo de personas no es fácil, por ese motivo la figura del jefe de proyecto es fundamental.

Sin un jefe de proyecto que haga bien su trabajo el equipo estará inmerso en el caos y la desorganización, te encontrarás con graves problemas de comunicación que derivarán en serios problemas con el cliente, entre los programadores. El trabajo se vuelve complicado, se pierde mucho tiempo en tomar decisiones, los programadores se sentirán perdidos y se buscarán la vida por su cuenta, nadie sabe lo que están haciendo los demás, nadie sabe cuanto llevamos hecho y cuando falta, etc.

No lo dudes si no hay un jefe de proyecto haciendo bien su trabajo, solicita la parada del proyecto hasta que se nombré a uno, y si es preciso coge tú el toro por los cuernos.

3. El responsable de producto debe ser el cliente

Nadie deberia saber más de su negocio que el propio cliente. Nosotros estamos para ayudar al cliente a poner en marcha una herramienta de software que le suponga mejoras en su empresa o negocio y que deberán tener una repercusión económica positiva.

Por este motivo es fundamental que la figura de responsable de producto corra a cargo de un empleado de nuestro cliente. Esta persona debe tener una importante dedicación en horas al proyecto, si no es así el jefe de proyecto debería pararlo inmediatamente hasta que se encuentre la persona que lo pueda llevar a cabo.

Esta persona debe estar en permanente contacto tanto con el jefe de proyecto como con los usuarios finales de la aplicación. Un grave error que debemos evitar es tratar directamente con los usuarios finales sin que esté presente el responsable de producto, lo más probable es que saques conclusiones incorrectas, tu análisis no sirva y haya que deshechar mucho código, tiempo y dinero.

Un buen responsable de producto también debe saber medir los tiempos, las necesidades de la empresa y saber decir no tanto a los usuarios finales como a los programadores cuando tratan de llegar más lejos de lo previsto inicialmente. Si tienes un buen jefe de proyecto y un buen responsable de producto, que aplican bien el criterio de menos es más hay más de un 75% de posibilidades de tener éxito.

4. Utiliza una herramienta online para la gestión de las tareas

Cada vez es más fácil encontrar proyectos donde el equipo está disperso geográficamente, además hay que tener en cuenta a los miembros del equipo que no son de tu empresa. Necesitamos trabajar como un único equipo y para eso es fundamental disponer de una herramienta que nos facilite la gestión de las tareas y la comunicación.

Están de moda las metodologías ágiles, y de esta moda una de las herramientas que mejor me ha funcionado y aportado grandes beneficios son los tableros kanban. Hay cientos de herramientas en el mercado para el uso de tableros kanban, yo te puedo comentar que tengo una magnífica experiencia de uso con dos de ellas:

  • kanbanpad que funciona perfectamente tanto en navegadores de escritorio como en móviles.
  • Trello, una aplicación web que cuenta también con versión para navegador y aplicaciones nativas para iOS y Android.

En otro artículos escribiré más en profundidad las experiencias con cada una de ellas y sus pros y contras.

Gracias a estas herramientas los equipos conocen las tareas pendientes, planificadas, en curso, en fase de pruebas o finalizadas. Todos, incluido el cliente, saben lo que están haciendo los demás, es fácil gestionar los errores encontrados durante las pruebas.

Mi recomendación es que dividas las tareas hasta que puedan ser realizadas en un día como mucho, el objetivo es doble, conseguir que pasen a pruebas tareas todos los días y que el programador se sienta más productivo. Por otro lado el equipo de desarrollo debe tener una comunicación constante, nosotros usamos un chat grupal, como el que nos ofrece por ejemplo Skype.

4. Iteraciones cortas

Si el proyecto lo permite es bueno tener contacto físico con el cliente. Nosotros intentamos tener una reunión presencial en el inicio de cada iteración, en esa reunión se definen y planifican las tareas a desarrollar en las siguientes 2 ó 3 semanas.

2 ó 3 semanas es tiempo suficiente para obtener avances visibles y a la vez es lo suficientemente corto como para reducir el coste de corregir errores en la gestión de las tareas del proyecto. Un mes es mucho tiempo, mejor si las iteraciones pueden ser de 2 semanas.

Las ventajas de realizar iteraciones cortas son múltiples, por un lado simplifica el control de la evolución del proyecto, algo crítico desde el punto de vista económico y del cumplimiento de plazos, por otro lado para los miembros del equipo es más positivo tener 3 tareas pendientes de hacer que ver una lista desde el inicio del proyecto con 100 tareas. Además, los proyectos evolucionan por lo que las tareas deben definirse a corto plazo para que sean efectivas.

Un aspecto fundamental es la prioridad de las tareas, nosotros aplicamos el criterio de priorizar siempre la resolución de incidencias encontradas durante las pruebas a seguir avanzando con otras tareas nuevas. La experiencia nos demuestra que muchas veces la resolución de una incidencia encontrada durante las pruebas de una tarea implica cambios de estructura y de programación que cuanto antes se aplique menos costo en tiempo y dinero supondrá para el proyecto.

En realidad cuando el equipo funciona bien trabaja en lo que podriamos denominar una iteración continua a la que añaden nuevas tareas cada 2 ó 3 semanas.

5. Programa en cloud

Cada día crece el número de personas que hacen teletrabajo y gracias a herramientas de desarrollo de aplicaciones PaaS como Velneo, también crecen el número de desarrolladores que programan en cloud tanto individualmente como en equipo. Programar en la nube aporta numerosas ventajas:

  • Tu código está siempre disponible estés donde estés.
  • No dependes de un equipo, puedes programar desde cualquier ordenador
  • Puedes programar en equipo sin tener que abrir tu red a accesos externos
  • Pruebas tu aplicación en un entorno más real que programar en local
  • Si tu aplicación está optimizada y funciona bien en cloud será un cohete en una red local

Evidentemente, programar en cloud también tiene contras:

  • Grabar tus desarrollos es más lento
  • Las pruebas de importación de datos requieren más tiempo o más programación

Pese a los inconvenientes, te recomiendo que siempre programes en cloud, y que excepcionalmente lo hagas en local para hacer tareas muy puntuales, depurar procesos complejos o pesados o para evitar bloqueos de proyectos con otros desarrolladores del equipo.

En otro artículo, daré más información sobre nuestra experiencia a la hora de abordar el desarrollo en equipo de una aplicación usando el cloud y combinándolo con servidores para uso individual de cada desarrollador y el uso de la importación de componentes.

Desarrollar en cloud tiene además 2 ventajas fundamentales para abordar estos proyectos:

  • El cliente y el responsable de producto pueden ver en todo momento como se avanza en el desarrollo de la aplicación. Es cierto que ven si avanzamos o no, pero la transparencia es nuestra aliada si somos buenos profesionales.
  • El cliente, el responsable de producto y los usuarios finales, puedes hacer las pruebas en tiempo real, con los mismos datos y condiciones que el equipo de desarrollo. Esto ayuda a que sea más sencillo comprender las incidencias reportadas.

Todo esto no implica que en una fase avanzada del proyecto sea conveniente poner en marcha un servidor de desarrollo en el cliente para que puedan tener libertad a la hora de hacer pruebas sin bloquear al equipo de desarrollo que constantemente necesita reiniciar las instancias para probar sus desarrollos.

6. Informa periódicamente a tu cliente de la evolución del proyecto

Salvo que tu cliente sea un autónomo o una empresa pequeña, no es habitual que la dirección participe de forma activa en el proyecto, y aunque el responsable de producto podrá informar de primera mano, es lógico que los directivos deseen conocer el estado del proyecto desde el punto de vista de la empresa que los está programando.

Por ese motivo es importante informar periódicamente, cada iteración o una vez al mes, enviando un informe donde se detallen las acciones realizadas, los módulos o funcionalidad que ya están programadas y probadas, las que se están probando, las que se están programando y las pendientes. No hace falta entrar en profundidad con detalles muy técnicos, hay que tener en cuenta el perfil de quién leerá nuestro informe.

Es importante ser realista y sincero, indicar en todo momento si el proyecto evoluciona favorablemente o si se están produciendo retrasos. Cuanto antes informes, más posibilidades hay que de se puedan tomar medidas correctoras y de que los propios directivos puedan ayudar en la resolución del problema.

Las personas que dieron viabilidad económica al proyecto, están implicadas personalmente en el mismo, y por regla general tienen el mismo deseo que todos los miembros del equipo del proyecto en que sea un éxito, por ese motivo debemos siempre verlos como nuestros aliados, no como nuestros enemigos o evaluadores.

7. Probar, probar, probar y aprobar

Todos los arranques son complicados. Si quieres evitar que la implantación de la aplicación sea un infierno debes asegurarte de que todos los usuarios tienen conocimiento de como funciona la aplicación, la han probado y han dado su visto bueno. Aún así, los datos de pruebas no te van a proteger de que surjan complicaciones durante el arranque, pero al menos evitarás que los usuarios vean a la aplicación como su enemigo, pues ellos mismo han tenido la oportunidad de probarla y aprobarla antes de su puesto en producción.

Para conseguir que los usuarios prueben la aplicación es indispensable el trabajo del responsable de producto que se encargará de probarla personalmente y de validarla con cada uno de los usuarios de la aplicación, bien personalmente o a través los responsables de departamento o área que deberán encargarse de trasladar las tareas de pruebas y validación a toda la organización.

El éxito siempre será el fruto del esfuerzo y del trabajo en equipo

Aún gestionando bien un proyecto y realizando un gran esfuerzo para que todo salga bien, siempre aparecerán muchas dificultades e imprevistos, que deberán superarse en equipo, con respeto, evitando buscar culpables y centrándonos siempre en resolver las incidencias que surjan y las necesidades de nuestro cliente.

Cuando la implantación se estabiliza y el proyecto se convierte en un caso de éxito, no te olvides nunca de disfrutarlo personalmente, con todo el equipo, con el cliente y añadirlo en tu lista de casos de éxito, ya que siempre puede ser la puerta a nuevos clientes y proyectos.

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Desarrolla aplicaciones a medida con éxito appeared first on Lógica mente Velneo V7.

Desarrollo de aplicaciones

“Cuando los demás llevan el 70% del desarrollo de su código realizado, yo todavía estoy pensando, cuando van por el 75% yo ya acabé”. Juan Muñoz-Cobos

.

Hace 15 años si alguien me preguntaba ¿Qué tal la empresa?, lo primero que le decía era el número de personas que éramos, si me preguntaban ¿Qué tal el programa? le decía, tiene 1 millón de líneas de código, 400 objetivos,  tenemos 8 módulos. Con el tiempo esas respuestas han variado, ahora hablo de facturación, rentabilidad y número de usuarios que lo usan los programas.

.

.

1.-La madurez de un software=al número de usuarios

La madurez de un software no depende del tiempo que lleve de desarrollado o lo bueno que seas programando, es directamente proporcional al número de usuarios reales que lo estén usando.

madurez del software

Siendo u=número de usuarios y t=tiempo el punto óptimo, es mucho uso en poco tiempo, eso hace tu software realmente valga la pena.

.

2.-Desarrolla poco y que se use mucho.

La metodología de desarrollo para productos nuevos MVP (mínimo producto viable) responde a la premisa,  hacer programas pequeños, con poca funcionalidad y que se usen mucho desde el principio, con eso consigues que el nucleo madure rápido y después desarrollas rápido sobre la base que está probada con muchos usuarios diferentes.

.

.

3- 10 empresas de 2 usuarios, mejor que una de 50.

El primer gran producto que desarrollé fue Visualtrans, el primer cliente fue una empresa de 50 usuarios amiga, con lo cual el programa no tuvo resistencias para su implantación y creció muy rápido en módulos y funcionalidad. Estaba orgulloso de los 10 módulos que habíamos desarrollado el primer año funcionando en 50 usuarios diferentes. Cuando en segundo año el software se extendió a 10 empresas, nos vimos obligados a rehacer el “core” y los 10 módulos, habíamos desarrollado un software casi a medida. Si consigues que tu software con poca funcionalidad se instale en 10 empresas diferentes entonces tendrás un producto y un “core” maduro de verdad.

.

.

4,.Cuando el “CORE” es maduro, no corres, vuelas.

Juan Muñoz-Cobos es el mejor arquitecto de software que  existe en España y  está entre los 5 mejores del mundo, desde mi punto de vista. Trabajar con él, es uno de los mejores Master que me ha dado la vida. Cuando empezamos en el proyecto Velneo me dijo una frase que nunca olvidaré:

“Cuando los demás llevan el 70% del desarrollo de su código realizado, yo todavía estoy pensando, cuando van por el 75% yo ya acabé”

Durante 3-4 años Velneo estuvo centrado en el “Core” de su Velneo V7 y parecía que aquello no avanzaba, un core que era probado por programadores reales (desde aquí agradezco a todos los que estuvieron programando sobre ese core durante dos años). En los últimos años no podemos seguir el avance de la plataforma y su madurez es conocida, programar sobre un core pensado, estable y probado por usuarios reales es básico si quieres tener éxito a largo plazo.


Actualizaciones y arrastrados con condición dinámica en Velneo V7

VITAMINA – 6

En esta vitamina aprenderás a hacer actualizaciones y arrastrados con condición dinámica en Velneo V7.

1. Planteando el problema

Los triggers (o eventos de tabla) y las actualizaciones (o macro-triggers automáticos) son dos funcionalidades muy utilizadas en nuestras bases de datos ya que nos aportan gran potencia de forma sencilla para gestionar cambios tanto en el registro que está siendo creado, modificado o eliminado como en los registros de otras tablas maestras o plurales enlazadas o de registros de tablas a las que accedemos mediante código.

La facilidad para crear las actualizaciones de tablas lleva implícito un efecto secundario y es que son disparados de forma automática cuando se producen cambios en campos que intervienen en la actualización, algo que es muy agradecido pero que en algunos casos puede resultar un problema. Veamos algunos ejemplos:

Caso A

Tenemos una tabla con actualizaciones que acumula valores en tablas maestras, pero cuando el alta se produce a través de un proceso de importación, no queremos que se ejecuten dichas actualizaciones porque duplican los valores que ya han sido importados en las tablas maestras.

Caso B

Tenemos una tabla de movimientos de almacén donde en el trigger posterior al alta, modificación o baja, cada vez que cambia el campo cantidad o precio se fuerza el recálculo “en cascada” de todos los registros, desde el modificado hasta el último de ese artículo calculando la existencia y el valor del almacén en cada movimiento. Pero nos gustaría que cuando hacemos cambios globales a todos los registros de un artículo sólo se realizase el cálculo de existencia y valoración de almacén una vez, ya que si se lanza por cada registro el número de veces que es modificado cada registro es el resultado de un cálculo factorial, lo que supone una gran pérdida de rendimiento en la ejecución de estos procesos.

2. Planteando la solución

Desde el punto de vista de teórico la solución es muy sencilla. Evitar que se ejecuten los triggers y actualizaciones siempre, y que sólo se ejecuten cuando nosotros lo deseemos.

Desde el punto de vista práctico parece en principio sencillo ya que las actualizaciones tienen una propiedad “condición” que permite indicar la fórmula a calcular con la condición que debe cumplirse para su ejecución, y los triggers son código en el podemos también usar sentencias de condición para evitar su ejecución. El problema aún así persiste ya que la condición para que no se ejecuten debe ser dinámica, es decir, no depende de los datos del registro sino que depende de las circunstancias en las que se producen las operaciones de alta, baja o modificación. Es decir, desde ciertos procesos, funciones o formularios sí deben ejecutarse y desde otros no.

3. Programando la solución

La solución pasa por conseguir que el registro sea “consciente” de si deben o no ejecutarse los triggers y actualizaciones, y que pase esa información a los triggers y actualizaciones para que actúen en consecuencia. Eso lo vamos a conseguir realizando los siguientes pasos:

  1. Añadir en la tabla un campo booleano, por ejemplo #CAL_ARR (Calcular datos arrastrados).
     
  2. Añadir en la tabla una variable local booleana, por ejemplo #CAL_ARR (Calcular datos arrastrados).
     
  3. En los triggers anteriores a alta, baja o modificación añadiremos el siguiente código para controlar si el campo booleano llega con el valor 1, en cuyo caso lo que hacemos es poner a 1 la variable local que será la que usemos a partir de este momento para condicionar la ejecución en triggers y actualizaciones, y el campo a 0 para evitar cualquier conflicto con un bucle infinito de actualizaciones en cascada.
     Cálculo de arrastrados - trigger anterior 
  4. Ahora sólo nos queda usar la variable local para controlar los componentes de actualización y el código de los triggers que deseamos ejecutar.
     Cálculo de arrastrados - trigger posterior
     Actualizaciones y arrastrados con condición dinámica en Velneo V7
     
  5. Ahora sólo queda que cuando vayas a crear, modificar o eliminar un registro de esta tabla, tanto desde un formulario, como de un manejador de evento, función, proceso, etc. pongas el valor del campo #CAL_ARR a 1 (si deseas que se ejecuten las actualizaciones y los cálculos arrastrados) o dejarlo a 0 (si deseas que no se ejecuten las actualizaciones y los cálculos arrastrados). Es importante que evites poner a 1 el valor de este campo en un trigger pues por error puedes llegar a provocar un bucle infinito o un desbordamiento del stack.
     

4. Conclusión

Práctico y sencillo de programar, podrás optimizar tu aplicación para que ejecuten los bucles de actualización de cálculos arrastrados y las actualizaciones el menor número de veces posible, independientemente de que las operaciones en la tabla se lancen desde objetos de interfaz, procesos en primer plano o en el servidor. Desgraciadamente en Velneo 6x no contamos con variables locales a nivel de tabla por lo que no podemos utilizar esta técnica.

Nota:

Si tu tabla tiene millones de registros y no te gusta usar un byte para obtener esta funcionalidad también puedes utilizar otro campo de la tabla donde puedas grabar al principio o al final del mismo un carácter o etiqueta que te identifique que se deben ejecutar los arrastrados y las actualizaciones. Por ejemplo, utilizar un campo #REF (Referencia) en el que pondríamos al principio de su contenido el símbolo “#”. En el trigger anterior si aparece ese símbolo actualizamos el campo referencia quitándoselo y poniendo a 1 la variable local para ejecutar los arrastrados, de esta forma nos ahorramos un campo.

 

Si te ha gustado este artículo, por favor compártelo con los tuyos en las redes sociales

The post Actualizaciones y arrastrados con condición dinámica en Velneo V7 appeared first on Lógica mente Velneo V7.