Búsqueda y arrays, una forma de hacer multibúsquedas (y II)

Intentaré explicar con otro ejemplo una nueva forma de hacer multibúsquedas en una tabla de datos usando de nuevo los arrays de Velneo.

El planteamiento es sencillo pero suficiente para desarrollar dos formas de hacer una multibúsqueda sobre una misma tabla: una con una rejilla en la que escogemos los datos de quién queremos mostrar de dentro de una lista de ellos y otra en la que introducimos nosotros los datos como si fuese un histórico.

Tenemos dos tablas, una de CLIENTES  y otra de VISITAS,  ésta última histórica de la primera, en la que iremos guardando las visitas que le hacemos a cada cliente en diferentes fechas. No he querido crear más campos para que el ejercicio fuera lo más sencillo y claro posible.

Esquema inicial de tablas

Esquema inicial de tablas

Primer planteamiento: el objetivo es que la aplicación busque todas las visitas que se han hecho a los clientes que yo elija en una rejilla en la que me muestra todos los clientes. Es lo que he llamado en el mapa visitas múltiple  selección y los objetos usados se guardan en la carpeta del mismo nombre.

He creado una tabla DUMMY  en memoria que se va a cargar con todos los clientes cada vez que se necesite a través de un tubo de lista.

esquema dummy

Esquema de tablas con CLIENTES, VISITAS y DUMMY

Con un formulario especial de la tabla VISITAS donde se muestra una rejilla con todos los DUMMY,  editable en su campo %ESCOGER%,  que en principio vale 0, pero que podemos cambiarlo en esa rejilla a 1 para que nos  busque las VISITAS  a ese CLIENTEDUMMY. Tras tener escogidos los CLIENTES  que queremos el proceso utiliza una cesta de VISITAS  y la potencia de los arrays, para ir cargando en la cesta las visitas de cada uno de los CLIENTES seleccionados y mostrarlos al final en una rejilla de la tabla VISITAS. Como se puede observar, la tabla DUMMY  no tiene ningún tipo de conexión con las otras dos tablas.

proceso multi

Proceso con DUMMY y "multiselección".

En el proceso se crea una cesta local de visitas donde se irán añadiendo las visitas de los CLIENTES  elegidos.

Se vacía la DUMMY   y  se rellena posteriormente mediante un tubo de lista con todos los clientes. Se crea el array.

A continuación se muestra un registro de VISITAS en el que hay una rejilla con los datos de la DUMMY. El primer campo %ESCOGIDO% es editable y se puede cambiar su valor de o a 1.

Se carga la lista DUMMY  por el índice “escogido” ( formado por el código y con campo condición para indexar %ESCOGIDO% igual a 1 ) y se van añadiendo al array los códigos de los clientes guardados en el campo %CODIGO%  de la tabla DUMMY.

Por último se caga el array, y se va leyendo cada item, que irá modificando la variable global en memoria $COD-CLIENTE$ para así lanzar la búsqueda VISITAS-COD-CLIENTE  y añadir los resultados obtenidos a la cesta. Por último se muestra la cesta.

Este planteamiento se lanza en la opción de menú búsqueda múltiple con rejilla editable

Segundo planteamiento. el objetivo es que la aplicación busque todas las visitas que se han hecho a los clientes que yo haya introducido en una rejilla. Es lo que he llamado en el mapa visitas múltiple  dando altas y los objetos usados se guardan en la carpeta del mismo nombre.

He creado una tabla DUMMYDOS  en memoria  a la que se van a añadir los clientes que se quiera mediante un formulario de alta

esquema con dummydos

Esquema con CLIENTES,VISITAS y DUMMYDOS

Esta vez DUMMYDOS si que actúa como histórica de CLIENTES, pues necesito rellenar esta tabla con un localizador y para ello , necesito que CLIENTES sea maestra de DUMMYSDOS.

El proceso llamado varía un poco, pero también creo que es sencillo y fácil de comprender.

proceso dummydos

Proceso que alimenta la cesta de las visitas

En este caso, cuando se recorre la lista de DUMMYDOS,  el dato que se debe añadir al item del array es el puntero al CLIENTE, que guarda el campo %CODIGO% de la ficha del maestro CLIENTES.

