Skip to content

Commit 19a5636

Browse files
committed
nfe: opção de envio sincrono/assincrono
1 parent 4fee8f9 commit 19a5636

File tree

3 files changed

+52
-33
lines changed

3 files changed

+52
-33
lines changed

src/erpbrasil/edoc/edoc.py

+14-12
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ class DocumentoEletronico(ABC):
3434
_consulta_servico_ao_enviar = False
3535
_consulta_documento_antes_de_enviar = False
3636

37-
def __init__(self, transmissao):
37+
def __init__(self, transmissao, envio_sincrono=False):
3838
self._transmissao = transmissao
39+
self.envio_sincrono = bool(envio_sincrono)
3940

4041
def _generateds_to_string_etree(self, ds, pretty_print=False):
4142
if type(ds) == _Element:
@@ -68,7 +69,7 @@ def _post(self, raiz, url, operacao, classe):
6869
retorno = self._transmissao.enviar(operacao, xml_etree)
6970
return analisar_retorno_raw(operacao, raiz, xml_string, retorno, classe)
7071

71-
def processar_documento(self, edoc):
72+
def processar_documento(self, edoc, envio_sincrono=False):
7273
"""Processar documento executa o envio do documento fiscal de forma
7374
completa ao serviço relacionado, esta é um método padrão que
7475
segue o seguinte workflow:
@@ -132,18 +133,19 @@ def processar_documento(self, edoc):
132133
#
133134

134135
proc_envio = self.envia_documento(edoc)
136+
if self.envio_sincrono:
137+
self.monta_processo(edoc, proc_envio)
135138
yield proc_envio
136139

137-
#
138-
# Deu errado?
139-
#
140-
if not proc_envio.resposta:
141-
return
142-
143-
if not self._verifica_resposta_envio_sucesso(proc_envio):
144-
#
145-
# Interrompe o processo
146-
#
140+
# Retorna imediatamente se alguma das condições abaixo for verdadeira:
141+
# 1. A resposta do processo de envio é falsa.
142+
# 2. A resposta do envio não indica sucesso.
143+
# 3. O envio é síncrono (não é necessário consultar o recibo).
144+
if (
145+
not proc_envio.resposta
146+
or not self._verifica_resposta_envio_sucesso(proc_envio)
147+
or self.envio_sincrono
148+
):
147149
return
148150

149151
#

src/erpbrasil/edoc/nfce.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,9 @@ def __init__(
258258
qrcode_versao="2",
259259
csc_token=None,
260260
csc_code=None,
261+
envio_sincrono=True,
261262
):
262-
super().__init__(transmissao, uf, versao, ambiente)
263-
self.mod = str(mod)
263+
super().__init__(transmissao, uf, versao, ambiente, mod, envio_sincrono)
264264
self.qrcode_versao = str(qrcode_versao)
265265
self.csc_token = str(csc_token)
266266
self.csc_code = str(csc_code)
@@ -333,7 +333,7 @@ def envia_documento(self, edoc):
333333
raiz = retEnviNFe.TEnviNFe(
334334
versao=self.versao,
335335
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
336-
indSinc="1",
336+
indSinc="1" if self.envio_sincrono else "0",
337337
)
338338
raiz.original_tagname_ = "enviNFe"
339339
xml_envio_string, xml_envio_etree = self._generateds_to_string_etree(raiz)

src/erpbrasil/edoc/nfe.py

+35-18
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ def localizar_url(servico, estado, mod="55", ambiente=2):
717717
class NFe(DocumentoEletronico):
718718
_namespace = "http://www.portalfiscal.inf.br/nfe"
719719
_edoc_situacao_arquivo_recebido_com_sucesso = "103"
720+
_edoc_situacao_arquivo_processado_com_sucesso = "104"
720721
_edoc_situacao_servico_em_operacao = "107"
721722

722723
# Desativado por padrão para evitar 'consumo indevido'
@@ -725,8 +726,16 @@ class NFe(DocumentoEletronico):
725726

726727
_maximo_tentativas_consulta_recibo = 5
727728

728-
def __init__(self, transmissao, uf, versao="4.00", ambiente="2", mod="55"):
729-
super().__init__(transmissao)
729+
def __init__(
730+
self,
731+
transmissao,
732+
uf,
733+
versao="4.00",
734+
ambiente="2",
735+
mod="55",
736+
envio_sincrono=False,
737+
):
738+
super().__init__(transmissao, envio_sincrono)
730739
self.versao = str(versao)
731740
self.ambiente = str(ambiente)
732741
self.uf = int(uf)
@@ -757,6 +766,7 @@ def status_servico(self):
757766
)
758767

759768
def consulta_documento(self, chave):
769+
# NfeConsultaProtocolo
760770
raiz = retConsSitNFe.TConsSitNFe(
761771
versao=self.versao,
762772
tpAmb=self.ambiente,
@@ -787,14 +797,11 @@ def envia_documento(self, edoc):
787797
raiz = retEnviNFe.TEnviNFe(
788798
versao=self.versao,
789799
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
790-
indSinc="0",
800+
indSinc="1" if self.envio_sincrono else "0",
791801
)
792802
raiz.original_tagname_ = "enviNFe"
793803
xml_envio_string, xml_envio_etree = self._generateds_to_string_etree(raiz)
794804
xml_envio_etree.append(etree.fromstring(xml_assinado))
795-
796-
# teste_string, teste_etree = self._generateds_to_string_etree(xml_envio_etree)
797-
798805
return self._post(
799806
xml_envio_etree,
800807
# 'https://hom.sefazvirtual.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl',
@@ -956,15 +963,18 @@ def _verifica_documento_ja_enviado(self, proc_consulta):
956963
return False
957964

958965
def _verifica_resposta_envio_sucesso(self, proc_envio):
959-
if (
960-
proc_envio.resposta.cStat
961-
== self._edoc_situacao_arquivo_recebido_com_sucesso
962-
):
963-
return True
964-
return False
966+
"""
967+
Verifica se a resposta do envio indica sucesso:
968+
- cStat "103" = "Lote recebido com sucesso" (assíncrono)
969+
- cStat "104" = "Lote processado com sucesso" (síncrono)
970+
"""
971+
return proc_envio.resposta.cStat in [
972+
self._edoc_situacao_arquivo_recebido_com_sucesso,
973+
self._edoc_situacao_arquivo_processado_com_sucesso,
974+
]
965975

966976
def _aguarda_tempo_medio(self, proc_envio):
967-
time.sleep(float(proc_envio.resposta.infRec.tMed) * 1.3)
977+
time.sleep(float(proc_envio.resposta.infRec.tMed))
968978

969979
def _edoc_situacao_em_processamento(self, proc_recibo):
970980
if proc_recibo.resposta.cStat == "105":
@@ -1020,9 +1030,14 @@ def consultar_distribuicao(
10201030
retDistDFeInt,
10211031
)
10221032

1023-
def monta_processo(self, edoc, proc_envio, proc_recibo):
1033+
def monta_processo(self, edoc, proc_envio, proc_recibo=None):
10241034
nfe = proc_envio.envio_raiz.find("{" + self._namespace + "}NFe")
1025-
protocolos = proc_recibo.resposta.protNFe
1035+
if proc_recibo:
1036+
protocolos = proc_recibo.resposta.protNFe
1037+
else:
1038+
# A falta do recibo indica envio no modo síncrono
1039+
# o protocolo é recuperado diretamente da resposta do envio.
1040+
protocolos = proc_envio.resposta.protNFe
10261041
if len(nfe) and protocolos:
10271042
if not isinstance(protocolos, list):
10281043
protocolos = [protocolos]
@@ -1035,9 +1050,11 @@ def monta_processo(self, edoc, proc_envio, proc_recibo):
10351050
xml_file, nfe_proc = self._generateds_to_string_etree(nfe_proc)
10361051
prot_nfe = nfe_proc.find("{" + self._namespace + "}protNFe")
10371052
prot_nfe.addprevious(nfe)
1038-
proc_recibo.processo = nfe_proc
1039-
proc_recibo.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
1040-
proc_recibo.protocolo = protocolo
1053+
1054+
proc = proc_recibo if proc_recibo else proc_envio
1055+
proc.processo = nfe_proc
1056+
proc.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
1057+
proc.protocolo = protocolo
10411058
return True
10421059

10431060
def monta_nfe_proc(self, nfe, prot_nfe):

0 commit comments

Comments
 (0)