Jump to content

Tratamento para envio de nfc-e offline


  • Este tópico foi criado há 1653 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

  • Membros Pro

Bom pessoal, tenho visto muitos comentários aqui no fórum a respeito de como tratar a emissão online / offline da nfc-e. Eu tenho feito assim, e por enquanto tem dado certo. Se alguém tiver alguma experiência e quiser postar aqui seria de muita utilidade.

Eu divido em duas etapas: a primeira etapa é o envio da nota offline e a segunda etapa seria o descarregamento (envio) das notas que ficaram offline.

Na primeira etapa eu faço o envio usando a rotina normal NFCE.ENVIAR colocando o comando de envio dentro de um bloco try except end. Ficaria mais ou menos assim:

Try
   Rotina de envio de nota
Except
   On E: Exception do
   if (pos('requisição não enviada', LowerCase(E.Message)) <> 0) or (pos('tempo limite', LowerCase(E.Message)) <> 0) then
      // Gerar a nota de forma offline
end;

O erro "requisição não enviada" ocorre quando o cliente está sem internet, já o erro "tempo limite" ocorre quando tem internet mas houve problema de conexão durante o envio. Portanto se ocorrer estes dois erros você emite o nfce offline e grava para posterior envio.

Uma nota importante: Ao enviar o componente acbr já vai estar carregado com os dados da nota. Portanto antes de fazer o envio offline altere as seguintes propriedades do componente:

NFCE.NotasFiscais.Items[0].NFe.Ide.tpEmis := teoffline;
NFCE.NotasFiscais.Items[0].NFe.Ide.xJust := 'Problemas técnicos no envio do cupom eletrônico';
NFCE.NotasFiscais.Items[0].NFe.Ide.dhCont := now;
NFCE.NotasFiscais.GerarNFe;
NFCE.NotasFiscais.Assinar;
NFCE.NotasFiscais.Validar;

Feito isto faça o envio offline.

Vamos agora a segunda etapa. Enviar os cupons que foram emitidos offline.

Da mesma forma você vai fazer o envio em um bloco protegido do try except end como no exemplo acima.

Try
   Rotina de envio de nota
Except
   On E: Exception do
   if (pos('requisição não enviada', LowerCase(E.Message)) <> 0) or (pos('tempo limite', LowerCase(E.Message)) <> 0) then
      // Não vai fazer nada, pois o cupom já foi emitido
   if pos('duplicidade', LowerCase(E.Message)) <> 0 then
      // tratar duplicidade.
end;

Para tratar a duplicidade eu fiz da seguinte maneira: Pesquisei o código retornado pelo componente (NFCE.WebServices.Enviar.cStat).

Se retornar o código 204 é porque por algum motivo (sabe-se lá qual) a sua nota já foi enviada e está no sefaz com o mesmo número e chave que você está enviando. Neste caso basta colocar uma flag de enviada nesta nota e pronto.

Se retornar o código 539 é porque tem uma nota com o mesmo número e chave diferente. Aí que está o pulo do gato. Isso provavelmente ocorreu porque você guardou esta nota para enviar posteriormente quando teve um erro de "Tempo Limite Atingido". A sua nota foi enviada mas você não recebeu o retorno devido a problemas na conexão. E porque a diferença da chave ? Justamente porque você fez alteração (conforme exemplo acima) na propriedade tpemis. Tem um campo da chave nfce que vai com o valor 1 quando emitida online e 9 quando emitida offline, portanto quando você alterou o tipo de emissão automaticamente alterou a chave. Então você faz o seguinte procedimento:

NFCE.NotasFiscais.Items[0].NFe.Ide.tpEmis := teNormal;
NFCE.NotasFiscais.Items[0].NFe.Ide.xJust := '';
NFCE.NotasFiscais.Items[0].NFe.Ide.dhCont := 0;
Try
   NFCE.NotasFiscais.GerarNFe;
   NFCE.NotasFiscais.Assinar;
   NFCE.NotasFiscais.Validar;
   NFCE.Enviar(NFCE.NotasFiscais.Items[0].NFe.Ide.nNF, False, true);
Except
   //exceção muda para pegar o cstat em seguida.
End;
if NFCE.WebServices.Enviar.cStat = 100 then //cstat = 100 nota foi enviada e aceita
   //marca a flag da nota como enviada.

Bom, fica aí a minha dica e se puder postem sugestões sobre como otimizar esse tratamento online / offline.

 

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • Membros Pro

Gostaria de contribuir com uma dica, no seu código:

Try
   Rotina de envio de nota
Except
   On E: Exception do
   if (pos('requisição não enviada', LowerCase(E.Message)) <> 0) or (pos('tempo limite', LowerCase(E.Message)) <> 0) then
      // Gerar a nota de forma offline
end;

Eu tive muitos problemas com impressora dentro da "Rotina de envio de nota" pois eu passava True para Imprimir no método Enviar, dessa forma se retornasse um erro de impressão o meu EXCEPT capturava e gerava a contingência, demorei alguns dias a perceber isso pois em programação minha impressora não dava erro. Com isso mudei o método Enviar para não imprimir e depois que a nota fosse autorizada chamo o método Imprimir;

Vou usar a sua dica para a duplicidade.

Anderson Rogerio Bejatto

Bacharel em Sistemas de Informação, Londrina - Paraná, www.saac.com.br

Colaborador e Assinante ACBrPro do Projeto ACBr - Automação Comercial Brasil

Link to comment
Share on other sites

  • Moderadores

Eu prefiro tratar os codigos de retorno:

         (pos('12007 - ', E.Message.ToUpper) > 0) or // erro de conexão
         (pos('12002 - ', E.Message.ToUpper) > 0) or // timeout
         (pos('12029 - ', E.Message.ToUpper) > 0) or // limite de tempo de conexão
         (pos('ERRO NAO CATALOGADO', E.Message.ToUpper) > 0) then // erros de tratamento do webservice

  • Like 2
  • Thanks 1

Equipe ACBr

Régys Borges da Silveira

http://www.regys.com.br

certificacao delphicertificacao delphi
Link to comment
Share on other sites

  • 1 month later...
  • Membros Pro

Caro Magno,

Agradeço o seu tópico, está me dando uma "grande luz". Estou com um sério problema nos meus clientes que cai na situação do seu "pulo do gato". Eles enviam a nota em modo SINCRONO e devido a problemas de conexão eu não tenho o retorno positivo da mesma.

Antes eu cancelava a gravação na base e perdia todos os dados da venda. Agora estou seguindo a sua dica e jogando em contingência.

Como você falou, ao tentar enviar a contingência, recebo o erro Duplicidade com chave diferente, pois a nota pra mim está como OFFLINE e para a SEFAZ está ONLINE. Até aí tudo bem. Dai para frente que eu não entendi o seu exemplo.

Você orienta gerar a mesma novamente de forma ONLINE e enviar... mas aí não vai dar Duplicidade com a mesma chave?

Você poderia postar o seu código frisando essa parte? Seria de grande ajuda

Desde já agradeço a atenção

Link to comment
Share on other sites

  • Membros Pro
NFCE.NotasFiscais.Items[0].NFe.Ide.tpEmis := teNormal;
NFCE.NotasFiscais.Items[0].NFe.Ide.xJust := '';
NFCE.NotasFiscais.Items[0].NFe.Ide.dhCont := 0;
Try
   NFCE.NotasFiscais.GerarNFe;
   NFCE.NotasFiscais.Assinar;
   NFCE.NotasFiscais.Validar;
   NFCE.Enviar(NFCE.NotasFiscais.Items[0].NFe.Ide.nNF, False, true);
Except
   //exceção muda para pegar o cstat em seguida.
End;
//cstat = 204 nota já existe com mesmo número e mesma chave.
if NFCE.WebServices.Enviar.cStat = 204 then
   //marca a flag da nota como enviada.

Acabei passando o código errado. Se for 204 ela já foi enviada com mesmo número e chave. Portanto, só marcar no seu banco de dados como enviada.

Se for 539, isso que dizer que a nota com esse número já foi enviada com uma chave diferente. Aí você altera a chave, como mostra as primeiras linhas e tenta enviar de novo. Se retornar 204, é porque realmente ela já tinha sido enviada. Aí você marca a flag de enviada no seu banco de dados.

Link to comment
Share on other sites

  • Membros Pro

Olá magno...Grato pela explicação...

Mas me tira outra dúvida... Não entendi o comentário desse seu except:

Except
   //exceção muda para pegar o cstat em seguida.
End;

Como assim? O que aconteceria ou eu deveria fazer aqui dentro?

Não deveria ser o comando abaixo a entrar nesse except, pois quando tentasse enviar dinovo (dessa vez como online) daria outra exceção de duplicidade, nesse caso com mesma chave - cstat 204

if NFCE.WebServices.Enviar.cStat = 204 then
   //marca a flag da nota como enviada.

 

Outra questão que já apontei até nesse outro tópico criado por mim http://www.projetoacbr.com.br/forum/topic/24237-nfc-e-em-duplicidade/. Esse negócio de enviar a nota em modo SINCRONO e não receber o retorno acontece direto comigo nos clientes, aí fiz igual você falou, coloco em CONTINGENCIA, pois não sei o que aconteceu com a mesma e libero o cliente.

Quando a internet volta eu tento enviar em contingência e descubro que ela havia realmente sido enviada ONLINE na última tentativa, pois dá erro de Duplicidade com Chave Diferente, troco o XML para online e envio dinovo, dá erro de Duplicidade com a Mesma Chave, tenho certeza que a nota já havia sido enviada e como ONLINE, marco como ONLINE na minha base e pronto. Aí que está a questão. Na minha base está tudo certo, mas o DANFE que o cliente levou nesse caso está com chave errada e QR Code errado, ele nunca vai conseguir consultar com esse DANFE que levou errado como CONTINGENCIA. Está certo o meu raciocínio? E se sim, ficamos a mercê da sorte nesse caso?

De ante mão já agradeço a sua atenção

Edited by doidopb
Link to comment
Share on other sites

Olá magno...Grato pela explicação...

Mas me tira outra dúvida... Não entendi o comentário desse seu except:

Except
   //exceção muda para pegar o cstat em seguida.
End;

Como assim? O que aconteceria ou eu deveria fazer aqui dentro?

Não deveria ser o comando abaixo a entrar nesse except, pois quando tentasse enviar dinovo (dessa vez como online) daria outra exceção de duplicidade, nesse caso com mesma chave - cstat 204

if NFCE.WebServices.Enviar.cStat = 204 then
   //marca a flag da nota como enviada.

 

Outra questão que já apontei até nesse outro tópico criado por mim http://www.projetoacbr.com.br/forum/topic/24237-nfc-e-em-duplicidade/. Esse negócio de enviar a nota em modo SINCRONO e não receber o retorno acontece direto comigo nos clientes, aí fiz igual você falou, coloco em CONTINGENCIA, pois não sei o que aconteceu com a mesma e libero o cliente.

Quando a internet volta eu tento enviar em contingência e descubro que ela havia realmente sido enviada ONLINE na última tentativa, pois dá erro de Duplicidade com Chave Diferente, troco o XML para online e envio dinovo, dá erro de Duplicidade com a Mesma Chave, tenho certeza que a nota já havia sido enviada e como ONLINE, marco como ONLINE na minha base e pronto. Aí que está a questão. Na minha base está tudo certo, mas o DANFE que o cliente levou nesse caso está com chave errada e QR Code errado, ele nunca vai conseguir consultar com esse DANFE que levou errado como CONTINGENCIA. Está certo o meu raciocínio? E se sim, ficamos a mercê da sorte nesse caso?

