diff --git a/pynfe/data/XSDs/README b/pynfe/data/XSDs/README index e5c82ce..0ed3562 100644 --- a/pynfe/data/XSDs/README +++ b/pynfe/data/XSDs/README @@ -58,10 +58,10 @@ Descrição unitária de cada schema - Pedido de Cancelamento de NF-e processado - inclui: leiauteCancNFe_v1.07 -- procInutNFe_v1.07: +- procInutNFe_v1.07 - Pedido de inutilzação de númeração de NF-e processado - inclui: leiauteInutNFe_v1.07 - procNFe_v1.10 - NF-e processada - - incluid: leiauteNFe_v1.10 \ No newline at end of file + - incluid: leiauteNFe_v1.10 diff --git a/pynfe/processamento/assinatura.py b/pynfe/processamento/assinatura.py index 17fe5c7..256a8e4 100644 --- a/pynfe/processamento/assinatura.py +++ b/pynfe/processamento/assinatura.py @@ -243,5 +243,4 @@ class AssinaturaA1(Assinatura): doc_xml.freeDoc() # E, por fim, desativa todas as funções ativadas anteriormente - self._desativar_funcoes_criptograficas() - + self._desativar_funcoes_criptograficas() \ No newline at end of file diff --git a/pynfe/processamento/validacao.py b/pynfe/processamento/validacao.py index e9a85c1..e1caef3 100644 --- a/pynfe/processamento/validacao.py +++ b/pynfe/processamento/validacao.py @@ -1,3 +1,76 @@ -class Validacao(object): - pass +#-*- coding:utf-8 -*- + +from os import path + +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') + +XSD_FOLDER = "pynfe/data/XSDs/" +XSD_NFE="nfe_v1.10.xsd" +XSD_NFE_PROCESSADA="procNFe_v1.10.xsd" +XSD_PD_CANCELAR_NFE="procCancNFe_v1.07.xsd" +XSD_PD_INUTILIZAR_NFE="procInutNFe_v1.07.xsd" + +def get_xsd(xsd_file): + """Retorna o caminho absoluto para um arquivo xsd. + Argumentos: + xsd_file - nome do arquivo xsd (utilizar nomes definidos em validacao.py) + """ + return path.abspath(path.join(XSD_FOLDER, xsd_file)) + +class Validacao(object): + '''Valida documentos xml a partir do xsd informado.''' + + def __init__(self): + self.clear_cache() + + def clear_cache(self): + self.MEM_CACHE = {} + + def validar_xml(self, xml_path, xsd_file, use_assert=False): + '''Valida um arquivo xml. + Argumentos: + xml_path - caminho para arquivo xml + xsd_file - caminho para o arquivo xsd + use_assert - levantar exceção caso documento não valide? + ''' + return self.validar_etree(etree.parse(xml_path), xsd_file, use_assert) + + def validar_etree(self, xml_doc, xsd_file, use_assert=False): + '''Valida um documento lxml diretamente. + Argumentos: + xml_doc - documento etree + xsd_file - caminho para o arquivo xsd + use_assert - levantar exceção caso documento não valide? + ''' + xsd_filepath = get_xsd(xsd_file) + + try: + # checa se o schema ja existe no cache + xsd_schema = self.MEM_CACHE[xsd_filepath] + except: + # lê xsd e atualiza cache + xsd_doc = etree.parse(xsd_filepath) + xsd_schema = etree.XMLSchema(xsd_doc) + self.MEM_CACHE[xsd_file] = xsd_schema + return use_assert and xsd_schema.assertValid(xml_doc) \ + or xsd_schema.validate(xml_doc) \ No newline at end of file diff --git a/run_tests.py b/run_tests.py index cfa92bb..072fe01 100644 --- a/run_tests.py +++ b/run_tests.py @@ -1,11 +1,24 @@ import sys, doctest, os, glob +from getopt import gnu_getopt as getopt CUR_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, CUR_DIR) if __name__ == '__main__': + run_level = None + optlist, args = getopt(sys.argv[1:], "l:", ['--level=']) + + for opt, arg in optlist: + if opt in ("-l", "--list"): + run_level = arg.zfill(2) + # Test each package - test_files = glob.glob('%s/*.txt' % os.path.join(CUR_DIR, 'tests')) + if run_level is None: + search_path = '%s/*.txt' % os.path.join(CUR_DIR, 'tests') + else: search_path = '%s/%s-*.txt' % \ + (os.path.join(CUR_DIR, 'tests'), run_level) + + test_files = glob.glob(search_path) test_files = map(lambda i: i[len(CUR_DIR)+1:], test_files) # Run the tests diff --git a/tests/01-basico.txt b/tests/01-basico.txt index fb236ac..dbbf7f7 100644 --- a/tests/01-basico.txt +++ b/tests/01-basico.txt @@ -1,145 +1,145 @@ TESTES BASICOS ============== - + >>> try: - ... set + ... set ... except: - ... from sets import Set as set + ... from sets import Set as set - + A biblioteca deve fornecer uma colecao de utilitarios para consumir o webservice da NF-e. - + Componentes ----------- - + A separacao entre os componentes da biblioteca deve seguir o seguinte modelo: - + --------------------------------------------------------------------- - | MODELO DE ENTIDADES | + | MODELO DE ENTIDADES | --------------------------------------------------------------------- - | | - | ------------ -------------- | - | | Entidade |-------<>| FonteDados | | - | ------------ -------------- | - | A | - | | | - | ----especializacao-------------------------- | - | | | | | | - | ------------ ----------- ----------- ------------------ | - | | Emitente | | Produto | | Cliente | | Transportadora | | - | ------------ ----------- ----------- ------------------ | - | *| *| *| *| | - | ------------------------------associacao---- | - | | | - | V* | - | --------------- ---------------- | - | | Nota Fiscal |------<>| Lote de NF-e | | - | --------------- 1 * ---------------- | - | | + | | + | ------------ -------------- | + | | Entidade |-------<>| FonteDados | | + | ------------ -------------- | + | A | + | | | + | ----especializacao-------------------------- | + | | | | | | + | ------------ ----------- ----------- ------------------ | + | | Emitente | | Produto | | Cliente | | Transportadora | | + | ------------ ----------- ----------- ------------------ | + | *| *| *| *| | + | ------------------------------associacao---- | + | | | + | V* | + | --------------- ---------------- | + | | Nota Fiscal |------<>| Lote de NF-e | | + | --------------- 1 * ---------------- | + | | --------------------------------------------------------------------- - - + + ---------------------------------------------------------------------------- - | PROCESSAMENTO | + | PROCESSAMENTO | ---------------------------------------------------------------------------- - | | - | ------------------ -------------- -------------------------------- | - | | Serializacao | | DANFE | | Comunicacao | | - | ------------------ -------------- -------------------------------- | - | | exportar() | | imprimir() | | transmitir() | | - | | importar() | -------------- | cancelar() | | - | ------------------ | situacao_nfe() | | - | | status_servico() | | - | ---------------------- | consultar_cadastro() | | - | | Validacao | | inutilizar_faixa_numeracao() | | - | ---------------------- -------------------------------- | - | | validar_arquivo() | | - | | validar_xml() | | - | | validar_etree() | ---------------------- | - | | validar_objetos() | | Assinatura | | - | ---------------------- ---------------------- | - | | assinar_arquivo() | | - | | assinar_xml() | | - | | assinar_etree() | | - | | assinar_objetos() | | - | ---------------------- | + | | + | ------------------ -------------- -------------------------------- | + | | Serializacao | | DANFE | | Comunicacao | | + | ------------------ -------------- -------------------------------- | + | | exportar() | | imprimir() | | transmitir() | | + | | importar() | -------------- | cancelar() | | + | ------------------ | situacao_nfe() | | + | | status_servico() | | + | ---------------------- | consultar_cadastro() | | + | | Validacao | | inutilizar_faixa_numeracao() | | + | ---------------------- -------------------------------- | + | | validar_arquivo() | | + | | validar_xml() | | + | | validar_etree() | ---------------------- | + | | validar_objetos() | | Assinatura | | + | ---------------------- ---------------------- | + | | assinar_arquivo() | | + | | assinar_xml() | | + | | assinar_etree() | | + | | assinar_objetos() | | + | ---------------------- | ---------------------------------------------------------------------------- - + Os pacotes da biblioteca sao: - -- utils (contem todas as funcionalidades utilitarias dentro da + +- utils (contem todas as funcionalidades utilitarias dentro da biblioteca, incluindo flags e funcoes genericas) - + >>> from pynfe import utils >>> set([attr for attr in dir(utils) if not attr.startswith('__')]) >= set(['flags']) True - + - entidades (contem todas as entidades da biblioteca) - + >>> from pynfe import entidades >>> set([attr for attr in dir(entidades) if not attr.startswith('__')]) == set([ - ... 'Cliente', 'Emitente', 'LoteNotaFiscal', 'NotaFiscal', 'Produto', - ... 'Transportadora', 'base', 'cliente', 'emitente', 'lotes', 'notafiscal', - ... 'produto', 'transportadora', 'fonte_dados', '_fonte_dados','certificado', - ... 'CertificadoA1']) + ... 'Cliente', 'Emitente', 'LoteNotaFiscal', 'NotaFiscal', 'Produto', + ... 'Transportadora', 'base', 'cliente', 'emitente', 'lotes', 'notafiscal', + ... 'produto', 'transportadora', 'fonte_dados', '_fonte_dados','certificado', + ... 'CertificadoA1']) True - + - processamento (contem todas as funcionalidades de processamento da biblioteca - + >>> from pynfe import processamento >>> set([attr for attr in dir(processamento) if not attr.startswith('__')]) == set([ - ... 'AssinaturaA1', 'ComunicacaoSefaz', 'DANFE', 'SerializacaoXML', 'Validacao', - ... 'assinatura', 'comunicacao', 'danfe', 'serializacao', 'validacao']) + ... 'AssinaturaA1', 'ComunicacaoSefaz', 'DANFE', 'SerializacaoXML', 'Validacao', + ... 'assinatura', 'comunicacao', 'danfe', 'serializacao', 'validacao']) True - + Ha ainda uma pasta dentro da pasta 'pynfe', chamada 'data', que deve armazenar listas longas de municipios, CNAEs, situacoes tributarias, XSD's, etc. - + >>> import os >>> DATA = os.path.join(os.curdir, 'pynfe', 'data') >>> DATA './pynfe/data' - + >>> os.path.isdir(DATA) True - + Geracao e importacao de XML --------------------------- - + As objetos Python devem ser traduzidos para arquivos XML e o caminho inverso, de introspecao, tambem deve ser feito, atraves de uma fabrica. - + >>> from pynfe.processamento.serializacao import Serializacao - + >>> bool(Serializacao.exportar) True - + >>> bool(Serializacao.importar) True - + A classe basica de Serializacao eh abstrata, ou seja, nao pode ser instanciada diretamente. - + >>> lista_de_nfs = [] - + >>> try: - ... Serializacao(lista_de_nfs) + ... Serializacao(lista_de_nfs) ... except Exception, e: - ... print e.message + ... print e.message Esta classe nao pode ser instanciada diretamente! - + Classe de serializacao especifica para XML, usando lxml - + >>> from pynfe.processamento.serializacao import SerializacaoXML - + Esse procedimento sera feito por padrao atraves da lxml, devido ao seu desempenho, mas pode ser extendido para outros formatos, dependendo do objetivo pretendido. - + >>> try: ... from lxml import etree ... except ImportError: @@ -148,7 +148,7 @@ objetivo pretendido. ... import xml.etree.cElementTree as etree ... except ImportError: ... try: - ... # Python 2.5 + ... # Python 2.5 ... import xml.etree.ElementTree as etree ... except ImportError: ... try: @@ -160,45 +160,45 @@ objetivo pretendido. ... import elementtree.ElementTree as etree ... except ImportError: ... print("A importacao do lxml falhou") - + Consumacao de WebService ------------------------ - + O webservice a ser consumido esta no padrao SOAP, que no Python sera interpretado pela biblioteca SUDS. - + >>> import suds - + Para executar estes testes é preciso instalar a soaplib, para servir WSDL via SOAP, num servidor falso (mock). - + >>> import soaplib - + Certificados Digitais --------------------- - + A biblioteca deve suportar certificados digitais X.509 v.3 do tipo A1. O tipo A3 é certificado por hardware e provavelmente bem mais complexo de colocar em prática. - + eCNPJ A1 - + A3 depende de configurar seu numero de serie. No Windows usa-se a DLL CAPICOM. Ao que tudo indica, o OpenSSL nao suporta esse tipo. - + A transmissao utiliza SSL3. - + No Windows o arquivo é usado como .pfx (pkcs12) - + No Linux o arquivo deve ser convertido para .pem - + Impressao do DANFE ------------------ - + Alem disso, deve gerar PDFs da DANFE, utilizando a engine Geraldo Reports. - + >>> import geraldo >>> import PIL diff --git a/tests/02-modelo-07-validacao.txt b/tests/02-modelo-07-validacao.txt new file mode 100644 index 0000000..77e6c6b --- /dev/null +++ b/tests/02-modelo-07-validacao.txt @@ -0,0 +1,34 @@ +Validação +--------- +A validação dos arquivos de nota fiscal são controladas pelo módulo validacao. + + >>> from pynfe.processamento.validacao import * + +A classe Validacao é utilizada para validar os tanto arquivos xml quanto documentos +etree. Não há problemas em utilizar list-comprehension com a mesma pois ela implementa +um cache simples. + + >>> from lxml import etree + >>> validador = Validacao() + >>> + >>> nfe = 'tests/xml/NFe.xml' + >>> nfe_assin = 'tests/xml/NFe_assinada.xml' + >>> nfe_inval = 'tests/xml/NFe_falhaSchema.xml' + >>> + >>> try: validador.validar_xml(nfe, XSD_NFE, True) + ... except Exception, e: print unicode(repr(e)) + True + >>> try: validador.validar_xml(nfe_inval, XSD_NFE, False) + ... except Exception, e: print unicode(repr(e)) + False + >>> try: validador.validar_xml(nfe_assin, XSD_NFE_PROCESSADA, True) + ... except Exception, e: print unicode(repr(e)) + True + +Note que o schema utilizado para validação contra o xml é definido por variáveis +globais presentes no módulo. São elas: + +- XSD_NFE : valida nfe's não certificadas +- XSD_NFE_PROCESSADA : valida nfe's certificadas +- XSD_PD_CANCELAR_NFE : valida um pedido de cancelamento de nfe +- XSD_PD_INUTILIZAR_NFE : valida um pedido de inutilização de nfe diff --git a/tests/xml/NFe.xml b/tests/xml/NFe.xml new file mode 100644 index 0000000..c0e2037 --- /dev/null +++ b/tests/xml/NFe.xml @@ -0,0 +1,223 @@ + + + + + 35 + 518005127 + Venda a vista + 0 + 55 + 1 + 1 + 2008-05-06 + 2008-05-06 + 0 + 3550308 + 1 + 1 + 3 + 2 + 1 + 0 + NF-eletronica.com + + + 99999090910270 + NF-e Associacao NF-e + NF-e + + Rua Central + 100 + Fundos + Distrito Industrial + 3502200 + Angatuba + SP + 17100171 + 1058 + Brasil + 1733021717 + + 123456789012 + + + 00000000000191 + DISTRIBUIDORA DE AGUAS MINERAIS + + AV DAS FONTES + 1777 + 10 ANDAR + PARQUE FONTES + 5030801 + Sao Paulo + SP + 13950000 + 1058 + BRASIL + 1932011234 + + + + + 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 + + 99171171000191 + Distribuidora de Bebidas Fazenda de SP Ltda. + 171999999119 + Rua Central 100 - Fundos - Distrito Industrial + SAO PAULO + SP + + + BXI1717 + SP + 123456789 + + + BXI1818 + SP + 123456789 + + + 10000 + CAIXA + LINDOYA + 500 + 1000000000.000 + 1200000000.000 + + XYZ10231486 + + + + + Nota Fiscal de exemplo NF-eletronica.com + + + diff --git a/tests/xml/NFe_assinada.xml b/tests/xml/NFe_assinada.xml new file mode 100644 index 0000000..e3dc170 --- /dev/null +++ b/tests/xml/NFe_assinada.xml @@ -0,0 +1 @@ +35518005127Venda a vista055112008-05-062008-05-0603550308113210NF-eletronica.com99999090910270NF-e Associacao NF-eNF-eRua Central100FundosDistrito Industrial3502200AngatubaSP171001711058Brasil173302171712345678901200000000000191DISTRIBUIDORA DE AGUAS MINERAISAV DAS FONTES177710 ANDARPARQUE FONTES5030801Sao PauloSP139500001058BRASIL193201123499171171000194AV PAULISTA12345TERREOCERQUEIRA CESAR3550308SAO PAULOSP99299299000194AV FARIA LIMA150015 ANDARPINHEIROS3550308SAO PAULOSP00001Agua Mineral5101dz1000000.0000110000000.00und12000000.00001000010000000.0018.001800000.000110000000.000.65650000110000000.002.00200000.0000002Agua Mineral5101pack5000000.0000210000000.00und3000000.00000.3333000010000000.0018.001800000.000110000000.000.65650000110000000.002.00200000.0020000000.0018.000020000000.0000000130000.00400000.00020000000.00099171171000191Distribuidora de Bebidas Fazenda de SP Ltda.171999999119Rua Central 100 - Fundos - Distrito IndustrialSAO PAULOSPBXI1717SP123456789BXI1818SP12345678910000CAIXALINDOYA5001000000000.0001200000000.000XYZ10231486Nota Fiscal de exemplo NF-eletronica.comxhTSDMH61e9uqe04lnoHT4ZzLSY=Iz5Z3PLQbzZt9jnBtr6xsmHZMOu/3plXG9xxfFjRCQYGnD1rjlhzBGrqt026Ca2VHHM/bHNepi6FuFkAi595GScKVuHREUotzifE2OIjgavvTOrMwbXG7+0LYgkwPFiPCao2S33UpZe7MneaxcmKQGKQZw1fP8fsWmaQ4cczZT8=MIIEuzCCA6OgAwIBAgIDMTMxMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJCUjELMAkGA1UECBMCUlMxFTATBgNVBAcTDFBvcnRvIEFsZWdyZTEdMBsGA1UEChMUVGVzdGUgUHJvamV0byBORmUgUlMxHTAbBgNVBAsTFFRlc3RlIFByb2pldG8gTkZlIFJTMSEwHwYDVQQDExhORmUgLSBBQyBJbnRlcm1lZGlhcmlhIDEwHhcNMDgwNDI4MDkwMTAyWhcNMDkwNDMwMjM1OTU5WjCBnjELMAkGA1UECBMCUlMxHTAbBgNVBAsTFFRlc3RlIFByb2pldG8gTkZlIFJTMR0wGwYDVQQKExRUZXN0ZSBQcm9qZXRvIE5GZSBSUzEVMBMGA1UEBxMMUE9SVE8gQUxFR1JFMQswCQYDVQQGEwJCUjEtMCsGA1UEAxMkTkZlIC0gQXNzb2NpYWNhbyBORi1lOjk5OTk5MDkwOTEwMjcwMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDh6RRv0bj4RYX+tDQrZRb5opa77LBVVs+6LphIfSF3TSWPfnKh0+xLlBFdmnB5YGgbbW9Uon6pZQTfaC8jZhRhI5eFRRofY/Ugoeo0NGt6PcIQNZQd6lLQ/ASd1qWwjqJoEa7udriKjy3h351Mf1bng1VxS1urqC3Dn39ZWIEwQIDAQABo4IBjjCCAYowIgYDVR0jAQEABBgwFoAUPT5TqhNWAm+ZpcVsvB7malDBjEQwDwYDVR0TAQH/BAUwAwEBADAPBgNVHQ8BAf8EBQMDAOAAMAwGA1UdIAEBAAQCMAAwgbwGA1UdEQEBAASBsTCBrqA4BgVgTAEDBKAvBC0wNzA4MTk1MTE1MTk0NTMxMDg3MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCgHQYFYEwBAwKgFAQSRmVybmFuZG8gQ2FudG8gQWx0oBkGBWBMAQMDoBAEDjk5OTk5MDkwOTEwMjcwoBcGBWBMAQMHoA4EDDAwMDAwMDAwMDAwMIEfZmVybmFuZG8tYWx0QHByb2NlcmdzLnJzLmdvdi5icjAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwUwYDVR0fAQEABEkwRzBFoEOgQYY/aHR0cDovL25mZWNlcnRpZmljYWRvLnNlZmF6LnJzLmdvdi5ici9MQ1IvQUNJbnRlcm1lZGlhcmlhMzguY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCNPpaZ3Byu3/70nObXE8NiM53j1ddIFXsb+v2ghCVd4ffExv3hYc+/a3lfgV8H/WfQsdSCTzS2cHrd4Aasr/eXfclVDmf2hcWz+R7iysOHuT6B6r+DvV3JcMdJJCDdynR5REa+zViMnVZo1G3KuceQ7/y5X3WFNVq4kwHvonJ9oExsWyw8rTwUK5bsjz0A2yEwXkmkJIngnF41sP31+9jCImiqkXcmsesFhxzX7iurAQAQCZOm7iwMWxQKcAjXCZrgSZWRQy6mU224sX3HTArHahmLJ9Iw+WYAua5qBJsiN6PC7v5tfhrEQFpcG39yMnOecxvkkPolDUyBa7d7xwgm \ No newline at end of file diff --git a/tests/xml/NFe_falhaSchema.xml b/tests/xml/NFe_falhaSchema.xml new file mode 100644 index 0000000..cc8b1ac --- /dev/null +++ b/tests/xml/NFe_falhaSchema.xml @@ -0,0 +1,223 @@ + + + + + 35 + 518005127 + Venda a vista + 0 + 55 + 1 + 1 + 2008-05-06 + 2008-05-06 + 0 + 3550308 + 1 + 1 + 3 + 2 + 1 + 0 + NF-eletronica.com 123456 + + + 99999090910270 + NF-e Associacao NF-e + NF-e + + Rua Central + 100 + Fundos + Distrito Industrial + 3502200 + Angatuba + SP + 17100171 + 1058 + Brasil + 1733021717 + + 123456789012 + + + 00000000000191 + DISTRIBUIDORA DE AGUAS MINERAIS + + AV DAS FONTES + 1777 + 10 ANDAR + PARQUE FONTES + 5030801 + Sao Paulo + SP + 13950000 + 1058 + BRASIL + 1932011234 + + + + + 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.00 + 1 + 10000000.00 + + und + 12000000.00 + 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 + + 99171171000191 + Distribuidora de Bebidas Fazenda de SP Ltda. + 171999999119 + Rua Central 100 - Fundos - Distrito Industrial + SAO PAULO + SP + + + BXI1717 + SP + 123456789 + + + BXI1818 + SP + 123456789 + + + 10000 + CAIXA + LINDOYA + 500 + 1000000000.000 + 1200000000.000 + + XYZ10231486 + + + + + Nota Fiscal de exemplo NF-eletronica.com + + + \ No newline at end of file