You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
7.3 KiB
184 lines
7.3 KiB
# -*- coding: utf-8 -*-
|
|
try:
|
|
set
|
|
except:
|
|
from sets import Set as set
|
|
|
|
try:
|
|
from lxml import etree
|
|
except ImportError:
|
|
try:
|
|
# Python 2.5 - cElementTree
|
|
import xml.etree.cElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Python 2.5 - ElementTree
|
|
import xml.etree.ElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Instalacao normal do cElementTree
|
|
import cElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Instalacao normal do ElementTree
|
|
import elementtree.ElementTree as etree
|
|
except ImportError:
|
|
raise Exception('Falhou ao importar lxml/ElementTree')
|
|
|
|
from pynfe.entidades import Emitente, Cliente, Produto, Transportadora, NotaFiscal
|
|
from pynfe.excecoes import NenhumObjetoEncontrado, MuitosObjetosEncontrados
|
|
from pynfe.utils import so_numeros, obter_municipio_por_codigo, obter_pais_por_codigo
|
|
|
|
class Serializacao(object):
|
|
"""Classe abstrata responsavel por fornecer as funcionalidades basicas para
|
|
exportacao e importacao de Notas Fiscais eletronicas para formatos serializados
|
|
de arquivos. Como XML, JSON, binario, etc.
|
|
|
|
Nao deve ser instanciada diretamente!"""
|
|
|
|
_fonte_dados = None
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
if cls == Serializacao:
|
|
raise Exception('Esta classe nao pode ser instanciada diretamente!')
|
|
else:
|
|
return super(Serializacao, cls).__new__(cls, *args, **kwargs)
|
|
|
|
def __init__(self, fonte_dados):
|
|
self._fonte_dados = fonte_dados
|
|
|
|
def exportar(self, destino, **kwargs):
|
|
"""Gera o(s) arquivo(s) de exportacao a partir da Nofa Fiscal eletronica
|
|
ou lista delas."""
|
|
|
|
raise Exception('Metodo nao implementado')
|
|
|
|
def importar(self, origem):
|
|
"""Fabrica que recebe o caminho ou objeto de origem e instancia os objetos
|
|
da PyNFe"""
|
|
|
|
raise Exception('Metodo nao implementado')
|
|
|
|
class SerializacaoXML(Serializacao):
|
|
def exportar(self, destino, **kwargs):
|
|
"""Gera o(s) arquivo(s) de Nofa Fiscal eletronica no padrao oficial da SEFAZ
|
|
e Receita Federal, para ser(em) enviado(s) para o webservice ou para ser(em)
|
|
armazenado(s) em cache local."""
|
|
|
|
# Carrega lista de Notas Fiscais
|
|
notas_fiscais = self._fonte_dados.obter_lista(_classe=NotaFiscal, **kwargs)
|
|
|
|
saida = []
|
|
|
|
# Dados do emitente
|
|
saida.append(self._serializar_emitente(self._obter_emitente_de_notas_fiscais(notas_fiscais)))
|
|
|
|
# Certificado Digital? XXX
|
|
|
|
# Clientes
|
|
#saida.append(self._serializar_clientes(**kwargs))
|
|
|
|
# Transportadoras
|
|
#saida.append(self._serializar_transportadoras(**kwargs))
|
|
|
|
# Produtos
|
|
#saida.append(self._serializar_produtos(**kwargs))
|
|
|
|
# Lote de Notas Fiscais
|
|
#saida.append(self._serializar_notas_fiscais(**kwargs))
|
|
|
|
def importar(self, origem):
|
|
"""Cria as instancias do PyNFe a partir de arquivos XML no formato padrao da
|
|
SEFAZ e Receita Federal."""
|
|
|
|
raise Exception('Metodo nao implementado')
|
|
|
|
def _obter_emitente_de_notas_fiscais(self, notas_fiscais):
|
|
lista = list(set([nf.emitente for nf in notas_fiscais if nf.emitente]))
|
|
|
|
if len(lista) == 0:
|
|
raise NenhumObjetoEncontrado('Nenhum objeto foi encontrado!')
|
|
elif len(lista) > 1:
|
|
raise MuitosObjetosEncontrados('Muitos objetos foram encontrados!')
|
|
|
|
return lista[0]
|
|
|
|
def _serializar_emitente(self, emitente, tag_raiz='emit'):
|
|
raiz = etree.Element(tag_raiz)
|
|
|
|
# Dados do emitente
|
|
etree.SubElement(raiz, 'CNPJ').text = so_numeros(emitente.cnpj)
|
|
etree.SubElement(raiz, 'xNome').text = emitente.razao_social
|
|
etree.SubElement(raiz, 'xFant').text = emitente.nome_fantasia
|
|
etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual
|
|
|
|
# Endereço
|
|
endereco = etree.SubElement(raiz, 'enderEmit')
|
|
etree.SubElement(endereco, 'xLgr').text = emitente.endereco_logradouro
|
|
etree.SubElement(endereco, 'nro').text = emitente.endereco_numero
|
|
etree.SubElement(endereco, 'xCpl').text = emitente.endereco_complemento
|
|
etree.SubElement(endereco, 'xBairro').text = emitente.endereco_bairro
|
|
etree.SubElement(endereco, 'cMun').text = emitente.endereco_municipio
|
|
etree.SubElement(endereco, 'xMun').text = obter_municipio_por_codigo(
|
|
emitente.endereco_municipio, emitente.endereco_uf,
|
|
)
|
|
etree.SubElement(endereco, 'UF').text = emitente.endereco_uf
|
|
etree.SubElement(endereco, 'CEP').text = so_numeros(emitente.endereco_cep)
|
|
etree.SubElement(endereco, 'cPais').text = emitente.endereco_pais
|
|
etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(emitente.endereco_pais)
|
|
etree.SubElement(endereco, 'fone').text = emitente.endereco_telefone
|
|
|
|
return etree.tostring(raiz, pretty_print=True)
|
|
|
|
def _serializar_cliente(self, cliente, tag_raiz='dest'):
|
|
raiz = etree.Element(tag_raiz)
|
|
|
|
# Dados do cliente
|
|
etree.SubElement(raiz, cliente.tipo_documento).text = so_numeros(cliente.numero_documento)
|
|
etree.SubElement(raiz, 'xNome').text = cliente.razao_social
|
|
etree.SubElement(raiz, 'IE').text = cliente.inscricao_estadual
|
|
|
|
# Endereço
|
|
endereco = etree.SubElement(raiz, 'enderDest')
|
|
etree.SubElement(endereco, 'xLgr').text = cliente.endereco_logradouro
|
|
etree.SubElement(endereco, 'nro').text = cliente.endereco_numero
|
|
etree.SubElement(endereco, 'xCpl').text = cliente.endereco_complemento
|
|
etree.SubElement(endereco, 'xBairro').text = cliente.endereco_bairro
|
|
etree.SubElement(endereco, 'cMun').text = cliente.endereco_municipio
|
|
etree.SubElement(endereco, 'xMun').text = obter_municipio_por_codigo(
|
|
cliente.endereco_municipio, cliente.endereco_uf,
|
|
)
|
|
etree.SubElement(endereco, 'UF').text = cliente.endereco_uf
|
|
etree.SubElement(endereco, 'CEP').text = so_numeros(cliente.endereco_cep)
|
|
etree.SubElement(endereco, 'cPais').text = cliente.endereco_pais
|
|
etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(cliente.endereco_pais)
|
|
etree.SubElement(endereco, 'fone').text = cliente.endereco_telefone
|
|
|
|
return etree.tostring(raiz, pretty_print=True)
|
|
|
|
def _serializar_transportadora(self, transportadora, tag_raiz='transporta'):
|
|
raiz = etree.Element(tag_raiz)
|
|
|
|
# Dados da transportadora
|
|
etree.SubElement(raiz, transportadora.tipo_documento).text = so_numeros(transportadora.numero_documento)
|
|
etree.SubElement(raiz, 'xNome').text = transportadora.razao_social
|
|
etree.SubElement(raiz, 'IE').text = transportadora.inscricao_estadual
|
|
|
|
# Endereço
|
|
etree.SubElement(raiz, 'xEnder').text = transportadora.endereco_logradouro
|
|
etree.SubElement(raiz, 'cMun').text = transportadora.endereco_municipio
|
|
etree.SubElement(raiz, 'xMun').text = obter_municipio_por_codigo(
|
|
transportadora.endereco_municipio, transportadora.endereco_uf,
|
|
)
|
|
etree.SubElement(raiz, 'UF').text = transportadora.endereco_uf
|
|
|
|
return etree.tostring(raiz, pretty_print=True)
|
|
|
|
def _serializar_produto(self, produto, tag_raiz='prod'):
|
|
# TODO
|
|
return ''
|
|
|
|
def _serializar_notas_fiscal(self, notas_fiscal, tag_raiz='infNFe'):
|
|
# TODO
|
|
return ''
|
|
|