Cómo implementar en nuestras aplicaciones las facturas serializadas, según la serie elegida la aplicación generará el contador correspondiente. Utilizaremos Delphi como lenguaje de programación, aunque es aplicable a cualquier lenguaje de programación.
Serialización de facturas y albaranes
La serialización de facturas y albaranes es una práctica muy común en casi todas las empresas que requieren de una aplicación de facturación. Por ejemplo, se recomienda que las facturas de abono tengan su propio contador, independiente del contador general de las facturas «normales». Para implementar esta distinción en una aplicación informática podremos utilizar la serialización que, además, nos servirá para otros muchos usos. Por ejemplo, para llevar contadores independientes según el tipo de factura.
Como ya hemos comentado, utilizaremos Delphi cómo lenguaje de programación y MySQL como motor de base de datos. Aunque la base de este manual sirve para cualquier lenguaje de programación (con los cambios pertinentes) y para cualquier motor de base de datos.
Preparar la base de datos para la serialización en la tabla de facturas
En primer lugar necesitaremos dos tablas en la base de datos para guardar los contadores y las series de las facturas/albaranes. En una tabla guardaremos las series disponibles y la tabla a la que se podrán asignar, a continuación os mostramos el script sql necesario para crearla:
1 2 3 4 5 6 7 |
CREATE TABLE serie ( codigo int(10) unsigned NOT NULL auto_increment, nombre char(2) NOT NULL, tabla varchar(50) NOT NULL, PRIMARY KEY (codigo), UNIQUE KEY serie_tabla_nombre USING BTREE (nombre, tabla) ) |
Por otro lado necesitaremos una segunda tabla donde se guardará el número por el que va cada serie de cada tabla, con el script sql siguiente:
1 2 3 4 5 6 7 8 |
CREATE TABLE contador ( codigo int(10) unsigned NOT NULL auto_increment, tabla varchar(100) NOT NULL, contador int(10) unsigned, serie char(2) NOT NULL, PRIMARY KEY USING BTREE (codigo), UNIQUE KEY contador_tabla_serie USING BTREE (tabla,serie) ) |
Lógicamente necesitaremos también una tabla para alojar las facturas, con el siguiente script SQL de creación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
CREATE TABLE factura ( codigo int(10) unsigned NOT NULL auto_increment, numexpediente varchar(15), numerofactura varchar(25) NOT NULL, serie char(2) NOT NULL, codigocliente int(10), matricula varchar(35), cobrado char(1), fechacobro datetime, importetotal float, clientecontacto varchar(100), fechacarga datetime, telefono varchar(40), email varchar(100), observacion varchar(255), porcentajebeneficio float, importebeneficio float, importetransportista float, codigotransportista int(10), pagadotransportista char(1), fechapagotransportista datetime, codusuarioa int(10) unsigned, codusuariom int(10) unsigned, fechaa datetime, fecham datetime, pesonetototal float, envasestotales float, paletstotales float, fecha datetime, fechavencimiento datetime, PRIMARY KEY USING BTREE (codigo), UNIQUE KEY factura_numerofactura USING BTREE (numerofactura, serie) ) |
En la tabla «factura», podremos observar que los dos campos utilizados para la serialización son «numerofactura» y «serie».
Para crear estas tablas podremos utilizar la aplicación AjpdSoft Administración Bases de Datos.
Componentes, controles, código fuente en Delphi 6 para serie de facturas y albaranes
Una vez creadas las tablas necesarias en la base de datos para la serialización de las facturas y albaranes, pasaremos ahora a explicar cómo programar cada opción en la aplicación que estemos desarrollando:
- Crearemos un formulario para la inserción y modificación de las series de la factura:
Se trata del formulario donde podremos introducir la Serie y la Tabla para la que la utilizaremos, en nuestro caso para la tabla «Factura». Los componentes de este formulario estarán enlazados con la tabla «Serie» creada anteriormente.
- Crearemos un formulario para la inserción y modificación de los contadores:
Este formulario contendrá los controles enlazados con la tabla «Contador» creada anteriormente. Este formulario mostrará el contador (número) y la serie, ambos se generarán de forma automática desde el formulario de la factura. Desde este formulario podremos modificarlos en caso necesario.
- Crearemos un formulario para la inserción y modificación de las facturas:
En este formulario será donde utilicemos las series y el contador, a continuación os mostramos el código fuente en Delphi del código que insertaremos en el evento OnClick del botón bGenerarNumFactura que es el que hay en la parte derecha del campo del número de factura. Este botón generará el número de forma automática según la serie introducida en el campo anterior (txtSerie):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
procedure TformGFactura.bGenerarNumFacturaClick( Sender: TObject); var ano, mes, dia : word; begin if txtSerie.Text = '' then begin MessageDlg('La serie de la factura debe tener un valor.', mtWarning, [mbok], 0); txtSerie.SetFocus; end else begin decodeDate(now, ano, mes, dia); md.tFacturanumerofactura.AsString := llenarCadena(floattostr(generarNumeroSerie ( txtSerie.Text, vtTablaFactura)), 6,'0', false) + '/' + inttostr(ano); end; end; |
Donde:
- txtSerie: es el TDBComboBox que contendrá un desplegable con las series disponibles para la tabla actual (Facturas).
- md.tFactura: es el componente TTable enlazado con la tabla «Facturas», donde se guardan los datos de la factura.
- llenarCadena: es una función que rellena una cadena dada con el carácter indicado y con el tamaño indicado. A continuación os mostramos el código de esta función:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function llenarCadena (cadena : string; numero : integer; caracter : Char; derecha : Boolean) : string; begin while Length(cadena) < numero do begin if derecha then cadena := cadena + caracter else cadena := caracter + cadena; end; llenarCadena := cadena; end; |
Esta función generará un número con el formato: 000032/2007.
- generarNumeroSerie: esta función accede a la tabla «Contador» y obtiene el número por el que vaya el contador según la serie y la tabla que se le pase como parámetro. También incrementa el contador de esta tabla y serie. El código de esta función es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
function generarNumeroSerie ( serie, tabla : string) : integer; var contador : integer; begin result := 1; with md.tcContador do begin Close; //obtenemos el contador de //la tabla contadores SQL.Clear; SQL.Add('SELECT *'); SQL.Add('FROM ' + vtTablaContador); SQL.Add('WHERE tabla = :pTabla and serie = :pSerie'); ParamByName('pTabla').DataType := ftString; ParamByName('pTabla').AsString := tabla; ParamByName('pSerie').DataType := ftString; ParamByName('pSerie').AsString := serie; Open; if not (FieldByName('Contador').AsInteger = 0) then begin try contador := FieldByName('contador').AsInteger + 1; //Incrementamos el contador de la tabla contadores Close; SQL.Clear; SQL.Add('UPDATE ' + vtTablaContador + ' SET contador = :pContador' + ' WHERE tabla = :pTabla' + ' and serie = :pSerie'); ParamByName('pContador').DataType := ftInteger; ParamByName('pContador').AsInteger := contador; ParamByName('pTabla').DataType := ftString; ParamByName('pTabla').AsString := tabla; ParamByName('pSerie').DataType := ftString; ParamByName('pSerie').AsString := serie; ExecSQL; close; result := contador; except Close; result := 1; MessageDlg ('El código no ha podido ' + 'generarse automáticamente.', mtError, [mbOK], 0); end; end else //si no existe el registro de //contador para la tabla actual, lo creamos begin try Close; SQL.Clear; SQL.Add('INSERT INTO ' + vtTablaContador + ' (tabla, serie, contador) ' + ' VALUES (:pTabla, :pSerie, 1)'); ParamByName('pTabla').DataType := ftString; ParamByName('pTabla').AsString := tabla; ParamByName('pSerie').DataType := ftString; ParamByName('pSerie').AsString := serie; ExecSQL; result := 1; Close; except Close; MessageDlg ('El contador no se ha ' + 'guardado correctamente.', mtError, [mbOK], 0); end; end; end; end; |
Donde:
- md.tcContador: es el TTable enlazado con la tabla «Contador», donde se guarda un registro por cada serie y factura con el número por el que vaya actualmente el contador.
La aplicación funcionando tendrá este aspecto: