Skip to content

Commit bcbc0fc

Browse files
committed
nfe: opção de envio sincrono/assincrono
1 parent b2274bb commit bcbc0fc

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 isinstance(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
@@ -259,9 +259,9 @@ def __init__(
259259
qrcode_versao="2",
260260
csc_token=None,
261261
csc_code=None,
262+
envio_sincrono=True,
262263
):
263-
super().__init__(transmissao, uf, versao, ambiente)
264-
self.mod = str(mod)
264+
super().__init__(transmissao, uf, versao, ambiente, mod, envio_sincrono)
265265
self.qrcode_versao = str(qrcode_versao)
266266
self.csc_token = str(csc_token)
267267
self.csc_code = str(csc_code)
@@ -334,7 +334,7 @@ def envia_documento(self, edoc):
334334
raiz = retEnviNFe.TEnviNFe(
335335
versao=self.versao,
336336
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
337-
indSinc="1",
337+
indSinc="1" if self.envio_sincrono else "0",
338338
)
339339
raiz.original_tagname_ = "enviNFe"
340340
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
@@ -719,6 +719,7 @@ def localizar_url(servico, estado, mod="55", ambiente=2):
719719
class NFe(DocumentoEletronico):
720720
_namespace = "http://www.portalfiscal.inf.br/nfe"
721721
_edoc_situacao_arquivo_recebido_com_sucesso = "103"
722+
_edoc_situacao_arquivo_processado_com_sucesso = "104"
722723
_edoc_situacao_servico_em_operacao = "107"
723724

724725
# Desativado por padrão para evitar 'consumo indevido'
@@ -727,8 +728,16 @@ class NFe(DocumentoEletronico):
727728

728729
_maximo_tentativas_consulta_recibo = 5
729730

730-
def __init__(self, transmissao, uf, versao="4.00", ambiente="2", mod="55"):
731-
super().__init__(transmissao)
731+
def __init__(
732+
self,
733+
transmissao,
734+
uf,
735+
versao="4.00",
736+
ambiente="2",
737+
mod="55",
738+
envio_sincrono=False,
739+
):
740+
super().__init__(transmissao, envio_sincrono)
732741
self.versao = str(versao)
733742
self.ambiente = str(ambiente)
734743
self.uf = int(uf)
@@ -759,6 +768,7 @@ def status_servico(self):
759768
)
760769

761770
def consulta_documento(self, chave):
771+
# NfeConsultaProtocolo
762772
raiz = retConsSitNFe.TConsSitNFe(
763773
versao=self.versao,
764774
tpAmb=self.ambiente,
@@ -789,14 +799,11 @@ def envia_documento(self, edoc):
789799
raiz = retEnviNFe.TEnviNFe(
790800
versao=self.versao,
791801
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
792-
indSinc="0",
802+
indSinc="1" if self.envio_sincrono else "0",
793803
)
794804
raiz.original_tagname_ = "enviNFe"
795805
xml_envio_string, xml_envio_etree = self._generateds_to_string_etree(raiz)
796806
xml_envio_etree.append(etree.fromstring(xml_assinado))
797-
798-
# teste_string, teste_etree = self._generateds_to_string_etree(xml_envio_etree)
799-
800807
return self._post(
801808
xml_envio_etree,
802809
# 'https://hom.sefazvirtual.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl',
@@ -958,15 +965,18 @@ def _verifica_documento_ja_enviado(self, proc_consulta):
958965
return False
959966

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

968978
def _aguarda_tempo_medio(self, proc_envio):
969-
time.sleep(float(proc_envio.resposta.infRec.tMed) * 1.3)
979+
time.sleep(float(proc_envio.resposta.infRec.tMed))
970980

971981
def _edoc_situacao_em_processamento(self, proc_recibo):
972982
if proc_recibo.resposta.cStat == "105":
@@ -1022,9 +1032,14 @@ def consultar_distribuicao(
10221032
retDistDFeInt,
10231033
)
10241034

1025-
def monta_processo(self, edoc, proc_envio, proc_recibo):
1035+
def monta_processo(self, edoc, proc_envio, proc_recibo=None):
10261036
nfe = proc_envio.envio_raiz.find("{" + self._namespace + "}NFe")
1027-
protocolos = proc_recibo.resposta.protNFe
1037+
if proc_recibo:
1038+
protocolos = proc_recibo.resposta.protNFe
1039+
else:
1040+
# A falta do recibo indica envio no modo síncrono
1041+
# o protocolo é recuperado diretamente da resposta do envio.
1042+
protocolos = proc_envio.resposta.protNFe
10281043
if len(nfe) and protocolos:
10291044
if not isinstance(protocolos, list):
10301045
protocolos = [protocolos]
@@ -1037,9 +1052,11 @@ def monta_processo(self, edoc, proc_envio, proc_recibo):
10371052
xml_file, nfe_proc = self._generateds_to_string_etree(nfe_proc)
10381053
prot_nfe = nfe_proc.find("{" + self._namespace + "}protNFe")
10391054
prot_nfe.addprevious(nfe)
1040-
proc_recibo.processo = nfe_proc
1041-
proc_recibo.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
1042-
proc_recibo.protocolo = protocolo
1055+
1056+
proc = proc_recibo if proc_recibo else proc_envio
1057+
proc.processo = nfe_proc
1058+
proc.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
1059+
proc.protocolo = protocolo
10431060
return True
10441061

10451062
def monta_nfe_proc(self, nfe, prot_nfe):

0 commit comments

Comments
 (0)