From ac43bb13e325f743f2728507518d8f7e33ddde8d Mon Sep 17 00:00:00 2001 From: Junior Tada Date: Tue, 15 Aug 2017 17:27:25 -0300 Subject: [PATCH] =?UTF-8?q?Corrigido=20tags=20da=20vers=C3=A3o=204.00=20na?= =?UTF-8?q?=20serializa=C3=A7=C3=A3o=20do=20xml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pynfe/entidades/notafiscal.py | 70 ++++++++++++++++++++++++++++++++++--- pynfe/processamento/serializacao.py | 61 +++++++++++++++++++++----------- pynfe/utils/webservices.py | 33 +++++++++++++---- 3 files changed, 132 insertions(+), 32 deletions(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 3c3a8a5..8eca8e2 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -56,10 +56,26 @@ class NotaFiscal(Entidade): data_saida_entrada = None # - Forma de pagamento (obrigatorio - seleciona de lista) - NF_FORMAS_PAGAMENTO - forma_pagamento = int() + # Removido na NF-e 4.00 + # forma_pagamento = int() # - Tipo de pagamento - # 01=Dinheiro 02=Cheque 03=Cartão de Crédito 04=Cartão de Débito 05=Crédito Loja 10=Vale Alimentação 11=Vale Refeição 12=Vale Presente 13=Vale Combustível 99=Outros + """ + Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e. + Para as notas com finalidade de Ajuste ou Devolução o campo Forma de Pagamento deve ser preenchido com 90=Sem Pagamento. + 01=Dinheiro + 02=Cheque + 03=Cartão de Crédito + 04=Cartão de Débito + 05=Crédito Loja + 10=Vale Alimentação + 11=Vale Refeição + 12=Vale Presente + 13=Vale Combustível + 14=Duplicata Mercantil + 90= Sem pagamento + 99=Outros + """ tipo_pagamento = int() # - Forma de emissao (obrigatorio - seleciona de lista) - NF_FORMAS_EMISSAO @@ -78,6 +94,7 @@ class NotaFiscal(Entidade): 2=Operação não presencial, pela Internet; 3=Operação não presencial, Teleatendimento; 4=NFC-e em operação com entrega a domicílio; + 5=Operação presencial, fora do estabelecimento; 9=Operação não presencial, outros. """ indicador_presencial = int() @@ -171,6 +188,11 @@ class NotaFiscal(Entidade): # - Total do IPI (somente leitura) totais_icms_total_ipi = Decimal() + # - Valor Total do IPI devolvido + # Deve ser informado quando preenchido o Grupo Tributos Devolvidos na emissão de nota finNFe=4 (devolução) nas operações com não contribuintes do IPI. + # Corresponde ao total da soma dos campos id:UA04. + totais_icms_total_ipi_dev = Decimal() + # - PIS (somente leitura) totais_icms_pis = Decimal() @@ -224,10 +246,32 @@ class NotaFiscal(Entidade): # - Valor aproximado total de tributos federais, estaduais e municipais. totais_tributos_aproximado = Decimal() + # - Valor Total do FCP (Fundo de Combate à Pobreza) + totais_fcp = Decimal() + + # - Valor total do ICMS relativo Fundo de Combate à Pobreza (FCP) da UF de destino + totais_fcp_destino = Decimal() + + # - Valor Total do FCP (Fundo de Combate à Pobreza) retido por substituição tributária + totais_fcp_st = Decimal() + + # - Valor Total do FCP retido anteriormente por Substituição Tributária + totais_fcp_st_ret = Decimal() + + # - Valor total do ICMS Interestadual para a UF de destino + totais_icms_inter_destino = Decimal() + + # - Valor total do ICMS Interestadual para a UF do remetente + totais_icms_inter_remetente = Decimal() + # Transporte # - Modalidade do Frete (obrigatorio - seleciona de lista) - MODALIDADES_FRETE - # - 0 - Por conta do emitente - # - 1 - Por conta do destinatario + # 0=Contratação do Frete por conta do Remetente (CIF); + # 1=Contratação do Frete por conta do Destinatário (FOB); + # 2=Contratação do Frete por conta de Terceiros; + # 3=Transporte Próprio por conta do Remetente; + # 4=Transporte Próprio por conta do Destinatário; + # 9=Sem Ocorrência de Transporte. transporte_modalidade_frete = int() # - Transportador (seleciona de Transportadoras) @@ -343,10 +387,18 @@ class NotaFiscal(Entidade): self.totais_icms_total_desconto += obj.desconto # self.totais_icms_total_ii += # tem que entender o cálculo self.totais_icms_total_ipi += obj.ipi_valor_ipi + self.totais_icms_total_ipi_dev += obj.ipi_valor_ipi_dev self.totais_icms_pis += obj.pis_valor self.totais_icms_cofins += obj.cofins_valor self.totais_icms_outras_despesas_acessorias += obj.outras_despesas_acessorias self.totais_icms_total_nota += obj.valor_total_bruto + # - Valor Total do FCP (Fundo de Combate à Pobreza) + self.totais_fcp += obj.fcp_valor + self.totais_fcp_destino += obj.fcp_destino_valor + self.totais_fcp_st += obj.fcp_st_valor + self.totais_fcp_st_ret += obj.fcp_st_ret_valor + self.totais_icms_inter_destino += obj.icms_inter_destino_valor + self.totais_icms_inter_remetente += obj.icms_inter_remetente_valor ## TODO calcular impostos aproximados #self.totais_tributos_aproximado += obj.tributos return obj @@ -574,6 +626,13 @@ class NotaFiscalProduto(Entidade): # - Valor do ICMS ST icms_st_valor = Decimal() + fcp_valor = Decimal() + fcp_destino_valor = Decimal() + fcp_st_valor = Decimal() + fcp_st_ret_valor = Decimal() + icms_inter_destino_valor = Decimal() + icms_inter_remetente_valor = Decimal() + # - IPI # - Situacao tributaria (seleciona de lista) - IPI_TIPOS_TRIBUTACAO ipi_situacao_tributaria = str() @@ -619,6 +678,9 @@ class NotaFiscalProduto(Entidade): # - Valor do IPI ipi_valor_ipi = Decimal() + # - Valor do IPI Devolvido + ipi_valor_ipi_dev = Decimal() + # - PIS # - PIS # - Situacao tributaria (obrigatorio - seleciona de lista) - PIS_TIPOS_TRIBUTACAO diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 4862980..c9dd6ae 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -378,7 +378,8 @@ class SerializacaoXML(Serializacao): etree.SubElement(ide, 'cUF').text = CODIGOS_ESTADOS[nota_fiscal.uf] etree.SubElement(ide, 'cNF').text = nota_fiscal.codigo_numerico_aleatorio etree.SubElement(ide, 'natOp').text = nota_fiscal.natureza_operacao - etree.SubElement(ide, 'indPag').text = str(nota_fiscal.forma_pagamento) + # Removido na NF-e 4.00 + # etree.SubElement(ide, 'indPag').text = str(nota_fiscal.forma_pagamento) etree.SubElement(ide, 'mod').text = str(nota_fiscal.modelo) etree.SubElement(ide, 'serie').text = nota_fiscal.serie etree.SubElement(ide, 'nNF').text = str(nota_fiscal.numero_nf) @@ -481,8 +482,17 @@ class SerializacaoXML(Serializacao): etree.SubElement(icms_total, 'vBC').text = '{:.2f}'.format(nota_fiscal.totais_icms_base_calculo) etree.SubElement(icms_total, 'vICMS').text = '{:.2f}'.format(nota_fiscal.totais_icms_total) etree.SubElement(icms_total, 'vICMSDeson').text = '{:.2f}'.format(nota_fiscal.totais_icms_desonerado) # Valor Total do ICMS desonerado + etree.SubElement(icms_total, 'vFCP').text = '{:.2f}'.format(nota_fiscal.totais_fcp) + if nota_fiscal.totais_fcp_destino: + etree.SubElement(icms_total, 'vFCPUFDest').text = '{:.2f}'.format(nota_fiscal.totais_fcp_destino) + if nota_fiscal.totais_icms_inter_destino: + etree.SubElement(icms_total, 'vICMSUFDest').text = '{:.2f}'.format(nota_fiscal.totais_icms_inter_destino) + if nota_fiscal.totais_icms_inter_remetente: + etree.SubElement(icms_total, 'vICMSUFRemet').text = '{:.2f}'.format(nota_fiscal.totais_icms_remetente) etree.SubElement(icms_total, 'vBCST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_base_calculo) etree.SubElement(icms_total, 'vST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_total) + etree.SubElement(icms_total, 'vFCPST').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st) + etree.SubElement(icms_total, 'vFCPSTRet').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st_ret) etree.SubElement(icms_total, 'vProd').text = str(nota_fiscal.totais_icms_total_produtos_e_servicos) etree.SubElement(icms_total, 'vFrete').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_frete) etree.SubElement(icms_total, 'vSeg').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_seguro) @@ -491,6 +501,7 @@ class SerializacaoXML(Serializacao): # Tributos etree.SubElement(icms_total, 'vII').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ii) etree.SubElement(icms_total, 'vIPI').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi) + etree.SubElement(icms_total, 'vIPIDevol').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi_dev) etree.SubElement(icms_total, 'vPIS').text = '{:.2f}'.format(nota_fiscal.totais_icms_pis) etree.SubElement(icms_total, 'vCOFINS').text = '{:.2f}'.format(nota_fiscal.totais_icms_cofins) @@ -499,13 +510,12 @@ class SerializacaoXML(Serializacao): if nota_fiscal.totais_tributos_aproximado: etree.SubElement(icms_total, 'vTotTrib').text = '{:.2f}'.format(nota_fiscal.totais_tributos_aproximado) + # Transporte + transp = etree.SubElement(raiz, 'transp') + etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete) + # Apenas NF-e if nota_fiscal.modelo == 55: - - # Transporte - transp = etree.SubElement(raiz, 'transp') - etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete) - # Transportadora if nota_fiscal.transporte_transportadora: transp.append(self._serializar_transportadora( @@ -548,26 +558,25 @@ class SerializacaoXML(Serializacao): for lacre in volume.lacres: etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre - # Somente NFC-e - """ Grupo obrigatório para a NFC-e, a critério da UF. Não informar para a NF-e (modelo 55). """ - if nota_fiscal.modelo == 65: - # Transporte - transp = etree.SubElement(raiz, 'transp') - etree.SubElement(transp, 'modFrete').text = str(9) - # Pagamento - pag = etree.SubElement(raiz, 'pag') - etree.SubElement(pag, 'tPag').text = str(nota_fiscal.tipo_pagamento).zfill(2) # 01=Dinheiro 02=Cheque 03=Cartão de Crédito 04=Cartão de Débito 05=Crédito Loja 10=Vale Alimentação 11=Vale Refeição 12=Vale Presente 13=Vale Combustível 99=Outros - etree.SubElement(pag, 'vPag').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota) - # Cartão NT2015.002 - cartao = etree.SubElement(pag, 'card') + # Pagamento + """ Obrigatório o preenchimento do Grupo Informações de Pagamento para NF-e e NFC-e. Para as notas com finalidade de Ajuste ou Devolução o +campo Forma de Pagamento deve ser preenchido com 90=Sem Pagamento. """ + pag = etree.SubElement(raiz, 'pag') + detpag = etree.SubElement(pag, 'detPag') + etree.SubElement(detpag, 'tPag').text = str(nota_fiscal.tipo_pagamento).zfill(2) + etree.SubElement(detpag, 'vPag').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota) + if nota_fiscal.tipo_pagamento == 3 or nota_fiscal.tipo_pagamento == 4: + cartao = etree.SubElement(detpag, 'card') """ Tipo de Integração do processo de pagamento com o sistema de automação da empresa: 1=Pagamento integrado com o sistema de automação da empresa (Ex.: equipamento TEF, Comércio Eletrônico); 2= Pagamento não integrado com o sistema de automação da empresa (Ex.: equipamento POS); """ etree.SubElement(cartao, 'tpIntegra').text = '2' #etree.SubElement(cartao, 'CNPJ').text = '' # Informar o CNPJ da Credenciadora de cartão de crédito / débito - #etree.SubElement(cartao, 'tBand').text = '' # 01=Visa 02=Mastercard 03=American Express 04=Sorocred 99=Outros + #etree.SubElement(cartao, 'tBand').text = '' # 01=Visa 02=Mastercard 03=American Express 04=Sorocred 05=Diners Club 06=Elo 07=Hipercard 08=Aura 09=Caba 99=Outros #etree.SubElement(cartao, 'cAut').text = '' # Identifica o número da autorização da transação da operação com cartão de crédito e/ou débito + # troco + # etree.SubElement(pag, 'vTroco').text = str('') # Informações adicionais if nota_fiscal.informacoes_adicionais_interesse_fisco or nota_fiscal.informacoes_complementares_interesse_contribuinte: @@ -658,22 +667,32 @@ class SerializacaoQrcode(object): url = url + '&cHashQRCode=' + url_hash.upper() - if uf.upper() == 'PR': + # url_chave - Texto com a URL de consulta por chave de acesso a ser impressa no DANFE NFC-e. + # Informar a URL da “Consulta por chave de acesso da NFC-e”. + # A mesma URL que deve estar informada no DANFE NFC-e para consulta por chave de acesso + lista_uf_padrao = ['PR', 'CE', 'RS', 'RJ', 'RO'] + if uf.upper() in lista_uf_padrao: qrcode = NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['URL'] elif uf.upper() == 'SP': if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['URL'] + url else: qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['URL'] + url + # AC, AM, RR, PA, else: if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url + url_chave = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['URL'] + url else: qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url - + url_chave = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['URL'] + url # adicionta tag infNFeSupl com qrcode info = etree.Element('infNFeSupl') etree.SubElement(info, 'qrCode').text = '' + etree.SubElement(info, 'urlChave').text = url_chave nfe.insert(1, info) # correção da tag qrCode, retira caracteres pois e CDATA tnfe = etree.tostring(nfe, encoding='unicode') diff --git a/pynfe/utils/webservices.py b/pynfe/utils/webservices.py index 399c35f..cb008ab 100644 --- a/pynfe/utils/webservices.py +++ b/pynfe/utils/webservices.py @@ -3,6 +3,8 @@ @author: Junior Tada, Leonardo Tada """ +# http://nfce.encat.org/desenvolvedor/qrcode/ +# http://nfce.encat.org/consumidor/consulte-sua-nota/ url consulta por chave # Nfc-e NFCE = { 'RO': { @@ -12,10 +14,12 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'http://www.nfce.sefin.ro.gov.br/consultanfce/consulta.jsp?', + 'URL': 'http://www.nfce.sefin.ro.gov.br' }, 'AC': { 'QR': 'sefaznet.ac.gov.br/nfce?', + 'URL': 'sefaznet.ac.gov.br/nfce/consulta', 'HTTPS': 'http://www.', 'HOMOLOGACAO': 'http://hml.' }, @@ -29,6 +33,7 @@ NFCE = { 'INUTILIZACAO': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/NfeInutilizacao2', 'EVENTOS': 'nfce.sefaz.am.gov.br/nfce-services-nac/services/RecepcaoEvento', 'QR': 'sefaz.am.gov.br/nfceweb/consultarNFCe.jsp?', + 'URL': 'sefaz.am.gov.br/nfceweb/formConsulta.do', 'HTTPS': 'http://sistemas.', 'HOMOLOGACAO': 'http://homnfce.' }, @@ -39,7 +44,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': '/nfce/servlet/qrcode?', + 'URL': '/nfce/servlet/wp_consulta_nfce', + 'HTTPS': 'https://www.sefaz.rr.gov.br', + 'HOMOLOGACAO': 'http://200.174.88.103:8080' }, 'PA': { 'STATUS': '', @@ -48,7 +56,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'view/consultas/nfce/nfceForm.seam?', + 'URL': 'view/consultas/nfce/consultanfce.seam', + 'HTTPS': 'https://appnfc.sefa.pa.gov.br/portal/', + 'HOMOLOGACAO': 'https://appnfc.sefa.pa.gov.br/portal-homologacao/' }, 'AP': { 'STATUS': '', @@ -57,7 +68,10 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': '/nfcep.php?', + 'URL': 'https://www.sefaz.ap.gov.br/sate/seg/SEGf_AcessarFuncao.jsp?cdFuncao=FIS_1261', + 'HTTPS': ' https://www.sefaz.ap.gov.br/nfce', + 'HOMOLOGACAO': 'https://www.sefaz.ap.gov.br/nfcehml' }, 'TO': { 'STATUS': '', @@ -85,7 +99,8 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'http://nfceh.sefaz.ce.gov.br/pages/ShowNFCe.html?', + 'URL': 'http://nfceh.sefaz.ce.gov.br/pages/consultaNota.jsf' }, 'RN': { #'QR': 'http://www.nfe.rn.gov.br/portal/consultarNFCe.jsp?', @@ -160,7 +175,8 @@ NFCE = { 'CHAVE': '', 'INUTILIZACAO': '', 'EVENTOS': '', - 'QR': '' + 'QR': 'http://www4.fazenda.rj.gov.br/consultaNFCe/QRCode?', + 'URL': 'www.nfce.fazenda.rj.gov.br/consulta' }, # Os Web Services de homologação da NFC-e 4.00 são: # https://homologacao.nfce.fazenda.sp.gov.br/ws/NFeAutorizacao4.asmx @@ -177,6 +193,7 @@ NFCE = { 'INUTILIZACAO': 'nfce.fazenda.sp.gov.br/ws/nfeinutilizacao2.asmx', 'EVENTOS': 'nfce.fazenda.sp.gov.br/ws/recepcaoevento.asmx', 'QR': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaQRCode.aspx?', + 'URL': 'nfce.fazenda.sp.gov.br/NFCeConsultaPublica/Paginas/ConsultaPublica.aspx', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, @@ -187,7 +204,8 @@ NFCE = { 'CHAVE': 'nfce.fazenda.pr.gov.br/nfce/NFeConsulta3', 'INUTILIZACAO': 'nfce.fazenda.pr.gov.br/nfce/NFeInutilizacao3', 'EVENTOS': 'nfce.fazenda.pr.gov.br/nfce/NFeRecepcaoEvento', - 'QR': 'http://www.dfeportal.fazenda.pr.gov.br/dfe-portal/rest/servico/consultaNFCe?', + 'QR': 'http://www.fazenda.pr.gov.br/nfce/qrcode?', + 'URL': 'http://www.fazenda.pr.gov.br', 'HTTPS': 'https://', 'HOMOLOGACAO': 'https://homologacao.' }, @@ -208,6 +226,7 @@ NFCE = { 'INUTILIZACAO': 'sefazrs.rs.gov.br/ws/nfeinutilizacao/nfeinutilizacao2.asmx', 'EVENTOS': 'sefazrs.rs.gov.br/ws/recepcaoevento/recepcaoevento.asmx', 'QR': 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx?', + 'URL': 'https://www.sefaz.rs.gov.br/NFCE/NFCE-COM.aspx', 'HTTPS': 'https://nfce.', 'HOMOLOGACAO': 'https://nfce-homologacao.' },