Marcelo Salhab Brogliato 6 years ago
parent
commit
5e50345ac6
  1. 2
      README.md
  2. 3
      pynfe/entidades/base.py
  3. 24
      pynfe/entidades/notafiscal.py
  4. 32
      pynfe/processamento/comunicacao.py
  5. 115
      pynfe/processamento/serializacao.py
  6. 30
      pynfe/utils/descompactar.py
  7. 10
      pynfe/utils/flags.py
  8. 134
      pynfe/utils/webservices.py
  9. 2
      requirements-nfse.txt

2
README.md

@ -1,5 +1,5 @@
Atenção este repositório já esta em desenvolvimento para a versão NF-e 4.00, para a versão 3.10 utilize a última [release](https://github.com/leotada/PyNFe/releases).
Atualizado para a versão 4.00 NF-e/NFC-e
-----------
Visão Geral

3
pynfe/entidades/base.py

@ -16,6 +16,9 @@ class Entidade(object):
self._fonte_dados.adicionar_objeto(self)
def __str__(self):
return self.__class__.__name__
def __repr__(self):
return '<%s %s>'%(self.__class__.__name__, str(self))

24
pynfe/entidades/notafiscal.py

@ -355,6 +355,7 @@ class NotaFiscal(Entidade):
self.duplicatas = []
self.observacoes_contribuinte = []
self.processos_referenciados = []
self.responsavel_tecnico = []
super(NotaFiscal, self).__init__(*args, **kwargs)
@ -386,7 +387,6 @@ class NotaFiscal(Entidade):
self.totais_icms_pis += obj.pis_valor
self.totais_icms_cofins += obj.cofins_valor
self.totais_icms_outras_despesas_acessorias += obj.outras_despesas_acessorias
self.totais_icms_total_nota += obj.valor_total_bruto
# - Valor Total do FCP (Fundo de Combate à Pobreza)
self.totais_fcp += obj.fcp_valor
self.totais_fcp_destino += obj.fcp_destino_valor
@ -396,6 +396,12 @@ class NotaFiscal(Entidade):
self.totais_icms_inter_remetente += obj.icms_inter_remetente_valor
## TODO calcular impostos aproximados
#self.totais_tributos_aproximado += obj.tributos
self.totais_icms_total_nota += obj.valor_total_bruto - obj.desconto + \
obj.icms_desonerado + obj.icms_st_valor + \
obj.total_frete + obj.total_seguro + \
obj.outras_despesas_acessorias + obj.ipi_valor_ipi
return obj
def adicionar_transporte_volume(self, **kwargs):
@ -417,11 +423,17 @@ class NotaFiscal(Entidade):
return obj
def adicionar_processo_referenciado(self, **kwargs):
u"""Adiciona uma instancia de Processo Referenciado"""
"""Adiciona uma instancia de Processo Referenciado"""
obj = NotaFiscalProcessoReferenciado(**kwargs)
self.processos_referenciados.append(obj)
return obj
def adicionar_responsavel_tecnico(self, **kwargs):
""" Adiciona uma instancia de Responsavel Tecnico """
obj = NotaFiscalResponsavelTecnico(**kwargs)
self.responsavel_tecnico.append(obj)
return obj
def _codigo_numerico_aleatorio(self):
self.codigo_numerico_aleatorio = str(random.randint(0, 99999999)).zfill(8)
return self.codigo_numerico_aleatorio
@ -1003,3 +1015,11 @@ class NotaFiscalServico(Entidade):
def __str__(self):
return ' '.join([str(self.identificador)])
class NotaFiscalResponsavelTecnico(Entidade):
# NT 2018/003
cnpj = str()
contato = str()
email = str()
fone = str()
csrt = str()

32
pynfe/processamento/comunicacao.py

@ -83,7 +83,12 @@ class ComunicacaoSefaz(Comunicacao):
if ind_sinc == 1:
try:
# Protocolo com envio OK
inf_prot = prot[0][0] # root protNFe
try:
inf_prot = prot[0][0] # root protNFe
except IndexError:
# Estados como GO vem com a tag header
inf_prot = prot[1][0]
lote_status = inf_prot.xpath("ns:retEnviNFe/ns:cStat", namespaces=ns)[0].text
# Lote processado
if lote_status == '104':
@ -168,7 +173,7 @@ class ComunicacaoSefaz(Comunicacao):
# url
url = self._get_url_an(consulta='DISTRIBUICAO')
# Monta XML para envio da requisição
raiz = etree.Element('distDFeInt', versao='1.00', xmlns=NAMESPACE_NFE)
raiz = etree.Element('distDFeInt', versao='1.01', xmlns=NAMESPACE_NFE)
etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
if self.uf:
etree.SubElement(raiz, 'cUFAutor').text = CODIGOS_ESTADOS[self.uf.upper()]
@ -176,15 +181,16 @@ class ComunicacaoSefaz(Comunicacao):
etree.SubElement(raiz, 'CNPJ').text = cnpj
else:
etree.SubElement(raiz, 'CPF').text = cpf
distNSU = etree.SubElement(raiz, 'distNSU')
etree.SubElement(distNSU, 'ultNSU').text = str(nsu).zfill(15)
# if chave:
# consChNFe = etree.SubElement(raiz, 'consChNFe')
# etree.SubElement(consChNFe, 'chNFe').text = chave
# Monta XML para envio da requisição
if not chave:
distNSU = etree.SubElement(raiz, 'distNSU')
etree.SubElement(distNSU, 'ultNSU').text = str(nsu).zfill(15)
if chave:
consChNFe = etree.SubElement(raiz, 'consChNFe')
etree.SubElement(consChNFe, 'chNFe').text = chave
#Monta XML para envio da requisição
xml = self._construir_xml_soap('NFeDistribuicaoDFe', raiz)
# print(url)
# print(etree.tostring(xml))
return self._post(url, xml)
def consulta_cadastro(self, modelo, cnpj):
@ -287,7 +293,7 @@ class ComunicacaoSefaz(Comunicacao):
'uf': uf,
'ano': ano,
'cnpj': cnpj,
'modelo': '55',
'modelo': '55' if modelo == 'nfe' else '65', # 55=NF-e; 65=NFC-e;
'serie': serie.zfill(3),
'num_ini': str(numero_inicial).zfill(9),
'num_fin': str(numero_final).zfill(9),
@ -353,7 +359,7 @@ class ComunicacaoSefaz(Comunicacao):
raise Exception('Modelo não encontrado! Defina modelo="nfe" ou "nfce"')
# Estados que utilizam outros ambientes
else:
lista_svrs = ['AC', 'RJ', 'RN', 'PB', 'SC', 'SE', 'PI']
lista_svrs = ['AC', 'RJ', 'RN', 'PB', 'SC', 'SE', 'PI', 'DF', 'ES']
lista_svan = ['MA','PA']
if self.uf.upper() in lista_svrs:
if self._ambiente == 1:
@ -419,7 +425,7 @@ class ComunicacaoSefaz(Comunicacao):
# limpa xml com caracteres bugados para infNFeSupl em NFC-e
xml = re.sub(
'<qrCode>(.*?)</qrCode>',
lambda x: x.group(0).replace('&lt;', '<').replace('&gt;', '>').replace('amp;', ''),
lambda x: x.group(0).replace('&lt;', '<').replace('&gt;', '>').replace('&amp;', ''),
etree.tostring(xml, encoding='unicode').replace('\n', '')
)
xml = xml_declaration + xml

115
pynfe/processamento/serializacao.py

@ -8,6 +8,7 @@ from pynfe.utils.webservices import NFCE
import base64
import hashlib
from datetime import datetime
import re
import pytz
@ -237,6 +238,10 @@ class SerializacaoXML(Serializacao):
etree.SubElement(prod, 'uTrib').text = produto_servico.unidade_tributavel
etree.SubElement(prod, 'qTrib').text = str(produto_servico.quantidade_tributavel)
etree.SubElement(prod, 'vUnTrib').text = '{:.4f}'.format(produto_servico.valor_unitario_tributavel or 0)
if produto_servico.desconto:
etree.SubElement(prod, 'vDesc').text = '{:.2f}'.format(produto_servico.desconto)
""" Indica se valor do Item (vProd) entra no valor total da NF-e (vProd)
0=Valor do item (vProd) não compõe o valor total da NF-e
1=Valor do item (vProd) compõe o valor total da NF-e (vProd) (v2.0)
@ -257,7 +262,7 @@ class SerializacaoXML(Serializacao):
# Lei da transparencia
# Tributos aprox por item
if produto_servico.valor_tributos_aprox:
etree.SubElement(imposto, 'vTotTrib').text = produto_servico.valor_tributos_aprox
etree.SubElement(imposto, 'vTotTrib').text = str(produto_servico.valor_tributos_aprox)
### ICMS
icms = etree.SubElement(imposto, 'ICMS')
@ -293,35 +298,35 @@ class SerializacaoXML(Serializacao):
etree.SubElement(icms_item, 'modBC').text = str(produto_servico.icms_modalidade_determinacao_bc)
# 00=Tributada integralmente.
if produto_servico.icms_modalidade == '00':
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# 10=Tributada e com cobrança do ICMS por substituição tributária
elif produto_servico.icms_modalidade == '10':
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# Modalidade de determinação da BC do ICMS ST
# 0=Preço tabelado ou máximo sugerido; 1=Lista Negativa (valor);2=Lista Positiva (valor);3=Lista Neutra (valor);4=Margem Valor Agregado (%);5=Pauta (valor);
etree.SubElement(icms_item, 'modBCST').text = str(produto_servico.icms_st_modalidade_determinacao_bc)
etree.SubElement(icms_item, 'modBCST').text = str(produto_servico.icms_st_modalidade_determinacao_bc)
etree.SubElement(icms_item, 'pMVAST').text = str(produto_servico.icms_st_percentual_adicional) # Percentual da margem de valor Adicionado do ICMS ST
etree.SubElement(icms_item, 'pRedBCST').text = str(produto_servico.icms_st_percentual_reducao_bc) # APercentual da Redução de BC do ICMS ST
etree.SubElement(icms_item, 'vBCST ').text = str(produto_servico.icms_st_valor_base_calculo)
etree.SubElement(icms_item, 'pICMSST ').text = str(produto_servico.icms_st_aliquota)
etree.SubElement(icms_item, 'vICMSST ').text = str(produto_servico.icms_st_valor)
etree.SubElement(icms_item, 'vBCST').text = str(produto_servico.icms_st_valor_base_calculo)
etree.SubElement(icms_item, 'pICMSST').text = str(produto_servico.icms_st_aliquota)
etree.SubElement(icms_item, 'vICMSST').text = str(produto_servico.icms_st_valor)
# 20=Com redução de base de cálculo
elif produto_servico.icms_modalidade == '20':
etree.SubElement(icms_item, 'pRedBC').text = '{:.2f}'.format(produto_servico.icms_percentual_reducao_bc or 0) # Percentual da Redução de BC
etree.SubElement(icms_item, 'vBC').text = '{:.2f}'.format(produto_servico.icms_valor_base_calculo or 0) # Valor da BC do ICMS
etree.SubElement(icms_item, 'vBC').text = '{:.2f}'.format(produto_servico.icms_valor_base_calculo or 0) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = '{:.2f}'.format(produto_servico.icms_aliquota or 0) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# NT_2016_002
# Inclusão das regras de validação N17b-20, N23b-20 e N27b-20 que impedem que seja informado zero como percentual de FCP ou FCP ST.
# Inclusão das regras de validação N17b-20, N23b-20 e N27b-20 que impedem que seja informado zero como percentual de FCP ou FCP ST.
# Os campos relativos ao Fundo de Combate à Pobreza só devem ser informados se o produto estiver sujeito a incidência do mesmo.
if produto_servico.fcp_valor:
if produto_servico.fcp_valor:
etree.SubElement(icms_item, 'vBCFCP').text = '{:.2f}'.format(produto_servico.fcp_base_calculo or 0) # Base de calculo FCP
etree.SubElement(icms_item, 'pFCP').text = '{:.2f}'.format(produto_servico.fcp_percentual or 0) # Percentual FCP
etree.SubElement(icms_item, 'vFCP').text = '{:.2f}'.format(produto_servico.fcp_valor or 0) # Valor Fundo Combate a Pobreza
etree.SubElement(icms_item, 'pFCP').text = '{:.2f}'.format(produto_servico.fcp_percentual or 0) # Percentual FCP
etree.SubElement(icms_item, 'vFCP').text = '{:.2f}'.format(produto_servico.fcp_valor or 0) # Valor Fundo Combate a Pobreza
# Impostos não implementados
else:
raise NotImplementedError
@ -350,7 +355,7 @@ class SerializacaoXML(Serializacao):
elif produto_servico.pis_modalidade == '03':
pis_item = etree.SubElement(pis, 'PISQtde')
etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade
etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
etree.SubElement(pis_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial)
etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
etree.SubElement(pis_item, 'vPIS').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0)
else:
@ -359,7 +364,7 @@ class SerializacaoXML(Serializacao):
etree.SubElement(pis_item, 'vBC').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0)
etree.SubElement(pis_item, 'pPIS').text = '{:.2f}'.format(produto_servico.pis_aliquota_percentual or 0)
if produto_servico.pis_modalidade is not '99':
etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial
etree.SubElement(pis_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial)
etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual
etree.SubElement(pis_item, 'vPIS').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0)
@ -386,9 +391,9 @@ class SerializacaoXML(Serializacao):
elif produto_servico.cofins_modalidade == '03':
cofins_item = etree.SubElement(cofins, 'COFINSQtde')
etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
etree.SubElement(cofins_item, 'qBCProd').text = produto_servico.quantidade_comercial
etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual
etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor
etree.SubElement(cofins_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial)
etree.SubElement(cofins_item, 'vAliqProd').text = '{:.4f}'.format(produto_servico.cofins_aliquota_percentual)
etree.SubElement(cofins_item, 'vCOFINS').text = '{:.2f}'.format(produto_servico.cofins_valor)
else:
cofins_item = etree.SubElement(cofins, 'COFINSOutr')
etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade
@ -411,6 +416,18 @@ class SerializacaoXML(Serializacao):
else:
return raiz
def _serializar_responsavel_tecnico(self, responsavel_tecnico, tag_raiz='infRespTec', retorna_string=True):
raiz = etree.Element(tag_raiz)
etree.SubElement(raiz, 'CNPJ').text = responsavel_tecnico.cnpj
etree.SubElement(raiz, 'xContato').text = responsavel_tecnico.contato
etree.SubElement(raiz, 'email').text = responsavel_tecnico.email
etree.SubElement(raiz, 'fone').text = responsavel_tecnico.fone
if retorna_string:
return etree.tostring(raiz, encoding="unicode", pretty_print=True)
else:
return raiz
def _serializar_nota_fiscal(self, nota_fiscal, tag_raiz='infNFe', retorna_string=True):
raiz = etree.Element(tag_raiz, versao=self._versao)
@ -607,14 +624,14 @@ class SerializacaoXML(Serializacao):
etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre
# Pagamento
""" Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e.
""" Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e.
Para as notas com finalidade de Ajuste ou Devolução o campo Forma de Pagamento deve ser preenchido com 90=Sem Pagamento. """
pag = etree.SubElement(raiz, 'pag')
detpag = etree.SubElement(pag, 'detPag')
if nota_fiscal.finalidade_emissao == '3' or nota_fiscal.finalidade_emissao == '4':
etree.SubElement(detpag, 'tPag').text = '90'
etree.SubElement(detpag, 'vPag').text = '{:.2f}'.format(0)
else:
else:
etree.SubElement(detpag, 'tPag').text = str(nota_fiscal.tipo_pagamento).zfill(2)
etree.SubElement(detpag, 'vPag').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota)
if nota_fiscal.tipo_pagamento == 3 or nota_fiscal.tipo_pagamento == 4:
@ -638,6 +655,12 @@ class SerializacaoXML(Serializacao):
if nota_fiscal.informacoes_complementares_interesse_contribuinte:
etree.SubElement(info_ad, 'infCpl').text = nota_fiscal.informacoes_complementares_interesse_contribuinte
# Responsavel Tecnico NT2018/003
if nota_fiscal.responsavel_tecnico:
raiz.append(self._serializar_responsavel_tecnico(
nota_fiscal.responsavel_tecnico[0], retorna_string=False))
if retorna_string:
return etree.tostring(raiz, encoding="unicode", pretty_print=True)
else:
@ -677,7 +700,7 @@ class SerializacaoXML(Serializacao):
class SerializacaoQrcode(object):
""" Classe que gera e serializa o qrcode de NFC-e no xml """
def gerar_qrcode(self, token, csc, xml, return_qr=False):
def gerar_qrcode(self, token, csc, xml, return_qr=False, online=True):
""" Classe para gerar url do qrcode da NFC-e """
# Procura atributos no xml
ns = {'ns':NAMESPACE_NFE}
@ -700,38 +723,56 @@ class SerializacaoQrcode(object):
except IndexError:
cpf = None
total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0]
icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0]
# icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0]
digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode()
data = base64.b16encode(data).decode()
digest = base64.b16encode(digest).decode()
lista_dia = re.findall("-\d{2}", str(data))
dia = str(lista_dia[1])
dia = dia[1:]
replacements = {'0': ''}
token = re.sub('([0])', lambda m: replacements[m.group()], token)
if cpf is None:
url = 'chNFe={}&nVersao={}&tpAmb={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
chave, VERSAO_QRCODE, tpamb, data.lower(), total, icms, digest.lower(), token)
#VERSAO_QRCODE =2
if online:
#versão online
url = '{}|{}|{}|{}'.format(chave,VERSAO_QRCODE, tpamb, token)
else:
url = 'chNFe={}&nVersao={}&tpAmb={}&cDest={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format(
chave, VERSAO_QRCODE, tpamb, cpf, data.lower(), total, icms, digest.lower(), token)
#versão offline
digest = digest.lower()
digest = digest.hex()
url = '{}|{}|{}|{}|{}|{}|{}'.format(
chave,VERSAO_QRCODE,tpamb,dia,total,digest,token
)
url_hash = hashlib.sha1(url.encode()+csc.encode()).digest()
url_complementar = url + csc
url_hash = hashlib.sha1(url_complementar.encode()).digest()
url_hash = base64.b16encode(url_hash).decode()
url = url + '&cHashQRCode=' + url_hash.upper()
url = 'p={}|{}'.format(url, url_hash)
# url_chave - Texto com a URL de consulta por chave de acesso a ser impressa no DANFE NFC-e.
# Informar a URL da “Consulta por chave de acesso da NFC-e”.
# Informar a URL da “Consulta por chave de acesso da NFC-e”.
# A mesma URL que deve estar informada no DANFE NFC-e para consulta por chave de acesso
lista_uf_padrao = ['PR', 'CE', 'RS', 'RJ', 'RO']
lista_uf_padrao = ['PR', 'CE', 'RS', 'RJ', 'RO', 'DF']
if uf.upper() in lista_uf_padrao:
qrcode = NFCE[uf.upper()]['QR'] + url
url_chave = NFCE[uf.upper()]['URL']
elif uf.upper() == 'SP':
if tpamb == '1':
qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['QR'] + url
url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['URL'] + url
url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['URL']
else:
qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['QR'] + url
url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['URL'] + url
# AC, AM, RR, PA,
url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['URL']
# BA tem comportamento distindo para qrcode e url
elif uf.upper() == 'BA':
if tpamb == '1':
qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url
else:
qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url
url_chave = url_chave = NFCE[uf.upper()]['URL']
# AC, AM, RR, PA,
else:
if tpamb == '1':
qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url

30
pynfe/utils/descompactar.py

@ -0,0 +1,30 @@
"""
@author: Lucas Resende
classe que descompacta o gzip recebido pela consulta distribuicao
"""
from io import BytesIO
import base64
import gzip
from lxml import etree
class DescompactaGzip(object):
@staticmethod
def descompacta(stringZipada):
"""
:paramn stringZipada: String
:return : Etree
"""
arq = BytesIO()
arq.write(base64.b64decode(stringZipada))
arq.seek(0)
zip = gzip.GzipFile(fileobj=arq)
texto = zip.read()
arq.close()
zip.close()
descompactado = texto.decode('utf-8')
return etree.fromstring(descompactado)

10
pynfe/utils/flags.py

@ -12,7 +12,7 @@ NAMESPACE_BETHA = 'http://www.betha.com.br/e-nota-contribuinte-ws'
VERSAO_PADRAO = '4.00'
VERSAO_QRCODE = '100'
VERSAO_QRCODE = '2'
TIPOS_DOCUMENTO = (
'CNPJ',
@ -40,7 +40,7 @@ ICMS_TIPOS_TRIBUTACAO = (
('ST', 'ICMS ST - Grupo de informação do ICMS ST devido para a UF de destino, nas operações interestaduais de produtos que tiveram retenção antecipada de ICMS por ST na UF do remetente. Repasse via Substituto Tributário.')
)
ICMS_ORIGENS = (
ICMS_ORIGENS = (
(0, 'Nacional, exceto as indicadas nos códigos 3, 4, 5 e 8. '),
(1, 'Estrangeira - Importação direta, exceto a indicada no código 6.'),
(2, 'Estrangeira - Adquirida no mercado interno, exceto a indicada no código 7.'),
@ -49,7 +49,7 @@ ICMS_ORIGENS = (
(5, 'Nacional, mercadoria ou bem com Conteúdo de Importação inferior ou igual a 40%. '),
(6, 'Estrangeira - Importação direta, sem similar nacional, constante em lista da CAMEX e gás natural. '),
(7, 'Estrangeira - Adquirida no mercado interno, sem similar nacional, constante em lista da CAMEX e gás natural.'),
(8, 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70%.')
(8, 'Nacional, mercadoria ou bem com Conteúdo de Importação superior a 70%.')
)
ICMS_MODALIDADES = (
@ -147,7 +147,7 @@ IPI_TIPOS_CALCULO = (
PIS_TIPOS_TRIBUTACAO = (
('01', 'PIS 01 - Operação Tributável - Base de cálculo = valor da operação alíquota normal (cumulativo/não cumulativo)'),
('02', 'PIS 02 - Operação Tributável - Base de cálculo = valor da operação (alíquota diferenciada)'),
('02', 'PIS 02 - Operação Tributável - Base de cálculo = valor da operação (alíquota diferenciada)'),
('03', 'PIS 03 - Operacao Tributavel - Base de cálculo = quantidade vendida x alíquota por unidade de produto)'),
('04', 'PIS 04 - Operacao Tributavel - Tributacao Monofasica - (Aliquota Zero)'),
('06', 'PIS 06 - Operacao Tributavel - Aliquota Zero'),
@ -184,7 +184,7 @@ PIS_TIPOS_CALCULO = IPI_TIPOS_CALCULO
COFINS_TIPOS_TRIBUTACAO = (
('01', 'COFINS 01 - Operação Tributável - Base de cálculo = valor da operação alíquota normal (cumulativo/não cumulativo)'),
('02', 'COFINS 02 - Operação Tributável - Base de cálculo = valor da operação (alíquota diferenciada)'),
('02', 'COFINS 02 - Operação Tributável - Base de cálculo = valor da operação (alíquota diferenciada)'),
('03', 'COFINS 03 - Operacao Tributavel - Base de cálculo = quantidade vendida x alíquota por unidade de produto)'),
('04', 'COFINS 04 - Operacao Tributavel - Tributacao Monofasica - (Aliquota Zero)'),
('06', 'COFINS 06 - Operacao Tributavel - Aliquota Zero'),

134
pynfe/utils/webservices.py

@ -27,12 +27,12 @@ NFCE = {
'AM': {
# csc_homologacao = '0123456789'
# token_homologacao = '000001'
'STATUS': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeStatusServico2',
'AUTORIZACAO': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeAutorizacao',
'RECIBO': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeRetAutorizacao',
'CHAVE': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeConsulta2',
'INUTILIZACAO': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeInutilizacao2',
'EVENTOS': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/RecepcaoEvento',
'STATUS': 'nfe.sefaz.am.gov.br/services2/services/NfeStatusServico4',
'AUTORIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeAutorizacao4',
'RECIBO': 'nfe.sefaz.am.gov.br/services2/services/NfeRetAutorizacao4',
'CHAVE': 'nfe.sefaz.am.gov.br/services2/services/NfeConsulta4',
'INUTILIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeInutilizacao4',
'EVENTOS': 'nfe.sefaz.am.gov.br/services2/services/RecepcaoEvento4',
'QR': 'sefaz.am.gov.br/nfceweb/consultarNFCe.jsp?',
'URL': 'sefaz.am.gov.br/nfceweb/formConsulta.do',
'HTTPS': 'http://sistemas.',
@ -108,7 +108,7 @@ NFCE = {
'QR': 'http://nfce.set.rn.gov.br/consultarNFCe.aspx?',
'HTTPS': '',
'HOMOLOGACAO': ''
},
'PB': {
'STATUS': '',
@ -126,10 +126,10 @@ NFCE = {
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': 'sefaz.pe.gov.br/nfce-web/consultarNFCe?',
'QR': 'sefaz.pe.gov.br/nfce/consulta?',
'HTTPS': 'http://nfce.',
'HOMOLOGACAO': 'http://nfcehomolog.',
'URL': 'sefaz.pe.gov.br/nfce-web/consultarNFCe'
'URL': 'sefaz.pe.gov.br/nfce/consulta'
},
'AL': {
'STATUS': '',
@ -152,19 +152,23 @@ NFCE = {
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': 'sefaz.ba.gov.br/servicos/nfce/modulos/geral/NFCEC_consulta_chave_acesso.aspx?',
'QR': 'sefaz.ba.gov.br/servicos/nfce/qrcode.aspx?',
'HTTPS': 'http://nfe.',
'HOMOLOGACAO': 'http://hnfe.',
'URL': 'nfe.sefaz.ba.gov.br/servicos/nfce/default.aspx'
},
'URL': 'http://hinternet.sefaz.ba.gov.br/nfce/consulta'
},
'MG': {
'STATUS': '',
'AUTORIZACAO': '',
'RECIBO': '',
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': ''
'STATUS': 'fazenda.mg.gov.br/nfce/services/NFeStatusServico4',
'AUTORIZACAO': 'fazenda.mg.gov.br/nfce/services/NFeAutorizacao4',
'RECIBO': 'fazenda.mg.gov.br/nfce/services/NFeRetAutorizacao4',
'CHAVE': 'fazenda.mg.gov.br/nfce/services/NFeConsultaProtocolo4',
'INUTILIZACAO': 'fazenda.mg.gov.br/nfce/services/NFeInutilizacao4',
'EVENTOS': 'fazenda.mg.gov.br/nfce/services/NFeRecepcaoEvento4',
'CADASTRO': 'fazenda.mg.gov.br/nfce/services/CadConsultaCadastro4',
'QR': 'fazenda.mg.gov.br/portalnfce/sistema/qrcode.xhtml?',
'HTTPS': 'https://nfce.',
'HOMOLOGACAO': 'https://hnfce.',
'URL': 'fazenda.mg.gov.br/portalnfce'
},
'ES': {
'STATUS': '',
@ -173,7 +177,10 @@ NFCE = {
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': ''
'QR': 'sefaz.es.gov.br/ConsultaNFCe/qrcode.aspx? ',
'HTTPS': 'http://nfe.',
'HOMOLOGACAO': 'http://homologacao.',
'URL': 'www.sefaz.es.gov.br/nfce/consulta'
},
'RJ': {
'STATUS': '',
@ -182,16 +189,16 @@ NFCE = {
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': 'http://www4.fazenda.rj.gov.br/consultaNFCe/QRCode?',
'QR': 'http://www4.fazenda.rj.gov.br/consultaNFCe/QRCode?',
'URL': 'www.nfce.fazenda.rj.gov.br/consulta'
},
# Os Web Services de homologação da NFC-e 4.00 são:
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeAutorizacao4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeConsultaProtocolo4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRetAutorizacao4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRecepcaoEvento4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeInutilizacao4.asmx
# Os Web Services de homologação da NFC-e 4.00 são:
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeAutorizacao4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeConsultaProtocolo4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRetAutorizacao4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeRecepcaoEvento4.asmx
# https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeInutilizacao4.asmx
'SP': {
'STATUS': 'nfce.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx',
'AUTORIZACAO': 'nfce.fazenda.sp.gov.br/ws/NFeAutorizacao4.asmx',
@ -200,7 +207,7 @@ NFCE = {
'INUTILIZACAO': 'nfce.fazenda.sp.gov.br/ws/NFeInutilizacao4.asmx',
'EVENTOS': 'nfce.fazenda.sp.gov.br/ws/NFeRecepcaoEvento4.asmx',
'QR': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaQRCode.aspx?',
'URL': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaPublica.aspx',
'URL': 'nfce.fazenda.sp.gov.br/consulta',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://homologacao.'
},
@ -213,7 +220,7 @@ NFCE = {
'EVENTOS': 'nfce.sefa.pr.gov.br/nfce/NFeRecepcaoEvento4?wsdl',
'CADASTRO': 'nfce.sefa.pr.gov.br/nfce/CadConsultaCadastro4?wsdl',
'QR': 'http://www.fazenda.pr.gov.br/nfce/qrcode?',
'URL': 'http://www.fazenda.pr.gov.br',
'URL': 'http://www.fazenda.pr.gov.br/nfce/consulta',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://homologacao.'
},
@ -261,8 +268,13 @@ NFCE = {
'EVENTOS': 'sefaz.go.gov.br/nfe/services/NFeRecepcaoEvento4?wsdl',
'QR': 'sefaz.go.gov.br/nfeweb/sites/nfce/danfeNFCe?',
'CADASTRO': 'sefaz.go.gov.br/nfe/services/CadConsultaCadastro4?wsdl',
'HTTPS': 'http://nfe.',
'HOMOLOGACAO': 'http://homolog.'
'HTTPS': 'https://nfe.',
'HOMOLOGACAO': 'https://homolog.',
'URL': 'sefaz.go.gov.br/nfeweb/sites/nfce/danfeNFCe'
},
'DF': {
'QR': 'http://www.fazenda.df.gov.br/nfce/qrcode?',
'URL': 'www.fazenda.df.gov.br/nfce/consulta'
},
# RO, AC, RR, PA, AP, TO, MA, PI, RN, PB, AL, SE, BA, ES, RJ, GO, DF
'SVRS': {
@ -290,12 +302,12 @@ NFE = {
'HOMOLOGACAO': 'https://hom'
},
'AM': {
'STATUS': 'nfe.sefaz.am.gov.br/services2/services/NfeStatusServico2',
'AUTORIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeAutorizacao',
'RECIBO': 'nfe.sefaz.am.gov.br/services2/services/NfeRetAutorizacao',
'CHAVE': 'nfe.sefaz.am.gov.br/services2/services/NfeConsulta2',
'INUTILIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeInutilizacao2',
'EVENTOS': 'nfe.sefaz.am.gov.br/services2/services/RecepcaoEvento',
'STATUS': 'nfe.sefaz.am.gov.br/services2/services/NfeStatusServico4',
'AUTORIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeAutorizacao4',
'RECIBO': 'nfe.sefaz.am.gov.br/services2/services/NfeRetAutorizacao4',
'CHAVE': 'nfe.sefaz.am.gov.br/services2/services/NfeConsulta4',
'INUTILIZACAO': 'nfe.sefaz.am.gov.br/services2/services/NfeInutilizacao4',
'EVENTOS': 'nfe.sefaz.am.gov.br/services2/services/RecepcaoEvento4',
'CADASTRO': 'nfe.sefaz.am.gov.br/services2/services/cadconsultacadastro2',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://hom'
@ -310,7 +322,7 @@ NFE = {
'CHAVE': 'sefaz.ce.gov.br/nfe4/services/NFeConsultaProtocolo4?WSDL',
'INUTILIZACAO': 'sefaz.ce.gov.br/nfe4/services/NFeInutilizacao4?WSDL',
'EVENTOS': 'sefaz.ce.gov.br/nfe4/services/NFeRecepcaoEvento4?WSDL',
'CADASTRO': 'sefaz.ce.gov.br/nfe2/services/CadConsultaCadastro2?wsdl',
'CADASTRO': 'nfe.sefaz.ce.gov.br/nfe4/services/CadConsultaCadastro4?wsdl',
'DOWNLOAD': 'sefaz.ce.gov.br/nfe2/services/NfeDownloadNF?wsdl',
'HTTPS': 'https://nfe.',
'HOMOLOGACAO': 'https://nfeh.'
@ -336,23 +348,23 @@ NFE = {
'CADASTRO': 'nfe.sefaz.ba.gov.br/webservices/CadConsultaCadastro4/CadConsultaCadastro4.asmx',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://h'
},
},
'MG': {
'STATUS': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeStatusServico4',
'AUTORIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeAutorizacao4',
'RECIBO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeRetAutorizacao4',
'CHAVE': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeConsulta4',
'INUTILIZACAO': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeInutilizacao4',
'EVENTOS': 'nfe.fazenda.mg.gov.br/nfe2/services/RecepcaoEvento',
'EVENTOS': 'nfe.fazenda.mg.gov.br/nfe2/services/NFeRecepcaoEvento4',
'CADASTRO': 'nfe.fazenda.mg.gov.br/nfe2/services/cadconsultacadastro2',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://h'
},
'SP': {
'STATUS': 'nfe.fazenda.sp.gov.br/ws/NFeStatusServico4.asmx',
'STATUS': 'nfe.fazenda.sp.gov.br/ws/nfestatusservico4.asmx',
'AUTORIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeautorizacao4.asmx',
'RECIBO': 'nfe.fazenda.sp.gov.br/ws/nferetautorizacao4.asmx',
'CHAVE': 'nfe.fazenda.sp.gov.br/ws/nfeconsulta4.asmx',
'CHAVE': 'nfe.fazenda.sp.gov.br/ws/nfeconsultaprotocolo4.asmx',
'INUTILIZACAO': 'nfe.fazenda.sp.gov.br/ws/nfeinutilizacao4.asmx',
'EVENTOS': 'nfe.fazenda.sp.gov.br/ws/nferecepcaoevento4.asmx',
'CADASTRO': 'nfe.fazenda.sp.gov.br/ws/cadconsultacadastro4.asmx',
@ -378,31 +390,31 @@ NFE = {
'CHAVE': 'sefazrs.rs.gov.br/ws/NfeConsulta/NfeConsulta4.asmx',
'INUTILIZACAO': 'sefazrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao4.asmx',
'EVENTOS': 'sefazrs.rs.gov.br/ws/recepcaoevento/recepcaoevento4.asmx',
'CADASTRO': 'https://cad.sefazrs.rs.gov.br/ws/cadconsultacadastro/cadconsultacadastro2.asmx',
'CADASTRO': 'cad.sefazrs.rs.gov.br/ws/cadconsultacadastro/cadconsultacadastro2.asmx',
'DOWNLOAD': 'sefazrs.rs.gov.br/ws/nfeDownloadNF/nfeDownloadNF.asmx',
'DESTINADAS': 'sefazrs.rs.gov.br/ws/nfeConsultaDest/nfeConsultaDest.asmx',
'HTTPS': 'https://nfe.',
'HOMOLOGACAO': 'https://nfe-homologacao.'
},
'MS': {
'STATUS': 'nfe.ms.gov.br/ws/NFeStatusServico4',
'AUTORIZACAO': 'nfe.ms.gov.br/ws/NFeAutorizacao4',
'RECIBO': 'nfe.ms.gov.br/ws/NFeRetAutorizacao4',
'CHAVE': 'nfe.ms.gov.br/ws/NFeConsultaProtocolo4',
'INUTILIZACAO': 'nfe.ms.gov.br/ws/NFeInutilizacao4',
'EVENTOS': 'nfe.ms.gov.br/ws/NFeRecepcaoEvento4',
'CADASTRO': 'nfe.fazenda.ms.gov.br/producao/services2/CadConsultaCadastro2',
'STATUS': 'nfe.sefaz.ms.gov.br/ws/NFeStatusServico4',
'AUTORIZACAO': 'nfe.sefaz.ms.gov.br/ws/NFeAutorizacao4',
'RECIBO': 'nfe.sefaz.ms.gov.br/ws/NFeRetAutorizacao4',
'CHAVE': 'nfe.sefaz.ms.gov.br/ws/NFeConsultaProtocolo4',
'INUTILIZACAO': 'nfe.sefaz.ms.gov.br/ws/NFeInutilizacao4',
'EVENTOS': 'nfe.sefaz.ms.gov.br/ws/NFeRecepcaoEvento4',
'CADASTRO': 'nfe.sefaz.ms.gov.br/ws/CadConsultaCadastro4',
'HTTPS': 'https://',
'HOMOLOGACAO': 'https://homologacao.'
'HOMOLOGACAO': 'https://hom.'
},
'MT': {
'STATUS': 'sefaz.mt.gov.br/nfews/v2/services/NfeStatusServico2?wsdl',
'AUTORIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeAutorizacao?wsdl',
'RECIBO': 'sefaz.mt.gov.br/nfews/v2/services/NfeRetAutorizacao?wsdl',
'CHAVE': 'sefaz.mt.gov.br/nfews/v2/services/NfeConsulta2?wsdl',
'INUTILIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeInutilizacao2?wsdl',
'EVENTOS': 'sefaz.mt.gov.br/nfews/v2/services/RecepcaoEvento?wsdl',
'CADASTRO': 'sefaz.mt.gov.br/nfews/v2/services/CadConsultaCadastro2?wsdl',
'STATUS': 'sefaz.mt.gov.br/nfews/v2/services/NfeStatusServico4?wsdl',
'AUTORIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeAutorizacao4?wsdl',
'RECIBO': 'sefaz.mt.gov.br/nfews/v2/services/NfeRetAutorizacao4?wsdl',
'CHAVE': 'sefaz.mt.gov.br/nfews/v2/services/NfeConsulta4?wsdl',
'INUTILIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeInutilizacao4?wsdl',
'EVENTOS': 'sefaz.mt.gov.br/nfews/v2/services/RecepcaoEvento4?wsdl',
'CADASTRO': 'sefaz.mt.gov.br/nfews/v2/services/CadConsultaCadastro4?wsdl',
'HTTPS': 'https://nfe.',
'HOMOLOGACAO': 'https://homologacao.'
},
@ -462,7 +474,7 @@ NFE = {
# Nfs-e
NFSE = {
#
#
'BETHA': {
'AUTORIZACAO':'GerarNfse',
'CANCELAR':'CancelarNfse',
@ -486,4 +498,4 @@ NFSE = {
'HTTPS':'https://producao.ginfes.com.br/ServiceGinfesImpl?wsdl',
'HOMOLOGACAO':'https://homologacao.ginfes.com.br/ServiceGinfesImpl?wsdl'
}
}
}

2
requirements-nfse.txt

@ -1,3 +1,3 @@
# Opcional para NFS-e
suds-jurko
pyxb
pyxb=1.2.4
Loading…
Cancel
Save