Fórum Emissaõ de Notas Fiscais (Só p/ Experientes) #149324

24/03/2003

0

Meu problema é o seguinte: (Uso Interbase 6 e Delphi 6)
Tenho um sistema que faz a rotina de Nota Fiscal e imprimi blz, o numero da Nota é gerado por trigger no before Insert, utilizo este numero gerado para referenciar os Itens com a Nota Fiscal, até ai blz.
Mas agora resolvi colocar meu sistema na rede e o problema é o seguinte:
Imagine que eu tenho duas máquinas na rede fazendo Notas Fiscais, então, a máquina 1 começa a fazer uma Nota e o trigger gera o numero 10 para ela, daí a máquina 2 tb começa a fazer uma nota e o trigger gera o numero 11 para ela.
Daí a máquina 2 grava primeiro que a máquina 1 e a máquina 1 cancela a operação de Nota Fiscal. Então eu perdi o numero 10 e isso não pode acontecer. Como devo fazer ? Será que alguém tem outra solução mais cabivel ?

Aguardo respostas....


camile_enhanced@ig.com.br


Beijos


Anonymous

Anonymous

Responder

Posts

24/03/2003

Belo

Meu problema é o seguinte: (Uso Interbase 6 e Delphi 6) Tenho um sistema que faz a rotina de Nota Fiscal e imprimi blz, o numero da Nota é gerado por trigger no before Insert, utilizo este numero gerado para referenciar os Itens com a Nota Fiscal, até ai blz. Mas agora resolvi colocar meu sistema na rede e o problema é o seguinte: Imagine que eu tenho duas máquinas na rede fazendo Notas Fiscais, então, a máquina 1 começa a fazer uma Nota e o trigger gera o numero 10 para ela, daí a máquina 2 tb começa a fazer uma nota e o trigger gera o numero 11 para ela. Daí a máquina 2 grava primeiro que a máquina 1 e a máquina 1 cancela a operação de Nota Fiscal. Então eu perdi o numero 10 e isso não pode acontecer. Como devo fazer ? Será que alguém tem outra solução mais cabivel ? Aguardo respostas.... camile_enhanced@ig.com.br Beijos


Prefiro o código na mão, estude este exemplo do proprio ClubDelphi:

procedure TDM.Incrementa(Nome_Tabela : String; Chave_Primaria : TField);
var Qry : TSQLQuery;
begin
if Chave_Primaria.DataSet.State <> dsInsert then
exit; //termina a execução caso não esteja em modo de inserção
Qry:=TSQLQuery.Create(nil); //cria uma instância do objeto
try
Qry.SQLConnection:=SQLConnect; //componente de conexão
Qry.SQL.Add(´SELECT MAX(´+Chave_Primaria.FieldName+´) FROM ´+Nome_Tabela);
Qry.Open;
if Qry.Fields[0].IsNull then //se a tabela está vazia retornará nulo
Chave_Primaria.AsInteger:=1 //então este será o primeiro registro
else Chave_Primaria.AsInteger:=Qry.Fields[0].AsInteger+1;
finally
FreeAndNil(Qry); //tira o objeto da memória
end;
end;
(**********************************************************************)
procedure TDM.SuaTabelaBeforePost(DataSet: TDataSet);
begin
Incrementa(´MARCAS´,SuaTabelaCOD_NOTA);
end;


Responder

Gostei + 0

25/03/2003

E_gama

Eh de costume, quando se utiliza numeraçao automatica, deixar para pegar o numero ao final da transacao, justamente para evitar esse tipo de problema, ou seja, seu aplicativo soh teria o numero da nota fiscal quando o usuario confirmar a emissao da mesma.

Nos meus sistemas, quando preciso obter numeracao automatica, utilizo SQL para obter o ultimo numero cadastrado:
[color=blue:c72b93448a]
QryUltNota.SQL.Text := select max(NFI_NUMERO) as ULT_NF from NFISCAL;
[/color:c72b93448a]
Com a SQL acima, tenho a ultima nota fiscal gravada, assim, adiciono +1 ao resultado e atualizo meu campo de ´numero da nota fiscal´ no evento ´BeforePost´ com o codigo abaixo:
[color=blue:c72b93448a]
QryUltNota.Open;
QryNFiscal.FieldByName(´NFI_NUMERO´).AsInteger := QryUltNota.FieldByName(´ULT_NF´).AsInteger + 1;
QryUltNota.Close;
[/color:c72b93448a]


Responder

Gostei + 0

25/03/2003

Anonymous

e_gama, como faço para pegar o numero no final da transação ?
Como faço para referenciar os Itens com esta Nota Fiscal ?


Beijos


Responder

Gostei + 0

25/03/2003

E_gama

Vou te responder com algumas perguntas:

1) Você tem uma tabela para ´Nota Fiscal´ e outra ´Para ítens da nota fiscal´ ?

2) Seu banco de dados está com os relacionamentos definidos, com integridade referencial e tudo mais?

2) Você está utilizando ´Master/Detail´ no seu formulário para relacionar as tabelas no seu formulário ?

Me responda essas perguntas para eu poder te ajudar...


Responder

Gostei + 0

25/03/2003

Anonymous

Já pensou em trocar o before insert pelo before post?

José

