Browse Source

Merge branch 'master3' of https://github.com/danimaribeiro/PyTrustNFe into master3

pull/231/head
Danimar Ribeiro 7 years ago
parent
commit
a0b45a9846
  1. 95
      README.md
  2. 29
      pytrustnfe/Servidores.py
  3. 32
      pytrustnfe/nfe/__init__.py
  4. 3
      pytrustnfe/nfe/templates/NFeDistribuicaoDFe.xml
  5. 2
      pytrustnfe/nfe/templates/NfeAutorizacao.xml
  6. 297
      pytrustnfe/xml/schemas/distDFeInt_v1.01.xsd
  7. 5
      pytrustnfe/xml/validate.py
  8. 2
      setup.py

95
README.md

@ -52,7 +52,102 @@ certificado = Certificado(certificado, 'senha_pfx')
obj = {'cnpj': '12345678901234', 'estado': '42'}
resposta = consulta_cadastro(certificado, obj=obj, ambiente=1, estado='42')
```
Consulta Distribuição NF-e sem Validação de Esquema:
```python
from pytrustnfe.certificado import Certificado
from pytrustnfe.nfe import consulta_distribuicao_nfe, xml_consulta_distribuicao_nfe
certificado = open("/path/certificado.pfx", "r").read()
certificado = Certificado(certificado, 'senha_pfx')
# Gerando xml e enviado consulta por Ultimo NSU
response1 = consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
modelo='55',
cnpj_cpf='12345678901234',
ultimo_nsu='123456789101213'
)
# Gerando xml e enviado consulta por Chave
response2 = consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
modelo='55',
cnpj_cpf='12345678901234',
chave_nfe='012345678901234567890123456789012345678912'
)
# Gerando xml e enviado consulta por NSU
response3 = consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
modelo='55',
cnpj_cpf='12345678901234',
nsu='123456789101213'
)
```
Consulta Distribuição NF-e com Validação de Esquema:
```python
from pytrustnfe.certificado import Certificado
from pytrustnfe.nfe import consulta_distribuicao_nfe, xml_consulta_distribuicao_nfe
from pytrustnfe.xml.validate import valida_nfe, SCHEMA_DFE
certificado = open("/path/certificado.pfx", "r").read()
certificado = Certificado(certificado, 'senha_pfx')
# Gerando XML para Consulta por Ultimo NSU
xml1 = xml_consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
cnpj_cpf='12345678901234',
ultimo_nsu='123456789101213'
)
# Validando o XML com Esquema
if valida_nfe(xml1, SCHEMA_DFE):
Warning("Erro na validação do esquema")
# Gerando XML para Consulta por Chave
xml2 = xml_consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
cnpj_cpf='12345678901234',
chave_nfe='012345678901234567890123456789012345678912'
)
# Validando o XML com Esquema
if valida_nfe(xml2, SCHEMA_DFE):
Warning("Erro na validação do esquema")
# Gerando XML para Consulta por NSU
xml3 = xml_consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
cnpj_cpf='12345678901234',
nsu='123456789101213'
)
# Validando o XML com Esquema
if valida_nfe(xml3, SCHEMA_DFE):
Warning("Erro na validação do esquema")
# Enviando xml de consulta para sefaz
response = consulta_distribuicao_nfe(
certificado,
ambiente=1,
estado='42',
modelo='55',
xml=xml1
)
```
Exemplo de uso da NFSe Paulistana
---------------------------------

29
pytrustnfe/Servidores.py

@ -132,7 +132,7 @@ SVRS = {
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl', # noqa
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro2.asmx?wsdl', # noqa
WS_NFE_CADASTRO: 'ws/cadconsultacadastro/cadconsultacadastro4.asmx?wsdl', # noqa
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.svrs.rs.gov.br',
@ -268,23 +268,22 @@ UFAM = {
},
NFCE_MODELO: {
AMBIENTE_PRODUCAO: {
'servidor': 'nfe.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'services2/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'services2/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'services2/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'services2/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'services2/services/NfeConsulta2',
WS_NFE_SITUACAO: 'services2/services/NfeStatusServico2',
WS_NFE_CADASTRO: 'services2/services/cadconsultacadastro2',
'servidor': 'nfce.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfce-services/services/RecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfce-services/services/NfeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfce-services/services/NfeRetAutorizacao4?wsdl',
WS_NFE_INUTILIZACAO: 'nfce-services/services/NfeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfce-services/services/NfeConsulta4?wsdl',
WS_NFE_SITUACAO: 'nfce-services/services/NfeStatusServico4?wsdl',
},
AMBIENTE_HOMOLOGACAO: {
'servidor': 'homnfce.sefaz.am.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'nfce-services-nac/services/RecepcaoEvento',
WS_NFE_AUTORIZACAO: 'nfce-services-nac/services/NfeAutorizacao',
WS_NFE_RET_AUTORIZACAO: 'nfce-services-nac/services/NfeRetAutorizacao',
WS_NFE_INUTILIZACAO: 'nfce-services-nac/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfce-services-nac/services/NfeConsulta2',
WS_NFE_SITUACAO: 'nfce-services-nac/services/NfeStatusServico2',
WS_NFE_RECEPCAO_EVENTO: 'nfce-services/services/RecepcaoEvento4?wsdl',
WS_NFE_AUTORIZACAO: 'nfce-services/services/NfeAutorizacao4?wsdl',
WS_NFE_RET_AUTORIZACAO: 'nfce-services/services/NfeRetAutorizacao4?wsdl',
WS_NFE_INUTILIZACAO: 'nfce-services/services/NfeInutilizacao4?wsdl',
WS_NFE_CONSULTA: 'nfce-services/services/NfeConsulta4?wsdl',
WS_NFE_SITUACAO: 'nfce-services/services/NfeStatusServico4?wsdl',
WS_NFCE_QR_CODE: 'http://homnfce.sefaz.am.gov.br/nfceweb/consultarNFCe.jsp',
}
}

32
pytrustnfe/nfe/__init__.py

@ -214,6 +214,22 @@ def xml_consulta_distribuicao_nfe(certificado, **kwargs): # Assinar
return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs)
def consulta_distribuicao_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_distribuicao_nfe(certificado, **kwargs)
return _send_v310(certificado, **kwargs)
def xml_download_nfe(certificado, **kwargs): # Assinar
return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs)
def download_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_download_nfe(certificado, **kwargs)
return _send_v310(certificado, **kwargs)
def _send_v310(certificado, **kwargs):
xml_send = kwargs["xml"]
base_url = localizar_url(
@ -243,19 +259,3 @@ def _send_v310(certificado, **kwargs):
'received_xml': response,
'object': obj.Body.nfeDistDFeInteresseResponse.nfeDistDFeInteresseResult
}
def consulta_distribuicao_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_distribuicao_nfe(certificado, **kwargs)
return _send_v310(certificado, **kwargs)
def xml_download_nfe(certificado, **kwargs): # Assinar
return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs)
def download_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_download_nfe(certificado, **kwargs)
return _send_v310(certificado, **kwargs)

3
pytrustnfe/nfe/templates/NFeDistribuicaoDFe.xml

@ -8,4 +8,7 @@
<consChNFe>
<chNFe>{{ chave_nfe }}</chNFe>
</consChNFe>
<consNSU>
<NSU>{{ nsu }}</NSU>
</consNSU>
</distDFeInt>

2
pytrustnfe/nfe/templates/NfeAutorizacao.xml

@ -259,7 +259,9 @@
</detExport>
{% endfor %}
{% endif %}
{% if NFe.infNFe.compra is defined %}
<xPed>{{ NFe.infNFe.compra.xPed }}</xPed>
{% endif %}
<nItemPed>{{ prod.nItemPed }}</nItemPed>
<nFCI>{{ prod.nFCI }}</nFCI>
{% for rastro in prod.rastro %}

297
pytrustnfe/xml/schemas/distDFeInt_v1.01.xsd

@ -0,0 +1,297 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.portalfiscal.inf.br/nfe" targetNamespace="http://www.portalfiscal.inf.br/nfe" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="TNSU">
<xs:annotation>
<xs:documentation>Tipo número sequencial único</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:token">
<xs:pattern value="[0-9]{15}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TQNSU">
<xs:annotation>
<xs:documentation>Tipo quantidade de NSU</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:unsignedShort">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="50"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TVerDistDFe">
<xs:annotation>
<xs:documentation>Tipo Versão dos leiautes do Web Service NFeDistribuicaoDFe</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:enumeration value="1.01"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TAmb">
<xs:annotation>
<xs:documentation>Tipo Ambiente</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:enumeration value="1"/>
<xs:enumeration value="2"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TCodUfIBGE">
<xs:annotation>
<xs:documentation>Tipo Código da UF da tabela do IBGE</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:enumeration value="11"/>
<xs:enumeration value="12"/>
<xs:enumeration value="13"/>
<xs:enumeration value="14"/>
<xs:enumeration value="15"/>
<xs:enumeration value="16"/>
<xs:enumeration value="17"/>
<xs:enumeration value="21"/>
<xs:enumeration value="22"/>
<xs:enumeration value="23"/>
<xs:enumeration value="24"/>
<xs:enumeration value="25"/>
<xs:enumeration value="26"/>
<xs:enumeration value="27"/>
<xs:enumeration value="28"/>
<xs:enumeration value="29"/>
<xs:enumeration value="31"/>
<xs:enumeration value="32"/>
<xs:enumeration value="33"/>
<xs:enumeration value="35"/>
<xs:enumeration value="41"/>
<xs:enumeration value="42"/>
<xs:enumeration value="43"/>
<xs:enumeration value="50"/>
<xs:enumeration value="51"/>
<xs:enumeration value="52"/>
<xs:enumeration value="53"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TCOrgaoIBGE">
<xs:annotation>
<xs:documentation>Tipo Código de orgão (UF da tabela do IBGE + 90 RFB)</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:enumeration value="11"/>
<xs:enumeration value="12"/>
<xs:enumeration value="13"/>
<xs:enumeration value="14"/>
<xs:enumeration value="15"/>
<xs:enumeration value="16"/>
<xs:enumeration value="17"/>
<xs:enumeration value="21"/>
<xs:enumeration value="22"/>
<xs:enumeration value="23"/>
<xs:enumeration value="24"/>
<xs:enumeration value="25"/>
<xs:enumeration value="26"/>
<xs:enumeration value="27"/>
<xs:enumeration value="28"/>
<xs:enumeration value="29"/>
<xs:enumeration value="31"/>
<xs:enumeration value="32"/>
<xs:enumeration value="33"/>
<xs:enumeration value="35"/>
<xs:enumeration value="41"/>
<xs:enumeration value="42"/>
<xs:enumeration value="43"/>
<xs:enumeration value="50"/>
<xs:enumeration value="51"/>
<xs:enumeration value="52"/>
<xs:enumeration value="53"/>
<xs:enumeration value="90"/>
<xs:enumeration value="91"/>
<xs:enumeration value="92"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TCnpj">
<xs:annotation>
<xs:documentation>Tipo Número do CNPJ</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="14"/>
<xs:pattern value="[0-9]{14}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TCpf">
<xs:annotation>
<xs:documentation>Tipo Número do CPF</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="11"/>
<xs:pattern value="[0-9]{11}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TVerAplic">
<xs:annotation>
<xs:documentation>Tipo Versão do Aplicativo</xs:documentation>
</xs:annotation>
<xs:restriction base="TString">
<xs:minLength value="1"/>
<xs:maxLength value="20"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TStat">
<xs:annotation>
<xs:documentation>Tipo Código da Mensagem enviada</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="3"/>
<xs:pattern value="[0-9]{3}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TMotivo">
<xs:annotation>
<xs:documentation>Tipo Motivo</xs:documentation>
</xs:annotation>
<xs:restriction base="TString">
<xs:maxLength value="255"/>
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TString">
<xs:annotation>
<xs:documentation> Tipo string genérico</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="[!-ÿ]{1}[ -ÿ]{0,}[!-ÿ]{1}|[!-ÿ]{1}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TChNFe">
<xs:annotation>
<xs:documentation>Tipo Chave da Nota Fiscal Eletrônica</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="44"/>
<xs:pattern value="[0-9]{44}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TProt">
<xs:annotation>
<xs:documentation>Tipo Número do Protocolo de Status</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="15"/>
<xs:pattern value="[0-9]{15}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDateTimeUTC">
<xs:annotation>
<xs:documentation>Data e Hora, formato UTC (AAAA-MM-DDThh:mm:ssTZD, onde TZD = +hh:mm ou -hh:mm)</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="(((20(([02468][048])|([13579][26]))-02-29))|(20[0-9][0-9])-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))T(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d([\-,\+](0[0-9]|10|11):00|([\+](12):00))"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TIe">
<xs:annotation>
<xs:documentation>Tipo Inscrição Estadual do Emitente // alterado EM 24/10/08 para aceitar ISENTO</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:maxLength value="14"/>
<xs:pattern value="[0-9]{2,14}|ISENTO"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TDec_1302">
<xs:annotation>
<xs:documentation>Tipo Decimal com 15 dígitos, sendo 13 de corpo e 2 decimais</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:pattern value="0|0\.[0-9]{2}|[1-9]{1}[0-9]{0,12}(\.[0-9]{2})?"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="distDFeInt">
<xs:annotation>
<xs:documentation>Schema de pedido de distribuição de DF-e de interesse</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="tpAmb" type="TAmb">
<xs:annotation>
<xs:documentation>
Identificação do Ambiente:
1 - Produção
2 - Homologação
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="cUFAutor" type="TCodUfIBGE" minOccurs="0">
<xs:annotation>
<xs:documentation>Código da UF do Autor</xs:documentation>
</xs:annotation>
</xs:element>
<xs:choice>
<xs:element name="CNPJ" type="TCnpj">
<xs:annotation>
<xs:documentation>CNPJ do interessado no DF-e</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CPF" type="TCpf">
<xs:annotation>
<xs:documentation>CPF do interessado no DF-e</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
<xs:choice>
<xs:element name="distNSU">
<xs:annotation>
<xs:documentation>Grupo para distribuir DF-e de interesse</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="ultNSU" type="TNSU">
<xs:annotation>
<xs:documentation>Último NSU recebido pelo ator. Caso seja informado com zero, ou com um NSU muito antigo, a consulta retornará unicamente as informações resumidas e documentos fiscais eletrônicos que tenham sido recepcionados pelo Ambiente Nacional nos últimos 3 meses.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="consNSU">
<xs:annotation>
<xs:documentation>Grupo para consultar um DF-e a partir de um NSU específico</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="NSU" type="TNSU">
<xs:annotation>
<xs:documentation>Número Sequencial Único. Geralmente esta consulta será utilizada quando identificado pelo interessado um NSU faltante. O Web Service retornará o documento ou informará que o NSU não existe no Ambiente Nacional. Assim, esta consulta fechará a lacuna do NSU identificado como faltante.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="consChNFe">
<xs:annotation>
<xs:documentation>Grupo para consultar uma NF-e a partir da chave de acesso</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="chNFe" type="TChNFe">
<xs:annotation>
<xs:documentation>Chave de acesso da NF-e a ser consultada</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
<xs:attribute name="versao" type="TVerDistDFe" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>

5
pytrustnfe/xml/validate.py

@ -8,11 +8,12 @@ from lxml import etree
PATH = os.path.dirname(os.path.abspath(__file__))
SCHEMA = os.path.join(PATH, 'schemas/enviNFe_v4.00.xsd')
SCHEMA_DFE = os.path.join(PATH, 'schemas/enviNFe_v4.00.xsd')
def valida_nfe(xml_nfe):
def valida_nfe(xml_nfe, schema=SCHEMA):
nfe = etree.fromstring(xml_nfe)
esquema = etree.XMLSchema(etree.parse(SCHEMA))
esquema = etree.XMLSchema(etree.parse(schema))
esquema.validate(nfe)
erros = [x.message for x in esquema.error_log]
return "\n".join(erros)

2
setup.py

@ -2,7 +2,7 @@
from setuptools import setup, find_packages
VERSION = "1.0.37"
VERSION = "1.0.39"
setup(

Loading…
Cancel
Save