< Características avanzadas > Programas xjs > Extensiones de acceso a datos

Extensiones de acceso a datos

<< Click to Display Table of Contents >>

Navegación:  Características avanzadas > Programas xjs >

Extensiones de acceso a datos

Contenido

  El objeto base y el objeto consulta

  Transacciones

  Documentador de tablas

  El objeto balance

  El objeto filtro

  Obras/Proyectos: El objeto presupuesto

 

El objeto base y el objeto consulta

Los programas xjs se comunican con las bases de datos de Sigrid (.sig) por medio del objeto base. Una referencia a este objeto se obtiene invocando al método base según la siguiente sintaxis:

var bd = base ([n]);

Si no se especifica ningún argumento, el objeto base referencia la base de datos actualmente abierta en la ventana principal Sigrid1. Si se especifica "0", como argumento, el método base solicita un origen de datos al que referenciar.

Para referenciar una base de datos distinta de la actualmente abierta en ventana principal, se creará el objeto base con el argumento 0, y a continuación se utilizará el método abre, indicando como argumento la cadena de conexión a la base de datos que se quiere referenciar. Por ejemplo, para abrir una base de datos Access llamada Demo.sig, que se encuentra en c:\Sigrid3:

var db = base (0);

db.abre ("c:\\Sigrid3\\Demo.sig")

El método consulta del objeto base permite ejecutar sentencias de interrogación o consulta a la base de datos, es decir sentencias SELECT construidas según la sintaxis SQL, retornando un objeto que almacena el conjunto de registros (recordset) resultado de la consulta.

var rs = bd.consulta (sqlselect);

El conjunto de registros u objeto consulta suministra los métodos necesarios para poder recorrer los registros recuperados, detectar cuando se alcanza el último registro, recuperar los valores de los campos o columnas del registro, etc. El tema referencia de acceso a datos contiene la lista de los métodos y propiedades del objeto base y del objeto consulta.

Una vez ejecutada la consulta la propiedad BOF (begin of file) valdrá 0 si se recuperó algún registro y 1 en caso contrario. Si se recuperó algún registro el objeto queda posicionado en el primero de ellos pudiendo recuperar los valores almacenados en cada campo del registro mediante el método campo.

rs.campo (numerocol | nombrecol);

el argumento que recibe puede ser el número de columna correspondiente al campo en la sentencia SELECT comenzando por cero (0), o bien el alias de columna especificada igualmente en la sentencia SELECT.

El siguiente código define la variable bas, asignándole el objeto base correspondiente a la base de datos abierta en la ventana Sigrid1, en el momento de ejecutarse el programa. Recupera los campos ide, cod y res de los registros de la tabla de conceptos en los que el campo tip vale 2. Y muestra en el Block de Notas los valores de ide, cod y res correspondientes al primer registro recuperado.

var bas = base();

var rs = bas.consulta ("Select ide, cod, res as resumen From con Where tip = 2");

if (!rs.BOF)

{

   write (rs.campo (0) + "\t");        // identificador

   write (rs.campo (1) + "\t");        // cod

   write (rs.campo ("resumen"));

}

Los métodos muevepri, muevesig, mueveant, mueveult, posicionan la consulta en el primer registro, en el siguiente, en el anterior y en el último dentro del conjunto de registros. Si se invoca el método muevesig una vez que se ha alcanzado el último registro, la propiedad EOF (end of file) valdrá 1 o verdadero.

El ejemplo que sigue recupera todos los campos de todos los registros de la tabla de conceptos y ejecuta un bucle para recorrer el conjunto de registros  hasta al alcanzar el último registro

var bas = base();

var rs = bas.consulta ("Select * From con");

while (!rs.EOF)

{

   for (i=0; i < rs.columnas; i++)

       write (rs.campo(i) + "\t");

   writeline ();

   rs.muevesig();

}

 

Transacciones

El método transaccion del objeto base permite iniciar una transacción en la base de datos representada por el objeto base:

var bas = base();

var tra= bas.transaccion();

tra.inicia();

bas.ejecuta ("UPDATE ...");

...

tra.termina();

Los cambios a realizar en la base de datos como consecuencia de la ejecución de las sentencias comprendidas entre el método inicia y termina se realizarán como uno solo, de forma que si se produce un error no se producirá ningún cambio.

El uso de transacciones asegura la integridad de los datos almacenados, de forma que no se produzcan inconsistencias.

Por ejemplo, en el procedimiento de cobro y pago de efectos distribuido con la aplicación se utilizan transacciones. Este procedimiento, por cada efecto de cobro o pago seleccionado en la ventana principal, tiene que generar una asiento contable y cambiar el estado del efecto. Estos dos cambios, alta del asiento y cambio de estado del efecto, han de llevarse a cabo en una transacción, de lo contrario podría producirse una caída de corriente eléctrica y quedar grabado el asiento sin que se hubiera cambiado el estado del efecto.

 

Documentador de tablas

El objeto consulta tiene una serie de miembros que permiten conocer el nombre, tipo y tamaño de los campos recuperados. Para ilustrar estos métodos el siguiente ejemplo muestra como obtener un informe con los nombres, tipos y tamaños de los campos de una tabla, el nombre de la tabla a documentar lo recibe como parámetro y utiliza el objeto impresor para mostrar la información. El tema Parámetros especifica la sintaxis para el manejo de parámetros en los programas xjs y en el tema extensiones de impresión se explican los principales métodos del objeto impresor.

El ejemplo comienza declarando el parámetro tabla, si el usuario no especifica un nombre de tabla se interrumpirá la ejecución del programa. En caso contrario llama al método consulta ejecutando la sentencia SELECT sobre la tabla recibida en el parámetro. A continuación define el array o matriz dbTypes de dos dimensiones para poder traducir el código retornado por el método camtipo a un literal representativo del tipo de dato definido para el campo. Seguidamente muestra una cabecera con el nombre de la tabla y los literales Nombre, Tipo, Tamaño. Ejecuta un bucle sobre el total de columnas de la tabla mostrando el nombre de la columna o campo retornado por camnombre, el literal correspondiente al tipo de campo y por último el tamaño retornado por camtamaño.

/************************************************************************

*   Documentador de tablas

*/

var tabla = ""      //// Nombre de la tabla p.e. con [[""]]

var DB = base

var imp = impresor

 

if (tabla == "")

{

   diaavisa ("Sigrid", "No se ha especificado el parámetro Nombre de la tabla");

   salir();

}

 

var rs = DB.consulta("Select * From " + tabla)

 

var dbTypes = new Array (8)

for (i=0; i <=8; i++)

   dbTypes [i] = new Array (1);

dbTypes [0][0] = 2; dbTypes [0][1] = "dbByte";

dbTypes [1][0] = 4; dbTypes [1][1] = "dbLong";

dbTypes [2][0] = 7; dbTypes [2][1] = "dbDouble";

dbTypes [3][0] = 8; dbTypes [3][1] = "dbDate";

dbTypes [4][0] = 10; dbTypes [4][1] = "dbText";

dbTypes [5][0] = 11; dbTypes [5][1] = "dbLongBinary";

dbTypes [6][0] = 12; dbTypes [6][1] = "dbMemo";

dbTypes [7][0] = 17; dbTypes [7][1] = "dbVarBinary";

 

imp (tabla, "l3 ln");

imp.linea ();

imp.tabla (". . .");

imp ("Nombre");imp("Tipo");imp("Tamaño");

imp.linea ("ln b1");

 

for (var i = 0; i < rs.columnas; i++)

{

   imp(rs.camnombre(i));

   var tipo = "";

   for (j=0; j<8;j++)

       if (parseInt(dbTypes[j]) == rs.camtipo(i))

       {

           tipo = dbTypes[j][1];

           break;

       }

   if (tipo == "")

       imp ("Desconocido");

   else

       imp (tipo);

   imp(rs.camtamaño(i));

   imp.linea();

}

 

El objeto balance

Los balances para la presentación anual de cuentas se definen en Sigrid mediante los archivos de definición de balances (.bal). Para que los programas xjs puedan procesar estos archivos y mostrar los resultados, la aplicación suministra el objeto balance.

Para crear una referencia a un objeto balance hay que invocar el método balance del objeto base, que recibe como argumento un nombre de archivo de definición de balance.

var bas = base ();

var bal = bas.balance (archivo.bal);

Los métodos calcula, calculafil y calculapre del objeto balance interpretarán las expresiones contenidas en el archivo de definición de balance y calcularán los saldos o presupuestos resultantes.

El método numero retorna el número total de líneas de definición existentes en el archivo, con este número se puede ejecutar un bucle para recuperar el tipo de línea, nivel, código, descripción, importe y expresión de cada línea.

El siguiente ejemplo abre el archivo de balance balpygn.bal, volcando su contenido a un archivo de texto mediante el método write (referencia de extensiones básicas).

var bas = base ();

var bal = bas.balance ("balpygn.bal");

bal.calcula();

var t = "";

for (i=0; i<bal.numero;i++)

{  t = (bal.tip(i) == 0) ? "" : (bal.tip(i))==3 ? "T" : "S";

   if (t != "")

       write (t);

   write (bal.niv (i) + "\\ ");        // nivel

   write (bal.cod (i) + "\\ ");        // código

   write (bal.pyd (i) + "\\ ");        // descripción

   write (bal.imp(i) + "\\ ");        // saldo calculado

   write (bal.exp (i) + "\\ ");        // expresión

   writeline ();

}

El archivo de definición de balance puede referenciar cuentas tanto financieras como analíticas, por lo que el objeto balance suministra métodos para ambos casos. El tema referencia de extensiones de acceso a datos contiene la lista detallada de los métodos del objeto balance.

 

El objeto filtro

El objeto filtro representa un filtro de apuntes, bien financieros u analíticos. Está programado para facilitar la consulta de saldos de las cuentas desde los programas xjs. Se crea un objeto filtro utilizando el método de igual nombre del objeto base, a continuación se invocará el método cenabre para establecer el periodo para el filtro y ejecutar la consulta de apuntes a la base de datos. Los métodos: debe, haber y saldo del objeto filtro retornarán el debe, haber o saldo respectivamente, de la cuenta que reciben como argumento, para el periodo establecido.

El siguiente ejemplo crea un filtro de apuntes analíticos para el ejercicio 2003, y obtiene el saldo de las cuenta cuyo código comienza por 6 y por 7, para el centro de coste de código CEN001.

var bas=base();

var filtro=bas.filtro()

filtro.cenabre ("", 20030101, 20031231)

var compras=filtro.saldo("CEN001.6")

var ventas=filtro.saldo ("CEN001.7")*(-1.0)

El tema referencia de extensiones de acceso a datos contiene la lista de los métodos del objeto filtro.

 

Obras/Proyectos: El objeto presupuesto

El presupuesto de las obras se estructura en niveles de capítulos y subcapítulos que se componen de partidas de obra, de forma que el importe de un capítulo será la suma de los importes de las partidas que lo componen. A su vez el precio de las partidas se calcula como suma del importe unitario de los elementos de su descomposición. Un descompuesto de una partida contribuirá al precio de la misma en una cantidad que se conoce como rendimiento.

Para facilitar el manejo de los presupuestos de obra desde los programas xjs, la aplicación suministra el objeto presupuesto.

Las partidas presupuestarias están almacenadas en la base de datos en la tabla obrparpar, el campo obride relaciona la partida con la obra a la que pertenece, la estructura de estas partidas se almacena en el campo padide, que contiene el ide del capítulo padre de una partida dada.

Los precios y mediciones de las partidas, correspondientes a un ámbito-fase/versión, se almacenan en la tabla obrparpre. La lectura del presupuesto de una obra desde el programa xjs, accediendo directamente a estas tablas sería mucho más lenta de ejecutar que utilizando el objeto presupuesto, y además requeriría implementar las funciones para el cálculo de los importes de capítulos y partidas.

Para utilizar un objeto presupuesto:

var bas=base();

var pre=bas.presupuesto()

