Browse Source

Merge branch 'master3' into master3-nfse_imperial

pull/110/head
pal0schi 8 years ago
committed by GitHub
parent
commit
c659ddbf1d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      pytrustnfe/Servidores.py
  2. 1764
      pytrustnfe/nfe/danfe.py
  3. 61
      pytrustnfe/nfse/dsf/__init__.py
  4. 0
      pytrustnfe/nfse/dsf/templates/cancelar.xml
  5. 0
      pytrustnfe/nfse/dsf/templates/consulta_notas.xml
  6. 0
      pytrustnfe/nfse/dsf/templates/consultarLote.xml
  7. 22
      pytrustnfe/nfse/dsf/templates/consultarNFSeRps.xml
  8. 0
      pytrustnfe/nfse/dsf/templates/enviar.xml
  9. 0
      pytrustnfe/nfse/dsf/templates/soap_header.xml
  10. 119
      pytrustnfe/nfse/floripa/__init__.py
  11. 7
      pytrustnfe/nfse/floripa/templates/cancelar_nota.xml
  12. 40
      pytrustnfe/nfse/floripa/templates/processar_nota.xml
  13. 1
      pytrustnfe/nfse/ginfes/__init__.py
  14. 2
      pytrustnfe/nfse/ginfes/templates/Rps.xml
  15. 4
      pytrustnfe/nfse/paulistana/__init__.py
  16. 13
      pytrustnfe/xml/__init__.py
  17. 10
      requirements.txt
  18. 11
      setup.py

8
pytrustnfe/Servidores.py

@ -332,8 +332,8 @@ UFBA = {
WS_NFE_SITUACAO: 'webservices/NfeStatusServico/NfeStatusServico.asmx',
WS_NFE_INUTILIZACAO: 'webservices/nfenw/nfeinutilizacao2.asmx',
WS_NFE_CADASTRO: 'webservices/nfenw/CadConsultaCadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'hnfe.sefaz.ba.gov.br',
@ -344,8 +344,8 @@ UFBA = {
WS_NFE_SITUACAO: 'webservices/NfeStatusServico/NfeStatusServico.asmx',
WS_NFE_INUTILIZACAO: 'webservices/nfenw/nfeinutilizacao2.asmx',
WS_NFE_CADASTRO: 'webservices/nfenw/CadConsultaCadastro2.asmx',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento',
WS_NFE_RECEPCAO_EVENTO: 'webservices/sre/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'webservices/sre/recepcaoevento.asmx',
}
}

1764
pytrustnfe/nfe/danfe.py
File diff suppressed because it is too large
View File

61
pytrustnfe/nfse/campinas/__init__.py → pytrustnfe/nfse/dsf/__init__.py

@ -24,13 +24,45 @@ def _render(certificado, method, **kwargs):
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 = 'http://issdigital.campinas.sp.gov.br/WsNFe2/LoteRps.jws?wsdl' # noqa
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(
@ -48,6 +80,11 @@ def _send(certificado, method, **kwargs):
'received_xml': e.fault.faultstring,
'object': None
}
except Exception as e:
if response:
raise Exception(response)
else:
raise e
return {
'sent_xml': xml_send,
@ -56,11 +93,23 @@ def _send(certificado, method, **kwargs):
}
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)
@ -72,5 +121,11 @@ def consulta_lote(**kwargs):
return _send(False, 'consultarLote', **kwargs)
def consultar_lote_rps(certificado, **kwarg):
return _send(certificado, 'consultarNFSeRps', **kwarg)
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
pytrustnfe/nfse/campinas/templates/cancelar.xml → pytrustnfe/nfse/dsf/templates/cancelar.xml

0
pytrustnfe/nfse/campinas/templates/consulta_notas.xml → pytrustnfe/nfse/dsf/templates/consulta_notas.xml

0
pytrustnfe/nfse/campinas/templates/consultarLote.xml → pytrustnfe/nfse/dsf/templates/consultarLote.xml

