Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correção do CDATA e FCP ST #331

Merged
merged 4 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions pynfe/entidades/base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
# -*- coding: utf-8 -*-

import warnings
from dataclasses import dataclass
from typing import List


@dataclass
class CampoDeprecated(object):
anterior: str
novo: str
motivo: str


class Entidade(object):
_fonte_dados = None
campos_deprecados: List[CampoDeprecated] = []

def __init__(self, **kwargs):
# Codigo para dinamizar a criacao de instancias de entidade,
Expand All @@ -24,6 +36,30 @@ def __str__(self):
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, str(self))

def __setattr__(self, name, value):
if hasattr(self, name):
# Verifica se o atributo é um campo deprecado
campo_deprecado = next(
(campo for campo in self.campos_deprecados if campo.anterior == name),
None,
)

if campo_deprecado:
if campo_deprecado.novo:
warnings.warn(
f"O campo {campo_deprecado.anterior} foi deprecado e será removido em versões futuras. "
f"Utilize {campo_deprecado.novo} no lugar. Motivo: {campo_deprecado.motivo}",
DeprecationWarning,
)
setattr(self, campo_deprecado.novo, value)
return
else:
raise AttributeError(
f"O campo {campo_deprecado.anterior} foi deprecado e removido."
f"Motivo: {campo_deprecado.motivo}"
)
super(Entidade, self).__setattr__(name, value)


class Lote(object):
pass
37 changes: 18 additions & 19 deletions pynfe/entidades/manifesto.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
import random
from decimal import Decimal

from .base import Entidade
from pynfe import get_version
from pynfe.utils.flags import MDFE_STATUS, CODIGOS_ESTADOS

from pynfe.utils import so_numeros
from pynfe.utils.flags import CODIGOS_ESTADOS, MDFE_STATUS

from decimal import Decimal
from .base import Entidade


class Manifesto(Entidade):
Expand Down Expand Up @@ -174,7 +173,10 @@ def _codigo_numerico_aleatorio(self):
return self.codigo_numerico_aleatorio

def _dv_codigo_numerico(self, key):
assert len(key) == 43
if not len(key) == 43:
raise ValueError(
f"Chave de acesso deve ter 43 caracteres antes de calcular o DV, chave: {key}"
)

weights = [2, 3, 4, 5, 6, 7, 8, 9]
weights_size = len(weights)
Expand All @@ -199,20 +201,17 @@ def _dv_codigo_numerico(self, key):
def identificador_unico(self):
# Monta 'Id' da tag raiz <infMDFe>
# Ex.: MDFe35080599999090910270580010000000011518005123
key = (
"%(uf)s%(ano)s%(mes)s%(cnpj)s%(mod)s%(serie)s%(nMDF)s%(tpEmis)s%(cMDF)s"
% {
"uf": CODIGOS_ESTADOS[self.uf],
"ano": self.data_emissao.strftime("%y"),
"mes": self.data_emissao.strftime("%m"),
"cnpj": so_numeros(self.emitente.cpfcnpj).zfill(14),
"mod": self.modelo,
"serie": str(self.serie).zfill(3),
"nMDF": str(self.numero_mdfe).zfill(9),
"tpEmis": str(self.forma_emissao),
"cMDF": self._codigo_numerico_aleatorio(),
}
)
key = "%(uf)s%(ano)s%(mes)s%(cnpj)s%(mod)s%(serie)s%(nMDF)s%(tpEmis)s%(cMDF)s" % {
"uf": CODIGOS_ESTADOS[self.uf],
"ano": self.data_emissao.strftime("%y"),
"mes": self.data_emissao.strftime("%m"),
"cnpj": so_numeros(self.emitente.cpfcnpj).zfill(14),
"mod": self.modelo,
"serie": str(self.serie).zfill(3),
"nMDF": str(self.numero_mdfe).zfill(9),
"tpEmis": str(self.forma_emissao),
"cMDF": self._codigo_numerico_aleatorio(),
}
return (
"MDFe%(uf)s%(ano)s%(mes)s%(cnpj)s%(mod)s%(serie)s%(nMDF)s%(tpEmis)s%(cMDF)s%(cDV)s"
% {
Expand Down
25 changes: 19 additions & 6 deletions pynfe/entidades/notafiscal.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pynfe.utils import so_numeros
from pynfe.utils.flags import CODIGOS_ESTADOS, NF_STATUS

from .base import Entidade
from .base import CampoDeprecated, Entidade


class NotaFiscal(Entidade):
Expand Down Expand Up @@ -497,7 +497,10 @@ def _codigo_numerico_aleatorio(self):
return self.codigo_numerico_aleatorio

def _dv_codigo_numerico(self, key):
assert len(key) == 43
if not len(key) == 43:
raise ValueError(
f"Chave de acesso deve ter 43 caracteres antes de calcular o DV, chave: {key}"
)

weights = [2, 3, 4, 5, 6, 7, 8, 9]
weights_size = len(weights)
Expand Down Expand Up @@ -548,6 +551,12 @@ def identificador_unico(self):


class NotaFiscalReferenciada(Entidade):
# Campos depreciados
campos_deprecados = [
CampoDeprecated("fcp_percentual", "fcp_aliquota", "Consistencia de nomes"),
CampoDeprecated("fcp_st_percentual", "fcp_st_aliquota", "Consistencia de nomes"),
]

# - Tipo (seleciona de lista) - NF_REFERENCIADA_TIPOS
tipo = str()

Expand Down Expand Up @@ -752,16 +761,20 @@ class NotaFiscalProduto(Entidade):

# - Fundo de Combate a Pobreza
fcp_base_calculo = Decimal()
fcp_percentual = Decimal()
fcp_aliquota = Decimal()
fcp_valor = Decimal()

# FCP ST
fcp_st_base_calculo = Decimal()
fcp_st_percentual = Decimal()
fcp_st_aliquota = Decimal()
fcp_st_valor = Decimal()

fcp_destino_valor = Decimal()
fcp_st_valor = Decimal()

# FCP ST Retido
fcp_st_ret_base_calculo = Decimal()
fcp_st_ret_aliquota = Decimal()
fcp_st_ret_valor = Decimal()

icms_inter_destino_valor = Decimal()
icms_inter_remetente_valor = Decimal()

Expand Down
48 changes: 19 additions & 29 deletions pynfe/processamento/serializacao.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ def _serializar_imposto_icms(

if produto_servico.fcp_valor:
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -536,7 +536,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_base_calculo or 0
) # Base de calculo FCP
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -571,7 +571,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -623,7 +623,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_base_calculo or 0
) # Base de calculo FCP
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -666,7 +666,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -710,7 +710,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_base_calculo or 0
) # Base de calculo FCP
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -742,15 +742,15 @@ def _serializar_imposto_icms(
icms_item, "vICMSSTRet"
).text = "{:.2f}".format(produto_servico.icms_st_ret_valor or 0)

if produto_servico.fcp_st_valor:
if produto_servico.fcp_st_ret_valor:
etree.SubElement(icms_item, "vBCFCPSTRet").text = "{:.2f}".format(
produto_servico.fcp_st_base_calculo or 0
produto_servico.fcp_st_ret_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPSTRet").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_ret_aliquota or 0
)
etree.SubElement(icms_item, "vFCPSTRet").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
produto_servico.fcp_st_ret_valor or 0
)

# 61=Tributação monofásica sobre combustíveis cobrada anteriormente
Expand Down Expand Up @@ -794,7 +794,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_base_calculo or 0
) # Base de calculo FCP
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -824,7 +824,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -868,7 +868,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_base_calculo or 0
) # Base de calculo FCP
etree.SubElement(icms_item, "pFCP").text = "{:.2f}".format(
produto_servico.fcp_percentual or 0
produto_servico.fcp_aliquota or 0
) # Percentual FCP
etree.SubElement(icms_item, "vFCP").text = "{:.2f}".format(
produto_servico.fcp_valor or 0
Expand Down Expand Up @@ -901,7 +901,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -976,7 +976,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -1053,7 +1053,7 @@ def _serializar_imposto_icms(
produto_servico.fcp_st_base_calculo or 0
)
etree.SubElement(icms_item, "pFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_percentual or 0
produto_servico.fcp_st_aliquota or 0
)
etree.SubElement(icms_item, "vFCPST").text = "{:.2f}".format(
produto_servico.fcp_st_valor or 0
Expand Down Expand Up @@ -2011,21 +2011,11 @@ def gerar_qrcode(self, token, csc, xml, return_qr=False, online=True):
url_chave = NFCE[uf]["HOMOLOGACAO"] + NFCE[uf]["URL"]
# adicionta tag infNFeSupl com qrcode
info = etree.Element("infNFeSupl")
etree.SubElement(info, "qrCode").text = "<![CDATA[" + qrcode.strip() + "]]>"
etree.SubElement(info, "qrCode").text = etree.CDATA(qrcode.strip())
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")
.replace("\n", "")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("amp;", "")
)
etree.tostring(nfe.find(".//qrCode"), encoding="unicode").replace(
"\n", ""
).replace("&lt;", "<").replace("&gt;", ">").replace("amp;", "")
nfe = etree.fromstring(tnfe)

# retorna nfe com o qrcode incluido NT2015/002 e qrcode
if return_qr:
return nfe, qrcode.strip()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_nfe_serializacao_csosn_201.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def preenche_notafiscal_produto_csosn201(self):
icms_st_aliquota=0,
icms_st_valor=0,
fcp_st_base_calculo=Decimal("117.00"),
fcp_st_percentual=Decimal("0.01"),
fcp_st_aliquota=Decimal("0.01"),
fcp_st_valor=Decimal("1.17"),
pis_modalidade="51",
cofins_modalidade="51",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_nfe_serializacao_csosn_202.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def preenche_notafiscal_produto_csosn202(self):
icms_st_aliquota=0,
icms_st_valor=0,
fcp_st_base_calculo=Decimal("117.00"),
fcp_st_percentual=Decimal("0.01"),
fcp_st_aliquota=Decimal("0.01"),
fcp_st_valor=Decimal("1.17"),
pis_modalidade="51",
cofins_modalidade="51",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_nfe_serializacao_csosn_203.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def preenche_notafiscal_produto_csosn203(self):
icms_st_aliquota=0,
icms_st_valor=0,
fcp_st_base_calculo=Decimal("117.00"),
fcp_st_percentual=Decimal("0.01"),
fcp_st_aliquota=Decimal("0.01"),
fcp_st_valor=Decimal("1.17"),
pis_modalidade="51",
cofins_modalidade="51",
Expand Down
10 changes: 5 additions & 5 deletions tests/test_nfe_serializacao_csosn_900.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#!/usr/bin/env python
# *-* encoding: utf8 *-*

import datetime
import unittest
from decimal import Decimal

from pynfe.entidades.cliente import Cliente
from pynfe.entidades.emitente import Emitente
from pynfe.entidades.notafiscal import NotaFiscal
from pynfe.entidades.fonte_dados import _fonte_dados
from pynfe.processamento.serializacao import SerializacaoXML
from pynfe.entidades.notafiscal import NotaFiscal
from pynfe.processamento.assinatura import AssinaturaA1
from pynfe.processamento.serializacao import SerializacaoXML
from pynfe.processamento.validacao import Validacao
from pynfe.utils.flags import (
CODIGO_BRASIL,
Expand All @@ -18,8 +20,6 @@
XSD_NFE,
XSD_NFE_PROCESSADA,
)
from decimal import Decimal
import datetime


class SerializacaoNFeTestCase(unittest.TestCase):
Expand Down Expand Up @@ -149,7 +149,7 @@ def preenche_notafiscal_produto_csosn900(self):
icms_st_aliquota=Decimal("0.10"),
icms_st_valor=Decimal("1.17"),
fcp_st_base_calculo=Decimal("117.00"),
fcp_st_percentual=Decimal("0.01"),
fcp_st_aliquota=Decimal("0.01"),
fcp_st_valor=Decimal("1.17"),
pis_modalidade="51",
cofins_modalidade="51",
Expand Down
Loading
Loading