El segundo  planteamiento se lanza en la opción de menú búsqueda múltiple con rejilla “alimentada”

Seguro que es mejorable, pero es sólo un ejercicio para ver cuánto partido le podemos sacar a Velneo.

Link de descarga del mapa completo y en el foro de Velneo.

EDICION (8-sep-2010)

Tal y como me comenta por e-mail mi compañero y sin embargo amigo 🙂 Adelo Herrero el primer planteamiento se puede hacer sin la tabla DUMMY  usando la misma tabla de CLIENTES para simular la multiselección con el campo %ESCOGIDO%.

Tienes toda la razón Adelo. Se agradece el comentario y subo al link de descarga la versión actualizada con tu sugerencia.

Un saludo.

Anuncios

Búsqueda y arrays, una forma de hacer multibúsquedas (I)

Hace poco, un amigo me planteó el siguiente problema  que se le daba en una aplicación.

En una empresa, hay una serie de departamentos. Dentro de cada departamento, hay niveles de acceso a la información de una tabla (NOTICIAS). Cada persona de la empresa tiene un determinado NIVEL  dentro de cada DEPARTAMENTO y una persona solo puede acceder a las informaciones de cada uno de sus departamentos y dentro de ellas a las que su nivel se lo permita. Por ejemplo, si hay 10 niveles y tengo asignado en el departamento de contabilidad el nivel 4, podré acceder a toda la información de contabilidad con nivel 4, 5, 6,7,8,9 ó 10.

El esquema de tablas que hice fue el siguiente:

Esquema

Esquema de tablas

La tabla CLASIFICACION  tiene como objetivo mantener un histórico de los DEPARTAMENTOS  y NIVELES que tiene en cada uno de ellos cada PERSONA de la empresa. Tiene solamente tres campos punteros a maestro PERSONAS, DEPARTAMENTOS y NIVELES  y un índice de clave única formado por los tres campos punteros.

La tabla NOTICIAS  ( puede también llamarse APUNTES o NOTIFICACIONES, como cada cual quiera ) tiene un campo CODIGO, NOMBRE y un puntero a DEPARTAMENTO y otro a NIVELES que le renombré como Nivel Mínimo. A su vez creé un índice formado por la terna DEPARTAMENTO-NIVEL .

Para que desde una ficha de modificación de persona, se muestren las NOTICIAS  que le corresponde, monté los siguientes objetos visuales:

  • variable global en memoria  DEPARTAMENTO
  • variable global en memoria NIVEL
  • variable global en memoria TOTAL NIVELES

Las tres numéricas

  • Una búsqueda en la tabla NOTICIAS: NOTICIAS-PERSONA, en la que se busca por dos índices, primero por el de departamento, parte izquierda, valor $DEPARTAMENTO$  al que se le cruza la búsqueda por el índice NIVEL, entre límites, limite inicial $NIVEL$ , límite final $TOTAL NIVELES$
Búsqueda

Búsqueda de noticias-personas

  • Un proceso con origen ficha de PERSONAS que alimenta la rejilla que se mostrará en el formulario de modificación de la persona,con  las noticias a las que tiene acceso.

Proceso

En este proceso son fundamentales tres cosas: la cesta y los dos arrays.

Un array es un vector, con muchas dimensiones, es una forma de guardar datos de forma momentanea en un proceso y acceder a ellos dentro del mismo proceso.

El primer array (array departamento), guardará en cada item el DEPARTAMENTO que se guarda de la persona en la tabla CLASIFICACION y en el segundo (array nivel ) , el NIVEL. Con ello conseguimos tener por cada persona la terna DEPARTAMENTO-NIVEL, cada una en un array.

Sólo nos queda hacer un bucle for que se repita un número de veces igual al número de items que tienen los arrays para ir llamando a la búsqueda NOTICIAS-PERSONAS sucesivamente e ir añadiendo los resultados de cada una de ellas a una cesta local, que al final procesaremos y será la que se muestra en el formulario.

Podeis descargarlo aquí http://forum.velneo.com/es/viewtopic.php?p=80270#80270

Vserver: prueba de stress

Después de leer este verano las pruebas de stress que se han realizado a los distintos bancos para ver si eran capaces de superar las crisis, se me ocurrió plantear una prueba del mismo tipo con el vServer.