Meu problema é o seguinte: (Uso Interbase 6 e Delphi 6) Tenho um sistema que faz a rotina de Nota Fiscal e imprimi blz, o numero da Nota é gerado por trigger no before Insert, utilizo este numero gerado para referenciar os Itens com a Nota Fiscal, até ai blz. Mas agora resolvi colocar meu sistema na rede e o problema é o seguinte: Imagine que eu tenho duas máquinas na rede fazendo Notas Fiscais, então, a máquina 1 começa a fazer uma Nota e o trigger gera o numero 10 para ela, daí a máquina 2 tb começa a fazer uma nota e o trigger gera o numero 11 para ela. Daí a máquina 2 grava primeiro que a máquina 1 e a máquina 1 cancela a operação de Nota Fiscal. Então eu perdi o numero 10 e isso não pode acontecer. Como devo fazer ? Será que alguém tem outra solução mais cabivel ? Aguardo respostas.... camile_enhanced@ig.com.br Beijos



Responder

Gostei + 0

25/03/2003

Anonymous

E-gama, sim para todas as suas perguntas....


Responder

Gostei + 0

25/03/2003

E_gama

Bem, eu não sei em que nível de programação você está.
Vou te passar uma apostila (talvez você até já tenha) que tem muitos conceitos em relação a esse assunto. Acredito ser uma boa idéia você dar uma lida nela (principalmente no capítulo sobre ´Master/Detail´).

Espero que lhe ajude...

[url]http://www.salesiano.com.br/egama/delphics.zip[/url]


Responder

Gostei + 0

25/03/2003

Aroldo Zanela

Meu problema é o seguinte: (Uso Interbase 6 e Delphi 6) Tenho um sistema que faz a rotina de Nota Fiscal e imprimi blz, o numero da Nota é gerado por trigger no before Insert, utilizo este numero gerado para referenciar os Itens com a Nota Fiscal, até ai blz. Mas agora resolvi colocar meu sistema na rede e o problema é o seguinte: Imagine que eu tenho duas máquinas na rede fazendo Notas Fiscais, então, a máquina 1 começa a fazer uma Nota e o trigger gera o numero 10 para ela, daí a máquina 2 tb começa a fazer uma nota e o trigger gera o numero 11 para ela. Daí a máquina 2 grava primeiro que a máquina 1 e a máquina 1 cancela a operação de Nota Fiscal. Então eu perdi o numero 10 e isso não pode acontecer. Como devo fazer ? Será que alguém tem outra solução mais cabivel ? Aguardo respostas.... camile_enhanced@ig.com.br Beijos

Camile,
Apesar de ser iniciante, estava verificando algumas informações sobre interbase e encontrei a seguinbte informação no site www.firebase.com.br - ´No InterBase existem dois tipos de Trigger (BEFORE e AFTER). Isto é, é disparado um gatilho antes do INSERT/UPDATE/DELETE e ou é disparado um gatilho após o INSERT/UPDATE/DELETE´.
Portanto, minha sugestão seria criar uma chave artificial (p.e: auto-incremento) que deveria ser obtida pelo disparo da trigger ´before insert´ para amarrar o relacionamento de mestre/detalhe e numa trigger ´after insert´ obteria o número da nota fiscal.
No site referenciado acima existem muitas informações úteis para quem usa Interbase.
Imagino uma série de outras formas para se resolver o seu problema, esta me parece a de menor esforço.


Responder

Gostei + 0

26/03/2003

Aroldo Zanela

Camila,

Encontrei esse material aqui. Dá uma olhada, caso não tenha resolvido de forma satisfatória:

http://www.firebase.com.br/fb/

Como manter uma sequencia contínua de números

Como manter uma sequência ininterrupta de números
Extraído do Help do Interbase Objects (IBO)
Tradução e adaptação : Carlos Henrique Cantu - exclusivo para a Interbase-BR

Nota : O exemplo utiliza propriedades específicas do IBO, mas para aqueles que não utilizam os componentes IBO, creio que poderão adaptar a idéia sem muitas dificuldades.

Vamos usar um exemplo para manter o número de notas fiscais contínuo.

Primeiro passo, utilize como chave primária uma chave substituta, onde não seja importante o fato haver ´furos´ na sequência dos números, e ligue ela à um generator através da propriedade GeneratorLinks. Chame esse campo de IDNotas e um outro de Numero_Nota.

Depois, em uma transação subsequente separada (por exemplo, na hora de imprimir a nota) faça com que seja atribuído através de um generator o valor para Numero_Nota. Faça com que essa transação seja especial, configurada assim : ServerAutoCommit=true, Isolation=tiCommitted, RecVersion=false e LockWait=true. Também faça com que o comando SQL de atualização contenha uma clausula WHERE Numero_Nota IS NULL para que ele não use um registro que esteja sendo utilizado por uma outra operação rápida. Certifique-se que a edição foi realmente executada checando a propriedade RowsAffected. Essa é uma combinação especial que faz com que a operação seja 100¬ garantida em um ambiente multi-usuário.

Depois da nota ter sido impressa, de maneira semelhante, atualize o registro novamente para indicar que ela foi impressa.

A opção ServerAutoCommit garante que a atualização seja postada pelo servidor, independente de ter que se esperar que o cliente de a ordem de commit. Isso remove uma grande chance de falha.

A combinação da opção NoRecVersion e LockWait previne o aparecimento de um erro devido à um deadlock. Isso fará com que a atualização espere até o final de outras transações que possam estar trabalhando com o mesmo registro, antes de le-lo e atualiza-lo. Se isso não fosse feito, ela leria o registro, executaria o update, chamaria o evento BEFORE UPDATE, incrementaria o generator, encontraria um deadlock, cancelaria o update e causaria uma quebra na sequência de valores.

Espero que esse breve resumo ajude a resolver esse tipo de problema. É muito importante que voce faça essa operação 100¬ garantida em um ambiente multi-usuário e acredito que esse método seja o mais seguro. Duvido que outras variações se saiam bem um teste stressante.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar