From 880506db778b8ce0cb64db19b0ec575c879d0bb5 Mon Sep 17 00:00:00 2001 From: Junior Tada Date: Wed, 22 Jul 2015 17:23:20 -0300 Subject: [PATCH] add tag vTotTrib (valor de tributos aproximado) --- pynfe/entidades/notafiscal.py | 10 +++++ pynfe/processamento/assinatura.py | 9 ++--- pynfe/processamento/comunicacao.py | 14 ++++--- pynfe/processamento/serializacao.py | 77 ++++++++++++++++++++----------------- 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 517691d..eba683b 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -140,6 +140,9 @@ class NotaFiscal(Entidade): # - Total do ICMS (somente leitura) totais_icms_total = Decimal() + # - Total do ICMS Desonerado (somente leitura) + totais_icms_desonerado = Decimal() + # - Base de calculo do ICMS ST (somente leitura) totais_icms_st_base_calculo = Decimal() @@ -214,6 +217,9 @@ class NotaFiscal(Entidade): # - Retencao da Prev. Social totais_retencao_retencao_previdencia_social = Decimal() + # - Valor aproximado total de tributos federais, estaduais e municipais. + totais_tributos_aproximado = Decimal() + # Transporte # - Modalidade do Frete (obrigatorio - seleciona de lista) - MODALIDADES_FRETE # - 0 - Por conta do emitente @@ -324,6 +330,7 @@ class NotaFiscal(Entidade): self.produtos_e_servicos.append(obj) self.totais_icms_base_calculo += obj.icms_valor_base_calculo self.totais_icms_total += obj.icms_valor + self.totais_icms_desonerado += obj.icms_desonerado self.totais_icms_st_base_calculo += obj.icms_st_valor_base_calculo self.totais_icms_st_total += obj.icms_st_valor self.totais_icms_total_produtos_e_servicos += obj.valor_total_bruto @@ -539,6 +546,9 @@ class NotaFiscalProduto(Entidade): # - Valor do ICMS icms_valor = Decimal() + # - ICMS Desonerado + icms_desonerado = Decimal() + # - Motivo da desoneração do ICMS # TODO: Criar opções possíveis em flags.py icms_motivo_desoneracao = int() diff --git a/pynfe/processamento/assinatura.py b/pynfe/processamento/assinatura.py index fc5871a..0db1450 100644 --- a/pynfe/processamento/assinatura.py +++ b/pynfe/processamento/assinatura.py @@ -26,20 +26,19 @@ class AssinaturaA1(Assinatura): """Classe responsavel por efetuar a assinatura do certificado digital no XML informado. Passar XML como string.""" - def assinar(self, xml, retona_string=True): + def assinar(self, xml, retona_string=False: arquivo_cert = CertificadoA1(self.certificado) chave, cert = arquivo_cert.separar_arquivo(self.senha, caminho=False) signer = signxml.xmldsig(xml, digest_algorithm="sha1") signer.sign(method=signxml.methods.enveloped, key=chave, cert=cert, - algorithm="rsa-sha1", c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315', - reference_uri='#NFe42140903657739000169550020000000011000000011') + algorithm="rsa-sha1", c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315') # reference_uri nao funciona #verified_data = signer.verify(require_x509=True, ca_pem_file="cert.pem") ##chave_id = xml.find('.//infNFe[@Id]').attrib['Id'] - #xml.findall('.//{http://www.w3.org/2000/09/xmldsig#}Reference')[0] \ - # .attrib['URI'] = '#chaveteste' + xml.findall('.//{http://www.w3.org/2000/09/xmldsig#}Reference')[0] \ + .attrib['URI'] = '#'+xml.findall('infNFe')[0].attrib['Id'] if retona_string: return etree.tostring(xml, encoding="unicode", pretty_print=True) diff --git a/pynfe/processamento/comunicacao.py b/pynfe/processamento/comunicacao.py index cf79f90..06cf249 100644 --- a/pynfe/processamento/comunicacao.py +++ b/pynfe/processamento/comunicacao.py @@ -42,6 +42,8 @@ class ComunicacaoSefaz(Comunicacao): raiz.append(nota_fiscal) # Monta XML para envio da requisição xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeAutorizacao'), metodo='NfeAutorizacao', dados=raiz) + #xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeRecepcao2'), metodo='NfeRecepcao2', dados=raiz) + #print (xml) return self._post(url, xml) @@ -57,7 +59,7 @@ class ComunicacaoSefaz(Comunicacao): url = self._get_url(modelo=modelo, consulta='RECIBO') # Monta XML do corpo da requisição raiz = etree.Element('consReciNFe', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE) - etree.SubElement(raiz, 'versao').text = self._versao + #etree.SubElement(raiz, 'versao').text = self._versao etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente) etree.SubElement(raiz, 'nRec').text = numero # Monta XML para envio da requisição @@ -186,7 +188,7 @@ class ComunicacaoSefaz(Comunicacao): def _cabecalho_soap(self, metodo): u"""Monta o XML do cabeçalho da requisição SOAP""" - raiz = etree.Element('nfeCabecMsg') + raiz = etree.Element('nfeCabecMsg', xmlns=NAMESPACE_METODO+metodo) etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()] etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO return raiz @@ -203,7 +205,7 @@ class ComunicacaoSefaz(Comunicacao): def _construir_xml_status_pr(self, cabecalho, metodo, dados): u"""Mota o XML para o envio via SOAP""" - raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'soap': NAMESPACE_SOAP}, xmlns=NAMESPACE_METODO+metodo) + raiz = etree.Element('{%s}Envelope'%NAMESPACE_SOAP, nsmap={'xsi': NAMESPACE_XSI, 'xsd': NAMESPACE_XSD,'soap': NAMESPACE_SOAP}) c = etree.SubElement(raiz, '{%s}Header'%NAMESPACE_SOAP) c.append(cabecalho) body = etree.SubElement(raiz, '{%s}Body'%NAMESPACE_SOAP) @@ -224,8 +226,10 @@ class ComunicacaoSefaz(Comunicacao): chave_cert = (cert, chave) # Abre a conexão HTTPS try: - # Passa o lxml.etree para string - xml = etree.tostring(xml, encoding='unicode', pretty_print=False).replace('ds:','') + xml_declaration='' + # Passa o lxml.etree para string + xml = etree.tostring(xml, encoding='unicode', pretty_print=False).replace('ds:','').replace(':ds','') + xml = xml_declaration + xml # Faz o request com o servidor print (xml) result = requests.post(url, xml, headers=self._post_header(), cert=chave_cert, verify=False) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 3c4dcfe..df33779 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -90,6 +90,9 @@ class SerializacaoXML(Serializacao): etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(emitente.endereco_pais) etree.SubElement(endereco, 'fone').text = emitente.endereco_telefone etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual + # Apenas NF-e + #if nota_fiscal.modelo == 55: + #etree.SubElement(raiz, 'IEST').text = emitente.inscricao_estadual_subst_tributaria etree.SubElement(raiz, 'IEST').text = emitente.inscricao_estadual_subst_tributaria etree.SubElement(raiz, 'IM').text = emitente.inscricao_municipal etree.SubElement(raiz, 'CNAE').text = emitente.cnae_fiscal @@ -217,7 +220,7 @@ class SerializacaoXML(Serializacao): icms = etree.SubElement(imposto, 'ICMS') icms_csosn = ('102', '103', '300', '400') if produto_servico.icms_modalidade in icms_csosn: - icms_item = etree.SubElement(icms, 'ICMS'+produto_servico.icms_modalidade) + icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade) etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem) etree.SubElement(icms_item, 'CSOSN').text = produto_servico.icms_csosn elif produto_servico.icms_modalidade == '101': @@ -406,23 +409,26 @@ class SerializacaoXML(Serializacao): 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, 'vICMSDeson').text = str(nota_fiscal.totais_icms_desonerado) # Valor Total do ICMS desonerado 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) + + # Tributos + 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) - - + etree.SubElement(icms_total, 'vTotTrib').text = str(nota_fiscal.totais_tributos_aproximado) + # Apenas NF-e if nota_fiscal.modelo == 55: - # Tributos - 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, 'vII').text = str(nota_fiscal.totais_icms_total_ii) # Transporte transp = etree.SubElement(raiz, 'transp') @@ -434,38 +440,37 @@ class SerializacaoXML(Serializacao): 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 + # Veículo + veiculo = etree.SubElement(transp, 'veicTransp') + etree.SubElement(veiculo, 'placa').text = nota_fiscal.transporte_veiculo_placa # Obrigatório EX: XXX9999 + 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 + #etree.SubElement(info_ad, 'infCpl').text = nota_fiscal.informacoes_complementares_interesse_contribuinte if retorna_string: return etree.tostring(raiz, encoding="unicode", pretty_print=True)