From 069c561ec753d43f5d5651ce3e47f4100571f967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marinho=20Brand=C3=A3o?= Date: Wed, 13 Jan 2010 18:57:16 -0200 Subject: [PATCH] Continuando trabalho da serializacao para XML --- pynfe/entidades/notafiscal.py | 2 +- pynfe/processamento/serializacao.py | 53 ++++-- pynfe/utils/__init__.py | 36 +--- pynfe/utils/flags.py | 30 ++++ tests/03-processamento-01-serializacao-xml.txt | 230 ++++++++++++++++++++++++- 5 files changed, 307 insertions(+), 44 deletions(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 036695a..9925536 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -45,7 +45,7 @@ class NotaFiscal(Entidade): # - Finalidade de emissao (obrigatorio - seleciona de lista) - NF_FINALIDADES_EMISSAO finalidade_emissao = int() - # - UF + # - UF - converter para codigos em CODIGOS_ESTADOS uf = str() # - Municipio de ocorrencia diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 3c92b1d..9a5c61c 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -28,6 +28,7 @@ except ImportError: 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 +from pynfe.utils.flags import CODIGOS_ESTADOS class Serializacao(object): """Classe abstrata responsavel por fornecer as funcionalidades basicas para @@ -103,7 +104,7 @@ class SerializacaoXML(Serializacao): return lista[0] - def _serializar_emitente(self, emitente, tag_raiz='emit'): + def _serializar_emitente(self, emitente, tag_raiz='emit', retorna_string=True): raiz = etree.Element(tag_raiz) # Dados do emitente @@ -128,9 +129,12 @@ class SerializacaoXML(Serializacao): 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) + if retorna_string: + return etree.tostring(raiz, pretty_print=True) + else: + return raiz - def _serializar_cliente(self, cliente, tag_raiz='dest'): + def _serializar_cliente(self, cliente, tag_raiz='dest', retorna_string=True): raiz = etree.Element(tag_raiz) # Dados do cliente @@ -154,9 +158,12 @@ class SerializacaoXML(Serializacao): 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) + if retorna_string: + return etree.tostring(raiz, pretty_print=True) + else: + return raiz - def _serializar_transportadora(self, transportadora, tag_raiz='transporta'): + def _serializar_transportadora(self, transportadora, tag_raiz='transporta', retorna_string=True): raiz = etree.Element(tag_raiz) # Dados da transportadora @@ -172,13 +179,37 @@ class SerializacaoXML(Serializacao): ) etree.SubElement(raiz, 'UF').text = transportadora.endereco_uf - return etree.tostring(raiz, pretty_print=True) + if retorna_string: + return etree.tostring(raiz, pretty_print=True) + else: + return raiz - def _serializar_produto(self, produto, tag_raiz='prod'): - # TODO + def _serializar_produto(self, produto, tag_raiz='prod', retorna_string=True): + # Provavelmente nao vai ser feito desta forma, e sim como serializacao do produto + # na NF (NotaFiscalProduto) return '' - def _serializar_notas_fiscal(self, notas_fiscal, tag_raiz='infNFe'): - # TODO - return '' + def _serializar_notas_fiscal(self, nota_fiscal, tag_raiz='infNFe', retorna_string=True): + raiz = etree.Element(tag_raiz) + + # Dados da Nota Fiscal + ide = etree.SubElement(raiz, 'ide') + etree.SubElement(ide, 'cUF').text = CODIGOS_ESTADOS[nota_fiscal.uf] + etree.SubElement(ide, 'natOp').text = nota_fiscal.natureza_operacao + etree.SubElement(ide, 'mod').text = str(nota_fiscal.modelo) + etree.SubElement(ide, 'serie').text = nota_fiscal.serie + etree.SubElement(ide, 'nNF').text = nota_fiscal.numero_nf + etree.SubElement(ide, 'dEmi').text = nota_fiscal.data_emissao.strftime('%Y-%m-%d') + etree.SubElement(ide, 'dSaiEnt').text = nota_fiscal.data_saida_entrada.strftime('%Y-%m-%d') + + # Emitente + raiz.append(self._serializar_emitente(nota_fiscal.emitente, retorna_string=False)) + + # Destinatário + raiz.append(self._serializar_cliente(nota_fiscal.cliente, retorna_string=False)) + + if retorna_string: + return etree.tostring(raiz, pretty_print=True) + else: + return raiz diff --git a/pynfe/utils/__init__.py b/pynfe/utils/__init__.py index dcbd31f..ef67cbd 100644 --- a/pynfe/utils/__init__.py +++ b/pynfe/utils/__init__.py @@ -15,43 +15,17 @@ def obter_pais_por_codigo(codigo): if codigo == '1058': return 'Brasil' -ARQUIVOS_ESTADOS = { - 'RO': 'MunIBGE-UF11.txt', - 'AC': 'MunIBGE-UF12.txt', - 'AM': 'MunIBGE-UF13.txt', - 'RR': 'MunIBGE-UF14.txt', - 'PA': 'MunIBGE-UF15.txt', - 'AP': 'MunIBGE-UF16.txt', - 'TO': 'MunIBGE-UF17.txt', - 'MA': 'MunIBGE-UF21.txt', - 'PI': 'MunIBGE-UF22.txt', - 'CE': 'MunIBGE-UF23.txt', - 'RN': 'MunIBGE-UF24.txt', - 'PB': 'MunIBGE-UF25.txt', - 'PE': 'MunIBGE-UF26.txt', - 'AL': 'MunIBGE-UF27.txt', - 'SE': 'MunIBGE-UF28.txt', - 'BA': 'MunIBGE-UF29.txt', - 'MG': 'MunIBGE-UF31.txt', - 'ES': 'MunIBGE-UF32.txt', - 'RJ': 'MunIBGE-UF33.txt', - 'SP': 'MunIBGE-UF35.txt', - 'PR': 'MunIBGE-UF41.txt', - 'SC': 'MunIBGE-UF42.txt', - 'RS': 'MunIBGE-UF43.txt', - 'MS': 'MunIBGE-UF50.txt', - 'MT': 'MunIBGE-UF51.txt', - 'GO': 'MunIBGE-UF52.txt', - 'DF': 'MunIBGE-UF53.txt', -} - CAMINHO_DATA = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data') CAMINHO_MUNICIPIOS = os.path.join(CAMINHO_DATA, 'MunIBGE') @memoize def carregar_arquivo_municipios(uf): - caminho_arquivo = os.path.join(CAMINHO_MUNICIPIOS, ARQUIVOS_ESTADOS[uf.upper()]) + caminho_arquivo = os.path.join( + CAMINHO_MUNICIPIOS, + 'MunIBGE-UF%s.txt'%flags.CODIGOS_ESTADOS[uf.upper()], + ) + # Carrega o conteudo do arquivo fp = file(caminho_arquivo) linhas = list(fp.readlines()) fp.close() diff --git a/pynfe/utils/flags.py b/pynfe/utils/flags.py index 15a7bab..4a090f8 100644 --- a/pynfe/utils/flags.py +++ b/pynfe/utils/flags.py @@ -149,4 +149,34 @@ ORIGENS_PROCESSO = ( CODIGO_BRASIL = '1058' +CODIGOS_ESTADOS = { + 'RO': '11', + 'AC': '12', + 'AM': '13', + 'RR': '14', + 'PA': '15', + 'AP': '16', + 'TO': '17', + 'MA': '21', + 'PI': '22', + 'CE': '23', + 'RN': '24', + 'PB': '25', + 'PE': '26', + 'AL': '27', + 'SE': '28', + 'BA': '29', + 'MG': '31', + 'ES': '32', + 'RJ': '33', + 'SP': '35', + 'PR': '41', + 'SC': '42', + 'RS': '43', + 'MS': '50', + 'MT': '51', + 'GO': '52', + 'DF': '53', +} + diff --git a/tests/03-processamento-01-serializacao-xml.txt b/tests/03-processamento-01-serializacao-xml.txt index 0c0eed9..017d1e3 100644 --- a/tests/03-processamento-01-serializacao-xml.txt +++ b/tests/03-processamento-01-serializacao-xml.txt @@ -61,11 +61,14 @@ Instancia a NF >>> nota_fiscal = NotaFiscal( ... emitente=emitente, ... transporte_transportadora=transportadora, + ... cliente=cliente, + ... uf='GO', ... modelo=55, ... serie='1', ... numero_nf='1', ... data_emissao=datetime.date.today(), - ... natureza_operacao='Venda no Varejo', + ... data_saida_entrada=datetime.date.today(), + ... natureza_operacao='Venda a vista', ... ) >>> _fonte_dados.contar_objetos() @@ -139,6 +142,231 @@ Serializando por partes - Gera os arquivos XML a partir dos dados das instancias da NF-e + + >>> print serializador._serializar_notas_fiscal(nota_fiscal) + + + 52 + 518005127 + Venda a vista + 0 + 55 + 1 + 1 + 2010-01-13 + 2010-01-13 + 0 + 3550308 + 1 + 1 + 3 + 2 + 1 + 0 + NF-eletronica.com + + + 12345678000190 + Tarsila Calcados Ltda. + Tarsila Calcados Ltda. + 123456789012 + + Rua 10 + 15 + qd 17, lt 10 + Setor Oeste + 5208806 + Goianira + GO + 75370000 + 1058 + Brasil + 6242421212 + + + + 12345678901 + Jose Felipe da Silva + 9876543210 + + AV DAS ROSAS + 1777 + 10 ANDAR + PARQUE FONTES + 3304557 + Rio de Janeiro + RJ + 23950000 + 1058 + Brasil + 2132011234 + + + + 99171171000194 + AV PAULISTA + 12345 + TERREO + CERQUEIRA CESAR + 3550308 + SAO PAULO + SP + + + 99299299000194 + AV FARIA LIMA + 1500 + 15 ANDAR + PINHEIROS + 3550308 + SAO PAULO + SP + + + + 00001 + + Agua Mineral + 5101 + dz + 1000000.0000 + 1 + 10000000.00 + + und + 12000000.0000 + 1 + + + + + 0 + 00 + 0 + 10000000.00 + 18.00 + 1800000.00 + + + + + 01 + 10000000.00 + 0.65 + 65000 + + + + + 01 + 10000000.00 + 2.00 + 200000.00 + + + + + + + 00002 + + Agua Mineral + 5101 + pack + 5000000.0000 + 2 + 10000000.00 + + und + 3000000.0000 + 0.3333 + + + + + 0 + 00 + 0 + 10000000.00 + 18.00 + 1800000.00 + + + + + 01 + 10000000.00 + 0.65 + 65000 + + + + + 01 + 10000000.00 + 2.00 + 200000.00 + + + + + + + 20000000.00 + 18.00 + 0 + 0 + 20000000.00 + 0 + 0 + 0 + 0 + 0 + 130000.00 + 400000.00 + 0 + 20000000.00 + + + + 0 + + 123123123000112 + WS Cargas S/A + 171999999119 + Rua Central 100 - Fundos - Distrito Industrial + 3304557 + Rio de Janeiro + RJ + + + BXI1717 + SP + 123456789 + + + BXI1818 + SP + 123456789 + + + 10000 + CAIXA + LINDOYA + 500 + 1000000000.000 + 1200000000.000 + + XYZ10231486 + + + + + Nota Fiscal de exemplo NF-eletronica.com + + + + - Quando gerados me lote, apenas o primeiro arquivo deve ter o cabecalho padrao do XML 1.0 -