La idea es sencilla. Crear una aplicación con una sola tabla pero con un número grande de registros y someterla a unas cuantas pruebas sencillas y ver cómo se comportaba.

Para ello creé una aplicación con las siguientes tablas

  • NAMES: tabla a la que importé nombres de personas. Indices Código y Nombre
  • APELLIDOS :  en ella importé un listado completo de apellidos. Indices Código y Nombre
  • PERSONAS:  la tabla con la que realicé las pruebas. Inices Código, Nombre, Palabras y Trozos

Un demonio llamaba a un proceso que daba de alta 3000 registros de cada vez en la tabla PERSONAS, escogiendo aleatoriamente , un nombre propio y dos apellidos.

Tras dejarlo cargado en el vServer unas 26 horas, se habían generado 4.689.000 registros.

Ficha técnica de la prueba

HARDWARE Y S.O.

Pentium Dual Core a 2,5 GHz y con 4 Gb de memoria RAM

Microsoft Windows Server 2003 standart edition  service pack 1

vServer versión 6.3.9

Registros en la tabla: 4.689.000

Tamaño del archivo .dat :     609.022 Kb

Tamaño del archivo .idx:  1.538.008 Kb

Realicé siempre las mismas pruebas:

  1. Búsqueda por código. Sencillo ,simplemente cargar la lista en pantalla con la opción de menú Búsqueda
  2. Una vez tenía el resultado anterior, reordenar por código
  3. Una vez ordenada por código, reordenar por Nombre

Además, realicé el paso 2 y el 3 una segunda vez sin cerrar el vClient, para ver si el comportamiento mejoraba tras las primeras ordenaciones.

Los resultados fueron estos

1. Búsqueda por código:   8 seg.

2. Reordenar por código: 1ª vez 8 min 40 seg    2ª vez 45 seg.

3. Reordenar por nombre: 1ª vez 12 min 15 seg    2ª vez 37 seg.

Tras estas pruebas, hice una regeneración de índices de la tabla que tardó en finalizar  5 min y 32 seg. Con ello esperaba una mejora significativa en los tiempos de las pruebas pero los resultados no produjeron mejoras dignas de mención.

ACTUALIZACION

Repetida la prueba en remoto, con el navegador atacando la aplicación en el vServer desde otro equipo

  1. Búsqueda por código  1 min 35 segundos
  2. Reordenar por código: 42 minutos 30 segundos.

NUEVA ACTUALIZACIÓN A 30-8-2010.

Prueba en local.

Siguiendo la sugerencia de Paco, he reducido el campo código a numérico de 3 cifras con los siguientes resultados

  1. Búsqueda por código:  8 segundos
  2. Reordenar por código: 7 minutos 3 segundos

