committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1168 additions and 840 deletions
-
39pytrustnfe/nfe/danfe.py
-
131pytrustnfe/nfse/dsf/__init__.py
-
18pytrustnfe/nfse/dsf/templates/cancelar.xml
-
11pytrustnfe/nfse/dsf/templates/consulta_notas.xml
-
10pytrustnfe/nfse/dsf/templates/consultarLote.xml
-
22pytrustnfe/nfse/dsf/templates/consultarNFSeRps.xml
-
108pytrustnfe/nfse/dsf/templates/enviar.xml
-
12pytrustnfe/nfse/dsf/templates/soap_header.xml
-
2pytrustnfe/xml/__init__.py
-
1setup.py
@ -0,0 +1,131 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
# © 2017 Fábio Luna, Trustcode |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import os |
||||
|
import suds |
||||
|
from lxml import etree |
||||
|
from pytrustnfe.xml import render_xml, sanitize_response |
||||
|
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key |
||||
|
from pytrustnfe.nfse.assinatura import Assinatura |
||||
|
from pytrustnfe.client import get_client |
||||
|
|
||||
|
|
||||
|
def _render(certificado, method, **kwargs): |
||||
|
path = os.path.join(os.path.dirname(__file__), 'templates') |
||||
|
if method == "testeEnviar": |
||||
|
xml_send = render_xml(path, 'enviar.xml', True, **kwargs) |
||||
|
else: |
||||
|
xml_send = render_xml(path, '%s.xml' % method, False, **kwargs) |
||||
|
|
||||
|
if type(xml_send) != str: |
||||
|
xml_send = etree.tostring(xml_send) |
||||
|
|
||||
|
return xml_send |
||||
|
|
||||
|
|
||||
|
def _get_url(**kwargs): |
||||
|
|
||||
|
try: |
||||
|
cod_cidade = kwargs['nfse']['cidade'] |
||||
|
except (KeyError, TypeError): |
||||
|
raise KeyError("Código de cidade inválido!") |
||||
|
|
||||
|
urls = { |
||||
|
# Belém - PA |
||||
|
'2715': 'http://www.issdigitalbel.com.br/WsNFe2/LoteRps.jws', |
||||
|
# Sorocaba - SP |
||||
|
'7145': 'http://issdigital.sorocaba.sp.gov.br/WsNFe2/LoteRps.jws', |
||||
|
# Teresina - PI |
||||
|
'1219': 'http://www.issdigitalthe.com.br/WsNFe2/LoteRps.jws', |
||||
|
# Campinas - SP |
||||
|
'6291': 'http://issdigital.campinas.sp.gov.br/WsNFe2/LoteRps.jws?wsdl', |
||||
|
# Uberlandia - MG |
||||
|
'5403': 'http://udigital.uberlandia.mg.gov.br/WsNFe2/LoteRps.jws', |
||||
|
# São Luis - MA |
||||
|
'0921': 'https://stm.semfaz.saoluis.ma.gov.br/WsNFe2/LoteRps?wsdl', |
||||
|
# Campo Grande - MS |
||||
|
'2729': 'http://issdigital.pmcg.ms.gov.br/WsNFe2/LoteRps.jws?wsdl', |
||||
|
} |
||||
|
|
||||
|
try: |
||||
|
return urls[str(cod_cidade)] |
||||
|
except KeyError: |
||||
|
raise KeyError("DSF não emite notas da cidade {}!".format( |
||||
|
cod_cidade)) |
||||
|
|
||||
|
|
||||
|
def _send(certificado, method, **kwargs): |
||||
|
url = _get_url(**kwargs) |
||||
|
|
||||
|
path = os.path.join(os.path.dirname(__file__), 'templates') |
||||
|
|
||||
|
xml_send = _render(path, method, **kwargs) |
||||
|
client = get_client(url) |
||||
|
response = False |
||||
|
|
||||
|
if certificado: |
||||
|
cert, key = extract_cert_and_key_from_pfx( |
||||
|
certificado.pfx, certificado.password) |
||||
|
cert, key = save_cert_key(cert, key) |
||||
|
signer = Assinatura(cert, key, certificado.password) |
||||
|
xml_send = signer.assina_xml(xml_send, '') |
||||
|
|
||||
|
try: |
||||
|
response = getattr(client.service, method)(xml_send) |
||||
|
response, obj = sanitize_response(response.encode()) |
||||
|
except suds.WebFault as e: |
||||
|
return { |
||||
|
'sent_xml': xml_send, |
||||
|
'received_xml': e.fault.faultstring, |
||||
|
'object': None |
||||
|
} |
||||
|
except Exception as e: |
||||
|
if response: |
||||
|
raise Exception(response) |
||||
|
else: |
||||
|
raise e |
||||
|
|
||||
|
return { |
||||
|
'sent_xml': xml_send, |
||||
|
'received_xml': response, |
||||
|
'object': obj |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def xml_enviar(certificado, **kwargs): |
||||
|
return _render(certificado, 'enviar', **kwargs) |
||||
|
|
||||
|
|
||||
|
def enviar(certificado, **kwargs): |
||||
|
if "xml" not in kwargs: |
||||
|
kwargs['xml'] = xml_enviar(certificado, **kwargs) |
||||
|
return _send(certificado, 'enviar', **kwargs) |
||||
|
|
||||
|
|
||||
|
def xml_teste_enviar(certificado, **kwargs): |
||||
|
return _render(certificado, 'testeEnviar', **kwargs) |
||||
|
|
||||
|
|
||||
|
def teste_enviar(certificado, **kwargs): |
||||
|
if "xml" not in kwargs: |
||||
|
kwargs['xml'] = xml_teste_enviar(certificado, **kwargs) |
||||
|
return _send(certificado, 'testeEnviar', **kwargs) |
||||
|
|
||||
|
|
||||
|
def cancelar(certificado, ** kwargs): |
||||
|
return _send(certificado, 'cancelar', **kwargs) |
||||
|
|
||||
|
|
||||
|
def consulta_lote(**kwargs): |
||||
|
return _send(False, 'consultarLote', **kwargs) |
||||
|
|
||||
|
|
||||
|
def xml_consultar_nfse_rps(certificado, **kwargs): |
||||
|
return _render(certificado, 'consultarNFSeRps', **kwargs) |
||||
|
|
||||
|
|
||||
|
def consultar_nfse_rps(certificado, **kwargs): |
||||
|
if "xml" not in kwargs: |
||||
|
kwargs['xml'] = xml_consultar_nfse_rps(certificado, **kwargs) |
||||
|
return _send(certificado, 'consultarNFSeRps', **kwargs) |
||||
@ -0,0 +1,18 @@ |
|||||
|
<ns1:ReqCancelamentoNFSe xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
||||
|
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqCancelamentoNFSe.xsd"> |
||||
|
<Cabecalho> |
||||
|
<CodCidade>{{ cancelamento.cidade }}</CodCidade> |
||||
|
<CPFCNPJRemetente>{{ cancelamento.cpf_cnpj }}</CPFCNPJRemetente> |
||||
|
<transacao>true</transacao> |
||||
|
<Versao>1</Versao> |
||||
|
</Cabecalho> |
||||
|
<Lote Id="lote:1ABCDZ"> |
||||
|
<Nota Id="nota:{{ cancelamento.nota_id }}"> |
||||
|
<InscricaoMunicipalPrestador>{{ cancelamento.inscricao_municipal }}</InscricaoMunicipalPrestador> |
||||
|
<NumeroNota>{{ cancelamento.nota_id }}</NumeroNota> |
||||
|
<CodigoVerificacao>{{ cancelamento.assinatura }}</CodigoVerificacao> |
||||
|
<MotivoCancelamento>{{ cancelamento.motivo }}</MotivoCancelamento> |
||||
|
</Nota> |
||||
|
</Lote> |
||||
|
</ns1:ReqCancelamentoNFSe> |
||||
@ -0,0 +1,11 @@ |
|||||
|
<ns1:ReqConsultaNotas xmlns:ns1="http://localhost:8080/WsNFe2/lote" xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaNotas.xsd"> |
||||
|
<Cabecalho Id="Consulta:notas"> |
||||
|
<CodCidade>{{ consulta.cidade }}</CodCidade> |
||||
|
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente> |
||||
|
<InscricaoMunicipalPrestador>{{ consulta.inscricao_municipal }}</InscricaoMunicipalPrestador> |
||||
|
<dtInicio>{{ consulta.data_inicio }}</dtInicio> |
||||
|
<dtFim>{{ consulta.data_final }}</dtFim> |
||||
|
<NotaInicial>{{ consulta.nota_inicial }}</NotaInicial> |
||||
|
<Versao>1</Versao> |
||||
|
</Cabecalho> |
||||
|
</ns1:ReqConsultaNotas> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<ns1:ReqConsultaLote xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
||||
|
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaLote.xsd"> |
||||
|
<Cabecalho> |
||||
|
<CodCidade>{{ consulta.cidade }}</CodCidade> |
||||
|
<CPFCNPJRemetente>{{ consulta.cpf_cnpj }}</CPFCNPJRemetente> |
||||
|
<Versao>1</Versao> |
||||
|
<NumeroLote>{{ consulta.lote }}</NumeroLote> |
||||
|
</Cabecalho> |
||||
|
</ns1:ReqConsultaLote> |
||||
@ -0,0 +1,22 @@ |
|||||
|
<ns1:ReqConsultaNFSeRPS |
||||
|
xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
||||
|
xmlns:tipos="http://localhost:8080/WsNFe2/tp" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqConsultaNFSeRPS.xsd"> |
||||
|
<Cabecalho> |
||||
|
<CodCidade>{{ nfse.cidade }}</CodCidade> |
||||
|
<CPFCNPJRemetente>{{ nfse.cpf_cnpj }}</CPFCNPJRemetente> |
||||
|
<transacao>true</transacao> |
||||
|
<Versao>1</Versao> |
||||
|
</Cabecalho> |
||||
|
<Lote Id="lote:{{ nfse.lote }}"> |
||||
|
{% for rps in nfse.lista_rps -%} |
||||
|
<RPSConsulta> |
||||
|
<RPS Id="rps:{{ rps.numero }}"> |
||||
|
<InscricaoMunicipalPrestador>{{ rps.prestador.inscricao_municipal }}</InscricaoMunicipalPrestador> |
||||
|
<NumeroRPS>{{ rps.numero }}</NumeroRPS> |
||||
|
<SeriePrestacao>{{ rps.serie_prestacao }}</SeriePrestacao> |
||||
|
</RPS> |
||||
|
</RPSConsulta> |
||||
|
{% endfor %} |
||||
|
</Lote> |
||||
|
</ns1:ReqConsultaNFSeRPS> |
||||
@ -0,0 +1,108 @@ |
|||||
|
<ns1:ReqEnvioLoteRPS xmlns:ns1="http://localhost:8080/WsNFe2/lote" |
||||
|
xmlns:tipos="http://localhost:8080/WsNFe2/tp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://localhost:8080/WsNFe2/lote http://localhost:8080/WsNFe2/xsd/ReqEnvioLoteRPS.xsd"> |
||||
|
<Cabecalho> |
||||
|
<CodCidade>{{ nfse.cidade }}</CodCidade> |
||||
|
<CPFCNPJRemetente>{{ nfse.cpf_cnpj }}</CPFCNPJRemetente> |
||||
|
<RazaoSocialRemetente>{{ nfse.remetente }}</RazaoSocialRemetente> |
||||
|
<transacao>{{ nfse.transacao }}</transacao> |
||||
|
<dtInicio>{{ nfse.data_inicio|format_date }}</dtInicio> |
||||
|
<dtFim>{{ nfse.data_fim|format_date }}</dtFim> |
||||
|
<QtdRPS>{{ nfse.total_rps }}</QtdRPS> |
||||
|
<ValorTotalServicos>{{ nfse.total_servicos }}</ValorTotalServicos> |
||||
|
<ValorTotalDeducoes>{{ nfse.total_deducoes }}</ValorTotalDeducoes> |
||||
|
<Versao>1</Versao> |
||||
|
<MetodoEnvio>WS</MetodoEnvio> |
||||
|
</Cabecalho> |
||||
|
<Lote Id="{{ nfse.lote_id }}"> |
||||
|
{% for rps in nfse.lista_rps -%} |
||||
|
<RPS Id="{{ rps.numero }}"> |
||||
|
<Assinatura>{{ rps.assinatura }}</Assinatura> |
||||
|
<InscricaoMunicipalPrestador>{{ rps.prestador.inscricao_municipal }} |
||||
|
</InscricaoMunicipalPrestador> |
||||
|
<RazaoSocialPrestador>{{ rps.prestador.razao_social }}</RazaoSocialPrestador> |
||||
|
<TipoRPS>RPS</TipoRPS> |
||||
|
<SerieRPS>{{ rps.serie }}</SerieRPS> |
||||
|
<NumeroRPS>{{ rps.numero }}</NumeroRPS> |
||||
|
<DataEmissaoRPS>{{ rps.data_emissao|format_datetime }} |
||||
|
</DataEmissaoRPS> |
||||
|
<SituacaoRPS>{{ rps.situacao }}</SituacaoRPS> |
||||
|
<SerieRPSSubstituido></SerieRPSSubstituido> |
||||
|
<NumeroRPSSubstituido>0</NumeroRPSSubstituido> |
||||
|
<NumeroNFSeSubstituida>0</NumeroNFSeSubstituida> |
||||
|
<DataEmissaoNFSeSubstituida>1900-01-01</DataEmissaoNFSeSubstituida> |
||||
|
<SeriePrestacao>{{ rps.serie_prestacao }}</SeriePrestacao> |
||||
|
<InscricaoMunicipalTomador>{{ rps.tomador.inscricao_municipal }}</InscricaoMunicipalTomador> |
||||
|
<CPFCNPJTomador>{{ rps.tomador.cpf_cnpj }}</CPFCNPJTomador> |
||||
|
<RazaoSocialTomador>{{ rps.tomador.razao_social }} |
||||
|
</RazaoSocialTomador> |
||||
|
<TipoLogradouroTomador>{{ rps.tomador.tipo_logradouro }} |
||||
|
</TipoLogradouroTomador> |
||||
|
<LogradouroTomador>{{ rps.tomador.logradouro }}</LogradouroTomador> |
||||
|
<NumeroEnderecoTomador>{{ rps.tomador.numero }} |
||||
|
</NumeroEnderecoTomador> |
||||
|
<TipoBairroTomador>{{ rps.tomador.tipo_bairro }}</TipoBairroTomador> |
||||
|
<BairroTomador>{{ rps.tomador.bairro }}</BairroTomador> |
||||
|
<CidadeTomador>{{ rps.tomador.cidade }}</CidadeTomador> |
||||
|
<CidadeTomadorDescricao>{{ rps.tomador.cidade_descricao }} |
||||
|
</CidadeTomadorDescricao> |
||||
|
<CEPTomador>{{ rps.tomador.cep }}</CEPTomador> |
||||
|
<EmailTomador>{{ rps.tomador.email }}</EmailTomador> |
||||
|
<CodigoAtividade>{{ rps.codigo_atividade }}</CodigoAtividade> |
||||
|
<AliquotaAtividade>{{ rps.aliquota_atividade }}</AliquotaAtividade> |
||||
|
<TipoRecolhimento>{{ rps.tipo_recolhimento }}</TipoRecolhimento> |
||||
|
<MunicipioPrestacao>{{ rps.municipio_prestacao }} |
||||
|
</MunicipioPrestacao> |
||||
|
<MunicipioPrestacaoDescricao>{{ rps.municipio_descricao_prestacao }} |
||||
|
</MunicipioPrestacaoDescricao> |
||||
|
<Operacao>{{ rps.operacao }}</Operacao> |
||||
|
<Tributacao>{{ rps.tributacao }}</Tributacao> |
||||
|
<ValorPIS>{{ rps.valor_pis }}</ValorPIS> |
||||
|
<ValorCOFINS>{{ rps.valor_cofins }}</ValorCOFINS> |
||||
|
<ValorINSS>{{ rps.valor_inss }}</ValorINSS> |
||||
|
<ValorIR>{{ rps.valor_ir }}</ValorIR> |
||||
|
<ValorCSLL>{{ rps.valor_csll }}</ValorCSLL> |
||||
|
<AliquotaPIS>{{ rps.aliquota_pis }}</AliquotaPIS> |
||||
|
<AliquotaCOFINS>{{ rps.aliquota_cofins }}</AliquotaCOFINS> |
||||
|
<AliquotaINSS>{{ rps.aliquota_inss }}</AliquotaINSS> |
||||
|
<AliquotaIR>{{ rps.aliquota_ir }}</AliquotaIR> |
||||
|
<AliquotaCSLL>{{ rps.aliquota_csll }}</AliquotaCSLL> |
||||
|
<DescricaoRPS>{{ rps.descricao }}</DescricaoRPS> |
||||
|
<DDDPrestador>{{ rps.prestador.ddd }}</DDDPrestador> |
||||
|
<TelefonePrestador>{{ rps.prestador.telefone }}</TelefonePrestador> |
||||
|
<DDDTomador>{{ rps.tomador.ddd }}</DDDTomador> |
||||
|
<TelefoneTomador>{{ rps.tomador.telefone }}</TelefoneTomador> |
||||
|
<MotCancelamento>{{ rps.motivo_cancelamento }}</MotCancelamento> |
||||
|
{% if rps.deducoes|count > 0 %} |
||||
|
<Deducoes> |
||||
|
{% for deducao in rps.deducoes -%} |
||||
|
<Deducao> |
||||
|
<DeducaoPor>{{ deducao.por }}</DeducaoPor> |
||||
|
<TipoDeducao>{{ deducao.tipo }}</TipoDeducao> |
||||
|
<CPFCNPJReferencia>{{ deducao.cnpj_referencia }}</CPFCNPJReferencia> |
||||
|
<NumeroNFReferencia>{{ deducao.nf_referencia }}</NumeroNFReferencia> |
||||
|
<ValorTotalReferencia>{{ deducao.valor_referencia }}</ValorTotalReferencia> |
||||
|
<PercentualDeduzir>{{ deducao.percentual_deduzir }}</PercentualDeduzir> |
||||
|
<ValorDeduzir>{{ deducao.valor_deduzir }}</ValorDeduzir> |
||||
|
</Deducao> |
||||
|
{% endfor %} |
||||
|
</Deducoes> |
||||
|
{% endif %} |
||||
|
{% if rps.deducoes|count == 0 %} |
||||
|
<Deducoes /> |
||||
|
{% endif %} |
||||
|
<Itens> |
||||
|
{% for item in rps.itens -%} |
||||
|
<Item> |
||||
|
<DiscriminacaoServico>{{ item.descricao }}</DiscriminacaoServico> |
||||
|
<Quantidade>{{ item.quantidade }}</Quantidade> |
||||
|
<ValorUnitario>{{ item.valor_unitario }}</ValorUnitario> |
||||
|
<ValorTotal>{{ item.valor_total }}</ValorTotal> |
||||
|
<Tributavel>S</Tributavel> |
||||
|
</Item> |
||||
|
{% endfor %} |
||||
|
</Itens> |
||||
|
</RPS> |
||||
|
{% endfor %} |
||||
|
</Lote> |
||||
|
</ns1:ReqEnvioLoteRPS> |
||||
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" |
||||
|
xmlns:dsf="http://dsfnet.com.br"> |
||||
|
<soapenv:Body> |
||||
|
<dsf:enviar soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> |
||||
|
<mensagemXml xsi:type="xsd:string"><![CDATA[ |
||||
|
{% block content %}{% endblock %} |
||||
|
]]></mensagemXml> |
||||
|
</dsf:enviar> |
||||
|
</soapenv:Body> |
||||
|
</soapenv:Envelope> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue