Skip to content

Commit 9f81c8b

Browse files
committed
Cria testes para NFe com CSOSN e corrige serialização
1 parent 743cd51 commit 9f81c8b

11 files changed

+3228
-7
lines changed

pynfe/processamento/serializacao.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,8 @@ def _serializar_imposto_icms(self, produto_servico, tag_raiz='imposto', retorna_
547547
icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade)
548548
etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
549549
etree.SubElement(icms_item, 'CSOSN').text = produto_servico.icms_csosn
550-
etree.SubElement(icms_item, 'pCredSN').text = str(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
551-
etree.SubElement(icms_item, 'vCredICMSSN').text = str(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
550+
etree.SubElement(icms_item, 'pCredSN').text = '{:.2f}'.format(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
551+
etree.SubElement(icms_item, 'vCredICMSSN').text = '{:.2f}'.format(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
552552

553553
# 102=Tributada pelo Simples Nacional sem permissão de crédito
554554
# 103=Isenção do ICMS no Simples Nacional para faixa de receita bruta
@@ -563,7 +563,10 @@ def _serializar_imposto_icms(self, produto_servico, tag_raiz='imposto', retorna_
563563
# 202=Tributada pelo Simples Nacional sem permissão de crédito e com cobrança do ICMS por substituição tributária
564564
# 203=Isenção do ICMS no Simples Nacional para faixa de receita bruta e com cobrança do ICMS por substituição tributária
565565
elif produto_servico.icms_modalidade in ('201', '202', '203'):
566-
icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade)
566+
if produto_servico.icms_modalidade == '201':
567+
icms_item = etree.SubElement(icms, 'ICMSSN201')
568+
elif produto_servico.icms_modalidade in ['202', '203']:
569+
icms_item = etree.SubElement(icms, 'ICMSSN202')
567570
etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
568571
etree.SubElement(icms_item, 'CSOSN').text = produto_servico.icms_csosn
569572

@@ -580,8 +583,8 @@ def _serializar_imposto_icms(self, produto_servico, tag_raiz='imposto', retorna_
580583
etree.SubElement(icms_item, 'vFCPST').text = '{:.2f}'.format(produto_servico.fcp_st_valor or 0)
581584

582585
if produto_servico.icms_modalidade == '201':
583-
etree.SubElement(icms_item, 'pCredSN').text = str(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
584-
etree.SubElement(icms_item, 'vCredICMSSN').text = str(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
586+
etree.SubElement(icms_item, 'pCredSN').text = '{:.2f}'.format(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
587+
etree.SubElement(icms_item, 'vCredICMSSN').text = '{:.2f}'.format(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
585588

586589
# 500=ICMS cobrado anteriormente por substituição tributária (substituído) ou por antecipação
587590
elif produto_servico.icms_modalidade == '500':
@@ -616,8 +619,8 @@ def _serializar_imposto_icms(self, produto_servico, tag_raiz='imposto', retorna_
616619
etree.SubElement(icms_item, 'vFCPST').text = '{:.2f}'.format(produto_servico.fcp_st_valor or 0)
617620

618621
if produto_servico.icms_aliquota > 0:
619-
etree.SubElement(icms_item, 'pCredSN').text = str(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
620-
etree.SubElement(icms_item, 'vCredICMSSN').text = str(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
622+
etree.SubElement(icms_item, 'pCredSN').text = '{:.2f}'.format(produto_servico.icms_aliquota) # Alíquota aplicável de cálculo do crédito (Simples Nacional).
623+
etree.SubElement(icms_item, 'vCredICMSSN').text = '{:.2f}'.format(produto_servico.icms_credito) # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
621624

622625
else:
623626
raise NotImplementedError
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
#!/usr/bin/env python
2+
# *-* encoding: utf8 *-*
3+
4+
import unittest
5+
6+
from pynfe.entidades.cliente import Cliente
7+
from pynfe.entidades.emitente import Emitente
8+
from pynfe.entidades.notafiscal import NotaFiscal
9+
from pynfe.entidades.fonte_dados import _fonte_dados
10+
from pynfe.processamento.serializacao import SerializacaoXML
11+
from pynfe.processamento.assinatura import AssinaturaA1
12+
from pynfe.processamento.validacao import Validacao
13+
from pynfe.utils.flags import (
14+
CODIGO_BRASIL,
15+
NAMESPACE_NFE,
16+
NAMESPACE_SIG,
17+
XSD_FOLDER_NFE,
18+
XSD_NFE,
19+
XSD_NFE_PROCESSADA,
20+
)
21+
from decimal import Decimal
22+
import datetime
23+
24+
25+
class SerializacaoNFeTestCase(unittest.TestCase):
26+
"""
27+
Imprimir o XML completo:
28+
print(etree.tostring(self.xml_assinado))
29+
30+
"""
31+
32+
def setUp(self):
33+
self.certificado = "./tests/certificado.pfx"
34+
self.senha = bytes('123456', 'utf-8')
35+
self.uf = 'pr'
36+
self.homologacao = True
37+
38+
self.ns = {'ns': NAMESPACE_NFE}
39+
self.ns_sig = {'ns': NAMESPACE_SIG}
40+
41+
self.validacao = Validacao()
42+
self.xsd_procNFe = self.validacao.get_xsd(
43+
xsd_file=XSD_NFE_PROCESSADA,
44+
xsd_folder=XSD_FOLDER_NFE
45+
)
46+
self.xsd_nfe = self.validacao.get_xsd(
47+
xsd_file=XSD_NFE,
48+
xsd_folder=XSD_FOLDER_NFE
49+
)
50+
51+
def preenche_emitente(self):
52+
self.emitente = Emitente(
53+
razao_social='NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL',
54+
nome_fantasia='Nome Fantasia da Empresa',
55+
cnpj='99999999000199', # cnpj apenas números
56+
codigo_de_regime_tributario='1', # 1 para simples nacional ou 3 para normal
57+
inscricao_estadual='9999999999', # numero de IE da empresa
58+
inscricao_municipal='12345',
59+
cnae_fiscal='9999999', # cnae apenas números
60+
endereco_logradouro='Rua da Paz',
61+
endereco_numero='666',
62+
endereco_bairro='Sossego',
63+
endereco_municipio='Paranavaí',
64+
endereco_uf='PR',
65+
endereco_cep='87704000',
66+
endereco_pais=CODIGO_BRASIL
67+
)
68+
return self.emitente
69+
70+
def preenche_destinatario(self):
71+
self.cliente = Cliente(
72+
razao_social='JOSE DA SILVA',
73+
tipo_documento='CPF', # CPF ou CNPJ
74+
75+
numero_documento='12345678900', # numero do cpf ou cnpj
76+
indicador_ie=9, # 9=Não contribuinte
77+
endereco_logradouro='Rua dos Bobos',
78+
endereco_numero='Zero',
79+
endereco_complemento='Ao lado de lugar nenhum',
80+
endereco_bairro='Aquele Mesmo',
81+
endereco_municipio='Brasilia',
82+
endereco_uf='DF',
83+
endereco_cep='12345123',
84+
endereco_pais=CODIGO_BRASIL,
85+
endereco_telefone='11912341234',
86+
)
87+
return self.cliente
88+
89+
def preenche_notafiscal_produto_csosn101(self):
90+
91+
utc = datetime.timezone.utc
92+
data_emissao = datetime.datetime(2021, 1, 14, 12, 0, 0, tzinfo=utc)
93+
data_saida_entrada = datetime.datetime(2021, 1, 14, 13, 10, 20, tzinfo=utc)
94+
95+
self.notafiscal = NotaFiscal(
96+
emitente=self.emitente,
97+
cliente=self.cliente,
98+
uf='PR',
99+
natureza_operacao='VENDA', # venda, compra, transferência, devolução, etc
100+
forma_pagamento=0, # 0=Pagamento à vista; 1=Pagamento a prazo; 2=Outros.
101+
tipo_pagamento=1,
102+
modelo=55, # 55=NF-e; 65=NFC-e
103+
serie='1',
104+
numero_nf='111', # Número do Documento Fiscal.
105+
data_emissao=data_emissao,
106+
data_saida_entrada=data_saida_entrada,
107+
tipo_documento=1, # 0=entrada; 1=saida
108+
municipio='4118402', # Código IBGE do Município
109+
tipo_impressao_danfe=1, # 0=Sem geração de DANFE;1=DANFE normal, Retrato;2=DANFE normal Paisagem;3=DANFE Simplificado;4=DANFE NFC-e;
110+
forma_emissao='1', # 1=Emissão normal (não em contingência);
111+
cliente_final=1, # 0=Normal;1=Consumidor final;
112+
indicador_destino=1,
113+
indicador_presencial=1,
114+
finalidade_emissao='1', # 1=NF-e normal;2=NF-e complementar;3=NF-e de ajuste;4=Devolução de mercadoria.
115+
processo_emissao='0', # 0=Emissão de NF-e com aplicativo do contribuinte;
116+
transporte_modalidade_frete=1,
117+
informacoes_adicionais_interesse_fisco='Mensagem complementar',
118+
totais_tributos_aproximado=Decimal('21.06'),
119+
)
120+
121+
self.notafiscal.adicionar_produto_servico(
122+
codigo='000328', # id do produto
123+
descricao='Produto teste',
124+
ncm='99999999',
125+
# cest='0100100', # NT2015/003
126+
ean='1234567890121',
127+
cfop='5102',
128+
unidade_comercial='UN',
129+
quantidade_comercial=Decimal('12'), # 12 unidades
130+
valor_unitario_comercial=Decimal('9.75'), # preço unitário
131+
valor_total_bruto=Decimal('117.00'), # preço total
132+
unidade_tributavel='UN',
133+
quantidade_tributavel=Decimal('12'),
134+
valor_unitario_tributavel=Decimal('9.75'),
135+
ean_tributavel='SEM GTIN',
136+
ind_total=1,
137+
icms_modalidade='101',
138+
icms_origem=0,
139+
icms_csosn='101',
140+
icms_aliquota=Decimal('3.00'), # Alíquota aplicável de cálculo do crédito (Simples Nacional).
141+
icms_credito=Decimal('10.00'), # Valor crédito do ICMS que pode ser aproveitado nos termos do art. 23 da LC 123 (Simples Nacional)
142+
pis_modalidade='51',
143+
cofins_modalidade='51',
144+
pis_valor_base_calculo=Decimal('117.00'),
145+
pis_aliquota_percentual=Decimal('0.65'),
146+
pis_valor=Decimal('0.76'),
147+
cofins_valor_base_calculo=Decimal('117.00'),
148+
cofins_aliquota_percentual=Decimal('3.00'),
149+
cofins_valor=Decimal('3.51'),
150+
valor_tributos_aprox='21.06',
151+
numero_pedido='12345',
152+
numero_item='1',
153+
nfci='12345678-AAAA-FFFF-1234-000000000000',
154+
informacoes_adicionais='Informações adicionais',
155+
ipi_valor_ipi_dev=Decimal('0.00'),
156+
pdevol=Decimal('0.00'),
157+
)
158+
self.notafiscal.adicionar_nota_fiscal_referenciada(
159+
chave_acesso='12345678901234567890123456789012345678900001'
160+
)
161+
self.notafiscal.adicionar_nota_fiscal_referenciada(
162+
chave_acesso='12345678901234567890123456789012345678900002'
163+
)
164+
165+
self.notafiscal.adicionar_responsavel_tecnico(
166+
cnpj='99999999000199',
167+
contato='Teste PyNFe',
168+
169+
fone='11912341234'
170+
)
171+
172+
def serializa_nfe(self):
173+
serializador = SerializacaoXML(_fonte_dados, homologacao=self.homologacao)
174+
return serializador.exportar()
175+
176+
def assina_xml(self):
177+
a1 = AssinaturaA1(self.certificado, self.senha)
178+
return a1.assinar(self.xml)
179+
180+
def validacao_com_xsd_do_xml_gerado_sem_processar(self):
181+
self.validacao.validar_etree(
182+
xml_doc=self.xml_assinado,
183+
xsd_file=self.xsd_nfe,
184+
use_assert=True
185+
)
186+
187+
def total_e_produto_csosn101_test(self):
188+
# Produto
189+
cProd = self.xml_assinado.xpath('//ns:det/ns:prod/ns:cProd', namespaces=self.ns)[0].text
190+
cEAN = self.xml_assinado.xpath('//ns:det/ns:prod/ns:cEAN', namespaces=self.ns)[0].text
191+
xProd = self.xml_assinado.xpath('//ns:det/ns:prod/ns:xProd', namespaces=self.ns)[0].text
192+
NCM = self.xml_assinado.xpath('//ns:det/ns:prod/ns:NCM', namespaces=self.ns)[0].text
193+
# CEST = self.xml_assinado.xpath('//ns:det/ns:prod/ns:CEST', namespaces=self.ns)[0].text
194+
# indEscala = self.xml_assinado.xpath('//ns:det/ns:prod/ns:indEscala', namespaces=self.ns)[0].text
195+
CEST = None
196+
indEscala = None
197+
CFOP = self.xml_assinado.xpath('//ns:det/ns:prod/ns:CFOP', namespaces=self.ns)[0].text
198+
uCom = self.xml_assinado.xpath('//ns:det/ns:prod/ns:uCom', namespaces=self.ns)[0].text
199+
qCom = self.xml_assinado.xpath('//ns:det/ns:prod/ns:qCom', namespaces=self.ns)[0].text
200+
vUnCom = self.xml_assinado.xpath('//ns:det/ns:prod/ns:vUnCom', namespaces=self.ns)[0].text
201+
vProd = self.xml_assinado.xpath('//ns:det/ns:prod/ns:vProd', namespaces=self.ns)[0].text
202+
cEANTrib = self.xml_assinado.xpath('//ns:det/ns:prod/ns:cEANTrib', namespaces=self.ns)[0].text
203+
uTrib = self.xml_assinado.xpath('//ns:det/ns:prod/ns:uTrib', namespaces=self.ns)[0].text
204+
qTrib = self.xml_assinado.xpath('//ns:det/ns:prod/ns:qTrib', namespaces=self.ns)[0].text
205+
vUnTrib = self.xml_assinado.xpath('//ns:det/ns:prod/ns:vUnTrib', namespaces=self.ns)[0].text
206+
indTot = self.xml_assinado.xpath('//ns:det/ns:prod/ns:indTot', namespaces=self.ns)[0].text
207+
xPed = self.xml_assinado.xpath('//ns:det/ns:prod/ns:xPed', namespaces=self.ns)[0].text
208+
nItemPed = self.xml_assinado.xpath('//ns:det/ns:prod/ns:nItemPed', namespaces=self.ns)[0].text
209+
nFCI = self.xml_assinado.xpath('//ns:det/ns:prod/ns:nFCI', namespaces=self.ns)[0].text
210+
211+
self.assertEqual(cProd, '000328')
212+
self.assertEqual(cEAN, '1234567890121')
213+
self.assertEqual(xProd, 'Produto teste')
214+
self.assertEqual(NCM, '99999999')
215+
self.assertEqual(CEST, None)
216+
self.assertEqual(indEscala, None)
217+
self.assertEqual(CFOP, '5102')
218+
self.assertEqual(uCom, 'UN')
219+
self.assertEqual(qCom, '12')
220+
self.assertEqual(vUnCom, '9.7500000000')
221+
self.assertEqual(vProd, '117.00')
222+
self.assertEqual(cEANTrib, 'SEM GTIN')
223+
self.assertEqual(uTrib, 'UN')
224+
self.assertEqual(qTrib, '12')
225+
self.assertEqual(vUnTrib, '9.7500000000')
226+
self.assertEqual(indTot, '1')
227+
self.assertEqual(xPed, '12345')
228+
self.assertEqual(nItemPed, '1')
229+
self.assertEqual(nFCI, '12345678-AAAA-FFFF-1234-000000000000')
230+
231+
# Impostos
232+
# ICMS
233+
orig = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:ICMS/ns:ICMSSN101/ns:orig', namespaces=self.ns)[0].text
234+
CSOSN = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:ICMS/ns:ICMSSN101/ns:CSOSN', namespaces=self.ns)[0].text
235+
pCredSN = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:ICMS/ns:ICMSSN101/ns:pCredSN', namespaces=self.ns)[0].text
236+
vCredICMSSN = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:ICMS/ns:ICMSSN101/ns:vCredICMSSN', namespaces=self.ns)[0].text
237+
238+
self.assertEqual(orig, '0')
239+
self.assertEqual(CSOSN, '101')
240+
self.assertEqual(pCredSN, '3.00')
241+
self.assertEqual(vCredICMSSN, '10.00')
242+
243+
# PIS
244+
CST_PIS = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:PIS/ns:PISOutr/ns:CST', namespaces=self.ns)[0].text
245+
self.assertEqual(CST_PIS, '51')
246+
247+
# COFINS
248+
CST_COFINS = self.xml_assinado.xpath('//ns:det/ns:imposto/ns:COFINS/ns:COFINSOutr/ns:CST', namespaces=self.ns)[0].text
249+
self.assertEqual(CST_COFINS, '51')
250+
251+
# Informações Adicionais do produto
252+
infAdProd = self.xml_assinado.xpath('//ns:det/ns:infAdProd', namespaces=self.ns)[0].text
253+
self.assertEqual(infAdProd, 'Informacoes adicionais')
254+
255+
# Totalizadores
256+
vBC = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vBC', namespaces=self.ns)[0].text
257+
vICMS = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vICMS', namespaces=self.ns)[0].text
258+
vICMSDeson = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vICMSDeson', namespaces=self.ns)[0].text
259+
vFCP = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vFCP', namespaces=self.ns)[0].text
260+
vBCST = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vBCST', namespaces=self.ns)[0].text
261+
vST = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vST', namespaces=self.ns)[0].text
262+
vFCPST = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vFCPST', namespaces=self.ns)[0].text
263+
vFCPSTRet = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vFCPSTRet', namespaces=self.ns)[0].text
264+
vProd = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vProd', namespaces=self.ns)[0].text
265+
vFrete = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vFrete', namespaces=self.ns)[0].text
266+
vSeg = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vSeg', namespaces=self.ns)[0].text
267+
vDesc = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vDesc', namespaces=self.ns)[0].text
268+
vII = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vII', namespaces=self.ns)[0].text
269+
vIPI = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vIPI', namespaces=self.ns)[0].text
270+
vIPIDevol = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vIPIDevol', namespaces=self.ns)[0].text
271+
vPIS = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vPIS', namespaces=self.ns)[0].text
272+
vCOFINS = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vCOFINS', namespaces=self.ns)[0].text
273+
vOutro = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vOutro', namespaces=self.ns)[0].text
274+
vNF = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vNF', namespaces=self.ns)[0].text
275+
vTotTrib = self.xml_assinado.xpath('//ns:total/ns:ICMSTot/ns:vTotTrib', namespaces=self.ns)[0].text
276+
277+
self.assertEqual(vBC, '0.00')
278+
self.assertEqual(vICMS, '0.00')
279+
self.assertEqual(vICMSDeson, '0.00')
280+
self.assertEqual(vFCP, '0.00')
281+
self.assertEqual(vBCST, '0.00')
282+
self.assertEqual(vST, '0.00')
283+
self.assertEqual(vFCPST, '0.00')
284+
self.assertEqual(vFCPSTRet, '0.00')
285+
self.assertEqual(vProd, '117.00')
286+
self.assertEqual(vFrete, '0.00')
287+
self.assertEqual(vSeg, '0.00')
288+
self.assertEqual(vDesc, '0.00')
289+
self.assertEqual(vII, '0.00')
290+
self.assertEqual(vIPI, '0.00')
291+
self.assertEqual(vIPIDevol, '0.00')
292+
self.assertEqual(vPIS, '0.76')
293+
self.assertEqual(vCOFINS, '3.51')
294+
self.assertEqual(vOutro, '0.00')
295+
self.assertEqual(vNF, '117.00')
296+
self.assertEqual(vTotTrib, '21.06')
297+
298+
def test_notafiscal_produto_csosn101(self):
299+
# Preenche as classes do pynfe
300+
self.emitente = self.preenche_emitente()
301+
self.cliente = self.preenche_destinatario()
302+
self.notafiscal = self.preenche_notafiscal_produto_csosn101()
303+
304+
# Serializa e assina o XML
305+
self.xml = self.serializa_nfe()
306+
self.xml_assinado = self.assina_xml()
307+
308+
# Teste do conteúdo das tags do XML
309+
self.total_e_produto_csosn101_test()
310+
311+
# Testa a validação do XML com os schemas XSD
312+
self.validacao_com_xsd_do_xml_gerado_sem_processar()
313+
314+
315+
if __name__ == '__main__':
316+
unittest.main()

0 commit comments

Comments
 (0)