Skip to content

Commit

Permalink
Merge pull request #331 from nuvelbr/master
Browse files Browse the repository at this point in the history
Correção do CDATA e FCP ST
  • Loading branch information
juniortada authored Mar 20, 2024
2 parents d8b0d2b + 1e90b9f commit 52470db
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 68 deletions.
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

0 comments on commit 52470db

Please sign in to comment.