Prueba en remoto

  1. Búsqueda por código : 1 minuto 5 segundos
  2. Reordenar por código: 40 minutos 5 segundos

    Nuevos tamaños de los archivos:

    • personas.dat    595.284 Kb
    • persona.idx  1.094.204 Kb

    Programar es prever

    He estado un tiempo sin escribir nada en el blog, y los próximos cambios que se van a dar en la legislación española sobre la aplicación del impuesto del IVA en las facturas me ha animado a hacerlo.

    Hasta ahora, la forma habitual de enfocar el recargo del IVA en las facturas, al menos en las aplicaciones que yo desarrollaba y en alguna otra de otros programadores que conozco se basaba en guardar los valores de los porcentajes de los impuestos en variables globales de disco.

    El próximo cambio de valores me ha hecho pensar que programar es prever, y quién nos dice que dichos valores no vayan a sufrir variaciones a lo largo del tiempo de aquí a unos meses o años.

    Por ello me he planteado pasar todo ello a una estrucutura de tablas lo más flexible posible y que no tenga que implicar la actuación del programador a la hora de hacer estos cambios.

    Esquema general de tablas

    Esquema general de tablas

    Basándonos en una aplicación sencilla de facturas de ventas, el esquema que he ideado es el mostrado en la imagen.

    Partimos de una tabla principal de IMPUESTOS  en los que podremos dar de alta tanto IVA como IGIC, IRPF, Recargo de equivalencia….

    En la tabla TIPOS-IVA se añadirán los distintos tipos de cada impuesto. Por ejemplo, en el caso del IVA irán los registros: General, Reducido, Superreducido y Exento, por ejemplo.

    Y en la tabla valores del IVA , tanto los porcentajes de cada uno de estos TIPOS como su fecha de entrada en vigor.

    He añadido además una tabla de COMPATIBLES para tener una relación de qué impuestos son compatibles entre sí y por tanto aplicables en una única factura. Por poner un ejemplo de incompatiblidad, el impuesto IGIC aplicable en la comunidad autónoma de Canarias , NO es compatible con el IVA, pues de alguna forma el primero sustituye al segundo.

    Todos los valores anteriores, se dán de alta automáticamente al iniciar la aplicación mediante llamadas a diferentes procesos sin origen en el proceso de arranque GENERAL.

    Proceso GENERAL

    Proceso GENERAL

    Desde este proceso GENERAL  se hacen llamadas a diferentes procesos sin origen que van dando de alta los registros necesarios en las diferentes tablas

    Los procesos interesantes son

    IVAS-ALTAS

    IGIC-ALTAS

    IRPF-ALTAS

    RECARGO-ALTAS

    En la imagen no aparece, pero también se incluye un proceso para dar de alta los registros de la tabla COMPATIBLES.

    Podremos escoger qué impuestos vamos a usar de forma general en el formulario de CONFIGURACIÓN  en la pestaña “fiscales” y sus valores habituales , así como personalizar para cada cliente qué impuestos le vamos a aplicar de forma general en las facturas que les emitamos y sus valores, todo ello con subindexaciones para que sólo podamos escoger los TIPOS  del IMPUESTO  elegido.

    Así mismo, en los artículos  escogeremos también el IMPUESTO  y su TIPO, calculando el porcentaje aplicado según los dos campos anteriores.

    En la tabla de MOVIMIENTOS (lineas de la factura ) en el campo PORCENT-IVA-FACT  he usado como valor inicial la función IVA-PORCENT  a la que le paso los parámetros : fecha de la factura, tipo de impuesto, e impuesto. Esta función, dependiendo de esos tres parámetros, me calcula el valor de ese impuesto-tipo que graba a la linea en esa fecha de factura. La función es manifiestamente mejorable pero me pareció una solución válida para conseguir el fin que se necesitaba, la devolución del tanto por ciento en vigor.

    En la tabla FACTURAS uso 7 campos BASE IMP , dado que el IGIC tiene hasta siete registros en la tabla TIPOS-IVA, y desde MOVIMIENTOS hay tambien 7 actualizaciones distintas a los respectivos cambios, todas ellas condicionadas a los distintos binomios IMPUESTO  TIPOS-IVA  que estemos usando.

    Como en una factura pueden coexistir dos impuestos que la graban ( por ejemplo IVA y Recargo de Equivalencia ) y uno que la resta  ( IRPF ) he creado los respectivos campos para calcular los valores de dichos impuestos con respecto a las bases imponibles correspondientes, así como la retención del IRPF sobre el total de la suma de las bases, todo ello mediante las funciones correspondientes que dependen de la fecha de la factura, del tipo y del impuesto.

    Por último indicar que todo aquel que quiera el mapa del programa, puede escribirme un correo a agustismv@gmail.com y se lo proporcionaré con mucho gusto para que lo useis como queráis.

    P. D: pensando en la v7, bastaría con conectar la tabla  VALORES-IVA  con PAISES  y así la tendríamos para distintos paises.

    ¿Tubos?…¿y eso qué es? (y iii)

    Veamos con un ejemplo real la diferencia de actuación de los tubos de lista y de ficha.

    Supongamos una aplicación en la que hacemos albaranes y facturas con una estructura de tablas como la siguiente.

    Esquema de tablasHe puesto las tablas de cabeceras de albaranes y de facturas como submaestra de años para aprovechar su código como contador y así que comience a contar en 1 en cada año ( ver articulo )

    Así mismo las lineas son a su vez submaestras de las cabeceras correspondientes.

    Los campos que tenemos en las tablas cabeceras son practicamente los mismo en una y en otra tabla , al igual que ocurre con los campos de las tablas lineas.

    Hagamos ahora los objetos visuales que nos permitirán facturar un albarán.

    El proceso general para hacerlo sérá: tenemos una ficha de Cabecera de Albarán de la que

    cuelgan sus históricos Lineas de Albarán. Tomaremos los datos de la CAlbarán y los pasaremos a un ficha de CFacturas. Una vez hecho esto, he de recorrer las lineas de LAlbaranes para hacer lo mismo, es decir, llevarlas a LFacturas pero indicándoles a dichas lineas a qué CFactura pertenecen. Para ello usaremos dos métodos. El primero mediante dos tubos de ficha y el segundo con un tubo de ficha y otro de lista.

    Método 1: dos tubos de ficha

    Crearemos primero el tubo de ficha para pasar datos desde una Cabecera de Albarán a una Cabecera de factura

    Tubo de cabecera

    Vemos que los capilares que usamos son pocos, no  utilizamos todos los campos, sólamente los que son necesarios para definir la factura al final del tubo, el cliente, el año y el almacén, en caso de ser multialmacén. El resto de los campos de CFactura, se “rellenarán” o bien por contenidos iniciales de los mismos o bien mediante actualizaciones desde las lineas

    Después creamos el tubo de ficha para las lineas en el que usaré dos capilares, el puntero al Artículo y la cantidad de unidades vendidas.

    El proceso para facturar un único albarán será el siguiente.

    Proceso en el que ser realiza la facturación de un albarán.

    Con lo que obtenemos la factura con sus lineas correspondientes.

    Método dos: un tubo de ficha para las cabeceras y un tubo de lista para las lineas

    Creamos el tubo de lista desde LAlbaranes a LFacturas, con los mismos capilares que los usados en el tubo de ficha. Los cambios irán en el proceso de facturación que se lanza desde la ficha de CAlbarán

    Facturación

    Observar que en el post del primer tubo, ya no uso los Set para guardar valores en varialbles locales sino la instrucción de proceso

    Guardar ficha, lo que nos permitirá usar un Tubo de lista con inducción. Esta inducción nos permite indicar a todas y cada una de las lineas de factura que se van creando a la salida del tubo de lista a qué ficha de maestro( CFactura) pertenecen.

    La inducción hace que cada línea de la factura apunte a la misma cabecera, es decir, introduce el código del registro de la cabecera de la factura en el campo enlazado de los registros de Líneas de Factura.

    Cualquiera de los dos métodos es válido. El primero, con tubo de ficha en las lineas, nos permite modificar los registros de salida del tubo, en cambio el tubo de lista no lo permite.

    En el caso de tener que facturar varios albaranes en una única factura, podríamos hacer un proceso con origen lista de CAlbaranes para poder lanzarlo como una opción desde una toolbar en una  búsqueda de albaranes presentada en una rejilla multiselección, para ejecutarlo contra los seleccionados. Dividiremos así mismo el proceso en dos. En el primero, ordenamos la lista por Cliente para luego multipartirlo por ese mismo campo. Con ello logramos una “minilista” con cada todos los albaranes de un cliente, y por cada una de esas minilistas, ejecutamos el proceso que los factura.

    Proceso llamador

    Proceso llamado en el que se realiza la facturación de la minilista de los albaranes de un único cliente. Este proceso se repetirá por cada una de las multiparticiones que se obtengan en el proceso llamador.

    vDeveloper: vayamos por partes (y vi). Recapitulación.

    Como componente final de las tablas tenemos las actualizaciones. Una actualización no permite modificar registros de otras tablas con las que estemos unidos mediante un puntero a singular,es decir, puedo modificar registros de tablas a las que apunte mediante un puntero a maestro, un puntero indirecto o un hermano contiguo.

    Su mayor potencia reside en su autorecálculo. Me explico. Supongamos que mediante una actualización, voy llevando a un campo de la tabla Cabeceras de facturas el número de artículos que voy vendiendo. Cada vez que introduzco una linea y pongo las unidades vendidas, al dar de alta la linea se lanza la actualización y me aumenta el contador. Pues bien, si de nuevo entro en la linea y cambio el valor de las unidades, la actualización se rehace, deshace la actualización con el anteriro valor y la rehace con el nuevo. Pero si por alguna causa, borramos una linea, también se recalcula la actualización Y SIN TENER QUE ESCRIBIR NI UNA SOLA LINEA DE CODIGO.

    Con  un ejemplo práctico veremos la potencia que encierran las actualizaciones. Supongamos una aplicación para hacer albaranes de venta. Vendemos artículos que tienen un stockaje de almacén y que pueden ir grabados con distintos tipos de IVA. Además queremos llevar en una tabla el IVA repercutido por meses de los distintos tipos de IVA por separado. 

    TABLA TIPO TABLA DE DATOS PADRE
    CLIENTES Maestro normal con clave numérica –
    ARTICULOS Maestro normal con clave numérica –
    ALBARANES VENTAS Maestro normal con clave numérica –
    LÍNEAS ALBARANES VENTAS Sub Maestro ALBARANES VENTAS
    FACTURAS Maestro normal con clave numérica –
    LINEAS FACTURAS Sub Maestro FACTURAS

    AÑOS. mestra normal con clave numérica

    IVA ACUMUALDO. Histórica de Años
    A las tablas se han añadido los siguientes campos:

    Tabla de ARTICULOS:
    IDENTIFICADOR PVP NOMBRE P.V.P. TIPO Numérico LONGITUD 3
    IDENTIFICADOR IVA NOMBRE I.VA. TIPO Numérico LONGITUD 1 RANGO MÁXIMO 99 CONT. INI $IVA1$
    IDENTIFICADOR PVP-SIN-IVA NOMBRE PVP sin IVA TIPO Fórmula Numérica
    FÓRMULA fRedondear( 100 * %PVP% / (100+%IVA%),2 )
    IDENTIFICADOR STOCK  NOMBRE Stock TIPO Numérico LONGITUD 2 SIGNO Activado

    Tabla de ALBARANES VENTAS:
    IDENTIFICADOR FECHA NOMBRE Fecha TIPO Fecha CONTENIDO INICIAL fHoy ()
    IDENTIFICADOR NLINEAS NOMBRE Número de líneas TIPO NuméricoLONGITUD 2
    Declaramos tres bases imponibles (una por cada tipo de IVA):

    IDENTIFICADOR BASE1 NOMBRE Base Imponible 1ª TIPO Numérico LONGITUD 4 SIGNO Activado
    IDENTIFICADOR IVA1 NOMBRE I.VA. 1º TIPO Numérico LONGITUD 1 RANGO MÁXIMO 99 CONT INI $IVA1$
    Declaramos también otros dos IVA’s más.
    IDENTIFICADOR IMP-IVA1 NOMBRE Importe I.V.A. 1º TIPO Fórmula NuméricaSIGNO Activado
    FÓRMULA fRedondear(fPorcentaje(%BASE1%,%IVA1% ) )
    fPorcentaje (Valor, porcentaje), devuelve el número resultante de aplicar el porcentaje al valor.

    Declaramos otros dos campos para calcular el Importe de IVA 2º y del IVA 3º, respectivamente de igual forma que el anterior

    IDENTIFICADOR TOTAL NOMBRE TotalTIPO Fórmula NuméricaSIGNO Activado
    FÓRMULA %BASE1%+%BASE2%+%BASE3%+ %IMP-IVA1%+%IMP-IVA2%+%IMP-IVA3%
    IDENTIFICADOR FACTURADO NOMBRE ¿Facturado?TIPO Booleano (Sí / No) CONTENIDO INICIAL 0
    Tabla de LINEAS ALBARANES VENTAS:
    IDENTIFICADOR CANTIDAD NOMBRE Cantidad TIPO Numérico LONGITUD 2
    IDENTIFICADOR PVP NOMBRE P.V.P. TIPO Numérico LONGITUD 3 CONTENIDO INICIAL %ARTICULOS.PVP%
    IDENTIFICADOR IVA NOMBRE % I.V.A. TIPO Numérico LONGITUD 1 CONTENIDO INICIAL %ARTICULOS.IVA%
    IDENTIFICADOR IMPORTE-SIN-IVA NOMBRE Importe sin Iva TIPO Fórmula numérica SIGNO Activado
    FÓRMULA %CANTIDAD% * %PVP%
    IDENTIFICADOR IMPORTE-DEL-IVA NOMBRE Importe del Iva TIPO Fórmula numérica SIGNO Activado
    FÓRMULA fRedondear(fPorcentaje(%IMPORTE-SIN-IVA%, %IVA%))
    IDENTIFICADOR IMPORTE+IVA NOMBRE Importe con Iva TIPO Fórmula numérica SIGNO Activado
    FÓRMULA %IMPORTE-SIN-IVA%+%IMPORTE-DEL-IVA%
    La tabla FACTURAS tiene la misma estructura que la de ALBARANES VENTAS, a excepción de los campos NLINEAS y FACTURADO, que no los tiene.

    TABLA AÑOS: nos quedamos con el campo código y borramos el campo nombre y los índices NOMBRE, PALABRAS Y TROZOS. Esta tabla, en la que sólo vamos a llevar los años, podemos cargarla de datos con un proceso llamado desde el AUTOEXEC-ON-INIT que tendrá la siguiente estructuraGenera los años

    TABLA IVAREPERCUTIDO. Tendrá los campos

    TRIMESTRE 1 IVA1: numérico , longitud 4 con 2 decimales y signo

    TRIMESTRE 2 IVA1: numérico , longitud 4 con 2 decimales y signo

    TRIMESTRE 3 IVA1: numérico , longitud 4 con 2 decimales y signo

    TRIMESTRE 4 IVA1: numérico , longitud 4 con 2 decimales y signo

    En estos campos llevaremos los IVAS repercutidos por trimestre, para las bases imponibles que correspondan al IVA del tipo 1.  Para los otros tipos de IVAS no tenemos más que hacer otros tantos campos del mismo tipo que el anterior, cuatro por cada tipo

    La estructura de tablas queda como sigue

    Esquema de tablasPara tener guardados los valores de los IVAS usaremos tres varialbles globales en disco, de tipo numérico y con longitud 3 y dos decimales.

    Para guardar los datos generales de la empresa tenemos dos opciones, o bien usar también variables globales en disco en las que iremos guardando los datos de la empresa, como razón social, NIF, domicilio, código postal, población …. así como un objeto visual tipo dibujo para el logo de la empresa usado en los albaranes o las facturas u otra opción que suelo usar y que es crear una tabla llamada CONFIGURACION en la que se crean los diferentes campos que necesite para definir los datos generales de la empresa, incluidos uno o varios campos objeto dibujo en los que guardar distintos logos.

    Con ella, nos evitamos tener que tocar con le vDeveloper un objeto dibujo si la empresa cambia de logo, por ejemplo. Para usarla desde las tablas de las cabeceras de Albaranes o Facturas, simplemente, hacemos un puntero a maestro en cada una de ellas a la tabla configuración, con lo que tenemos acceso a todos los campos sobre todo a la hora de imprimir los informes.

    Para rellenar inicalmente los valores de la única ficha de esta tabla, podemos lanzár un proceso llamado desde el AUTOEXEC-ON -INIT que tenga las siguientes lineas

    Proceso de configuracionEn este mismo proceso podríamos controlar si se ha dado valor a al menos una de las variables globales donde se guardan los IVAS y mostrar el formulario de Configuración en el que tendremos los controles de edición de las variables.

    Al mismo nivel que Cargar lista->CONF…..                     

    añadimos

    if $IVA-1$=0

    cargar lista , CONFIGURACION, CODIO

    seleccionar ficha por posición->1

    modificar ficha seleccionada con formulario, CONFIGURACION

    Vayamos con las primeras actualizaciones. Desde la tabla de Lineas de facturas haremos actualizaciones a los campos donde guardamos las distintas bases imponibles, dependiendo del valor del IVA que se aplique al artículo de la linea. Para ello vamos a la carpeta de actualizaciones e insertamos una nueva. Toda actualización necesita un puntero a una ficha para poder actualizar un valor de la tabla apuntada con un valor de un campo de la tabla origen. En este caso, tenemos el puntero a maestro desde la tabla Lineas de Facturas a la tabla Cabeceras. Usaremos este puntero para actualizar las tres bases imponibles, dependiendo del tipo de IVA que se haya usado para la linea.

    Actualización a MaestroPara ello usaremo la fórmula condición para modificar. En el caso editado de la base 1, si el iva de la lineas es igual al guardado en la variable IVA 1 lanzaremos la actualización, modificando el campo BASE1, del modo acumular ( sumar a lo que ya había ) lo que está guardado en el campo IMPORTE SIN IVA.

    Para el resto de los campos BASE, lo único que variará será la condición de modificación además del campo a modificar.

    Si borramos, o modificamos una linea afectando el valor del campo IMPORTE SIN IVA la actualización, ella sóla y sin programar nada más, se encargará de corregir los datos anteriores y salvaguardar los nuevos

    Hagamos ahora una actualización a través de un puntero a tabla de datos indirecta real

    En la tabla Cabeceras de Facturas creamos un puntero indirecto a la tabla IVAS Repercutidos a través del índice de clave única AÑOS  de esta última tabla, resolviendo el AÑO del origen que el AÑO del destino, y activando el flag Dar de alta si no existe por si es la primera factura de un año determinado que introducimos y por tanto en la tabla IVAS Repercutidos aún no hay creado un registro para ese año.

    Puntero

    Sólo nos queda lanzar una nueva actualización a través de este puntero para que nos lleve los ivas repercutidos en los trimestres adecuados de cada año.

     Para ello creamos una nueva actualización a través del puntero indirecto.La haremos para el primer trimeste del IVA 1.

    La condición será que el trimestre de la fecha sea el 1 y actualizaremos el campo TRIMESTRE 1 IVA 1 con lo que haya guardado en el campo IMP-IVA 1  de la tabla Cabeceras de facturas.

    Lo mismo haremos ,cambiano la condición para los diferentes trimestes e IVAS.

    Podríamos también hacerlo para los doce meses de cada año. Sólo tenemos que hacer 12 campos por IVA y montar las actualizaciones de la misma forma.

     

    Actualizar por puntero indirecto

    Si tenemos también implementada a parte de compras en nuestra aplicación, podríamos llevar el IVA soportado en la misma tabla y llevar desde la Cabecera de Facturas de Compra todos los IVAs soportados por trimestre o por meses de cada año, y a la vez un campo fórmula en el que nos calculara la diferencia entre el soportado y el repercutido.

    Como hemos visto, con las actualizaciones y los punteros y sin escribir ni una sola linea de código, hemos hecho toda la labor, todo en la parte izquiera del vDeveloper. Combinando toda la potencia de los componentes de las tablas con un buen análisis del problema, tenemos el 90% de la aplicación hecha, a falta de hacer los objetos visuales y de resolver cosas que Velneo no tiene implementadas de forma tan directa pero que haremos con los procesos.

    Actualizacion puntero indirecto

    vDeveloper: vayamos por partes (v)

    El tercer elemento de una tabla son los triggers o eventos de tablas.

    Con ellos vamos a poder lanzar procesos que se ejecutarán siempre con origen una ficha de una tabla. Van a sernos muy útiles a la hora de hacer comprobaciones, de modificar valores de campos dependiendo de las condiciones que establezcamos…. además se dá la ventaja de que tenemos la seguridad de que siempre se ejecutan pues no dependen de una pérdida de foco o de que el usuario haya pulsado un determinado botón.

    Los eventos de tablas o triggers son de tres tipos: anteriores a , internos a y posteriores a.  A su vez se pueden lanzar desde tres sitios distintos: en un alta, en una modificación y en una baja. Por lo tanto, mezclando ambas cosas tendremos nueve maneras o formas de lanzarlos

    Tipos de triggers ¿En qué orden son lanzados los triggers?

    1. Trigger anterior

    2.La acción asociada: alta, modificación o baja

    3. Trigger interno

    4. Actualizaciones, que veremos a continuación

    5. Trigger posterior.

    A la hora de usar los triggers debemos de tener en cuenta varias particularidades: en la versión C/S no incluir  nada que implique la intervención del usuario, por ejemplo, visualizar un mensaje, mostrar un formulario, una pregunta, petición de un dato, etc. El motivo es que este tipo de operaciones se llevan a cabo en el Servidor, por lo que el mensaje o el formulario no serían presentados en el Cliente, sino en el propio Servidor. Si en un evento de tabla se incluyese algo que implicase la intervención del usuario, será obviado por el Servidor. Sólo en los triggers anteriores a se pueden cambiar valores de campos de las fichas , si ponemos una instrucción de proceso “modificar campo” ésta sólo se ejecutará si el trigger es anterior a.

    A %d blogueros les gusta esto: