Browse Source

fix nfse natal

pull/262/head
Gabriela Cavalcante da Silva 6 years ago
parent
commit
9b125f513e
  1. 2
      .gitignore
  2. 51
      nfse-example.py
  3. 11
      pytrustnfe/nfe/assinatura.py
  4. 57
      pytrustnfe/nfse/natal/__init__.py
  5. 8
      pytrustnfe/nfse/natal/templates/EnvelopeSoap.xml
  6. 111
      pytrustnfe/nfse/natal/templates/Exemplo_LoteRPS.xml
  7. 79
      pytrustnfe/nfse/natal/templates/Rps.xml
  8. 3
      pytrustnfe/nfse/natal/templates/cabecalho.xml
  9. 6
      pytrustnfe/nfse/natal/templates/recepcionarLoteRps.xml
  10. 9
      pytrustnfe/nfse/susesu/templates/EnviarNota.xml
  11. 7
      pytrustnfe/xml/__init__.py
  12. 2
      tests/test_nfse_natal.py

2
.gitignore

@ -14,3 +14,5 @@ docs/_build
.cache
.pytest_cache
.vscode/
*.pfx
sent_xml.xml

51
nfse-example.py

@ -1,3 +1,4 @@
import ipdb
import xml.dom.minidom
import os
from pytrustnfe.nfse.natal import recepcionar_lote_rps
@ -9,46 +10,45 @@ rps_list = [
"numero": "1",
"serie": "UNICA",
"tipo_rps": "1",
"data_emissao": "2020-01-279",
"data_emissao": "2010-06-16T21:00:00",
"natureza_operacao": "1",
"regime_tributacao": "1",
"optante_simples": "1",
"incentivador_cultural": "2",
"status": "1",
"servico": {
"valor_servico": "1.00",
"pis": "0",
"cofins": "0",
"inss": "0",
"ir": "0",
"csll": "0",
"iss_retido": "2",
"iss": "2",
"retencoes": "2",
"base_calculo": "0.00",
"aliquota": "2",
"codigo_servico": "01.07",
"cnae_servico": "6209100",
"descricao": "Sistema NFSe",
"discriminacao": "Sistema NFSe",
"codigo_municipio": "2408102",
},
"prestador": {
"cnpj": "23809070000190",
"inscricao_municipal": "2143992",
"razao_social": "SERVICOS DE TI",
"fantasia": "SERVICOS DE TI",
"endereco": "AV AMINTAS",
"numero": "3755",
"complemento": "SALA 32",
"bairro": "Lagoa Nova",
"codigo_municipio": "2408102",
"uf": "RN",
"cep": "59075810",
"telefone": "4132095554",
"email": "SUPORTE@EMAIL.COM.BR",
"inscricao_municipal": "2143992"
},
"tomador": {
"cpf_cnpj": "01812418000166",
"inscricao_municipal": "2143992",
"razao_social": "LEONIR",
"endereco": "RUA GROBEIRO",
"numero": "128",
"complemento": "ANDAR 14",
"bairro": "Lagoa Nova",
"cidade": "3159506",
"codigo_municipio": "3159506",
"uf": "BH",
"cep": "1231231313",
"cep": "30160010",
"email": "leonir@yahoo.com.br",
"orgao_gerador": {"codigo_municipio": "3159506"},
},
}
]
@ -60,15 +60,18 @@ nfse = {
}
caminho = os.path.dirname(__file__)
pfx_source = open(os.path.join(caminho, "tests/teste.pfx"), "rb").read()
pfx = Certificado(pfx_source, "123456")
pfx_source = open(os.path.join(caminho, "tsmx-a1.pfx"), "rb").read()
pfx = Certificado(pfx_source, "12345678")
retorno = recepcionar_lote_rps(pfx, nfse=nfse, ambiente="homologacao")
# dom = xml.dom.minidom.parseString(retorno['received_xml'])
# received_xml = dom.toprettyxml()
# print(received_xml)
dom = xml.dom.minidom.parseString(retorno.get("sent_xml"))
dom = xml.dom.minidom.parseString(retorno['sent_xml']['nfseDadosMsg'])
sent_xml = dom.toprettyxml()
print(sent_xml)
myfile = open("sent_xml.xml", "w")
myfile.write(sent_xml)
dom = xml.dom.minidom.parseString(retorno['received_xml'])
received_xml = dom.toprettyxml()
print(received_xml)

11
pytrustnfe/nfe/assinatura.py

@ -24,9 +24,10 @@ class Assinatura(object):
method=signxml.methods.enveloped,
signature_algorithm="rsa-sha1",
digest_algorithm="sha1",
c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
c14n_algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments",
)
#import ipdb
#ipdb.set_trace()
ns = {}
ns[None] = signer.namespaces["ds"]
signer.namespaces = ns
@ -37,11 +38,11 @@ class Assinatura(object):
)
if reference:
element_signed = signed_root.find(".//*[@Id='%s']" % reference)
signature = signed_root.find(
signature = signed_root.findall(
".//{http://www.w3.org/2000/09/xmldsig#}Signature"
)
if element_signed is not None and signature is not None:
parent = element_signed.getparent()
parent.append(signature)
element_intern = element_signed.getchildren()
element_intern.append(signature)
return etree.tostring(signed_root, encoding=str)

57
pytrustnfe/nfse/natal/__init__.py

@ -2,6 +2,9 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
from OpenSSL import crypto
from base64 import b64encode
from requests import Session
from zeep import Client
from zeep.transports import Transport
@ -12,24 +15,45 @@ from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
from pytrustnfe.nfe.assinatura import Assinatura
def sign_rps(path, certificado, **kwargs):
if "nfse" in kwargs:
lote = ""
for item in kwargs["nfse"]["lista_rps"]:
data = {"rps": item}
xml_rps = render_xml(path, "Rps.xml", True, **data)
signer = Assinatura(certificado.pfx, certificado.password)
lote += signer.assina_xml(
xml_rps, f"rps:{item.get('numero')}{item.get('serie')}"
)
return lote
return ""
def _render(certificado, method, **kwargs):
path = os.path.join(os.path.dirname(__file__), "templates")
xml_send = render_xml(path, "%s.xml" % method, True, **kwargs)
lote = ""
if method == "RecepcionarLoteRps":
lote = sign_rps(path, certificado, **kwargs)
kwargs["lote"] = lote
xml_send = render_xml(path, "%s.xml" % method, False, **kwargs)
reference = ""
signer = Assinatura(certificado.pfx, certificado.password)
xml_send = signer.assina_xml(xml_send, reference)
referencia = "lote"
xml_send = signer.assina_xml(xml_send, f"{referencia}")
return xml_send
def _send(certificado, method, **kwargs):
base_url = ""
if kwargs["ambiente"] == "producao":
base_url = "https://aparecida.siltecnologia.com.br/tbw/services/Abrasf10?wsdl"
base_url = "" # https://wsnfsev1.natal.rn.gov.br:8444"
else:
base_url = "https://aparecida.siltecnologia.com.br/tbwhomologacao/services/Abrasf10?wsdl"
base_url = "https://wsnfsev1homologacao.natal.rn.gov.br:8443/axis2/services/NfseWSServiceV1?wsdl"
cert, key = extract_cert_and_key_from_pfx(certificado.pfx, certificado.password)
cert, key = extract_cert_and_key_from_pfx(
certificado.pfx, certificado.password)
cert, key = save_cert_key(cert, key)
disable_warnings()
@ -38,24 +62,29 @@ def _send(certificado, method, **kwargs):
session.verify = False
transport = Transport(session=session)
client = Client(base_url, transport=transport)
xml_send = kwargs["xml"]
response = client.service[method](xml_send)
client = Client(wsdl=base_url, transport=transport)
xml_send = {}
xml_send = {
"nfseDadosMsg": kwargs["xml"],
"nfseCabecMsg": """<?xml version="1.0"?>
<cabecalho xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" versao="1" xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
<versaoDados>1</versaoDados>
</cabecalho>""",
}
response = client.service[method](**xml_send)
response, obj = sanitize_response(response)
return {"sent_xml": xml_send, "received_xml": response, "object": obj}
def xml_recepcionar_lote_rps(certificado, **kwargs):
return _render(certificado, "recepcionarLoteRps", **kwargs)
return _render(certificado, "RecepcionarLoteRps", **kwargs)
def recepcionar_lote_rps(certificado, **kwargs):
if "xml" not in kwargs:
kwargs["xml"] = xml_recepcionar_lote_rps(certificado, **kwargs)
print(kwargs["xml"])
return {"sent_xml": kwargs["xml"]}
# return _send(certificado, 'recepcionarLoteRps', **kwargs)
return _send(certificado, "RecepcionarLoteRps", **kwargs)
def xml_consultar_lote_rps(certificado, **kwargs):

8
pytrustnfe/nfse/natal/templates/EnvelopeSoap.xml

@ -0,0 +1,8 @@
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<RecepcionarLoteRpsRequest xmlns="http://nfse.abrasf.org.br">
<nfseCabecMsg><![CDATA[{% include 'cabecalho.xml' %}]]></nfseCabecMsg>
<nfseDadosMsg><![CDATA[{% include 'RecepcionarLoteRps.xml' %}]]></nfseDadosMsg>
</RecepcionarLoteRpsRequest>
</soap:Body>
</soap:Envelope>

111
pytrustnfe/nfse/natal/templates/Exemplo_LoteRPS.xml

@ -0,0 +1,111 @@
<EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
<LoteRps Id="lote">
<NumeroLote>1</NumeroLote>
<Cnpj>27596568000505</Cnpj>
<InscricaoMunicipal>1000047</InscricaoMunicipal>
<QuantidadeRps>1</QuantidadeRps>
<ListaRps>
<Rps>
<InfRps Id="rps:1ABCDZ">
<IdentificacaoRps>
<Numero>1</Numero>
<Serie>ABCDH</Serie>
<Tipo>1</Tipo>
</IdentificacaoRps>
<DataEmissao>2010-06-16T21:00:00</DataEmissao>
<NaturezaOperacao>1</NaturezaOperacao>
<RegimeEspecialTributacao>6</RegimeEspecialTributacao>
<OptanteSimplesNacional>1</OptanteSimplesNacional>
<IncentivadorCultural>2</IncentivadorCultural>
<Status>1</Status>
<Servico>
<Valores>
<ValorServicos>1000</ValorServicos>
<ValorPis>10</ValorPis>
<ValorCofins>10</ValorCofins>
<ValorInss>10</ValorInss>
<ValorIr>10</ValorIr>
<ValorCsll>10</ValorCsll>
<IssRetido>1</IssRetido>
<ValorIss>50</ValorIss>
<OutrasRetencoes>10</OutrasRetencoes>
<BaseCalculo>1000</BaseCalculo>
<Aliquota>0.05</Aliquota>
</Valores>
<ItemListaServico>11.01</ItemListaServico>
<CodigoCnae>4520005</CodigoCnae>
<Discriminacao>Teste.</Discriminacao>
<CodigoMunicipio>3106200</CodigoMunicipio>
</Servico>
<Prestador>
<Cnpj>27596568000505</Cnpj>
<InscricaoMunicipal>1000047</InscricaoMunicipal>
</Prestador>
<Tomador>
<IdentificacaoTomador>
<CpfCnpj>
<Cnpj>24533572000102</Cnpj>
</CpfCnpj>
<InscricaoMunicipal>1000039</InscricaoMunicipal>
</IdentificacaoTomador>
<RazaoSocial>INSCRICAO DE TESTE SIATU - DAGUA -PAULINOS</RazaoSocial>
<Endereco>
<Endereco>DA BAHIA</Endereco>
<Numero>200</Numero>
<Complemento>ANDAR 14</Complemento>
<Bairro>CENTRO</Bairro>
<CodigoMunicipio>2408102</CodigoMunicipio>
<Uf>RN</Uf>
<Cep>30160010</Cep>
</Endereco>
<Contato>
<Email>marcelo@teste.com.br</Email>
</Contato>
</Tomador>
<ConstrucaoCivil>
<CodigoObra>1234</CodigoObra>
<Art>1234</Art>
</ConstrucaoCivil>
</InfRps>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#rps:1ABCDZ">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>mMyQLAm4psxx52kaD8Jlta3ouPM=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>qBKfaNz6RbsYUxCOrjGZ9zrdgiGL7QSBxjlhYRlKDNlDERlDWvM8gi28yus8FoUb0v2CTKKIBz0tzfqxgk60rke4YCMkTzdWfpm7ofMIhYC9VHqbWdInC20znOKygJy5hyIx6JBoyXbejnw/0KF+2E1P1ZehqXJWZqY+KPaIGAY=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIE7DCCA9SgAwIBAgIQZMlLC9ZEsHWsnvJNdMI2yzANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDEsMCoGA1UECxMjU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgLSBTUkYxGDAWBgNVBAMTD0FDIFBST0RFTUdFIFNSRjAeFw0wNzEwMzEwMDAwMDBaFw0xMDEwMzAyMzU5NTlaMIGQMQswCQYDVQQGEwJCUjETMBEGA1UEChQKSUNQLUJyYXNpbDEqMCgGA1UECxQhU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwtU1JGMRIwEAYDVQQLFAlTUkYgZS1DUEYxLDAqBgNVBAMTI0VER0FSIERPIENBUk1PIEZFUlJFSVJBOjQzMjYwMTUyNjg3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6M+9XT5KLQN3IH8mAr+S6vxiochY/EwF8EhtNoxPTYl+zr0Dh+eZsRG31bN410nr2OrwncrRorMK8Ngq+j3FnNF0nIMigaaa5NAEfIk3Yy4kuqrTUZBpqUJvCqc3mkF3C3XD0MTmtbVTWCvYIk+qn3t5ShHyMnQcuah5Q0ItSbQIDAQABo4IB6TCCAeUwgZUGA1UdEQSBjTCBiqA9BgVgTAEDAaA0BDIyMTAzMTk2NDQzMjYwMTUyNjg3MDAwMDAwMDAwMDAwMDAwMDBNLTI4ODQwODVTU1BNR6AXBgVgTAEDBqAOBAwwMDAwMDAwMDAwMDCgHgYFYEwBAwWgFQQTMDAwMDAwMDAwMDAwMDAwMDAwMIEQZWRnYXJAcGJoLmdvdi5icjAJBgNVHRMEAjAAMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2lnbi5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDUFJPREVNR0VTUkYvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBTdO9vtjZcRRUMBQ020Ev0O7niacDAOBgNVHQ8BAf8EBAMCBeAwVQYDVR0gBE4wTDBKBgZgTAECAxQwQDA+BggrBgEFBQcCARYyaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9kcGMwHQYDVR0lBBYwFAYIKwYBBQUHAwQGCCsGAQUFBwMCMDgGCCsGAQUFBwEBBCwwKjAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AuY2VydGlzaWduLmNvbS5icjANBgkqhkiG9w0BAQUFAAOCAQEAYFcjZj4lGVEREHBaHtcRletWS6/mvpkxmodwj3ele5yXsxuqSZd7ebHbKewXx7gkyaWFkFAxFanQhls2tYKjg6haqt2b0AO1FsitVIHkMcxRwkU9G+1ec8yfdxymra2VdXazkxuvqKABgxkqKnaFdHjje7cjWDgwparymH64mTlHkSQz59GutJW0xfwBHcMGx0/9/iIug6pfMQivWf0NMVpFNzxO5ZNPEuOeBhVDxQr4+KB+4B9xDai/3J6f42UNbSy+z3xuB0K8/7V7BsFUYOYFSNnBrXhvbvXtZOtteX65V0r1+RJJX5OK+PAPhZ57T1LEmHMggdo5kli3Nr1KFQ==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Rps>
</ListaRps>
</LoteRps>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="Ass_lote">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#lote">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>n42EhtzDSnZ071g+44ZMBCc74UQ=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>pQyeXnJ2S9KyUJ1BE3k3PZuDpk7WkD2nMPLoELSLJeNBe9TwmLhImsIUS4inAUreuTsjfrs2BUmChN6jPA0/1cSR0GbblLsHFN+IwPE2dnPN/u0vIOmsan4MuW1OnlH6KexmDHRj/uFwjoXfSJ0JJE1u9bYdbsp5LGlFuc//CCQ=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIE7DCCA9SgAwIBAgIQZMlLC9ZEsHWsnvJNdMI2yzANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDEsMCoGA1UECxMjU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgLSBTUkYxGDAWBgNVBAMTD0FDIFBST0RFTUdFIFNSRjAeFw0wNzEwMzEwMDAwMDBaFw0xMDEwMzAyMzU5NTlaMIGQMQswCQYDVQQGEwJCUjETMBEGA1UEChQKSUNQLUJyYXNpbDEqMCgGA1UECxQhU2VjcmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwtU1JGMRIwEAYDVQQLFAlTUkYgZS1DUEYxLDAqBgNVBAMTI0VER0FSIERPIENBUk1PIEZFUlJFSVJBOjQzMjYwMTUyNjg3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6M+9XT5KLQN3IH8mAr+S6vxiochY/EwF8EhtNoxPTYl+zr0Dh+eZsRG31bN410nr2OrwncrRorMK8Ngq+j3FnNF0nIMigaaa5NAEfIk3Yy4kuqrTUZBpqUJvCqc3mkF3C3XD0MTmtbVTWCvYIk+qn3t5ShHyMnQcuah5Q0ItSbQIDAQABo4IB6TCCAeUwgZUGA1UdEQSBjTCBiqA9BgVgTAEDAaA0BDIyMTAzMTk2NDQzMjYwMTUyNjg3MDAwMDAwMDAwMDAwMDAwMDBNLTI4ODQwODVTU1BNR6AXBgVgTAEDBqAOBAwwMDAwMDAwMDAwMDCgHgYFYEwBAwWgFQQTMDAwMDAwMDAwMDAwMDAwMDAwMIEQZWRnYXJAcGJoLmdvdi5icjAJBgNVHRMEAjAAMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly9pY3AtYnJhc2lsLmNlcnRpc2lnbi5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDUFJPREVNR0VTUkYvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBTdO9vtjZcRRUMBQ020Ev0O7niacDAOBgNVHQ8BAf8EBAMCBeAwVQYDVR0gBE4wTDBKBgZgTAECAxQwQDA+BggrBgEFBQcCARYyaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9kcGMwHQYDVR0lBBYwFAYIKwYBBQUHAwQGCCsGAQUFBwMCMDgGCCsGAQUFBwEBBCwwKjAoBggrBgEFBQcwAYYcaHR0cDovL29jc3AuY2VydGlzaWduLmNvbS5icjANBgkqhkiG9w0BAQUFAAOCAQEAYFcjZj4lGVEREHBaHtcRletWS6/mvpkxmodwj3ele5yXsxuqSZd7ebHbKewXx7gkyaWFkFAxFanQhls2tYKjg6haqt2b0AO1FsitVIHkMcxRwkU9G+1ec8yfdxymra2VdXazkxuvqKABgxkqKnaFdHjje7cjWDgwparymH64mTlHkSQz59GutJW0xfwBHcMGx0/9/iIug6pfMQivWf0NMVpFNzxO5ZNPEuOeBhVDxQr4+KB+4B9xDai/3J6f42UNbSy+z3xuB0K8/7V7BsFUYOYFSNnBrXhvbvXtZOtteX65V0r1+RJJX5OK+PAPhZ57T1LEmHMggdo5kli3Nr1KFQ==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</EnviarLoteRpsEnvio>

79
pytrustnfe/nfse/natal/templates/Rps.xml

@ -1,5 +1,5 @@
<Rps>
<InfRps Id="{{ rps.numero }}">
<InfRps Id="rps:{{ rps.numero }}{{ rps.serie }}">
<IdentificacaoRps>
<Numero>{{ rps.numero }}</Numero>
<Serie>{{ rps.serie }}</Serie>
@ -10,47 +10,57 @@
<RegimeEspecialTributacao>{{ rps.regime_tributacao }}</RegimeEspecialTributacao>
<OptanteSimplesNacional>{{ rps.optante_simples }}</OptanteSimplesNacional>
<IncentivadorCultural>{{ rps.incentivador_cultural }}</IncentivadorCultural>
<Status>{{ rps.status }}</Status>
<Servico>
<Valores>
<ValorServicos>{{ rps.servico.valor_servico }}</ValorServicos>
<ValorPis>{{ rps.servico.pis }}</ValorPis>
<ValorCofins>{{ rps.servico.cofins }}</ValorCofins>
<ValorInss>{{ rps.servico.inss }}</ValorInss>
<ValorIr>{{ rps.servico.ir }}</ValorIr>
<ValorCsll>{{ rps.servico.csll }}</ValorCsll>
<IssRetido>{{ rps.servico.iss_retido }}</IssRetido>
<ValorIss>{{ rps.servico.iss }}</ValorIss>
<OutrasRetencoes>{{ rps.servico.retencoes }}</OutrasRetencoes>
<BaseCalculo>{{ rps.servico.base_calculo }}</BaseCalculo>
<Aliquota>{{ rps.servico.aliquota }}</Aliquota>
</Valores>
<ItemListaServico>{{ rps.servico.codigo_servico }}</ItemListaServico>
<CodigoCnae>{{ rps.servico.cnae_servico }}</CodigoCnae>
<CodigoTributacaoMunicipio>{{ rps.servico.codigo_tributacao_municipio }}</CodigoTributacaoMunicipio>
<Discriminacao>{{ rps.servico.descricao }}</Discriminacao>
<Discriminacao>{{ rps.servico.discriminacao }}</Discriminacao>
<CodigoMunicipio>{{ rps.servico.codigo_municipio }}</CodigoMunicipio>
</Servico>
<PrestadorServico>
<IdentificacaoPrestador>
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj>
<InscricaoMunicipal>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipal>
</IdentificacaoPrestador>
<Prestador>
<Cnpj>{{ rps.prestador.cnpj }}</Cnpj>
<InscricaoMunicipal>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipal>
<RazaoSocial>{{ rps.prestador.razaosocial }}</RazaoSocial>
<NomeFantasia>{{ rps.prestador.fantasia }}</NomeFantasia>
<Endereco>
<Endereco>{{ rps.prestador.endereco }}</Endereco>
<Numero>{{ rps.prestador.numero }}</Numero>
<Complemento>{{ rps.prestador.complemento }}</Complemento>
<Bairro>{{ rps.prestador.bairro }}</Bairro>
<CodigoMunicipio>{{ rps.prestador.codigomunicipal }}</CodigoMunicipio>
<Uf>{{ rps.prestador.uf }}</Uf>
<Cep>{{ rps.prestador.cep }}</Cep>
<Endereco>{{ rps.prestador.endereco }}</Endereco>
<Numero>{{ rps.prestador.numero }}</Numero>
<Complemento>{{ rps.prestador.complemento }}</Complemento>
<Bairro>{{ rps.prestador.bairro }}</Bairro>
<CodigoMunicipio>{{ rps.prestador.codigomunicipal }}</CodigoMunicipio>
<Uf>{{ rps.prestador.uf }}</Uf>
<Cep>{{ rps.prestador.cep }}</Cep>
</Endereco>
<Contato>
<Telefone>{{ rps.prestador.telefone }}</Telefone>
<Email>{{ rps.prestador.email }}</Email>
{% if rps.prestador.telefone is defined -%}
<Telefone>{{ rps.prestador.telefone }}</Telefone>
{% endif %}
{% if rps.prestador.email is defined -%}
<Email>{{ rps.prestador.email }}</Email>
{% endif %}
</Contato>
</PrestadorServico>
<TomadorServico>
</Prestador>
<Tomador>
<IdentificacaoTomador>
<CpfCnpj>
{% if rps.tomador.cnpj_cpf|length == 14 %}
<Cnpj>{{ rps.tomador.cnpj_cpf }}</Cnpj>
{% if rps.tomador.cpf_cnpj|length == 14 %}
<Cnpj>{{ rps.tomador.cpf_cnpj }}</Cnpj>
{% endif %}
{% if rps.tomador.cnpj_cpf|length == 11 %}
<Cpf>{{ rps.tomador.cnpj_cpf }}</Cpf>
{% if rps.tomador.cpf_cnpj|length == 11 %}
<Cpf>{{ rps.tomador.cpf_cnpj }}</Cpf>
{% endif %}
</CpfCnpj>
{% if rps.tomador.inscricao_municipal is defined -%}
@ -59,29 +69,29 @@
</IdentificacaoTomador>
<RazaoSocial>{{ rps.tomador.razao_social }}</RazaoSocial>
<Endereco>
<Endereco>{{ rps.tomador.logradouro }}</Endereco>
<Numero>{{ rps.tomador.numero }}</Numero>
{% if rps.tomador.complemento is defined -%}
<Complemento>{{ rps.tomador.complemento }}</Complemento>
{% endif %}
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<CodigoMunicipio>{{ rps.tomador.codigo_municipio }}</CodigoMunicipio>
<Uf>{{ rps.tomador.uf }}</Uf>
<Cep>{{ rps.tomador.cep }}</Cep>
<Endereco>{{ rps.tomador.endereco }}</Endereco>
<Numero>{{ rps.tomador.numero }}</Numero>
<Complemento>{{ rps.tomador.complemento }}</Complemento>
<Bairro>{{ rps.tomador.bairro }}</Bairro>
<CodigoMunicipio>{{ rps.tomador.codigo_municipio }}</CodigoMunicipio>
<Uf>{{ rps.tomador.uf }}</Uf>
<Cep>{{ rps.tomador.cep }}</Cep>
</Endereco>
<Contato>
{% if rps.tomador.telefone is defined -%}
<Telefone>{{ rps.tomador.telefone }}</Telefone>
{% endif %}
{% if rps.tomador.email is defined -%}
<Telefone>{{ rps.tomador.email }}</Telefone>
<Email>{{ rps.tomador.email }}</Email>
{% endif %}
</Contato>
{% if rps.tomador.orgao_gerador is defined -%}
<OrgaoGerador>
<CodigoMunicipio>{{ rps.tomador.orgao_gerador.codigo_municipio }}</CodigoMunicipio>
<Uf>{{ rps.tomador.orgao_gerador.uf }}</Uf>
</OrgaoGerador>
</TomadorServico>
{% endif %}
</Tomador>
{% if rps.intermediario is defined -%}
<IntermediarioServico>
<RazaoSocial>{{ rps.intermediario.razao_social }}</RazaoSocial>
@ -98,4 +108,5 @@
</ContrucaoCivil>
{% endif %}
</InfRps>
<Signature Id="placeholder"></Signature>
</Rps>

3
pytrustnfe/nfse/natal/templates/cabecalho.xml

@ -0,0 +1,3 @@
<cabecalho versao="2.01" xmlns="http://www.abrasf.org.br/nfse.xsd">
<versaoDados>2.01</versaoDados>
</cabecalho>

6
pytrustnfe/nfse/natal/templates/recepcionarLoteRps.xml

@ -1,13 +1,11 @@
<EnviarLoteRpsEnvio xmlns="http://www.abrasf.org.br/ABRASF/arquivos/nfse.xsd">
<LoteRps Id="{{ nfse.numero_lote }}">
<LoteRps Id="lote">
<NumeroLote>{{ nfse.numero_lote }}</NumeroLote>
<Cnpj>{{ nfse.cnpj_prestador }}</Cnpj>
<InscricaoMunicipal>{{ nfse.inscricao_municipal }}</InscricaoMunicipal>
<QuantidadeRps>{{ nfse.lista_rps|length }}</QuantidadeRps>
<ListaRps>
{% for rps in nfse.lista_rps -%}
{% include 'Rps.xml' %}
{% endfor %}
{{lote}}
</ListaRps>
</LoteRps>
</EnviarLoteRpsEnvio>

9
pytrustnfe/nfse/susesu/templates/EnviarNota.xml

@ -1,5 +1,6 @@
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.nfse">
<x:Header/>
<x:Body>
<EnviarNota xmlns="http://susesu.com.br/">
<codPrefeitura>{{ codigo_prefeitura }}</codPrefeitura>
<notaFiscal>
@ -10,5 +11,5 @@
<cnpjPrestador>{{ cnpj_prestador }}</cnpjPrestador>
<senhaNFD>{{ senha_nfd }}</senhaNFD>
</EnviarNota>
</soap:Body>
</soap:Envelope>
</x:Body>
</x:Envelope>

7
pytrustnfe/xml/__init__.py

@ -17,7 +17,8 @@ def recursively_empty(e):
def render_xml(path, template_name, remove_empty, **nfe):
nfe = recursively_normalize(nfe)
env = Environment(loader=FileSystemLoader(path), extensions=["jinja2.ext.with_"])
env = Environment(loader=FileSystemLoader(
path), extensions=["jinja2.ext.with_"])
env.filters["normalize"] = filters.strip_line_feed
env.filters["normalize_str"] = filters.normalize_str
env.filters["format_percent"] = filters.format_percent
@ -41,7 +42,7 @@ def render_xml(path, template_name, remove_empty, **nfe):
if recursively_empty(elem):
parent.remove(elem)
return root
return etree.tostring(root, encoding=str)
return root
def sanitize_response(response):
@ -53,7 +54,7 @@ def sanitize_response(response):
continue
i = elem.tag.find("}")
if i >= 0:
elem.tag = elem.tag[i + 1 :]
elem.tag = elem.tag[i + 1:]
objectify.deannotate(tree, cleanup_namespaces=True)
return response, objectify.fromstring(etree.tostring(tree))

2
tests/test_nfse_natal.py

@ -70,7 +70,7 @@ class test_nfse_natal(unittest.TestCase):
def test_recepcionar_lote_rps(self):
pfx_source = open(os.path.join(self.caminho, "teste.pfx"), "rb").read()
pfx = Certificado(pfx_source, "123456")
pfx = Certificado(pfx_source, "123456", ambiente="homologacao")
nfse = self._get_nfse()
path = os.path.join(os.path.dirname(__file__), "XMLs")

Loading…
Cancel
Save