diff --git a/pynfe/entidades/base.py b/pynfe/entidades/base.py index bec7cc1..a06058e 100644 --- a/pynfe/entidades/base.py +++ b/pynfe/entidades/base.py @@ -13,6 +13,9 @@ class Entidade(object): if self._fonte_dados: self._fonte_dados.adicionar_objeto(self) + def __repr__(self): + return '<%s %s>'%(self.__class__.__name__, str(self)) + class Lote(object): pass diff --git a/pynfe/entidades/cliente.py b/pynfe/entidades/cliente.py index 03d6ec3..c70c03e 100644 --- a/pynfe/entidades/cliente.py +++ b/pynfe/entidades/cliente.py @@ -50,3 +50,6 @@ class Cliente(Entidade): # - Telefone endereco_telefone = str() + def __str__(self): + return ' '.join([self.tipo_documento, self.numero_documento]) + diff --git a/pynfe/entidades/emitente.py b/pynfe/entidades/emitente.py index b4ba179..6d5ea61 100644 --- a/pynfe/entidades/emitente.py +++ b/pynfe/entidades/emitente.py @@ -54,6 +54,6 @@ class Emitente(Entidade): # Logotipo logotipo = None - def __repr__(self): - return ''%(self.cnpj, self.razao_social) + def __str__(self): + return self.cnpj diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 22c6975..74d7c85 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -294,6 +294,9 @@ class NotaFiscal(Entidade): super(NotaFiscal, self).__init__(*args, **kwargs) + def __str__(self): + return ' '.join([self.modelo, self.serie, self.numero_nf]) + def adicionar_nota_fiscal_referenciada(self, **kwargs): u"""Adiciona uma instancia de Nota Fisca referenciada""" self.notas_fiscais_referenciadas.append(NotaFiscalReferenciada(**kwargs)) diff --git a/pynfe/entidades/produto.py b/pynfe/entidades/produto.py index c316d2d..3f9a430 100644 --- a/pynfe/entidades/produto.py +++ b/pynfe/entidades/produto.py @@ -61,6 +61,9 @@ class Produto(Entidade): super(Produto, self).__init__(*args, **kwargs) + def __str__(self): + return ' '.join([self.codigo, self.descricao]) + def adicionar_icms(self, **kwargs): u"""Adiciona uma instancia de ICMS a lista de ICMS do produto""" self.icms.append(ProdutoICMS(**kwargs)) diff --git a/pynfe/entidades/transportadora.py b/pynfe/entidades/transportadora.py index c329a49..9483219 100644 --- a/pynfe/entidades/transportadora.py +++ b/pynfe/entidades/transportadora.py @@ -27,3 +27,6 @@ class Transportadora(Entidade): # - Municipio (obrigatorio) endereco_municipio = str() + def __str__(self): + return ' '.join([self.tipo_documento, self.numero_documento]) + diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index c5ddab0..1283d9c 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -1,4 +1,9 @@ try: + set +except: + from sets import Set as set + +try: from lxml import etree except ImportError: try: @@ -19,6 +24,9 @@ except ImportError: except ImportError: raise Exception('Falhou ao importar lxml/ElementTree') +from pynfe.entidades import Emitente, Cliente, Produto, Transportadora, NotaFiscal +from pynfe.excecoes import NenhumObjetoEncontrado, MuitosObjetosEncontrados + class Serializacao(object): """Classe abstrata responsavel por fornecer as funcionalidades basicas para exportacao e importacao de Notas Fiscais eletronicas para formatos serializados @@ -26,7 +34,7 @@ class Serializacao(object): Nao deve ser instanciada diretamente!""" - lista_de_nfs = None + _fonte_dados = None def __new__(cls, *args, **kwargs): if cls == Serializacao: @@ -34,10 +42,10 @@ class Serializacao(object): else: return cls(*args, **kwargs) - def __init__(self, nf_ou_lista): - self.lista_de_nfs = isinstance(nf_ou_lista, list) and nf_ou_lista or [nf_ou_lista] + def __init__(self, fonte_dados): + self._fonte_dados = fonte_dados - def exportar(self, destino): + def exportar(self, **kwargs): """Gera o(s) arquivo(s) de exportacao a partir da Nofa Fiscal eletronica ou lista delas.""" @@ -50,39 +58,52 @@ class Serializacao(object): raise Exception('Metodo nao implementado') class SerializacaoXML(Serializacao): - def exportar(self, objetos, destino): + def exportar(self, **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(objetos)) + saida.append(self._serializar_emitente(self._obter_emitente_de_notas_fiscais(notas_fiscais))) # Certificado Digital? XXX # Clientes - saida.append(self._serializar_clientes(objetos)) + saida.append(self._serializar_clientes(**kwargs)) # Transportadoras - saida.append(self._serializar_transportadoras(objetos)) + saida.append(self._serializar_transportadoras(**kwargs)) # Produtos - saida.append(self._serializar_produtos(objetos)) + saida.append(self._serializar_produtos(**kwargs)) # Lote de Notas Fiscais - saida.append(self._serializar_notas_fiscais(objetos)) + saida.append(self._serializar_notas_fiscais(**kwargs)) # FIXME return '\n'.join(saida) - def importar(self, objetos, origem): + 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): + emitentes = 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, objetos): return '' diff --git a/tests/02-modelo-00-definicoes-gerais.txt b/tests/02-modelo-00-definicoes-gerais.txt index b2d02b8..7e0f5e1 100644 --- a/tests/02-modelo-00-definicoes-gerais.txt +++ b/tests/02-modelo-00-definicoes-gerais.txt @@ -102,6 +102,8 @@ O contador de objetos retorna a quantidade de instancias que casem com os argume >>> fonte_dados.contar_objetos(_classe=Emitente, razao_social='Emitente Novo') 1 + >>> fonte_dados._objetos + Permitir tambem remover objetos (que por padrao remove apenas da lista da memoria e nao eh persistente. diff --git a/tests/03-processamento-01-serializacao-xml.txt b/tests/03-processamento-01-serializacao-xml.txt index 3fda08e..bc75c41 100644 --- a/tests/03-processamento-01-serializacao-xml.txt +++ b/tests/03-processamento-01-serializacao-xml.txt @@ -4,6 +4,8 @@ PROCESSAMENTO - SERIALIZACAO PARA XML Gerar arquivos XML ------------------ + >>> from pynfe.processamento.serializacao import SerializacaoXML + - Gera os arquivos XML a partir dos dados das instancias da NF-e - Quando gerados me lote, apenas o primeiro arquivo deve ter o cabecalho padrao do XML 1.0