Skip to content

Commit

Permalink
nfe: opção de envio sincrono/assincrono
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniospneto committed May 8, 2024
1 parent 8f10e76 commit a9e52c5
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 33 deletions.
26 changes: 14 additions & 12 deletions src/erpbrasil/edoc/edoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class DocumentoEletronico(ABC):
_consulta_servico_ao_enviar = False
_consulta_documento_antes_de_enviar = False

def __init__(self, transmissao):
def __init__(self, transmissao, envio_sincrono=False):
self._transmissao = transmissao
self.envio_sincrono = bool(envio_sincrono)

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

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

proc_envio = self.envia_documento(edoc)
if self.envio_sincrono:
self.monta_processo(edoc, proc_envio)
yield proc_envio

#
# Deu errado?
#
if not proc_envio.resposta:
return

if not self._verifica_resposta_envio_sucesso(proc_envio):
#
# Interrompe o processo
#
# Retorna imediatamente se alguma das condições abaixo for verdadeira:
# 1. A resposta do processo de envio é falsa.
# 2. A resposta do envio não indica sucesso.
# 3. O envio é síncrono (não é necessário consultar o recibo).
if (
not proc_envio.resposta
or not self._verifica_resposta_envio_sucesso(proc_envio)
or self.envio_sincrono
):
return

#
Expand Down
6 changes: 3 additions & 3 deletions src/erpbrasil/edoc/nfce.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ def __init__(
qrcode_versao="2",
csc_token=None,
csc_code=None,
envio_sincrono=True,
):
super().__init__(transmissao, uf, versao, ambiente)
self.mod = str(mod)
super().__init__(transmissao, uf, versao, ambiente, mod, envio_sincrono)
self.qrcode_versao = str(qrcode_versao)
self.csc_token = str(csc_token)
self.csc_code = str(csc_code)
Expand Down Expand Up @@ -333,7 +333,7 @@ def envia_documento(self, edoc):
raiz = retEnviNFe.TEnviNFe(
versao=self.versao,
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
indSinc="1",
indSinc="1" if self.envio_sincrono else "0",
)
raiz.original_tagname_ = "enviNFe"
xml_envio_string, xml_envio_etree = self._generateds_to_string_etree(raiz)
Expand Down
53 changes: 35 additions & 18 deletions src/erpbrasil/edoc/nfe.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ def localizar_url(servico, estado, mod="55", ambiente=2):
class NFe(DocumentoEletronico):
_namespace = "http://www.portalfiscal.inf.br/nfe"
_edoc_situacao_arquivo_recebido_com_sucesso = "103"
_edoc_situacao_arquivo_processado_com_sucesso = "104"
_edoc_situacao_servico_em_operacao = "107"

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

_maximo_tentativas_consulta_recibo = 5

def __init__(self, transmissao, uf, versao="4.00", ambiente="2", mod="55"):
super().__init__(transmissao)
def __init__(
self,
transmissao,
uf,
versao="4.00",
ambiente="2",
mod="55",
envio_sincrono=False,
):
super().__init__(transmissao, envio_sincrono)
self.versao = str(versao)
self.ambiente = str(ambiente)
self.uf = int(uf)
Expand Down Expand Up @@ -757,6 +766,7 @@ def status_servico(self):
)

def consulta_documento(self, chave):
# NfeConsultaProtocolo
raiz = retConsSitNFe.TConsSitNFe(
versao=self.versao,
tpAmb=self.ambiente,
Expand Down Expand Up @@ -787,14 +797,11 @@ def envia_documento(self, edoc):
raiz = retEnviNFe.TEnviNFe(
versao=self.versao,
idLote=datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
indSinc="0",
indSinc="1" if self.envio_sincrono else "0",
)
raiz.original_tagname_ = "enviNFe"
xml_envio_string, xml_envio_etree = self._generateds_to_string_etree(raiz)
xml_envio_etree.append(etree.fromstring(xml_assinado))

# teste_string, teste_etree = self._generateds_to_string_etree(xml_envio_etree)

return self._post(
xml_envio_etree,
# 'https://hom.sefazvirtual.fazenda.gov.br/NFeAutorizacao4/NFeAutorizacao4.asmx?wsdl',
Expand Down Expand Up @@ -956,15 +963,18 @@ def _verifica_documento_ja_enviado(self, proc_consulta):
return False

def _verifica_resposta_envio_sucesso(self, proc_envio):
if (
proc_envio.resposta.cStat
== self._edoc_situacao_arquivo_recebido_com_sucesso
):
return True
return False
"""
Verifica se a resposta do envio indica sucesso:
- cStat "103" = "Lote recebido com sucesso" (assíncrono)
- cStat "104" = "Lote processado com sucesso" (síncrono)
"""
return proc_envio.resposta.cStat in [
self._edoc_situacao_arquivo_recebido_com_sucesso,
self._edoc_situacao_arquivo_processado_com_sucesso,
]

def _aguarda_tempo_medio(self, proc_envio):
time.sleep(float(proc_envio.resposta.infRec.tMed) * 1.3)
time.sleep(float(proc_envio.resposta.infRec.tMed))

def _edoc_situacao_em_processamento(self, proc_recibo):
if proc_recibo.resposta.cStat == "105":
Expand Down Expand Up @@ -1020,9 +1030,14 @@ def consultar_distribuicao(
retDistDFeInt,
)

def monta_processo(self, edoc, proc_envio, proc_recibo):
def monta_processo(self, edoc, proc_envio, proc_recibo=None):
nfe = proc_envio.envio_raiz.find("{" + self._namespace + "}NFe")
protocolos = proc_recibo.resposta.protNFe
if proc_recibo:
protocolos = proc_recibo.resposta.protNFe
else:
# A falta do recibo indica envio no modo síncrono
# o protocolo é recuperado diretamente da resposta do envio.
protocolos = proc_envio.resposta.protNFe
if len(nfe) and protocolos:
if not isinstance(protocolos, list):
protocolos = [protocolos]
Expand All @@ -1035,9 +1050,11 @@ def monta_processo(self, edoc, proc_envio, proc_recibo):
xml_file, nfe_proc = self._generateds_to_string_etree(nfe_proc)
prot_nfe = nfe_proc.find("{" + self._namespace + "}protNFe")
prot_nfe.addprevious(nfe)
proc_recibo.processo = nfe_proc
proc_recibo.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
proc_recibo.protocolo = protocolo

proc = proc_recibo if proc_recibo else proc_envio
proc.processo = nfe_proc
proc.processo_xml = self._generateds_to_string_etree(nfe_proc)[0]
proc.protocolo = protocolo
return True

def monta_nfe_proc(self, nfe, prot_nfe):
Expand Down

0 comments on commit a9e52c5

Please sign in to comment.