From 9c006ebd7405a37cbb99c62fda19330b602fe4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marinho=20Brand=C3=A3o?= Date: Thu, 14 Jan 2010 17:03:53 -0200 Subject: [PATCH] Finalizando primeira etapa da serializacao para XML --- pynfe/entidades/notafiscal.py | 8 +- pynfe/processamento/serializacao.py | 86 +++++++++++++++- pynfe/utils/flags.py | 14 +-- tests/02-modelo-05-notafiscal.txt | 4 +- tests/03-processamento-01-serializacao-xml.txt | 130 +++++++++++++++++++------ 5 files changed, 196 insertions(+), 46 deletions(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index a64df18..45d2be9 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -332,7 +332,7 @@ class NotaFiscal(Entidade): @property @memoize def identificador_unico(self): - # Monta 'Id' da raiz + # Monta 'Id' da tag raiz # Ex.: NFe35080599999090910270550010000000011518005123 return "NFe%(uf)s%(ano)s%(mes)s%(cnpj)s%(mod)s%(serie)s%(nNF)s%(tpEmis)s%(cNF)s%(cDV)s"%{ 'uf': CODIGOS_ESTADOS[self.uf], @@ -440,11 +440,11 @@ class NotaFiscalProduto(Entidade): icms_situacao_tributaria = str() # - Origem (obrigatorio - seleciona de lista) - ICMS_ORIGENS - icms_origem = str() + icms_origem = int() # - ICMS # - Modalidade de determinacao da BC ICMS (seleciona de lista) - ICMS_MODALIDADES - icms_modalidade_determinacao_bc = str() + icms_modalidade_determinacao_bc = int() # - Percentual reducao da BC ICMS icms_percentual_reducao_bc = Decimal() @@ -735,7 +735,7 @@ class NotaFiscalTransporteVolume(Entidade): class NotaFiscalTransporteVolumeLacre(Entidade): # - Numero de lacres - numero_lacres = str() + numero_lacre = str() class NotaFiscalCobrancaDuplicata(Entidade): # - Numero diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 930e468..fc6928c 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -219,17 +219,40 @@ class SerializacaoXML(Serializacao): etree.SubElement(prod, 'xProd').text = produto_servico.descricao etree.SubElement(prod, 'CFOP').text = produto_servico.cfop etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial - etree.SubElement(prod, 'qCom').text = '%f'%(produto_servico.quantidade_comercial or 0) - etree.SubElement(prod, 'vUnCom').text = '%f'%(produto_servico.valor_unitario_comercial or 0) - etree.SubElement(prod, 'vProd').text = '%f'%(produto_servico.valor_total_bruto or 0) + etree.SubElement(prod, 'qCom').text = str(produto_servico.quantidade_comercial or 0) + etree.SubElement(prod, 'vUnCom').text = str(produto_servico.valor_unitario_comercial or 0) + etree.SubElement(prod, 'vProd').text = str(produto_servico.valor_total_bruto or 0) etree.SubElement(prod, 'cEANTrib').text = produto_servico.ean_tributavel etree.SubElement(prod, 'uTrib').text = produto_servico.unidade_tributavel - etree.SubElement(prod, 'qTrib').text = '%f'%(produto_servico.quantidade_tributavel) - etree.SubElement(prod, 'vUnTrib').text = '%f'%(produto_servico.valor_unitario_tributavel) + etree.SubElement(prod, 'qTrib').text = str(produto_servico.quantidade_tributavel) + etree.SubElement(prod, 'vUnTrib').text = str(produto_servico.valor_unitario_tributavel) # Imposto imposto = etree.SubElement(raiz, 'imposto') + icms = etree.SubElement(imposto, 'ICMS') + icms_item = etree.SubElement(icms, 'ICMS'+produto_servico.icms_situacao_tributaria) + etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem) + etree.SubElement(icms_item, 'CST').text = produto_servico.icms_situacao_tributaria + etree.SubElement(icms_item, 'modBC').text = str(produto_servico.icms_modalidade_determinacao_bc) + etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) + etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) + etree.SubElement(icms_item, 'vICMS').text = str(produto_servico.icms_valor) + + pis = etree.SubElement(imposto, 'PIS') + pis_item = etree.SubElement(pis, 'PISAliq') + etree.SubElement(pis_item, 'CST').text = str(produto_servico.pis_situacao_tributaria) + etree.SubElement(pis_item, 'vBC').text = str(produto_servico.pis_valor_base_calculo) + etree.SubElement(pis_item, 'pPIS').text = str(produto_servico.pis_aliquota_percentual) + etree.SubElement(pis_item, 'vPIS').text = str(produto_servico.pis_valor) + + cofins = etree.SubElement(imposto, 'COFINS') + cofins_item = etree.SubElement(cofins, 'COFINSAliq') + etree.SubElement(cofins_item, 'CST').text = str(produto_servico.cofins_situacao_tributaria) + etree.SubElement(cofins_item, 'vBC').text = str(produto_servico.cofins_valor_base_calculo) + etree.SubElement(cofins_item, 'pCOFINS').text = str(produto_servico.cofins_aliquota_percentual) + etree.SubElement(cofins_item, 'vCOFINS').text = str(produto_servico.cofins_valor) + if retorna_string: return etree.tostring(raiz, pretty_print=True) else: @@ -289,10 +312,63 @@ class SerializacaoXML(Serializacao): raiz.append(det) + # Totais + total = etree.SubElement(raiz, 'total') + icms_total = etree.SubElement(total, 'ICMSTot') + etree.SubElement(icms_total, 'vBC').text = str(nota_fiscal.totais_icms_base_calculo) + etree.SubElement(icms_total, 'vICMS').text = str(nota_fiscal.totais_icms_total) + etree.SubElement(icms_total, 'vBCST').text = str(nota_fiscal.totais_icms_st_base_calculo) + etree.SubElement(icms_total, 'vST').text = str(nota_fiscal.totais_icms_st_total) + etree.SubElement(icms_total, 'vProd').text = str(nota_fiscal.totais_icms_total_produtos_e_servicos) + etree.SubElement(icms_total, 'vFrete').text = str(nota_fiscal.totais_icms_total_frete) + etree.SubElement(icms_total, 'vSeg').text = str(nota_fiscal.totais_icms_total_seguro) + etree.SubElement(icms_total, 'vDesc').text = str(nota_fiscal.totais_icms_total_desconto) + etree.SubElement(icms_total, 'vII').text = str(nota_fiscal.totais_icms_total_ii) + etree.SubElement(icms_total, 'vIPI').text = str(nota_fiscal.totais_icms_total_ipi) + etree.SubElement(icms_total, 'vPIS').text = str(nota_fiscal.totais_icms_pis) + etree.SubElement(icms_total, 'vCOFINS').text = str(nota_fiscal.totais_icms_cofins) + etree.SubElement(icms_total, 'vOutro').text = str(nota_fiscal.totais_icms_outras_despesas_acessorias) + etree.SubElement(icms_total, 'vNF').text = str(nota_fiscal.totais_icms_total_nota) + # Transporte transp = etree.SubElement(raiz, 'transp') + etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete) + + # Transportadora transp.append(self._serializar_transportadora(nota_fiscal.transporte_transportadora, retorna_string=False)) + # Veículo + veiculo = etree.SubElement(transp, 'veicTransp') + etree.SubElement(veiculo, 'placa').text = nota_fiscal.transporte_veiculo_placa + etree.SubElement(veiculo, 'UF').text = nota_fiscal.transporte_veiculo_uf + etree.SubElement(veiculo, 'RNTC').text = nota_fiscal.transporte_veiculo_rntc + + # Reboque + reboque = etree.SubElement(transp, 'reboque') + etree.SubElement(reboque, 'placa').text = nota_fiscal.transporte_reboque_placa + etree.SubElement(reboque, 'UF').text = nota_fiscal.transporte_reboque_uf + etree.SubElement(reboque, 'RNTC').text = nota_fiscal.transporte_reboque_rntc + + # Volumes + for volume in nota_fiscal.transporte_volumes: + vol = etree.SubElement(transp, 'vol') + etree.SubElement(vol, 'qVol').text = str(volume.quantidade) + etree.SubElement(vol, 'esp').text = volume.especie + etree.SubElement(vol, 'marca').text = volume.marca + etree.SubElement(vol, 'nVol').text = volume.numeracao + etree.SubElement(vol, 'pesoL').text = str(volume.peso_liquido) + etree.SubElement(vol, 'pesoB').text = str(volume.peso_bruto) + + # Lacres + lacres = etree.SubElement(vol, 'lacres') + for lacre in volume.lacres: + etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre + + # Informações adicionais + info_ad = etree.SubElement(raiz, 'infAdic') + etree.SubElement(info_ad, 'infAdFisco').text = nota_fiscal.informacoes_adicionais_interesse_fisco + etree.SubElement(info_ad, 'infCpl').text = nota_fiscal.informacoes_complementares_interesse_contribuinte + # 'Id' da tag raiz # Ex.: NFe35080599999090910270550010000000011518005123 raiz.attrib['Id'] = nota_fiscal.identificador_unico diff --git a/pynfe/utils/flags.py b/pynfe/utils/flags.py index 3be8135..f7054ba 100644 --- a/pynfe/utils/flags.py +++ b/pynfe/utils/flags.py @@ -20,16 +20,16 @@ ICMS_TIPOS_TRIBUTACAO = ( ) ICMS_ORIGENS = ( - 'Nacional', - 'Estrangeira - Importacao Direta', - 'Estrangeira - Adquirida no Mercado Interno', + (0, 'Nacional'), + (1, 'Estrangeira - Importacao Direta'), + (2, 'Estrangeira - Adquirida no Mercado Interno'), ) ICMS_MODALIDADES = ( - 'Margem Valor Agregado', - 'Pauta (valor)', - 'Preco Tabelado Max. (valor)', - 'Valor da Operacao', + (0, 'Margem Valor Agregado'), + (1, 'Pauta (valor)'), + (2, 'Preco Tabelado Max. (valor)'), + (3, 'Valor da Operacao'), ) NF_STATUS = ( diff --git a/tests/02-modelo-05-notafiscal.txt b/tests/02-modelo-05-notafiscal.txt index a590739..030789a 100644 --- a/tests/02-modelo-05-notafiscal.txt +++ b/tests/02-modelo-05-notafiscal.txt @@ -1102,9 +1102,9 @@ Nenhum dos campos deve permitir acentos e/ou cedilhas. >>> hasattr(NotaFiscalTransporteVolume, 'lacres') True - - Numero de lacres + - Numero de lacre - >>> hasattr(NotaFiscalTransporteVolumeLacre, 'numero_lacres') + >>> hasattr(NotaFiscalTransporteVolumeLacre, 'numero_lacre') True - Cobranca diff --git a/tests/03-processamento-01-serializacao-xml.txt b/tests/03-processamento-01-serializacao-xml.txt index 398dd61..9b54069 100644 --- a/tests/03-processamento-01-serializacao-xml.txt +++ b/tests/03-processamento-01-serializacao-xml.txt @@ -4,7 +4,8 @@ PROCESSAMENTO - SERIALIZACAO PARA XML Populando fonte de dados ------------------------ - >>> import datetime, decimal + >>> import datetime + >>> from decimal import Decimal >>> from pynfe.entidades import Emitente, Cliente, NotaFiscal, Transportadora >>> from pynfe.entidades.notafiscal import NotaFiscalEntregaRetirada >>> from pynfe.entidades.fontes_dados import _fonte_dados @@ -73,6 +74,34 @@ Instancia a NF ... municipio='3550308', ... codigo_numerico_aleatorio='51800512', ... dv_codigo_numerico_aleatorio='3', + ... + ... # Totais + ... totais_icms_base_calculo=Decimal('20000000.00'), + ... totais_icms_total=Decimal('18.00'), + ... totais_icms_st_base_calculo=Decimal('0'), + ... totais_icms_st_total=Decimal('0'), + ... totais_icms_total_produtos_e_servicos=Decimal('20000000.00'), + ... totais_icms_total_frete=Decimal('0'), + ... totais_icms_total_seguro=Decimal('0'), + ... totais_icms_total_desconto=Decimal('0'), + ... totais_icms_total_ii=Decimal('0'), + ... totais_icms_total_ipi=Decimal('0'), + ... totais_icms_pis=Decimal('130000.00'), + ... totais_icms_cofins=Decimal('400000.00'), + ... totais_icms_outras_despesas_acessorias=Decimal('0'), + ... totais_icms_total_nota=Decimal('20000000.00'), + ... + ... # Transporte + ... transporte_modalidade_frete=0, + ... + ... # Informacoes adicionais + ... informacoes_adicionais_interesse_fisco='Nota Fiscal de exemplo PyNFe', + ... transporte_veiculo_placa='BXI1717', + ... transporte_veiculo_rntc='123456789', + ... transporte_veiculo_uf='SP', + ... transporte_reboque_placa='BXI1818', + ... transporte_reboque_rntc='123456789', + ... transporte_reboque_uf='SP', ... ) >>> nota_fiscal.retirada = NotaFiscalEntregaRetirada( ... tipo_documento='CNPJ', @@ -95,32 +124,76 @@ Instancia a NF ... endereco_uf='RJ', ... ) >>> nf_prod1 = nota_fiscal.adicionar_produto_servico( + ... # prod ... codigo='00001', ... descricao='Agua Mineral', ... cfop='5101', ... unidade_comercial='dz', - ... quantidade_comercial=decimal.Decimal('2'), - ... valor_unitario_comercial=decimal.Decimal('10.0'), - ... valor_total_bruto=decimal.Decimal('20.0'), + ... quantidade_comercial=Decimal('2'), + ... valor_unitario_comercial=Decimal('10.0'), + ... valor_total_bruto=Decimal('20.0'), ... unidade_tributavel='und', - ... quantidade_tributavel=decimal.Decimal('24.0'), - ... valor_unitario_tributavel=decimal.Decimal('3.00'), + ... quantidade_tributavel=Decimal('24.0'), + ... valor_unitario_tributavel=Decimal('3.00'), + ... + ... # imposto + ... icms_origem=0, + ... icms_situacao_tributaria='00', + ... icms_modalidade_determinacao_bc=0, + ... icms_valor_base_calculo=Decimal('10000000.00'), + ... icms_aliquota=Decimal('18.00'), + ... icms_valor=Decimal('1800000.00'), + ... pis_situacao_tributaria='01', + ... pis_valor_base_calculo=Decimal('10000000.00'), + ... pis_aliquota_percentual=Decimal('0.65'), + ... pis_valor=Decimal('65000'), + ... cofins_situacao_tributaria='01', + ... cofins_valor_base_calculo=Decimal('10000000.00'), + ... cofins_aliquota_percentual=Decimal('2.00'), + ... cofins_valor=Decimal('200000.00'), ... ) >>> nf_prod2 = nota_fiscal.adicionar_produto_servico( ... codigo='00002', ... descricao='Agua Mineral', ... cfop='5101', ... unidade_comercial='pack', - ... quantidade_comercial=decimal.Decimal('5000000'), - ... valor_unitario_comercial=decimal.Decimal('2.0'), - ... valor_total_bruto=decimal.Decimal('10000000.0'), + ... quantidade_comercial=Decimal('5000000'), + ... valor_unitario_comercial=Decimal('2.0'), + ... valor_total_bruto=Decimal('10000000.0'), ... unidade_tributavel='und', - ... quantidade_tributavel=decimal.Decimal('3000000.0'), - ... valor_unitario_tributavel=decimal.Decimal('0.3333'), + ... quantidade_tributavel=Decimal('3000000.0'), + ... valor_unitario_tributavel=Decimal('0.3333'), + ... + ... # imposto + ... icms_origem=0, + ... icms_situacao_tributaria='00', + ... icms_modalidade_determinacao_bc=0, + ... icms_valor_base_calculo=Decimal('10000000.00'), + ... icms_aliquota=Decimal('18.00'), + ... icms_valor=Decimal('1800000.00'), + ... pis_situacao_tributaria='01', + ... pis_valor_base_calculo=Decimal('10000000.00'), + ... pis_aliquota_percentual=Decimal('0.65'), + ... pis_valor=Decimal('65000'), + ... cofins_situacao_tributaria='01', + ... cofins_valor_base_calculo=Decimal('10000000.00'), + ... cofins_aliquota_percentual=Decimal('2.00'), + ... cofins_valor=Decimal('200000.00'), + ... ) + >>> vol1 = nota_fiscal.adicionar_transporte_volume( + ... quantidade=10000, + ... especie='CAIXA', + ... marca='LINDOYA', + ... numeracao='500', + ... peso_liquido=Decimal('1000000000.000'), + ... peso_bruto=Decimal('1200000000.000'), + ... ) + >>> lacre1 = vol1.adicionar_lacre( + ... numero_lacre='XYZ10231486', ... ) >>> _fonte_dados.contar_objetos() - 8 + 10 Gerar arquivos XML ------------------ @@ -195,7 +268,7 @@ Serializando por partes NFe52100112345678000190550010000000011518005123 >>> print serializador._serializar_notas_fiscal(nota_fiscal) - + 52 51800512 @@ -276,17 +349,17 @@ Serializando por partes 00001 - + Agua Mineral 5101 dz - 2.000000 - 10.000000 - 20.000000 - + 2 + 10.0 + 20.0 + und - 24.000000 - 3.000000 + 24.0 + 3.00 @@ -320,17 +393,17 @@ Serializando por partes 00002 - + Agua Mineral 5101 pack - 5000000.000000 - 2.000000 - 10000000.000000 - + 5000000 + 2.0 + 10000000.0 + und - 3000000.000000 - 0.333300 + 3000000.0 + 0.3333 @@ -413,7 +486,8 @@ Serializando por partes - Nota Fiscal de exemplo NF-eletronica.com + Nota Fiscal de exemplo PyNFe +