De ante mão já agradeço a sua atenção

Eu estou parado exatamente nesta situação. Se o cliente for consultar a chave ou o qrcode vai aparecer como NFCe inexistente.

Link to comment
Share on other sites

Olá magno...Grato pela explicação...

Mas me tira outra dúvida... Não entendi o comentário desse seu except:

Except
   //exceção muda para pegar o cstat em seguida.
End;

Como assim? O que aconteceria ou eu deveria fazer aqui dentro?

Não deveria ser o comando abaixo a entrar nesse except, pois quando tentasse enviar dinovo (dessa vez como online) daria outra exceção de duplicidade, nesse caso com mesma chave - cstat 204

if NFCE.WebServices.Enviar.cStat = 204 then
   //marca a flag da nota como enviada.

 

Outra questão que já apontei até nesse outro tópico criado por mim http://www.projetoacbr.com.br/forum/topic/24237-nfc-e-em-duplicidade/. Esse negócio de enviar a nota em modo SINCRONO e não receber o retorno acontece direto comigo nos clientes, aí fiz igual você falou, coloco em CONTINGENCIA, pois não sei o que aconteceu com a mesma e libero o cliente.

Quando a internet volta eu tento enviar em contingência e descubro que ela havia realmente sido enviada ONLINE na última tentativa, pois dá erro de Duplicidade com Chave Diferente, troco o XML para online e envio dinovo, dá erro de Duplicidade com a Mesma Chave, tenho certeza que a nota já havia sido enviada e como ONLINE, marco como ONLINE na minha base e pronto. Aí que está a questão. Na minha base está tudo certo, mas o DANFE que o cliente levou nesse caso está com chave errada e QR Code errado, ele nunca vai conseguir consultar com esse DANFE que levou errado como CONTINGENCIA. Está certo o meu raciocínio? E se sim, ficamos a mercê da sorte nesse caso?

De ante mão já agradeço a sua atenção

Eu estou parado exatamente nesta situação. Se o cliente for consultar a chave ou o qrcode vai aparecer como NFCe inexistente.

Estou com o mesmo problema, alguém saberia como proceder nessa situação ???Desde já agradeço......

Link to comment
Share on other sites

  • Membros Pro

Neste caso eu acho que não tem jeito. Pois se a nota chegou e você não teve retorno e emitiu a nota em contigencia e o cliente saiu com a chave de contigencia, não há o que fazer. Isso só tem como evitar se você trabalhar somente de modo síncrono o que é totalmente o inviável no ponto de venda ou totalmente de modo assincrono o que eu não sei se é permitido. Acho que como a nfce ainda esta engatinhando talvez surja uma maneira de resolver. Hoje não vejo como.

Link to comment
Share on other sites

Neste caso eu acho que não tem jeito. Pois se a nota chegou e você não teve retorno e emitiu a nota em contigencia e o cliente saiu com a chave de contigencia, não há o que fazer. Isso só tem como evitar se você trabalhar somente de modo síncrono o que é totalmente o inviável no ponto de venda ou totalmente de modo assincrono o que eu não sei se é permitido. Acho que como a nfce ainda esta engatinhando talvez surja uma maneira de resolver. Hoje não vejo como.

Obrigado pela ajuda Magnosystem... verdade o jeito é aguardar uma futura solução para essa situação, como você citou eu poderia trabalhar somente no modo síncrono mas para a venda realmente é inviável!!!  

Link to comment
Share on other sites

Amigos tenho ma duvida, se eu emito uma NFCe em contigencia off-line no dia 18/10/2015 e a minha internet volta no dia 19/10/2015 qual data deve ir e quais variaveis devo preencher, pois o que parece é que temos um prazo de 24hrs para emitir, estou certo ?

adelsonuchoa eu não seto nenhuma data só carrego o xml e faço o envio para sefaz:

ACBrNFe1.NotasFiscais.Clear;
ACBrNFe1.NotasFiscais.LoadFromFile(sCaminhoXML, True);

ACBrNFe1.Enviar(lote,True,False); 

Não sei se te ajuda.....

 

 

Link to comment
Share on other sites

  • Membros Pro

Neste caso eu acho que não tem jeito. Pois se a nota chegou e você não teve retorno e emitiu a nota em contigencia e o cliente saiu com a chave de contigencia, não há o que fazer. Isso só tem como evitar se você trabalhar somente de modo síncrono o que é totalmente o inviável no ponto de venda ou totalmente de modo assincrono o que eu não sei se é permitido. Acho que como a nfce ainda esta engatinhando talvez surja uma maneira de resolver. Hoje não vejo como.

Caro magnosystem, grato pela resposta.

Mais tem um detalhe, eu só trabalho nos PDVs em modo SINCRONO e mesmo assim tenho esse problema, em todos os meus clientes. É relativo, com a internet boa a incidência é menor, mas com a internet ruim (por exemplo o 3G que aqui é péssimo) a incidência é bem maior.

Outro detalhe, assim como o Régys questionou... Porque é inviável trabalhar nos PDVs somente em modo síncrono???

Edited by doidopb
Link to comment
Share on other sites

Neste caso eu acho que não tem jeito. Pois se a nota chegou e você não teve retorno e emitiu a nota em contigencia e o cliente saiu com a chave de contigencia, não há o que fazer. Isso só tem como evitar se você trabalhar somente de modo síncrono o que é totalmente o inviável no ponto de venda ou totalmente de modo assincrono o que eu não sei se é permitido. Acho que como a nfce ainda esta engatinhando talvez surja uma maneira de resolver. Hoje não vejo como.

Caro magnosystem, grato pela resposta.

Mais tem um detalhe, eu só trabalho nos PDVs em modo SINCRONO e mesmo assim tenho esse problema, em todos os meus clientes. É relativo, com a internet boa a incidência é menor, mas com a internet ruim (por exemplo o 3G que aqui é péssimo) a incidência é bem maior.

Outro detalhe, assim como o Régys questionou... Porque é inviável trabalhar nos PDVs somente em modo síncrono???

Por "Assíncrono" eu entendo "Contingência". Estou certo?

Não que seja "inviável", mas pelos motivos que você mesmo citou (Internet lenta, timeout do sefaz), trabalhar sempre "síncrono" dá muito problema. O que pode ser feito é um timeout na aplicação e caso o modo síncrono estoure esse timeout, gere a mesma nota em modo assíncrono (contingência) e cancele/inutilize a "síncrona".

Uma dica é assistir os vídeos sobre NFC-e no site http://www.desenvolvedoresdaruma.com.br/home/index.php,lá tem muitas dicas de como proceder em diferentes situações.

Edited by flavio80s
Link to comment
Share on other sites

  • Membros Pro

Olá flavio80s... Sobre seu comentário:

Por "Assíncrono" eu entendo "Contingência". Estou certo?

Está errado. Segue abaixo:

O método de enviar NFCe   Sincrono   , é o modo em que ao enviar o XML da Nota, o servidor já retorna a resposta se a nota foi autorizada ou rejeitada na mesma requisição. Neste formato de envio é possível enviar apenas um lote com uma nota.

 

O método de enviar NFCe   Assincrono   (EnviarNF) é o modo convencional, igual ao do NFe, onde o usuário envia um lote de NFCe, contendo no máximo 50 notas. Com o lote enviado, o servidor retorna que o lote está em processamento. Para verificar se as notas foram realmente autorizadas é necessário fazer uma consulta de recibo.

 

Fonte: https://ciranda.me/tsdn/base-de-conhecimento/post/componente-nfc-e-enviarnfcesincrono-e-enviarnfceassincrono

Portanto na verdade os mesmos problemas que terei em relação a internet no modo SINCRONO, também terei no modo ASSINCRONO, mas ao meu ver, com uma menor complexidade de tratamento.

Observe, no primeiro (Sincrono) eu envio e já recebo a resposta se deu tudo certo ou não. Se deu algum problema envio em CONTINGÊNCIA (envio offline e imprimir duas vias - Cliente e Estabelecimento) e continuo vendendo.

No segundo (Assincrono) eu tenho que enviar, consultar o recibo e só depois, da mesma forma, checo se deu algum problema e envio em CONTINGÊNCIA e continuo vendendo.

Edited by doidopb
  • Like 2
Link to comment
Share on other sites

  • Membros Pro

Acho que eu usei a expressão errada. Eu pensava que modo assíncrono e offline fossem a mesma coisa e não é. Quando eu falei que para driblar isto é só se trabalhar totalmente online, o que é inviável, visto que pode o cliente estar sem internet, ou totalmente offline o que eu não sei se pode.

 

Então Regys quando eu disse inviável trabalhar somente no modo síncrono, entenda, trabalhar somente no modo online.

Link to comment
Share on other sites

  • Membros Pro

Acho que "matei" o problema através do vídeo https://www.youtube.com/watch?v=znVzIe8T4PE. E a solução é mais uma questão de não observar o óbvio do que pode ser feito.

Se observarem o vídeo e trazerem a nossa realidade do ACBR, a contingência só pode acontecer através de 2 motivos:

1 - Falta de internet

2 - Timeout (ou o tal BURACO NEGRO citado no vídeo)

No caso da falta da internet é fácil, emite em contingência e pronto. Pois temos a certeza que a nota não foi autorizada.

No caso do Timeout, não sabemos o que aconteceu. O problema está no tratamento que damos a ela, pois nós emitimos ela em contingência, entregamos para o cliente e REZAMOS para que ela realmente não tenha sido autorizada. O que o Claudenir faz no vídeo é uma grande "sacada". Como ele não sabe o que aconteceu, ele pula o número e já emite direto em contingência, para ter certeza que essa nota realmente não foi autorizada. Aí depois ele checa o que aconteceu com a anterior, se autorizou então CANCELA, se não, INUTILIZA. Pronto.

Cliente com chave certa, QR Code certo, além de nossa aplicação está com a base certa.

Acho que fechamos a problemática.

Agora surgiu outra... Como diferenciar o erro se é de internet ou de timeout (BURACO NEGRO)?

  • Like 3
Link to comment
Share on other sites

  • Moderadores

Eu prefiro tratar os codigos de retorno:

         (pos('12007 - ', E.Message.ToUpper) > 0) or // erro de conexão
         (pos('12002 - ', E.Message.ToUpper) > 0) or // timeout
         (pos('12029 - ', E.Message.ToUpper) > 0) or // limite de tempo de conexão
         (pos('ERRO NAO CATALOGADO', E.Message.ToUpper) > 0) then // erros de tratamento do webservice

Acho que por aqui matamos.

  • Like 1

Equipe ACBr

Régys Borges da Silveira

http://www.regys.com.br

certificacao delphicertificacao delphi
Link to comment
Share on other sites

  • Membros Pro

Eu prefiro tratar os codigos de retorno:

         (pos('12007 - ', E.Message.ToUpper) > 0) or // erro de conexão
         (pos('12002 - ', E.Message.ToUpper) > 0) or // timeout
         (pos('12029 - ', E.Message.ToUpper) > 0) or // limite de tempo de conexão
         (pos('ERRO NAO CATALOGADO', E.Message.ToUpper) > 0) then // erros de tratamento do webservice

Acho que por aqui matamos.

Para fechar bem Régys...

Sei que o 12002 é do timeout, pois sempre que tenho essa problemática, é com esse código. Pela leitura de suas descrições acima, o 12007 seria o de falha de internet. Estou certo?

E em que categoria entra o 12029, falha de internet ou timeout (buraco negro)?

Link to comment
Share on other sites

  • Este tópico foi criado há 1653 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.