Este objeto se asocia a una obra determinada invocando el método abre, que recibe como argumento el ide de la obra y abre la estructura presupuestaria de dicha obra. Opcionalmente puede abrirse para un contrato, y expediente determinado, retornan sólo los elementos (capítulos y partidas) asociadas al contrato y expediente:

pre.abre (obride)    o     pre.abre (obride, ctride)    o pre.abre (obride, ctride, expide)

Una vez abierto el presupuesto , la propiedad pre.numero almacena el número de elementos y el método pre.partida(n) retorna el objeto partida correspondiente al elemento n del presupuesto. Así el primer capítulo de la estructura presupuestaria será pre.partida(0).

Cada partida tiene una serie de propiedades tales como su nivel, código, resumen, etc.

Para obtener los precios y mediciones de una partida en un ámbito-fase/versión de la obra se invoca el método presupuestos:

pre.presupuestos (ambide, fase/versión)

siendo ambide el ide del ámbito para el que se calcula el presupuesto y fase/versión el número de fase o versión.

Los ámbitos admiten fases o versiones dependiendo de la clase que tengan establecida en la tabla auxiliar de ámbitos

Clase                      

Proyecto -> Versiones

Estudio -> Versiones

Oferta -> Versiones

Planificación-Máster -> Versiones

Coste -> Fases

Venta -> Fases

Valorado-Producción -> Fases

Las fases son dependientes de la obra y se almacenan en la tabla obrfas, las versiones dependen de la obra-ámbito, y se almacenan junto con las fases en la tabla obrfasamb. Los ámbitos se identifican por su ide en la tabla auxiliar auxobramb, las fases y versiones se identifican por su número, siendo la fase cero especial, ya que se considera la fase correspondiente al presupuesto total previsto.

El método presupuestos establecerá las propiedades de cada elemento (capítulo/partida) del presupuesto: canant (cantidad anterior), canori (cantidad origen), can (cantidad parcial), pre (precio), imp (importe), impori (importe origen), impinc (importe incurrido).

Al imprimir o volcar en una consulta las mediciones, precios e importes del presupuesto de obra hay que tener en cuenta el número de decimales definidos en la obra para cada uno de estos datos. Las propiedades deci, decr, decc y decp, almacenan los decimales establecidos para: importes, rendimientos, cantidades y precios. Que pueden no coincidir con el número de decimales establecidos en los parámetros de la empresa.

El siguiente ejemplo una vez abierto el árbol presupuestario, calcula el presupuesto para un ámbito-fase y  recorre los capítulos-partidas para imprimir: el código, descripción, unidades, precio e importe a origen de cada partida.

var imp=impresor(cni)

var bas=base();

...

var pre=bas.presupuesto()

pre.abre(obride)

pre.presupuestos (ambide, fase)

for (var i=0;i<pre.numero;i++) {

   var par=pre.partida(i)

   imp (par.cod)

   imp (par.res)

   imp (formato (par.canori, pre.decc), "a2")

   imp (formato (par.pre, pre.decp), "a2")

   imp (formato (par.impori, pre.deci), "a2")

   imp.linea()  

}

Los documentos de compra/venta (albaranes, facturas), partes de trabajo y hojas de gastos se asocian a las partidas presupuestarias de una obra, quedando almacenado en sus líneas de detalle el ide de la partida a la que corresponden. Para determinar el importe de estos documentos imputados a una partida, tanto el objeto presupuesto como el objeto partida suministran el método consulta.

pre.consulta (N, sql)

Pueden ejecutarse varias consultas que se identificarán por un número entero, N, de forma que el método consulta aplicado a una partida recibe como argumento este número. La cadena que se pasa al método consulta como segundo argumento será un SELECT en el que el primer campo a recuperar debe ser siempre el ide de la partida, el segundo será el importe que se quiere obtener.

El siguiente ejemplo, es un informe de impresión rápida, que imprime las partidas presupuestarias a las que se han imputado albaranes de compra, mostrando el código, resumen, y el importe imputado, correspondientes al presupuesto de la obra seleccionada en ventana principal.

var bas=base()

var imp=impresor()

var conl=panselactual

var obride=conl[0]

