From 90e98191da94ab38e96b94749e93e22af4db17b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Wed, 22 May 2019 13:53:18 -0300 Subject: [PATCH 01/12] =?UTF-8?q?Corre=C3=A7=C3=A3o=20URL=20estado=20de=20?= =?UTF-8?q?Goi=C3=A1s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Sefaz GO agora usa https e não http. Adicionado o parâmetro URL necessário para emissão da NFC-e --- pynfe/utils/webservices.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pynfe/utils/webservices.py b/pynfe/utils/webservices.py index bf08aeb..c120805 100644 --- a/pynfe/utils/webservices.py +++ b/pynfe/utils/webservices.py @@ -263,8 +263,9 @@ NFCE = { 'EVENTOS': 'sefaz.go.gov.br/nfe/services/NFeRecepcaoEvento4?wsdl', 'QR': 'sefaz.go.gov.br/nfeweb/sites/nfce/danfeNFCe?', 'CADASTRO': 'sefaz.go.gov.br/nfe/services/CadConsultaCadastro4?wsdl', - 'HTTPS': 'http://nfe.', - 'HOMOLOGACAO': 'http://homolog.' + 'HTTPS': 'https://nfe.', + 'HOMOLOGACAO': 'https://homolog.', + 'URL': 'sefaz.go.gov.br/nfeweb/sites/nfce/danfeNFCe' }, 'DF': { 'QR': 'http://www.fazenda.df.gov.br/nfce/qrcode?', From 274235231e28c8c46c53692e6eb79fc652a75e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Wed, 22 May 2019 13:57:58 -0300 Subject: [PATCH 02/12] =?UTF-8?q?Corre=C3=A7=C3=A3o=20para=20emiss=C3=A3o?= =?UTF-8?q?=20estado=20de=20GO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O retorno do estado de GO vem com a tag header, com isso, ao tentar ler o status do lote não dava certo pois tentava realizar a leitura em um indice que não existe. --- pynfe/processamento/comunicacao.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pynfe/processamento/comunicacao.py b/pynfe/processamento/comunicacao.py index 0cfdeb2..5b915ea 100644 --- a/pynfe/processamento/comunicacao.py +++ b/pynfe/processamento/comunicacao.py @@ -82,7 +82,12 @@ class ComunicacaoSefaz(Comunicacao): if ind_sinc == 1: try: # Protocolo com envio OK - inf_prot = prot[0][0] # root protNFe + try: + inf_prot = prot[0][0] # root protNFe + except IndexError: + # Estados como GO vem com a tag header + inf_prot = prot[1][0] + lote_status = inf_prot.xpath("ns:retEnviNFe/ns:cStat", namespaces=ns)[0].text # Lote processado if lote_status == '104': From ce85d97e5d32bc3709588ea4dda85e8d4b1c6338 Mon Sep 17 00:00:00 2001 From: juniortada Date: Mon, 3 Jun 2019 09:02:52 -0300 Subject: [PATCH 03/12] NT 2018/003 Responsavel tecnico --- pynfe/entidades/notafiscal.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index c2fc6ac..3c994c0 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -355,6 +355,7 @@ class NotaFiscal(Entidade): self.duplicatas = [] self.observacoes_contribuinte = [] self.processos_referenciados = [] + self.responsavel_tecnico = [] super(NotaFiscal, self).__init__(*args, **kwargs) @@ -417,11 +418,17 @@ class NotaFiscal(Entidade): return obj def adicionar_processo_referenciado(self, **kwargs): - u"""Adiciona uma instancia de Processo Referenciado""" + """Adiciona uma instancia de Processo Referenciado""" obj = NotaFiscalProcessoReferenciado(**kwargs) self.processos_referenciados.append(obj) return obj + def adicionar_responsavel_tecnico(self, **kwargs): + """ Adiciona uma instancia de Responsavel Tecnico """ + obj = NotaFiscalResponsavelTecnico(**kwargs) + self.responsavel_tecnico.append(obj) + return obj + def _codigo_numerico_aleatorio(self): self.codigo_numerico_aleatorio = str(random.randint(0, 99999999)).zfill(8) return self.codigo_numerico_aleatorio @@ -1003,3 +1010,11 @@ class NotaFiscalServico(Entidade): def __str__(self): return ' '.join([str(self.identificador)]) + +class NotaFiscalResponsavelTecnico(Entidade): + # NT 2018/003 + cnpj = str() + contato = str() + email = str() + fone = str() + csrt = str() From e10381968f886ff029927f5f09c43316dddafe8f Mon Sep 17 00:00:00 2001 From: juniortada Date: Mon, 3 Jun 2019 09:23:00 -0300 Subject: [PATCH 04/12] =?UTF-8?q?serializa=C3=A7=C3=A3o=20xml=20respons?= =?UTF-8?q?=C3=A1vel=20tecnico=20NT2018/003?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pynfe/processamento/serializacao.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 077bbb2..9f623ad 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -410,6 +410,18 @@ class SerializacaoXML(Serializacao): else: return raiz + def _serializar_responsavel_tecnico(self, responsavel_tecnico, tag_raiz='infRespTec', retorna_string=True): + raiz = etree.Element(tag_raiz) + etree.SubElement(raiz, 'CNPJ').text = responsavel_tecnico.cnpj + etree.SubElement(raiz, 'xContato').text = responsavel_tecnico.contato + etree.SubElement(raiz, 'email').text = responsavel_tecnico.email + etree.SubElement(raiz, 'fone').text = responsavel_tecnico.fone + + if retorna_string: + return etree.tostring(raiz, encoding="unicode", pretty_print=True) + else: + return raiz + def _serializar_nota_fiscal(self, nota_fiscal, tag_raiz='infNFe', retorna_string=True): raiz = etree.Element(tag_raiz, versao=self._versao) @@ -636,6 +648,13 @@ class SerializacaoXML(Serializacao): if nota_fiscal.informacoes_complementares_interesse_contribuinte: etree.SubElement(info_ad, 'infCpl').text = nota_fiscal.informacoes_complementares_interesse_contribuinte + # Responsavel Tecnico NT2018/003 + if nota_fiscal.responsavel_tecnico: + for resp_tec in nota_fiscal.responsavel_tecnico: + raiz.append(self._serializar_responsavel_tecnico(resp_tec, returna_string=False)) + return + + if retorna_string: return etree.tostring(raiz, encoding="unicode", pretty_print=True) else: From 7411d225e0d3f05127efb64c0de4d21c834ddda2 Mon Sep 17 00:00:00 2001 From: juniortada Date: Mon, 3 Jun 2019 09:25:38 -0300 Subject: [PATCH 05/12] [fix] erro retorna_string --- pynfe/processamento/serializacao.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index 9f623ad..e43decc 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -651,7 +651,7 @@ class SerializacaoXML(Serializacao): # Responsavel Tecnico NT2018/003 if nota_fiscal.responsavel_tecnico: for resp_tec in nota_fiscal.responsavel_tecnico: - raiz.append(self._serializar_responsavel_tecnico(resp_tec, returna_string=False)) + raiz.append(self._serializar_responsavel_tecnico(resp_tec, retorna_string=False)) return From 5b42dea7b04df5b64b9f9c75fb0aa2eb52897ccc Mon Sep 17 00:00:00 2001 From: juniortada Date: Mon, 3 Jun 2019 09:40:44 -0300 Subject: [PATCH 06/12] [fix] add um responsavel quando existir (uf am, ms, pe, pr, sc e to) --- pynfe/processamento/serializacao.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index e43decc..c6e56e9 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -650,9 +650,8 @@ class SerializacaoXML(Serializacao): # Responsavel Tecnico NT2018/003 if nota_fiscal.responsavel_tecnico: - for resp_tec in nota_fiscal.responsavel_tecnico: - raiz.append(self._serializar_responsavel_tecnico(resp_tec, retorna_string=False)) - return + raiz.append(self._serializar_responsavel_tecnico( + nota_fiscal.responsavel_tecnico[0], retorna_string=False)) if retorna_string: From 9bfc52c5cb4de3b6127b9ec031b5734c4b10bc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Mon, 3 Jun 2019 16:07:40 -0300 Subject: [PATCH 07/12] =?UTF-8?q?Corre=C3=A7=C3=A3o=20no=20valor=20total?= =?UTF-8?q?=20da=20nota?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alterado o valor total da nota para considerar os outros itens que fazem parte da somatória do total seguindo o manual do contribuinte e utilizando apenas os campos que estão sendo utilizadas no projeto. --- pynfe/entidades/notafiscal.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 3c994c0..92f555f 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -387,7 +387,6 @@ class NotaFiscal(Entidade): 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 @@ -397,6 +396,13 @@ class NotaFiscal(Entidade): self.totais_icms_inter_remetente += obj.icms_inter_remetente_valor ## TODO calcular impostos aproximados #self.totais_tributos_aproximado += obj.tributos + + # self.totais_icms_total_nota = total + self.totais_icms_total_nota += obj.valor_total_bruto - obj.desconto + \ + obj.icms_desonerado + obj.icms_st_valor + \ + obj.total_frete + obj.total_seguro + \ + obj.outras_despesas_acessorias + obj.ipi_valor_ipi + return obj def adicionar_transporte_volume(self, **kwargs): From 4d54ea301cc4830fc484fc0ebfb3b66309e2269f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Mon, 3 Jun 2019 16:10:14 -0300 Subject: [PATCH 08/12] Adicionado desconto por item Adicionado tag de desconto no item --- pynfe/processamento/serializacao.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index c6e56e9..aa0d0f0 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -236,6 +236,10 @@ class SerializacaoXML(Serializacao): etree.SubElement(prod, 'uTrib').text = produto_servico.unidade_tributavel etree.SubElement(prod, 'qTrib').text = str(produto_servico.quantidade_tributavel) etree.SubElement(prod, 'vUnTrib').text = '{:.4f}'.format(produto_servico.valor_unitario_tributavel or 0) + + if produto_servico.desconto: + etree.SubElement(prod, 'vDesc').text = '{:.2f}'.format(produto_servico.desconto) + """ Indica se valor do Item (vProd) entra no valor total da NF-e (vProd) 0=Valor do item (vProd) não compõe o valor total da NF-e 1=Valor do item (vProd) compõe o valor total da NF-e (vProd) (v2.0) From 6736ff6a8b82ee5822fd4065b6cf43137536d1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Mon, 3 Jun 2019 16:12:33 -0300 Subject: [PATCH 09/12] =?UTF-8?q?Retirado=20coment=C3=A1rio=20desnecess?= =?UTF-8?q?=C3=A1rio.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pynfe/entidades/notafiscal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 92f555f..ed001bf 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -397,7 +397,6 @@ class NotaFiscal(Entidade): ## TODO calcular impostos aproximados #self.totais_tributos_aproximado += obj.tributos - # self.totais_icms_total_nota = total self.totais_icms_total_nota += obj.valor_total_bruto - obj.desconto + \ obj.icms_desonerado + obj.icms_st_valor + \ obj.total_frete + obj.total_seguro + \ From 2fa301b6d5f56a614e285b8998f237025454e2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Tue, 4 Jun 2019 18:00:01 -0300 Subject: [PATCH 10/12] =?UTF-8?q?Corre=C3=A7=C3=A3o=20na=20serializa=C3=A7?= =?UTF-8?q?=C3=A3o=20do=20pis=20e=20confins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alguns campos decimais do pis e confins não estavam sendo convertidos para string na hora da serialização. --- pynfe/processamento/serializacao.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index aa0d0f0..c87074a 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -353,7 +353,7 @@ class SerializacaoXML(Serializacao): elif produto_servico.pis_modalidade == '03': pis_item = etree.SubElement(pis, 'PISQtde') etree.SubElement(pis_item, 'CST').text = produto_servico.pis_modalidade - etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial + etree.SubElement(pis_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial) etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual etree.SubElement(pis_item, 'vPIS').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0) else: @@ -362,7 +362,7 @@ class SerializacaoXML(Serializacao): etree.SubElement(pis_item, 'vBC').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0) etree.SubElement(pis_item, 'pPIS').text = '{:.2f}'.format(produto_servico.pis_aliquota_percentual or 0) if produto_servico.pis_modalidade is not '99': - etree.SubElement(pis_item, 'qBCProd').text = produto_servico.quantidade_comercial + etree.SubElement(pis_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial) etree.SubElement(pis_item, 'vAliqProd').text = produto_servico.pis_aliquota_percentual etree.SubElement(pis_item, 'vPIS').text = '{:.2f}'.format(produto_servico.pis_valor_base_calculo or 0) @@ -389,9 +389,9 @@ class SerializacaoXML(Serializacao): elif produto_servico.cofins_modalidade == '03': cofins_item = etree.SubElement(cofins, 'COFINSQtde') etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade - etree.SubElement(cofins_item, 'qBCProd').text = produto_servico.quantidade_comercial - etree.SubElement(cofins_item, 'vAliqProd').text = produto_servico.cofins_aliquota_percentual - etree.SubElement(cofins_item, 'vCOFINS').text = produto_servico.cofins_valor + etree.SubElement(cofins_item, 'qBCProd').text = '{:.4f}'.format(produto_servico.quantidade_comercial) + etree.SubElement(cofins_item, 'vAliqProd').text = '{:.4f}'.format(produto_servico.cofins_aliquota_percentual) + etree.SubElement(cofins_item, 'vCOFINS').text = '{:.2f}'.format(produto_servico.cofins_valor) else: cofins_item = etree.SubElement(cofins, 'COFINSOutr') etree.SubElement(cofins_item, 'CST').text = produto_servico.cofins_modalidade From d47dac721ea38517ad1ee16ef1c6e09d33b74235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vyo=20Henrique?= Date: Thu, 6 Jun 2019 13:15:15 -0300 Subject: [PATCH 11/12] Corrigido problema de recursividade. Ao usar o debug estava gerando erro de recursividade por falta do metodo __str__ --- pynfe/entidades/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pynfe/entidades/base.py b/pynfe/entidades/base.py index 9f82806..1704944 100644 --- a/pynfe/entidades/base.py +++ b/pynfe/entidades/base.py @@ -16,6 +16,9 @@ class Entidade(object): self._fonte_dados.adicionar_objeto(self) + def __str__(self): + return self.__class__.__name__ + def __repr__(self): return '<%s %s>'%(self.__class__.__name__, str(self)) From f0955b8287d69bb0a59f9d48b893ac22c40438b4 Mon Sep 17 00:00:00 2001 From: juniortada Date: Mon, 17 Jun 2019 18:04:08 -0300 Subject: [PATCH 12/12] [fix] Corrigido url nfe MT #66 --- pynfe/utils/webservices.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pynfe/utils/webservices.py b/pynfe/utils/webservices.py index c120805..f58e8d1 100644 --- a/pynfe/utils/webservices.py +++ b/pynfe/utils/webservices.py @@ -403,13 +403,13 @@ NFE = { 'HOMOLOGACAO': 'https://homologacao.' }, 'MT': { - 'STATUS': 'nfe.sefaz.mt.gov.br/nfews/v2/services/NfeStatusServico4?wsdl', - 'AUTORIZACAO': 'nfe.sefaz.mt.gov.br/nfews/v2/services/NfeAutorizacao4?wsdl', - 'RECIBO': 'nfe.sefaz.mt.gov.br/nfews/v2/services/NfeRetAutorizacao4?wsdl', - 'CHAVE': 'nfe.sefaz.mt.gov.br/nfews/v2/services/NfeConsulta4?wsdl', - 'INUTILIZACAO': 'nfe.sefaz.mt.gov.br/nfews/v2/services/NfeInutilizacao4?wsdl', - 'EVENTOS': 'nfe.sefaz.mt.gov.br/nfews/v2/services/RecepcaoEvento4?wsdl', - 'CADASTRO': 'nfe.sefaz.mt.gov.br/nfews/v2/services/CadConsultaCadastro4?wsdl', + 'STATUS': 'sefaz.mt.gov.br/nfews/v2/services/NfeStatusServico4?wsdl', + 'AUTORIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeAutorizacao4?wsdl', + 'RECIBO': 'sefaz.mt.gov.br/nfews/v2/services/NfeRetAutorizacao4?wsdl', + 'CHAVE': 'sefaz.mt.gov.br/nfews/v2/services/NfeConsulta4?wsdl', + 'INUTILIZACAO': 'sefaz.mt.gov.br/nfews/v2/services/NfeInutilizacao4?wsdl', + 'EVENTOS': 'sefaz.mt.gov.br/nfews/v2/services/RecepcaoEvento4?wsdl', + 'CADASTRO': 'sefaz.mt.gov.br/nfews/v2/services/CadConsultaCadastro4?wsdl', 'HTTPS': 'https://nfe.', 'HOMOLOGACAO': 'https://homologacao.' },