22
pytrustnfe/nfse/dsf/templates/consultarNFSeRps.xml

@ -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
pytrustnfe/nfse/campinas/templates/enviar.xml → pytrustnfe/nfse/dsf/templates/enviar.xml

0
pytrustnfe/nfse/campinas/templates/soap_header.xml → pytrustnfe/nfse/dsf/templates/soap_header.xml

119
pytrustnfe/nfse/floripa/__init__.py

@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# © 2017 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os
import hashlib
import base64
import requests
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
URLS = {
'producao': {
'processar_nota': 'https://nfps-e.pmf.sc.gov.br/api/v1/processamento/notas/processa',
'cancelar_nota': 'https://nfps-e.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela'
},
'homologacao': {
'processar_nota': 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/processamento/notas/processa',
'cancelar_nota': 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/cancelamento/notas/cancela'
}
}
def _render(certificado, method, **kwargs):
path = os.path.join(os.path.dirname(__file__), 'templates')
xml_send = render_xml(path, '%s.xml' % method, False, **kwargs)
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, '')
return xml_send
def _get_oauth_token(**kwargs):
if kwargs['ambiente'] == 'producao':
url = 'https://nfps-e.pmf.sc.gov.br/api/v1/autenticacao/oauth/token'
else:
url = 'https://nfps-e-hml.pmf.sc.gov.br/api/v1/autenticacao/oauth/token'
m = hashlib.md5()
secret = "%s:%s" % (kwargs["client_id"], kwargs["secret_id"])
auth = base64.b64encode(secret.encode('utf-8'))
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic %s" % auth.decode('utf-8').replace('\n', '')
}
m.update(kwargs["password"].encode('utf-8'))
password = m.hexdigest().upper()
dados = "grant_type=password&username=%s&password=%s&client_id=%s&client_secret=%s" % (
kwargs["username"], password, kwargs["client_id"], kwargs["secret_id"])
r = requests.post(url, data=dados, headers=headers)
if r.status_code == 200:
return r.json()
else:
return r.json()
def _send(certificado, method, **kwargs):
url = URLS[kwargs['ambiente']][method]
xml_send = kwargs['xml']
token = _get_oauth_token(**kwargs)
if "access_token" not in token:
raise Exception("%s - %s: %s" % (token["status"], token["error"],
token["message"]))
kwargs.update({"numero": 1, 'access_token': token["access_token"]})
headers = {"Accept": "application/xml;charset=UTF-8",
"Content-Type": "application/xml",
"Authorization": "Bearer %s" % kwargs['access_token']}
r = requests.post(url, headers=headers, data=xml_send)
response, obj = sanitize_response(r.text.strip().encode('utf-8'))
return {
'sent_xml': xml_send,
'received_xml': response,
'object': obj,
'status_code': r.status_code,
}
def xml_processar_nota(certificado, **kwargs):
return _render(certificado, 'processar_nota', **kwargs)
def processar_nota(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_processar_nota(certificado, **kwargs)
return _send(certificado, 'processar_nota', **kwargs)
def xml_cancelar_nota(certificado, **kwargs):
return _render(certificado, 'cancelar_nota', **kwargs)
def cancelar_nota(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_cancelar_nota(certificado, **kwargs)
return _send(certificado, 'cancelar_nota', **kwargs)
def consultar_nota(certificado, **kwargs):
if kwargs['ambiente'] == 'producao':
url = "https://nfps-e.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (kwargs["numero"])
else:
url = "https://nfps-e-hml.pmf.sc.gov.br/api/v1/consultas/notas/numero/%s" % (kwargs["numero"])
headers = {"Accept": "application/json",
"Authorization": "Bearer %s" % kwargs['access_token']}
r = requests.get(url, headers=headers)
print(r.status_code)
if r.status_code == 200:
return r.text
else:
return r.text

7
pytrustnfe/nfse/floripa/templates/cancelar_nota.xml

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<xmlCancelamentoNfpse>
<motivoCancelamento>{{ cancelamento.motivo }}</motivoCancelamento>
<nuAedf>{{ cancelamento.aedf }}</nuAedf>
<nuNotaFiscal>{{ cancelamento.numero }}</nuNotaFiscal>
<codigoVerificacao>{{ cancelamento.codigo_verificacao }}</codigoVerificacao>
</xmlCancelamentoNfpse>

40
pytrustnfe/nfse/floripa/templates/processar_nota.xml

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<xmlProcessamentoNfpse>
<bairroTomador>{{ rps.tomador.bairro|normalize|escape }}</bairroTomador>
<baseCalculo>{{ rps.base_calculo }}</baseCalculo>
<baseCalculoSubstituicao>0.0</baseCalculoSubstituicao>
<cfps>{{ rps.cfps }}</cfps>
<codigoMunicipioTomador>{{ rps.tomador.cidade }}</codigoMunicipioTomador>
<codigoPostalTomador>{{ rps.tomador.cep }}</codigoPostalTomador>
<complementoEnderecoTomador>{{ rps.tomador.complemento|normalize|escape }}</complementoEnderecoTomador>
<dadosAdicionais>{{ rps.observacoes|normalize|escape }}</dadosAdicionais>
<dataEmissao>{{ rps.data_emissao }}</dataEmissao>
<emailTomador>{{ rps.tomador.email }}</emailTomador>
<identificacao>{{ rps.numero }}</identificacao>
<identificacaoTomador>{{ rps.tomador.cnpj_cpf }}</identificacaoTomador>
<inscricaoMunicipalTomador>{{ rps.tomador.inscricao_municipal }}</inscricaoMunicipalTomador>
<itensServico>
{% for item in rps.itens_servico -%}
<itemServico>
<aliquota>{{ item.aliquota }}</aliquota>
<cst>{{ item.cst_servico }}</cst>
<descricaoServico>{{ item.descricao|normalize|escape }}</descricaoServico>
<idCNAE>{{ item.cnae }}</idCNAE>
<quantidade>{{ item.quantidade }}</quantidade>
<valorTotal>{{ item.valor_total }}</valorTotal>
<valorUnitario>{{ item.valor_unitario }}</valorUnitario>
</itemServico>
{% endfor %}
</itensServico>
<logradouroTomador>{{ rps.tomador.logradouro|normalize|escape }}</logradouroTomador>
<nomeMunicipioTomador></nomeMunicipioTomador>
<numeroAEDF>{{ rps.aedf }}</numeroAEDF>
<numeroEnderecoTomador>{{ rps.tomador.numero }}</numeroEnderecoTomador>
<paisTomador>1058</paisTomador>
<razaoSocialTomador>{{ rps.tomador.razao_social|normalize|escape }}</razaoSocialTomador>
<telefoneTomador>{{ rps.tomador.telefone }}</telefoneTomador>
<ufTomador>{{ rps.tomador.uf }}</ufTomador>
<valorISSQN>{{rps.valor_issqn }}</valorISSQN>
<valorISSQNSubstituicao>0.0</valorISSQNSubstituicao>
<valorTotalServicos>{{ rps.valor_total }}</valorTotalServicos>
</xmlProcessamentoNfpse>

1
pytrustnfe/nfse/ginfes/__init__.py

@ -4,7 +4,6 @@
import os
import suds
from lxml import etree
from pytrustnfe.xml import render_xml, sanitize_response
from pytrustnfe.client import get_authenticated_client
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key

2
pytrustnfe/nfse/ginfes/templates/Rps.xml

@ -27,11 +27,11 @@
<ValorCsll>{{ rps.valor_csll }}</ValorCsll>
<IssRetido>{{ rps.iss_retido }}</IssRetido>
<ValorIss>{{ rps.valor_iss }}</ValorIss>
<ValorIssRetido>{{ rps.valor_iss_retido }}</ValorIssRetido>
<OutrasRetencoes>{{ rps.outras_retencoes }}</OutrasRetencoes>
<BaseCalculo>{{ rps.base_calculo }}</BaseCalculo>
<Aliquota>{{ rps.aliquota_issqn }}</Aliquota>
<ValorLiquidoNfse>{{ rps.valor_liquido_nfse }}</ValorLiquidoNfse>
<ValorIssRetido>{{ rps.valor_iss_retido }}</ValorIssRetido>
<DescontoIncondicionado>{{ rps.desconto_incondicionado }}</DescontoIncondicionado>
<DescontoCondicionado>{{ rps.desconto_condicionado }}</DescontoCondicionado>
</Valores>

4
pytrustnfe/nfse/paulistana/__init__.py

@ -54,10 +54,10 @@ def _send(certificado, method, **kwargs):
'object': None
}
response, obj = sanitize_response(response)
response, obj = sanitize_response(response.encode('utf-8'))
return {
'sent_xml': xml_send,
'received_xml': response,
'received_xml': response.decode(),
'object': obj
}

13
pytrustnfe/xml/__init__.py

@ -15,6 +15,18 @@ def recursively_empty(e):
return all((recursively_empty(c) for c in e.iterchildren()))
def recursively_normalize(vals):
for item in vals:
if type(vals[item]) is str:
vals[item] = vals[item].strip()
elif type(vals[item]) is dict:
recursively_normalize(vals[item])
elif type(vals[item]) is list:
for a in vals[item]:
recursively_normalize(a)
return vals
def render_xml(path, template_name, remove_empty, **nfe):
nfe = recursively_normalize(nfe)
env = Environment(
@ -28,7 +40,6 @@ def render_xml(path, template_name, remove_empty, **nfe):
env.filters["comma"] = filters.format_with_comma
template = env.get_template(template_name)
xml = template.render(**nfe)
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True,
strip_cdata=False)

10
requirements.txt

@ -1,14 +1,14 @@
lxml >= 3.5.0, < 4
lxml >= 3.5.0, < 5
coveralls
Jinja2
signxml
urllib3 >= 1.22
suds-jurko >= 0.6
suds-jurko-requests >= 1.1
defusedxml >= 0.4.1, < 0.6
eight >= 0.3.0, < 0.5
cryptography >= 1.8, < 1.10
pyOpenSSL >= 16.0.0, < 17
defusedxml >= 0.4.1, < 1
eight >= 0.3.0, < 1
cryptography >= 1.8, < 3
pyOpenSSL >= 16.0.0, < 18
certifi >= 2015.11.20.1
xmlsec >= 1.3.3
reportlab

11
setup.py

@ -1,7 +1,9 @@
# coding=utf-8
from setuptools import setup, find_packages
VERSION = "0.9.3"
VERSION = "0.9.11"
setup(
name="PyTrustNFe3",
@ -27,12 +29,13 @@ later (LGPLv2+)',
'nfe/templates/*xml',
'nfe/fonts/*ttf',
'nfse/paulistana/templates/*xml',
'nfse/campinas/templates/*xml',
'nfse/dsf/templates/*xml',
'nfse/ginfes/templates/*xml',
'nfse/simpliss/templates/*xml',
'nfse/betha/templates/*xml',
'nfse/susesu/templates/*xml',
'nfse/imperial/templates/*xml',
'nfse/floripa/templates/*xml',
'xml/schemas/*xsd',
]},
url='https://github.com/danimaribeiro/PyTrustNFe',
@ -42,9 +45,9 @@ later (LGPLv2+)',
install_requires=[
'Jinja2 >= 2.8',
'signxml >= 2.4.0',
'lxml >= 3.5.0, < 4',
'lxml >= 3.5.0, < 5',
'suds-jurko >= 0.6',
'suds-jurko-requests >= 1.1',
'suds-jurko-requests >= 1.2',
'reportlab'
],
tests_require=[

Loading…
Cancel
Save