var sql="SELECT paride, SUM(tot) "+

        "FROM dcapro "+

        "WHERE dcapro.obride="+obride+

        " GROUP BY paride"

var pre=bas.presupuesto(obride)

if (pre.numero) {

   pre.consulta(7, sql)

   for (i=0;i<pre.numero;i++) {

       par=pre.partida(i)

       tot=par.consulta(7)

       if (tot) {

            imp (par.cod)

            imp (par.res)

            imp (formato(tot, 2), "a2")

            imp.linea()

       }

   }

}

 

La descomposición de las partidas, al igual que las mediciones desglosadas, son dependientes del ámbito-fase/versión, y se almacenan como cadena de texto en la tabla obrparpre. Sin embargo, la planificación de compras, que se consulta en la ficha de las partidas cuando se ha seleccionado el ámbito de la clase Coste, es única para la obra, constituyendo las líneas de detalle del documento de planificación de compras (dcnpro).

Cada objeto partida de un presupuesto tiene a su vez un objeto descompuesto, que permite obtener los datos de la descomposición de la partida o de la planificación de compras de la obra.

El siguiente ejemplo es un informe de impresión rápida, que muestra un diálogo en el que especificar el ámbito-fase presupuestarios, e imprime las partidas del presupuesto de la obra-ámbito-fase seleccionados y su descomposición:

 

COMDatos

 

var tit="Ejemplo de pre.partida.descompuesto"

var bas=base()

var imp=impresor()

var conl=panselactual

var obride=conl[0]

var obrres=bas.camlee("con", "res", obride)

// Lee los ámbitos definidos para la obra

var ambitos=bas.buscaN("Select ambide, auxobramb.res "+

                                   "from obramb, auxobramb Where obramb.obride="+obride+

                                   " and auxobramb.ide=obramb.ambide Order by pos")

var ambt=""

for (var i=0;i<ambitos.length;i++)

           ambt+=ambitos[i][1]+((i<ambitos.length-1)?";":"")

// Lee las fases de la obra

var fast="Fase 0 (Previsto);"

var fases=bas.buscaN("Select fasnum, res from obrfas where obride="+obride+" order by fasnum")

for (var i=0;i<fases.length;i++)

       fast+=fases[i][1]+((i<fases.length-1)?";":"")

// Diálogo para seleccionar ámbito y fase

continua=true

while (continua) {

   var d=dialogo()

   d.texto(obrres, "ln")

   d.texto ("", "l0")

   d.opcionL (100, "Ambito", ambt, 20)

   d.opcionL (110, "Fase", fast, 20)

   if (d.crea("Descomposición", "OBRPARDES", 1)) salir()

   // Recupera el ámbito seleccionado

   var ambito=d.valor(100)

   for (var i=0;i<ambitos.length;i++)

   if (ambito==ambitos[i][1]) {ambito=ambitos[i][0];break}

   if (i==ambitos.length) diaavisa("Seleccionar un Ambito")

   else continua=false

}

// Recupera el número de fase seleccionada (por defecto 0)

var fase=d.valor(110)

for (var i=0;i<fases.length;i++)

       if (fase==fases[i][1]) {fase=fases[i][0];break}

if (i==fases.length) fase=0

 

var pre=bas.presupuesto(obride)

pre.presupuestos (ambito, fase)

var decr=pre.decr // decimales para rendimientos

var decp=pre.decp // decimales para precios

for (i=0;i<pre.numero;i++) {

    par=pre.partida(i)

   imp.tabla()

   imp (par.cod)

   imp (par.res)

   imp.linea("ln")

   for (var d=0;d<par.desnumero;d++) { // Descomposición

       var des=par.descompuesto(d)

       imp.tabla()

       imp (des.unimed)

       imp (des.res)

       imp (formato(des.ren, decr), "a2")

       imp (formato(des.pre, decp), "a2")

       imp (formato(des.ren*des.pre, decp), "a2")

       imp.linea ()

   }

}

El tema referencia de extensiones de acceso a datos contiene la lista de los métodos y propiedades del objeto presupuesto, partida y descompuesto.