Skip to content

Commit

Permalink
trabalho em andamento
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniospneto committed May 17, 2024
1 parent 5bf37bc commit b75f1ae
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 22 deletions.
2 changes: 1 addition & 1 deletion l10n_br_fiscal/constants/fiscal.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
]

AUTORIZADO = ("100", "150")
DENEGADO = ("110", "301", "302")
DENEGADO = ("110", "301", "302", "303")
LOTE_RECEBIDO = ["103"]
LOTE_PROCESSADO = ["104"]
LOTE_EM_PROCESSAMENTO = ["105"]
Expand Down
55 changes: 36 additions & 19 deletions l10n_br_nfe/models/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ def _processador(self, use_contingency_ws=False):

if self.document_type == MODELO_FISCAL_NFE:
params.update(
envio_sincrono=self.env.user.company_id.nfe_synchronous_processing,
envio_sincrono=self.env.company.nfe_synchronous_processing,
contingencia=use_contingency_ws,
)
return edoc_nfe(**params)
Expand Down Expand Up @@ -936,39 +936,45 @@ def _document_export(self, pretty_print=True):
return result

def _nfe_update_status_and_save_data(self, process):
"""
Updates the NFe status based on the webservice response,
handling different scenarios.
"""
self.ensure_one()
force_change_status = False
response = process.resposta

webservice = process.webservice
if hasattr(process, "protocolo"):
inf_prot = process.protocolo.infProt
else:
inf_prot = process.resposta.protNFe.infProt

# The ´nfeRetAutorizacaoLote´ webservice allows
# querying a batch of NFe, therefore in this case the return of protNFe
# is a list, but the localization only sends one NFe per batch.
if webservice == "nfeRetAutorizacaoLote":
inf_prot = response.protNFe[0].infProt
else:
inf_prot = response.protNFe.infProt
nfe_proc_xml = getattr(process, "processo_xml", None)
if nfe_proc_xml:
nfe_proc_xml = nfe_proc_xml.decode()
self._nfe_save_protocol(inf_prot, nfe_proc_xml)

# Para o webservice de consulta NFe, verifica-se o status na resposta
# principal. Isso é crucial porque, para NF-es canceladas, o status atual não
# reflete o do protocolo de autorização.
if process.webservice == "nfeConsultaNF":
# For ´nfeConsultaNF´ webservice, the status is checked in the main response.
# This is crucial because for canceled NFes, the current status does not
# reflect the authorization protocol status.
if webservice == "nfeConsultaNF":
c_stat = response.cStat
x_motivo = response.xMotivo
force_change_status = True
else:
c_stat = inf_prot.cStat
x_motivo = inf_prot.xMotivo

# update document
self.update(
{
"status_code": c_stat,
"status_name": x_motivo,
}
)

# change state
state_map = {
**dict.fromkeys(AUTORIZADO, SITUACAO_EDOC_AUTORIZADA),
Expand Down Expand Up @@ -1064,9 +1070,9 @@ def _nfe_consult_receipt(self):
# Consult receipt and process the response
rec_num = self.authorization_event_id.lot_receipt_number
receipt_process = processor.consulta_recibo(numero=rec_num)
if receipt_process.resposta.cStat == "104": # Batch Processed (Lote Processado)
if receipt_process.resposta.cStat == "104": # Lote Processado
self._nfe_response_add_proc(receipt_process)
return receipt_process
self._nfe_process_authorization(receipt_process)

def _nfe_response_add_proc(self, ws_response_process):
"""
Expand Down Expand Up @@ -1105,14 +1111,14 @@ def _nfe_create_proc(self, prot_nfe_element):
)
return proc_nfe_xml

def _document_status(self, use_contingency_ws):
def _document_status(self):
self.ensure_one()
status = super()._document_status()
if filter_processador_edoc_nfe(self):
status = self.check_nfe_status_in_sefaz(use_contingency_ws)
status = self.check_nfe_status_in_sefaz()
return status

def check_nfe_status_in_sefaz(self, use_contingency_ws=False):
def check_nfe_status_in_sefaz(self):
"""
Checks the status and protocol of an NF-e against SEFAZ's database.
It updates the NF-e status and saves the data if the NF-e is found
Expand All @@ -1130,7 +1136,7 @@ def _is_nfe_found(c_stat):
"""
return c_stat in ["100", "101", "110"]

nfe_manager = self._processador(use_contingency_ws=use_contingency_ws)
nfe_manager = self._processador()
check_response = nfe_manager.consulta_documento(chave=self.document_key)
status = check_response.resposta.xMotivo

Expand Down Expand Up @@ -1191,13 +1197,24 @@ def _nfe_send_for_authorization(self):
self._update_nfce_for_offline_contingency()
return
if service_response.resposta.infRec:
# only async case.
# Only ASYNC: The receipt is only applicable for asynchronous
# transmission.
self._nfe_process_send_asynchronous(service_response)
# Commit to secure receipt info for future queries.
in_testing = getattr(threading.current_thread(), "testing", False)
if not in_testing:
self.env.cr.commit()

Check warning on line 1206 in l10n_br_nfe/models/document.py

View check run for this annotation

Codecov / codecov/patch

l10n_br_nfe/models/document.py#L1206

Added line #L1206 was not covered by tests
continue
# Check if 'skip_consult_receipt' is set in the context. If it is
# True, skip the receipt consultation in this transaction. The user
# will need to trigger the consultation manually later to obtain
# the usage protocol.
skip_consult_receipt = self.env.context.get(
"skip_consult_receipt", False
)
if skip_consult_receipt:
break
else:
continue

Check warning on line 1217 in l10n_br_nfe/models/document.py

View check run for this annotation

Codecov / codecov/patch

l10n_br_nfe/models/document.py#L1217

Added line #L1217 was not covered by tests
authorization_response = service_response
if authorization_response:
self._nfe_process_authorization(authorization_response)
Expand Down
2 changes: 1 addition & 1 deletion l10n_br_nfe/tests/mocks/retConsReciNFe/autorizada.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<tpAmb>2</tpAmb>
<verAplic>sefaz_mocked</verAplic>
<nRec>423002202113232</nRec>
<cStat>100</cStat>
<cStat>104</cStat>
<xMotivo>Lote processado</xMotivo>
<cUF>42</cUF>
<dhRecbto>2023-06-11T01:18:19-03:00</dhRecbto>
Expand Down
35 changes: 35 additions & 0 deletions l10n_br_nfe/tests/mocks/retConsReciNFe/uso_denegado.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<soap:Body>
<nfeResultMsg
xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeRetAutorizacao4"
>
<retConsReciNFe versao="4.00" xmlns="http://www.portalfiscal.inf.br/nfe">
<tpAmb>2</tpAmb>
<verAplic>sefaz_mocked</verAplic>
<nRec>423002202113232</nRec>
<cStat>104</cStat>
<xMotivo>Lote processado</xMotivo>
<cUF>42</cUF>
<dhRecbto>2023-06-11T01:18:19-03:00</dhRecbto>
<protNFe versao="4.00">
<infProt>
<tpAmb>2</tpAmb>
<verAplic>SVRSnfce202307311112</verAplic>
<chNFe>33230807984267003800650040000000321935136447</chNFe>
<dhRecbto>2023-08-07T11:09:08-03:00</dhRecbto>
<nProt>333230000396082</nProt>
<digVal>zwJzbq4FXks09tlHU1GEWRI7t/A=</digVal>
<cStat>303</cStat>
<xMotivo
>Uso Denegado: Destinatário não habilitado a operar na UF</xMotivo>
</infProt>
</protNFe>
</retConsReciNFe>
</nfeResultMsg>
</soap:Body>
</soap:Envelope>
34 changes: 34 additions & 0 deletions l10n_br_nfe/tests/mocks/retConsSitNFe/uso_denegado.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
<soap:Body>
<nfeResultMsg
xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NFeConsultaProtocolo4"
>
<retConsSitNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">
<tpAmb>1</tpAmb>
<verAplic>sefaz_mocked</verAplic>
<cStat>110</cStat>
<xMotivo>Uso Denegado</xMotivo>
<cUF>26</cUF>
<dhRecbto>2020-02-13T14:20:52-03:00</dhRecbto>
<chNFe>26200124494200000106550010000010111352744151</chNFe>
<protNFe versao="4.00">
<infProt>
<tpAmb>1</tpAmb>
<verAplic>sefaz_mocked</verAplic>
<chNFe>26200124494200000106550010000010111352744151</chNFe>
<dhRecbto>2020-01-13T14:20:52-03:00</dhRecbto>
<nProt>135180772366783</nProt>
<digVal>4A20WByjTePGOz+LoGy1uVk2gaY=</digVal>
<cStat>302</cStat>
<xMotivo
>Uso Denegado: Irregularidade fiscal do destinatário</xMotivo>
</infProt>
</protNFe>
</retConsSitNFe>
</nfeResultMsg>
</soap:Body>
</soap:Envelope>
36 changes: 35 additions & 1 deletion l10n_br_nfe/tests/test_nfe_webservices.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
from odoo.fields import Datetime

from odoo.addons.l10n_br_fiscal.constants.fiscal import (
SITUACAO_EDOC_A_ENVIAR,
SITUACAO_EDOC_AUTORIZADA,
SITUACAO_EDOC_CANCELADA,
SITUACAO_EDOC_ENVIADA,
)
from odoo.addons.l10n_br_nfe.models.document import NFe

Expand All @@ -26,7 +28,7 @@ def is_libreoffice_command_available():
return False


class TestNFeWebservices(TestNFeExport):
class TestNFeWebServices(TestNFeExport):
def setUp(self):
nfe_list = [
{
Expand Down Expand Up @@ -91,3 +93,35 @@ def test_inutilizar(self):
.create({"document_id": nfe.id, "justification": "Era apenas um teste."})
)
inutilizar_wizard.doit()

@nfe_mock(
{
"nfeAutorizacaoLote": "retEnviNFe/lote_recebido.xml",
"nfeRetAutorizacaoLote": "retConsReciNFe/autorizada.xml",
}
)
def test_nfe_consult_receipt(self):
"""
Tests the asynchronous NFe transmission, separating the sending and
the consultation into two distinct steps.
"""
for nfe_data in self.nfe_list:
nfe = nfe_data["nfe"]
self.assertEqual(nfe.state_edoc, SITUACAO_EDOC_A_ENVIAR)
with mock.patch.object(NFe, "make_pdf"):
# Skip receipt consultation during the send action
nfe.with_context(skip_consult_receipt=True).action_document_send()
# Document has been sent, but the receipt has not been consulted yet,
# meaning the authorization protocol has not been received.
self.assertEqual(nfe.state_edoc, SITUACAO_EDOC_ENVIADA)
# Consult the receipt to receive the usage authorization.
nfe._nfe_consult_receipt()
self.assertEqual(nfe.state_edoc, SITUACAO_EDOC_AUTORIZADA)

@nfe_mock({"nfeConsultaNF": "retConsSitNFe/autorizado.xml"})
def test_nfe_consult(self):
for nfe_data in self.nfe_list:
nfe = nfe_data["nfe"]
self.assertEqual(nfe.state_edoc, SITUACAO_EDOC_A_ENVIAR)
nfe._document_status()
self.assertEqual(nfe.state_edoc, SITUACAO_EDOC_AUTORIZADA)

0 comments on commit b75f1ae

Please sign in to comment.