Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Saltos en secuencia de numero de factura.... (https://www.clubdelphi.com/foros/showthread.php?t=65817)

ronimaxh 15-01-2010 01:02:20

Saltos en secuencia de numero de factura....
 
Un saludos colegas del club, tengo una aplicacion hecha en delphi 2009 y firebird 2.1 con ibx.

Me esta pasando algo muy raro ultimamente, para generar mi numero de factura lo hago de la siguiente manera:
Código Delphi [-]
procedure Tfrmprincipal.genera_numero_fact;
begin
  with frmdata.st do
       begin
        DecodeDate(date,periodo,mes,dia);
         st_ctr:=false;
         if cod_tpo_ncf='0' then
            begin
              sql.Text:='select max(numero)as numero,max(periodo)as periodo from tb_cd_fact_t where periodo='+floattostr(periodo)+'and cod_tipo_ncf='+QuotedStr(cod_tpo_ncf);
              st_ctr:=true;
            end
         else
         sql.Text:='select max(numero)as numero,max(periodo)as periodo from tb_cd_fact_t where periodo='+floattostr(periodo)+'and cod_tipo_ncf >0 ';
         open;
         cont:=0;
         if not FieldByName('numero').IsNull then
            begin
              cont:=FieldByName('numero').Value;
              if periodo=FieldByName('periodo').Value then
                 begin
                   cont:=cont+1;
                   numero:=inttostr(cont);
                   numero:=StringOfChar('0',7-length (numero))+numero;
                   frmfactura.num_fact_edit.Text:=numero;
                 end
                 else
                 begin
                   numero:='1';
                   numero:=StringOfChar('0',7-length (numero))+numero;
                   frmfactura.num_fact_edit.Text:=numero;
                 end;
            end
            else
            begin
              numero:='1';
              numero:=StringOfChar('0',7-length (numero))+numero;
              frmfactura.num_fact_edit.Text:=numero;
            end;
       end;
end;

Nota: Derrepente me da saltos y me deja hueco en numero.
Realmente no se aque se deba, solo busco al maximo en la consulta,
no se si seran los componentes ibx esto esta muy raro. Cuando hago ciertas prueba generando numero de factura no ocurre y en produccion si.

Nota2: se que lo generadores me dejan muchos huecos y tambien he notado que cuando esto pasa produce esos saltos no se como controlarlos, alguna ayuda les agradesco.

Casimiro Noteví 15-01-2010 01:21:41

¿El programa permite eliminar una factura?, ¿puede que sea el problema?

Cañones 15-01-2010 02:29:00

Hola.
No soy muy bueno leyendo código ajeno, pero creo que buscas el número máximo y le sumas uno.
Yo utilizo una tabla en la DD.BB con nombre (nombre del comprobante) y valor, que es el último valor.
Cuando se confirma la venta, genero el número de comprobante. Accediendo al valor por medio de un dataset y asignado el nuevo valor. Es útil para el caso de concurrencias.
Con éste método es muy poco probable que haya huecos en los números de comprobantes.

Si querés te mando un mail con un apunte que lo explica muy bién. Es de un profesor de mi facultad.

Saludos a todos.

ronimaxh 15-01-2010 02:46:54

Gracias por contestar, la facturas no se eliminan solo se anulan.
Cañones favor de enviar el correo que ayuda reforzar.

Cualquier colega que pueda ayudar agradezco.

mamcx 15-01-2010 03:16:48

El primer problema que tienes es que generas el codigo en el cliente y no en la BD.

Deberias usar un generador. Definitivamente.

La razon del porque pueden haber "huecos" si hay acceso multiusuario es que varios clientes pueden solicitar una nueva numeracion al tiempo.

Dos clientes solicitan el siguiente maximo y a ambos se les da la misma respuesta. Luego, el usuario se cansa, anula, abandona o cancela.

Para hacer de un cuento largo uno corto, estos códigos deben ser generados en el instante preciso del INSERT. No se deben generar antes que le de al usuario tiempo de llenar datos y luego cancelar la acción. Eso da huecos.

El uso de la tabla no necesariamente te resuelve el asunto. Es el *momento* elegido para hacer el avance del consecutivo y si *bloqueas* la generación del consecutivo teniendo presente las implicaciones del acceso recurrente.

En términos de programación OO lo que estas buscando es un Singleton (http://es.wikipedia.org/wiki/Singleton), un único punto de acceso y alteración de datos. Seria algo asi, traducido de OO a como es un manejo de datos:

*TODO DENTRO DE LA BD, EN UNA TRANSACCION*
Código:

BLOQUEAR FILA/TABLA/GENERADOR DE NUMERACION

OBTENER SIGUIENTE

AUMENTAR

DESBLOQUEAR

RETORNAR


ronimaxh 15-01-2010 04:05:02

Gracias amigo por responder, ese codigo que puse es llamado en el instante del inicio del insert frmprincipal.genera_numero_fact(esta es una rutina).

Tambien los generadores dejan huecos.

Casimiro Noteví 15-01-2010 04:26:28

Cita:

Empezado por ronimaxh (Mensaje 350782)
la facturas no se eliminan solo se anulan.

¿Y en qué consiste esa anulación?

ronimaxh 15-01-2010 05:39:08

las facturas cuando se anulan solo cambia a status I (inactiva).

Neftali [Germán.Estévez] 15-01-2010 10:23:42

¿Cuantos usuarios trabajan de forma concurrente?
¿En qué momento insertas la factura?
¿Utilizas transacciones?
¿La insertas utilizando SQL o componentes DataAware?

marcoszorrilla 15-01-2010 10:26:33

Sería conveniente que en vez de por correo se ponga el código aquí en el Foro, así si la solución resulta interesante alguién más pueda beneficiarse.

Un Saludo.

ronimaxh 15-01-2010 14:24:00

De momento un usuario, luego se me conectaran más.
Inserto lo factura cuando ha eligido un producto y le da click al boton guardar,
inicio la transacción y luego genero el numero de factura y el del comprobante.
componentes que utilizo ibx. los Tedit, Tdblookupcombobox y dbgrid para presentar el detalle.


Nota: Lo que estoy probando es: Le puse indice al numero de factura y numero de comprobante en la tabla cabecera de factura. Para que cuando genere un numero la busqueda del maximo responda más rápido a ver si con esto mejora.

Cañones 15-01-2010 19:57:10

Cita:

Empezado por marcoszorrilla (Mensaje 350798)
Sería conveniente que en vez de por correo se ponga el código aquí en el Foro, así si la solución resulta interesante alguién más pueda beneficiarse.

Un Saludo.

Eso seguro. En unas horas pongo un post con la solución.

cloayza 15-01-2010 21:11:13

Este codigo te entrega codigos intercalados debido al

IF (Cod_Tpo_Ncf='0')

Dependiendo de esta condicion obtendra un MAX(Numero) Diferente...

Me tome la libertad reescribir el codigo...y eliminar algunas lineas que estan demas.

Código Delphi [-]
procedure Tfrmprincipal.genera_numero_fact;
begin
     with frmdata.st do
     begin
        DecodeDate(Date,Periodo,Mes,Dia);
         st_ctr:=false;

         If cod_tpo_ncf='0' Then
         Begin
             Sql.Text:='Select Max(Numero) As numero From tb_cd_fact_t Where cod_tipo_ncf='+QuotedStr(Cod_Tpo_Ncf);
             st_ctr:=True;
             //Como Resultado puede dar ejm: 10
         End
         Else
             Sql.Text:='Select Max(Numero) As Numero From tb_cd_fact_t Where cod_tipo_ncf >0';
           //Como Resultado puede dar ejm: 5

         //Deberias usar un solo MAX(Numero) sin condiciones para que te obtenga el maximo de la tabla...

         Open;

         Cont:=1;

         If (Not FieldByName('numero').IsNull) And (Periodo=FieldByName('Periodo').Value) Then
            Cont:=FieldByName('Numero').Value+1;

         Numero:=IntToStr(Cont);
         Numero:=StringOfChar('0',7-Length(Numero))+Numero;

         frmfactura.Num_Fact_Edit.Text:=Numero;

     end;
end;

Espero haber ayudado...Un abrazo

marcoszorrilla 16-01-2010 17:10:37

Yo añado que siempre he utilizado una tabla en donde guardo el último número de factura.

Las nuevas facturas les asigno un número provisional y si se consolidan, es decir no se cancelan a la mitad, entonces, bloqueo el registro le sumo uno al último número lo almaceno y de paso lo tomo para la nueva factura, de esta manera no es posible que estando en red dos usuarios repitan número de factura.

El acceso a la obtención del número lo hago en tres intentos con retardo de un par de segundos entre ellos por si diera la casualidad dificil más no imposible de que accedieran dos usuarios a la vez a la obtención del número.

Un Saludo.

ronimaxh 17-01-2010 02:13:17

Gracias amigos por sus buenos comentarios y tambien por la arreglo del codigo.
Código Delphi [-]
    Este codigo te entrega codigos intercalados debido al

IF (Cod_Tpo_Ncf='0')

Dependiendo de esta condicion obtendra un MAX(Numero) Diferente...

En esta condición tal y como dices depende de otros tipos de numero de facturas.

Nota: Yo he reforozado el codigo y presenta el numero generado cuando guarda la factura, ademas tambien el campo numero de factura esta indexado, realmente mejoro. ya en marcha probare en produccion a ver si todo sale mejor ahi. De todas forma les dejare saber.

movorack 18-01-2010 21:43:10

Aunque se que no es postgres, de este tema estuvimos conversando en este hilo http://www.clubdelphi.com/foros/showthread.php?t=49912

Echale un ojo... depronto te pueda ayudar.

Cañones 20-01-2010 22:20:31

Cita:

Empezado por marcoszorrilla (Mensaje 350945)
Yo añado que siempre he utilizado una tabla en donde guardo el último número de factura.

Las nuevas facturas les asigno un número provisional y si se consolidan, es decir no se cancelan a la mitad, entonces, bloqueo el registro le sumo uno al último número lo almaceno y de paso lo tomo para la nueva factura, de esta manera no es posible que estando en red dos usuarios repitan número de factura.

El acceso a la obtención del número lo hago en tres intentos con retardo de un par de segundos entre ellos por si diera la casualidad dificil más no imposible de que accedieran dos usuarios a la vez a la obtención del número.

Un Saludo.

Ni más ni menos como lo que dices.
Se podría refinar el tema de cuando y como se hace.

Saludos.

marcoszorrilla 20-01-2010 22:33:46

1.-Adjudico un número provisional a la factura, suelo utilizar el número de usuario multiplicado por 10 y lo sumo a la última que como digo se encuentra en un contador guardado en una tabla.

2.-Cuando el usuario decide grabar la factura, bloqueo el registro contador, le sumo uno y hago una actualización del número de la factura, tanto para la cabecera como para sus lineas detalle.

Un Saludo.

Cañones 21-01-2010 15:50:07

Cita:

Empezado por marcoszorrilla (Mensaje 351319)
1.-Adjudico un número provisional a la factura, suelo utilizar el número de usuario multiplicado por 10 y lo sumo a la última que como digo se encuentra en un contador guardado en una tabla.

2.-Cuando el usuario decide grabar la factura, bloqueo el registro contador, le sumo uno y hago una actualización del número de la factura, tanto para la cabecera como para sus lineas detalle.

Un Saludo.

Creo que sería mejor que trabajes con los datos en memoria y cuando se confirma la venta, asignas el número correspondiente y haces el comit.
Creo que es menos complicado que tener que eliminar el comprobante de la DD.BB en caso de que no se realice la venta.
Trabajando en memoria le asignas el -1 por ejemplo y ya no tendrías problemas.

Saludos.


La franja horaria es GMT +2. Ahora son las 09:55:16.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi