diff --git a/.gitignore b/.gitignore index 11179d1f..af4f1e7c 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,5 @@ target/ db.* TODO* + +venv \ No newline at end of file diff --git a/pynfe/entidades/base.py b/pynfe/entidades/base.py index f6e90a62..69301cc6 100644 --- a/pynfe/entidades/base.py +++ b/pynfe/entidades/base.py @@ -10,6 +10,7 @@ class CampoDeprecated(object): anterior: str novo: str motivo: str + apenas_warning: bool = False class Entidade(object): @@ -53,6 +54,12 @@ def __setattr__(self, name, value): ) setattr(self, campo_deprecado.novo, value) return + if campo_deprecado.apenas_warning: + warnings.warn( + f"O campo {campo_deprecado.anterior} foi deprecado e será removido em versões futuras. " + f"Motivo: {campo_deprecado.motivo}", + DeprecationWarning, + ) else: raise AttributeError( f"O campo {campo_deprecado.anterior} foi deprecado e removido." diff --git a/pynfe/entidades/notafiscal.py b/pynfe/entidades/notafiscal.py index 8fd10fb6..e458d6d5 100644 --- a/pynfe/entidades/notafiscal.py +++ b/pynfe/entidades/notafiscal.py @@ -12,6 +12,16 @@ class NotaFiscal(Entidade): + # campos deprecados + campos_deprecados = [ + CampoDeprecated( + "tipo_pagamento", + novo=None, + motivo="Por favor utilize os grupos de pagamento pela função adicionar_pagamento.", + apenas_warning=True, + ), + ] + status = NF_STATUS[0] # Código numérico aleatório que compõe a chave de acesso @@ -73,7 +83,7 @@ class NotaFiscal(Entidade): 90= Sem pagamento 99=Outros """ - tipo_pagamento = int() + tipo_pagamento = None # - Forma de emissao (obrigatorio - seleciona de lista) - NF_FORMAS_EMISSAO forma_emissao = str() @@ -381,6 +391,11 @@ class NotaFiscal(Entidade): # - Processo Referenciado (lista 1 para * / ManyToManyField) processos_referenciados = None + # - pagamentos + pagamentos = list() + # valor do troco + valor_troco = Decimal() + def __init__(self, *args, **kwargs): self.autorizados_baixar_xml = [] self.notas_fiscais_referenciadas = [] @@ -390,12 +405,19 @@ def __init__(self, *args, **kwargs): self.observacoes_contribuinte = [] self.processos_referenciados = [] self.responsavel_tecnico = [] + self.pagamentos = [] super(NotaFiscal, self).__init__(*args, **kwargs) def __str__(self): return " ".join([str(self.modelo), self.serie, self.numero_nf]) + def adicionar_pagamento(self, **kwargs): + """Adiciona uma instancia de Responsavel Tecnico""" + obj = NotaFiscalPagamentos(**kwargs) + self.pagamentos.append(obj) + return obj + def adicionar_autorizados_baixar_xml(self, **kwargs): obj = AutorizadosBaixarXML(**kwargs) self.autorizados_baixar_xml.append(obj) @@ -551,12 +573,6 @@ 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() @@ -588,6 +604,11 @@ class NotaFiscalReferenciada(Entidade): class NotaFiscalProduto(Entidade): + # Campos depreciados + campos_deprecados = [ + CampoDeprecated("fcp_percentual", "fcp_aliquota", "Consistencia de nomes"), + CampoDeprecated("fcp_st_percentual", "fcp_st_aliquota", "Consistencia de nomes"), + ] # - Dados # - Codigo (obrigatorio) codigo = str() @@ -1210,3 +1231,22 @@ class NotaFiscalResponsavelTecnico(Entidade): class AutorizadosBaixarXML(Entidade): CPFCNPJ = str() + + +class NotaFiscalPagamentos(Entidade): + # forma de pagamento flag: FORMAS_PAGAMENTO + t_pag = str() + # descrição da forma de pagametno + x_pag = str() + # valor + v_pag = Decimal() + # tipo de integracao: '', '1' integrado, '2' - não integrado + tp_integra = str() + # CNPJ da Credenciadora de cartão de crédito e/ou débito + cnpj = str() + # Bandeira da operadora de cartão de crédito e/ou débito flag: BANDEIRA_CARTAO + t_band = int() + # Número de autorização da operação cartão de crédito e/ou débito + c_aut = str() + # Indicador da Forma de Pagamento: 0=à Vista, 1=à Prazo + ind_pag = int() diff --git a/pynfe/processamento/serializacao.py b/pynfe/processamento/serializacao.py index bee0f056..1c8da02a 100644 --- a/pynfe/processamento/serializacao.py +++ b/pynfe/processamento/serializacao.py @@ -2,8 +2,11 @@ import base64 import hashlib import re +import warnings + from datetime import datetime +import pynfe.utils.xml_writer as xmlw from pynfe.entidades import Manifesto, NotaFiscal from pynfe.utils import ( etree, @@ -1341,6 +1344,71 @@ def _serializar_responsavel_tecnico( else: return raiz + def _serializar_pagamentos_antigo_deprecado(self, tipo_pagamento, finalidade_emissao, totais_icms_total_nota): + pag = etree.Element('pag') + detpag = etree.SubElement(pag, "detPag") + if ( + str(finalidade_emissao) == "3" + or str(finalidade_emissao) == "4" + ): + etree.SubElement(detpag, "tPag").text = "90" + etree.SubElement(detpag, "vPag").text = "{:.2f}".format(0) + else: + etree.SubElement(detpag, "tPag").text = str( + tipo_pagamento + ).zfill(2) + etree.SubElement(detpag, "vPag").text = "{:.2f}".format( + totais_icms_total_nota + ) + if tipo_pagamento == 3 or 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 + 2= Pagamento não integrado com o sistema de automação da empresa + """ + 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 + # 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('') + return pag + + def _serializar_pagamentos(self, pagamentos: list(), finalidade_emissao='', valor_troco = 0.00, retorna_string=True): + pag = etree.Element('pag') + if (finalidade_emissao in [3, 4]): + detpag = etree.SubElement(pag, "detPag") + etree.SubElement(detpag, "tPag").text = "90" + etree.SubElement(detpag, "vPag").text = "{:.2f}".format(0) + else: + for item in pagamentos: + det = etree.Element("detPag") + xmlw.write_txt(det, "indPag", item.ind_pag, False) + xmlw.write_txt(det, "tPag", item.t_pag, True) + xmlw.write_txt(det, 'xPag', item.x_pag, False) + xmlw.write_float(det, 'vPag', item.v_pag, True, 2, 2) + if item.tp_integra: + card = etree.SubElement(det, "card") + xmlw.write_txt(card, "tpIntegra", item.tp_integra, True) + xmlw.write_txt(card, "CNPJ", item.cnpj, False) + xmlw.write_txt(card, "tBand", item.t_band, False) + xmlw.write_txt(card, "cAut", item.c_aut, False) + pag.append(det) + + # troco + xmlw.write_float(pag, 'vTroco', valor_troco, False, 2, 2) + + if retorna_string: + return etree.tostring(pag, encoding="unicode", pretty_print=False) + else: + return pag + def _serializar_nota_fiscal( self, nota_fiscal, tag_raiz="infNFe", retorna_string=True ): @@ -1710,39 +1778,28 @@ def _serializar_nota_fiscal( """ 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") - if ( - str(nota_fiscal.finalidade_emissao) == "3" - or str(nota_fiscal.finalidade_emissao) == "4" - ): - etree.SubElement(detpag, "tPag").text = "90" - etree.SubElement(detpag, "vPag").text = "{:.2f}".format(0) + if (nota_fiscal.tipo_pagamento is not None): + warnings.warn( + "O campo 'tipo_pagamento' está obsoleto e será removido em versões futuras. " + "Utilize o campo 'pagamentos' em seu lugar.", + DeprecationWarning, + ) + raiz.append( + self._serializar_pagamentos_antigo_deprecado( + tipo_pagamento=nota_fiscal.tipo_pagamento, + finalidade_emissao=nota_fiscal.finalidade_emissao, + totais_icms_total_nota=nota_fiscal.totais_icms_total_nota, + ) + ) else: - 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 + raiz.append( + self._serializar_pagamentos( + pagamentos=nota_fiscal.pagamentos, + finalidade_emissao=nota_fiscal.finalidade_emissao, + valor_troco=nota_fiscal.valor_troco, + retorna_string=False + ) ) - 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 - 2= Pagamento não integrado com o sistema de automação da empresa - """ - 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 - # 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 ( diff --git a/pynfe/utils/__init__.py b/pynfe/utils/__init__.py index b831c361..8f53eb04 100644 --- a/pynfe/utils/__init__.py +++ b/pynfe/utils/__init__.py @@ -4,6 +4,8 @@ import os from unicodedata import normalize from signxml import XMLSigner +from typing import Literal +from decimal import Decimal try: from lxml import etree # noqa: F401 @@ -178,3 +180,67 @@ def __init__(self, method, signature_algorithm, digest_algorithm, c14n_algorithm def check_deprecated_methods(self): pass + +def is_empty(value): + """ + Verifica se um valor está vazio. + + Parameters: + - value: O valor a ser verificado. + + Returns: + - True se o valor estiver vazio, False caso contrário. + """ + if value is None: + return True + elif isinstance(value, (int, float, Decimal)) and value == Decimal(0): + # Verifica se o valor numérico é igual a zero. + return True + elif isinstance(value, str) and not value.strip(): + # Verifica se a string está vazia ou contém apenas espaços em branco. + return True + elif isinstance(value, (list, tuple, dict)) and not value: + # Verifica se a lista, tupla ou dicionário está vazio. + return True + else: + return False + + +def truncar_valor(float_number: float, decimal_places: int, suprimir_zeros: bool = False): + multiplier = 10**decimal_places + result = str(int(float_number * multiplier) / multiplier) + if suprimir_zeros: + result = result.rstrip("0").rstrip(".") + return result + + +def arredondar_valor(value: float, decimal_places: int, suprimir_zeros: bool = False): + f = f"%.{decimal_places}f" + result = f % value + if suprimir_zeros: + result = result.rstrip("0").rstrip(".") + return result + + +def ajustar_valor( + value: float, decimal_places: int = 2, min_decimal_places: int = 2, tipo: Literal["ROUND", "TRUNC"] = "ROUND", decimal_separator: str = "." +): + value = 0 if value is None else value + + formated_value: str = "0" + supress_zeros = min_decimal_places < decimal_places + + if tipo == "ROUND": + formated_value = arredondar_valor(value, decimal_places, supress_zeros) + else: + formated_value = truncar_valor(value, decimal_places, supress_zeros) + + pi, sep, dec = list(formated_value.partition(".")) + + # preenche com zeros a direita até a quantidade minima + if min_decimal_places: + dec = dec.ljust(min_decimal_places, "0") + # se não tem decimais não haverá separator + sep = decimal_separator if dec else "" + + return f"{pi}{sep}{dec}".replace(".", decimal_separator) \ No newline at end of file diff --git a/pynfe/utils/flags.py b/pynfe/utils/flags.py index fb41de2a..fe9b3449 100644 --- a/pynfe/utils/flags.py +++ b/pynfe/utils/flags.py @@ -601,3 +601,51 @@ "AN": "91", "EX": "99", } + +BANDEIRA_CARTAO = ( + ("01", "Visa"), + ("02", "MasterCard"), + ("03", "AmericanExpress"), + ("04", "Sorocred"), + ("05", "DinersClub"), + ("06", "Elo"), + ("07", "Hipercard"), + ("08", "Aura"), + ("09", "Cabal"), + ("10", "Alelo"), + ("11", "BanesCard"), + ("12", "CalCard"), + ("13", "Credz"), + ("14", "Discover"), + ("15", "GoodCard"), + ("16", "GrenCard"), + ("17", "Hiper"), + ("18", "JcB"), + ("19", "Mais"), + ("20", "MaxVan"), + ("21", "Policard"), + ("22", "RedeCompras"), + ("23", "Sodexo"), + ("24", "ValeCard"), + ("25", "Verocheque"), + ("26", "VR"), + ("27", "Ticket"), + ("99", "Outros"), +) + +FORMAS_PAGAMENTO = ( + ("01", "Dinheiro"), + ("02", "Cheque"), + ("03", "Cartao Credito"), + ("04", "Cartao Debito"), + ("05", "Credito Loja"), + ("10", "Vale Alimentacao"), + ("11", "Vale Refeicao"), + ("12", "Vale Presente"), + ("13", "Vale Combustivel"), + ("14", "Duplicata Mercantil"), + ("15", "Boleto Bancario"), + ("17", "Pagamento Instantaneo"), + ("90", "Sem Pagamento"), + ("99", "Outro"), +) diff --git a/pynfe/utils/xml_writer.py b/pynfe/utils/xml_writer.py new file mode 100644 index 00000000..d16e67d1 --- /dev/null +++ b/pynfe/utils/xml_writer.py @@ -0,0 +1,82 @@ +from lxml import etree +from decimal import Decimal +from . import ajustar_valor, is_empty +from typing import Literal, Any + +__MIN_LEN_ERROR = 'Tamanho do campo {} é menor que o mímino permitido "{}"' +__MAX_LEN_ERROR = 'Tamanho do campo {} é maior que o mímino permitido "{}"' + +def write_txt(root: etree.ElementTree, tag_name, value: str, required: bool, min_len=0, max_len=0): + """ + :param root: XML root + :param tag_name: Nome da TAG a ser escrita (str) + :param value: Valor a ser escrito na TAG (str) + :param min_len: comprimento minimo + :param max-len: comprimento maximo + :param required: Se `True` e esta vazio, escreve a TAG vazia, do contrario não precisa gerar a TAG + """ + tag_value = str(value).strip() + + # retorna sem gerar nada se a TAG não é obrigatoria + if is_empty(tag_value) and not required: + return + + if len(tag_value) < min_len: + raise Exception(__MIN_LEN_ERROR.format(len(tag_value), min_len)) + if max_len > 0 and len(tag_value) > max_len: + raise Exception(__MAX_LEN_ERROR.format(len(tag_value), max_len)) + + etree.SubElement(root, tag_name).text = tag_value + +def write_float(root: etree.ElementTree, tag_name: str, value: Decimal, required: bool, decimal_places = 2, min_decimals = 0, iat: Literal["ROUND", "TRUNC"]="ROUND"): + """ + :param root: XML root + :param tag_name: Nome da TAG a ser escrita (str) + :param value: Valor a ser escrito na TAG (str) + :param decimal_places: casas decimais + :param min_decimals: numero minimo de casas decimais + :param required: Se `True` e esta vazio, escreve a TAG vazia, do contrario não precisa gerar a TAG (considera 0 como vazio) + :param iat: indice de arredondamento/truncamento (default: ROUND) + """ + + # retorna sem gerar nada se a TAG não é obrigatoria + if is_empty(Decimal(value or '0')): + if not required: + return + raise Exception(f"{tag_name} - Valor requerido e não informado") + + tag_value = ajustar_valor( + value=value.__float__(), + decimal_places=decimal_places, + min_decimal_places=min_decimals, + tipo=iat + ) + + etree.SubElement(root, tag_name).text = tag_value + +def write_int(root: etree.ElementTree, tag_name: str, value: int, required: bool): + """ + :param root: XML root + :param tag_name: Nome da TAG a ser escrita (str) + :param value: Valor a ser escrito na TAG (str) + :param required: Se `True` e esta vazio, escreve a TAG vazia, do contrario não precisa gerar a TAG (considera 0 como vazio) + :param zero_is_empty: se `True` e o valor for zero será tratado como vazio + """ + + # retorna sem gerar nada se a TAG não é obrigatoria + if is_empty(value): + if not required: + return + raise Exception(f"{tag_name} - Valor requerido e não informado") + + etree.SubElement(root, tag_name).text = int(value) + + +def write_tag(root: etree.ElementTree, tag_name: str, value: Any, required: bool): + # retorna sem gerar nada se a TAG não é obrigatoria + if is_empty(value): + if not required: + return + raise Exception(f"{tag_name} - Valor requerido e não informado") + + etree.SubElement(root, tag_name).text = str(value) diff --git a/tests/test_nfce_serializacao.py b/tests/test_nfce_serializacao.py index d586d7fd..a4165313 100644 --- a/tests/test_nfce_serializacao.py +++ b/tests/test_nfce_serializacao.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # *-* encoding: utf8 *-* - import datetime import unittest from decimal import Decimal @@ -91,8 +90,6 @@ def preenche_notafiscal_produto(self): cliente=self.cliente, uf="PR", natureza_operacao="VENDA", # venda, compra, transferência, devolução, etc - forma_pagamento=0, # 0=Pagamento à vista; 1=Pagamento a prazo; 2=Outros. - tipo_pagamento=1, modelo=65, # 55=NF-e; 65=NFC-e serie="1", numero_nf="111", # Número do Documento Fiscal. @@ -110,6 +107,7 @@ def preenche_notafiscal_produto(self): transporte_modalidade_frete=1, informacoes_adicionais_interesse_fisco="Mensagem complementar", totais_tributos_aproximado=Decimal("1.01"), + valor_troco=Decimal('3.24674500'), ) self.notafiscal.adicionar_produto_servico( @@ -150,6 +148,8 @@ def preenche_notafiscal_produto(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=120.25, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() @@ -491,6 +491,14 @@ def total_e_produto_test(self): "//ns:total/ns:ICMSTot/ns:vTotTrib", namespaces=self.ns )[0].text + vTroco = self.xml_assinado.xpath( + "//ns:pag/ns:vTroco", namespaces=self.ns + )[0].text + + vPag = self.xml_assinado.xpath( + "//ns:pag/ns:detPag/ns:vPag", namespaces=self.ns + )[0].text + self.assertEqual(vBC, "0.00") self.assertEqual(vICMS, "0.00") self.assertEqual(vICMSDeson, "0.00") @@ -511,6 +519,7 @@ def total_e_produto_test(self): self.assertEqual(vOutro, "0.00") self.assertEqual(vNF, "117.00") self.assertEqual(vTotTrib, "1.01") + self.assertEqual(Decimal(vPag) - Decimal(vTroco), Decimal(vNF)) def test_notafiscal_produto_cst00(self): # Preenche as classes do pynfe diff --git a/tests/test_nfce_serializacao_sem_cliente.py b/tests/test_nfce_serializacao_sem_cliente.py index c8e024d9..92cc50f8 100644 --- a/tests/test_nfce_serializacao_sem_cliente.py +++ b/tests/test_nfce_serializacao_sem_cliente.py @@ -1,13 +1,15 @@ #!/usr/bin/env python # *-* encoding: utf8 *-* +import datetime import unittest +from decimal import Decimal 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, @@ -17,8 +19,6 @@ XSD_NFE, XSD_NFE_PROCESSADA, ) -from decimal import Decimal -import datetime class SerializacaoNFeTestCase(unittest.TestCase): @@ -93,6 +93,7 @@ def preenche_notafiscal_produto(self): transporte_modalidade_frete=1, informacoes_adicionais_interesse_fisco="Mensagem complementar", totais_tributos_aproximado=Decimal("1.01"), + valor_troco=Decimal('3.00'), ) self.notafiscal.adicionar_produto_servico( @@ -133,6 +134,8 @@ def preenche_notafiscal_produto(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=120.00, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML( fonte_dados=_fonte_dados, homologacao=self.homologacao, so_cpf=True diff --git a/tests/test_nfce_serializacao_somente_cpf.py b/tests/test_nfce_serializacao_somente_cpf.py index c673d47a..2b733136 100644 --- a/tests/test_nfce_serializacao_somente_cpf.py +++ b/tests/test_nfce_serializacao_somente_cpf.py @@ -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, @@ -18,8 +20,6 @@ XSD_NFE, XSD_NFE_PROCESSADA, ) -from decimal import Decimal -import datetime class SerializacaoNFeTestCase(unittest.TestCase): @@ -102,6 +102,7 @@ def preenche_notafiscal_produto(self): transporte_modalidade_frete=1, informacoes_adicionais_interesse_fisco="Mensagem complementar", totais_tributos_aproximado=Decimal("1.01"), + valor_troco=Decimal('3.00'), ) self.notafiscal.adicionar_produto_servico( @@ -142,6 +143,8 @@ def preenche_notafiscal_produto(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=120.00, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML( fonte_dados=_fonte_dados, homologacao=self.homologacao, so_cpf=True diff --git a/tests/test_nfe_serializacao_csosn_101.py b/tests/test_nfe_serializacao_csosn_101.py index 28af1a36..672c8c4c 100644 --- a/tests/test_nfe_serializacao_csosn_101.py +++ b/tests/test_nfe_serializacao_csosn_101.py @@ -168,6 +168,9 @@ def preenche_notafiscal_produto_csosn101(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) + + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() diff --git a/tests/test_nfe_serializacao_csosn_102.py b/tests/test_nfe_serializacao_csosn_102.py index 056ef63a..fe354d96 100644 --- a/tests/test_nfe_serializacao_csosn_102.py +++ b/tests/test_nfe_serializacao_csosn_102.py @@ -166,6 +166,8 @@ def preenche_notafiscal_produto_csosn102(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() diff --git a/tests/test_nfe_serializacao_csosn_103.py b/tests/test_nfe_serializacao_csosn_103.py index d5c4d8d2..a5c64272 100644 --- a/tests/test_nfe_serializacao_csosn_103.py +++ b/tests/test_nfe_serializacao_csosn_103.py @@ -166,6 +166,8 @@ def preenche_notafiscal_produto_csosn102(self): fone="11912341234", ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() diff --git a/tests/test_nfe_serializacao_csosn_201.py b/tests/test_nfe_serializacao_csosn_201.py index e069d777..358d9b5e 100644 --- a/tests/test_nfe_serializacao_csosn_201.py +++ b/tests/test_nfe_serializacao_csosn_201.py @@ -164,6 +164,9 @@ def preenche_notafiscal_produto_csosn201(self): pdevol=Decimal("0.00"), ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=118.17, ind_pag=0) + + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() diff --git a/tests/test_nfe_serializacao_csosn_202.py b/tests/test_nfe_serializacao_csosn_202.py index d9f2ea16..e3fc591a 100644 --- a/tests/test_nfe_serializacao_csosn_202.py +++ b/tests/test_nfe_serializacao_csosn_202.py @@ -113,6 +113,7 @@ def preenche_notafiscal_produto_csosn202(self): transporte_modalidade_frete=1, informacoes_adicionais_interesse_fisco="Mensagem complementar", totais_tributos_aproximado=Decimal("21.06"), + valor_troco=Decimal('1.83') ) self.notafiscal.adicionar_produto_servico( @@ -157,9 +158,11 @@ def preenche_notafiscal_produto_csosn202(self): nfci="12345678-AAAA-FFFF-1234-000000000000", informacoes_adicionais="Informações adicionais", ipi_valor_ipi_dev=Decimal("0.00"), - pdevol=Decimal("0.00"), + pdevol=Decimal("0.00") ) + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=120.00, ind_pag=0) + def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) return serializador.exportar() diff --git a/tests/test_nfe_serializacao_csosn_203.py b/tests/test_nfe_serializacao_csosn_203.py index a083dc51..55a98252 100644 --- a/tests/test_nfe_serializacao_csosn_203.py +++ b/tests/test_nfe_serializacao_csosn_203.py @@ -159,6 +159,8 @@ def preenche_notafiscal_produto_csosn203(self): ipi_valor_ipi_dev=Decimal("0.00"), pdevol=Decimal("0.00"), ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=118.17, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_csosn_300.py b/tests/test_nfe_serializacao_csosn_300.py index 879c4459..e8dcfea3 100644 --- a/tests/test_nfe_serializacao_csosn_300.py +++ b/tests/test_nfe_serializacao_csosn_300.py @@ -165,6 +165,8 @@ def preenche_notafiscal_produto_csosn300(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_csosn_400.py b/tests/test_nfe_serializacao_csosn_400.py index ac89295e..8a124578 100644 --- a/tests/test_nfe_serializacao_csosn_400.py +++ b/tests/test_nfe_serializacao_csosn_400.py @@ -165,6 +165,8 @@ def preenche_notafiscal_produto_csosn400(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_csosn_500.py b/tests/test_nfe_serializacao_csosn_500.py index 0cf04874..9b877eb6 100644 --- a/tests/test_nfe_serializacao_csosn_500.py +++ b/tests/test_nfe_serializacao_csosn_500.py @@ -165,6 +165,8 @@ def preenche_notafiscal_produto_csosn500(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_csosn_900.py b/tests/test_nfe_serializacao_csosn_900.py index 9f5eb1de..f48d6110 100644 --- a/tests/test_nfe_serializacao_csosn_900.py +++ b/tests/test_nfe_serializacao_csosn_900.py @@ -167,6 +167,8 @@ def preenche_notafiscal_produto_csosn900(self): ipi_valor_ipi_dev=Decimal("0.00"), pdevol=Decimal("0.00"), ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=119.34, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_00.py b/tests/test_nfe_serializacao_cst_00.py index f91fb589..d3e0644e 100644 --- a/tests/test_nfe_serializacao_cst_00.py +++ b/tests/test_nfe_serializacao_cst_00.py @@ -150,6 +150,8 @@ def preenche_notafiscal_produto_cst00(self): ipi_valor_ipi_dev=Decimal("10.00"), pdevol=Decimal("1.00"), ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=127.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_10.py b/tests/test_nfe_serializacao_cst_10.py index 9b176f2d..d37ef319 100644 --- a/tests/test_nfe_serializacao_cst_10.py +++ b/tests/test_nfe_serializacao_cst_10.py @@ -163,6 +163,8 @@ def preenche_notafiscal_produto_cst10(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_20.py b/tests/test_nfe_serializacao_cst_20.py index c4a48e39..cb21420d 100644 --- a/tests/test_nfe_serializacao_cst_20.py +++ b/tests/test_nfe_serializacao_cst_20.py @@ -163,6 +163,8 @@ def preenche_notafiscal_produto_cst20(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_30.py b/tests/test_nfe_serializacao_cst_30.py index 6bb562be..5416bb9b 100644 --- a/tests/test_nfe_serializacao_cst_30.py +++ b/tests/test_nfe_serializacao_cst_30.py @@ -169,6 +169,8 @@ def preenche_notafiscal_produto_cst30(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_40.py b/tests/test_nfe_serializacao_cst_40.py index 386f9d29..7784b125 100644 --- a/tests/test_nfe_serializacao_cst_40.py +++ b/tests/test_nfe_serializacao_cst_40.py @@ -158,6 +158,8 @@ def preenche_notafiscal_produto_cst40(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=107.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_41.py b/tests/test_nfe_serializacao_cst_41.py index e736eaab..59c0e33e 100644 --- a/tests/test_nfe_serializacao_cst_41.py +++ b/tests/test_nfe_serializacao_cst_41.py @@ -158,6 +158,8 @@ def preenche_notafiscal_produto_cst41(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=107.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_50.py b/tests/test_nfe_serializacao_cst_50.py index 9f0f7690..7ec6c94f 100644 --- a/tests/test_nfe_serializacao_cst_50.py +++ b/tests/test_nfe_serializacao_cst_50.py @@ -158,6 +158,8 @@ def preenche_notafiscal_produto_cst50(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=107.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_51.py b/tests/test_nfe_serializacao_cst_51.py index e22026af..f3f2f94f 100644 --- a/tests/test_nfe_serializacao_cst_51.py +++ b/tests/test_nfe_serializacao_cst_51.py @@ -156,6 +156,8 @@ def preenche_notafiscal_produto_cst51(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_60.py b/tests/test_nfe_serializacao_cst_60.py index ba78d1bd..b83f93f6 100644 --- a/tests/test_nfe_serializacao_cst_60.py +++ b/tests/test_nfe_serializacao_cst_60.py @@ -156,6 +156,8 @@ def preenche_notafiscal_produto_cst60(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento(t_pag="01", x_pag="Dinheiro", v_pag=117.00, ind_pag=0) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_70.py b/tests/test_nfe_serializacao_cst_70.py index deb600d1..f7b8a565 100644 --- a/tests/test_nfe_serializacao_cst_70.py +++ b/tests/test_nfe_serializacao_cst_70.py @@ -173,6 +173,15 @@ def preenche_notafiscal_produto_cst70(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento( + t_pag="03", + x_pag="Cartao Credito", + v_pag=118.46, + ind_pag=0, + tp_integra="2", + t_band="99", + ) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_cst_90.py b/tests/test_nfe_serializacao_cst_90.py index 878b7c23..c3da45d4 100644 --- a/tests/test_nfe_serializacao_cst_90.py +++ b/tests/test_nfe_serializacao_cst_90.py @@ -178,6 +178,22 @@ def preenche_notafiscal_produto_cst90(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento( + t_pag="01", + x_pag="Dinheiro", + v_pag=17.00, + ind_pag=0, + ) + + self.notafiscal.adicionar_pagamento( + t_pag="03", + x_pag="Cartao Credito", + v_pag=100.00, + ind_pag=0, + tp_integra="2", + t_band="99", + ) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_geral.py b/tests/test_nfe_serializacao_geral.py index c372b117..19312d83 100644 --- a/tests/test_nfe_serializacao_geral.py +++ b/tests/test_nfe_serializacao_geral.py @@ -163,6 +163,24 @@ def preenche_notafiscal_produto_cst00(self): email="pynfe@pynfe.io", fone="11912341234", ) + + self.notafiscal.adicionar_pagamento( + t_pag="03", + x_pag="Cartao Credito", + v_pag=117.00, + ind_pag=0, + tp_integra="2", + t_band="99", + ) + + self.notafiscal.adicionar_pagamento( + t_pag="03", + x_pag="Cartao Credito", + v_pag=117.00, + ind_pag=0, + tp_integra="2", + t_band="99", + ) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao) diff --git a/tests/test_nfe_serializacao_ii_di_ipi.py b/tests/test_nfe_serializacao_ii_di_ipi.py index 8c9e033e..561d3b63 100644 --- a/tests/test_nfe_serializacao_ii_di_ipi.py +++ b/tests/test_nfe_serializacao_ii_di_ipi.py @@ -200,6 +200,15 @@ def preenche_notafiscal_produto_cst00(self): imposto_importacao_valor=Decimal('0.00'), imposto_importacao_valor_iof=Decimal('1.11'), ) + + self.notafiscal.adicionar_pagamento( + t_pag="03", + x_pag="Cartao Credito", + v_pag=118.70, + ind_pag=0, + tp_integra="2", + t_band="99", + ) def serializa_nfe(self): serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao)