Skip to content

Commit 7c830b1

Browse files
felps-devclaude
andcommitted
feat: Add Reforma Tributaria IBS/CBS/IS support (EC 132/2023)
Add core XML infrastructure for Brazil's dual VAT system (IVA Dual): - CST enumerations for IBS, CBS and IS in flags.py - Product-level and invoice-level entity fields in notafiscal.py - XML serialization (impostoMisto group) in serializacao.py - Totals accumulation and vNF formula updated - 5 test cases covering all serialization scenarios - Documentation in docs/reforma_tributaria.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent aecf36f commit 7c830b1

8 files changed

Lines changed: 1043 additions & 30 deletions

File tree

docs/reforma_tributaria.md

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# Reforma Tributaria - IBS/CBS/IS (EC 132/2023)
2+
3+
Suporte ao IVA Dual brasileiro introduzido pela Emenda Constitucional 132/2023.
4+
5+
## Contexto
6+
7+
A Reforma Tributaria brasileira substitui gradualmente cinco tributos por tres novos impostos:
8+
9+
| Imposto | Tipo | Substitui | Competencia |
10+
|---------|------|-----------|-------------|
11+
| **CBS** (Contribuicao sobre Bens e Servicos) | Federal | PIS, COFINS | Uniao |
12+
| **IBS** (Imposto sobre Bens e Servicos) | Subnacional | ICMS, ISS | Estados + Municipios |
13+
| **IS** (Imposto Seletivo) | Extrafiscal | IPI (parcial) | Uniao |
14+
15+
### Cronograma de transicao
16+
17+
- **2026**: Fase de testes (aliquotas reduzidas CBS 0.9%, IBS 0.1%)
18+
- **2027-2028**: CBS integral, IBS em transicao
19+
- **2029-2032**: Reducao gradual de ICMS/ISS
20+
- **2033**: Extincao completa de ICMS/ISS
21+
22+
Durante a transicao, os impostos legados (ICMS, PIS, COFINS) **coexistem** com os novos (IBS, CBS, IS) na mesma NF-e.
23+
24+
## Escopo da implementacao
25+
26+
A implementacao atual cobre a **infraestrutura XML basica**:
27+
28+
- Campos de entidade (produto e nota fiscal)
29+
- Serializacao XML (grupo `<impostoMisto>` contendo `<CBS>`, `<IBS>`, `<IS>`)
30+
- Acumulacao de totais
31+
- CSTs (Codigos de Situacao Tributaria) para IBS, CBS e IS
32+
33+
**Nao inclui** (ainda): Split Payment, cashback, helpers de calculo da transicao, validacao XSD (schemas oficiais ainda nao publicados pela SEFAZ).
34+
35+
## CSTs disponiveis
36+
37+
### IBS e CBS (compartilham a mesma tabela)
38+
39+
```python
40+
from pynfe.utils.flags import IBS_CBS_TIPOS_TRIBUTACAO
41+
```
42+
43+
| CST | Descricao |
44+
|-----|-----------|
45+
| 01 | Tributada Integralmente |
46+
| 02 | Tributada com Reducao (Cesta Basica/Saude) |
47+
| 03 | Isencao |
48+
| 04 | Imunidade |
49+
| 05 | Suspensao |
50+
| 51 | Diferimento |
51+
| 70 | Monofasica (Combustiveis) |
52+
53+
### IS (Imposto Seletivo)
54+
55+
```python
56+
from pynfe.utils.flags import IS_TIPOS_TRIBUTACAO
57+
```
58+
59+
| CST | Descricao |
60+
|-----|-----------|
61+
| 01 | Tributada Integralmente |
62+
| 02 | Tributada com Reducao |
63+
| 03 | Isencao |
64+
| 04 | Imunidade |
65+
| 05 | Suspensao |
66+
67+
## Como usar
68+
69+
### Exemplo basico: produto com CBS + IBS + IS
70+
71+
```python
72+
from decimal import Decimal
73+
74+
nota_fiscal.adicionar_produto_servico(
75+
# ... campos obrigatorios do produto (codigo, descricao, ncm, cfop, etc.)
76+
codigo="001",
77+
descricao="Produto exemplo",
78+
ncm="99999999",
79+
ean="SEM GTIN",
80+
cfop="5102",
81+
unidade_comercial="UN",
82+
quantidade_comercial=Decimal("10"),
83+
valor_unitario_comercial=Decimal("100.00"),
84+
valor_total_bruto=Decimal("1000.00"),
85+
unidade_tributavel="UN",
86+
quantidade_tributavel=Decimal("10"),
87+
valor_unitario_tributavel=Decimal("100.00"),
88+
ean_tributavel="SEM GTIN",
89+
ind_total=1,
90+
91+
# ... impostos legados (ICMS, PIS, COFINS) continuam obrigatorios
92+
icms_modalidade="00",
93+
icms_origem=0,
94+
icms_csosn="",
95+
pis_modalidade="99",
96+
cofins_modalidade="99",
97+
pis_valor=Decimal("0.00"),
98+
cofins_valor=Decimal("0.00"),
99+
100+
# CBS - Contribuicao sobre Bens e Servicos (Federal)
101+
cbs_situacao_tributaria="01", # CST 01 = Tributada integralmente
102+
cbs_valor_base_calculo=Decimal("1000.00"),
103+
cbs_aliquota=Decimal("8.8000"), # 4 casas decimais
104+
cbs_valor=Decimal("88.00"),
105+
106+
# IBS - Imposto sobre Bens e Servicos (Estadual/Municipal)
107+
ibs_situacao_tributaria="01",
108+
ibs_valor_base_calculo=Decimal("1000.00"),
109+
ibs_aliquota=Decimal("17.7000"),
110+
ibs_valor=Decimal("177.00"),
111+
ibs_codigo_municipio_destino="4118402", # Codigo IBGE do municipio destino
112+
113+
# IS - Imposto Seletivo (opcional, apenas para produtos sujeitos)
114+
is_situacao_tributaria="01",
115+
is_valor_base_calculo=Decimal("1000.00"),
116+
is_aliquota=Decimal("1.0000"),
117+
is_valor=Decimal("10.00"),
118+
)
119+
```
120+
121+
### Exemplo: produto isento (CBS + IBS com CST 03)
122+
123+
```python
124+
nota_fiscal.adicionar_produto_servico(
125+
# ... campos do produto ...
126+
127+
# CBS isenta - apenas o CST, sem valores
128+
cbs_situacao_tributaria="03",
129+
130+
# IBS isenta
131+
ibs_situacao_tributaria="03",
132+
133+
# IS nao se aplica (nao informar = nao serializado)
134+
)
135+
```
136+
137+
### Exemplo: sem reforma tributaria (compatibilidade retroativa)
138+
139+
Se nenhum campo de IBS/CBS/IS for informado, o grupo `<impostoMisto>` **nao e emitido** no XML. Isso garante compatibilidade total com NF-e que nao precisam dos novos impostos.
140+
141+
```python
142+
# Produto sem campos de reforma tributaria = XML identico ao anterior
143+
nota_fiscal.adicionar_produto_servico(
144+
# ... apenas campos legados (ICMS, PIS, COFINS) ...
145+
)
146+
```
147+
148+
## Campos disponiveis
149+
150+
### Campos do produto (`adicionar_produto_servico`)
151+
152+
| Campo | Tipo | Descricao |
153+
|-------|------|-----------|
154+
| `cbs_situacao_tributaria` | `str` | CST da CBS (ex: "01", "03") |
155+
| `cbs_valor_base_calculo` | `Decimal` | Base de calculo da CBS |
156+
| `cbs_aliquota` | `Decimal` | Aliquota CBS (4 casas decimais) |
157+
| `cbs_valor` | `Decimal` | Valor da CBS |
158+
| `ibs_situacao_tributaria` | `str` | CST do IBS (ex: "01", "03") |
159+
| `ibs_valor_base_calculo` | `Decimal` | Base de calculo do IBS |
160+
| `ibs_aliquota` | `Decimal` | Aliquota IBS (4 casas decimais) |
161+
| `ibs_valor` | `Decimal` | Valor do IBS |
162+
| `ibs_codigo_municipio_destino` | `str` | Codigo IBGE do municipio destino |
163+
| `is_situacao_tributaria` | `str` | CST do IS (ex: "01", "02") |
164+
| `is_valor_base_calculo` | `Decimal` | Base de calculo do IS |
165+
| `is_aliquota` | `Decimal` | Aliquota IS (4 casas decimais) |
166+
| `is_valor` | `Decimal` | Valor do IS |
167+
168+
### Totais da nota fiscal (acumulados automaticamente)
169+
170+
| Campo | Descricao |
171+
|-------|-----------|
172+
| `totais_cbs` | Soma de `cbs_valor` de todos os produtos |
173+
| `totais_ibs` | Soma de `ibs_valor` de todos os produtos |
174+
| `totais_is` | Soma de `is_valor` de todos os produtos |
175+
176+
Os totais sao acumulados automaticamente ao chamar `adicionar_produto_servico()`. Os valores de IBS, CBS e IS tambem sao somados ao `totais_icms_total_nota` (vNF), pois sao impostos "por fora".
177+
178+
## Estrutura XML gerada
179+
180+
O grupo `<impostoMisto>` e adicionado dentro de `<imposto>`, apos `<COFINS>` e antes de `<impostoDevol>`:
181+
182+
```xml
183+
<det nItem="1">
184+
<prod>...</prod>
185+
<imposto>
186+
<ICMS>...</ICMS>
187+
<PIS>...</PIS>
188+
<COFINS>...</COFINS>
189+
<impostoMisto>
190+
<CBS>
191+
<CST>01</CST>
192+
<vBC>1000.00</vBC>
193+
<pCBS>8.8000</pCBS>
194+
<vCBS>88.00</vCBS>
195+
</CBS>
196+
<IBS>
197+
<CST>01</CST>
198+
<vBC>1000.00</vBC>
199+
<pIBS>17.7000</pIBS>
200+
<vIBS>177.00</vIBS>
201+
<cMunDest>4118402</cMunDest>
202+
</IBS>
203+
<IS>
204+
<CST>01</CST>
205+
<vBC>1000.00</vBC>
206+
<pIS>1.0000</pIS>
207+
<vIS>10.00</vIS>
208+
</IS>
209+
</impostoMisto>
210+
</imposto>
211+
</det>
212+
```
213+
214+
Os totais aparecem dentro de `<ICMSTot>`:
215+
216+
```xml
217+
<total>
218+
<ICMSTot>
219+
<!-- ... totais existentes ... -->
220+
<vNF>1275.00</vNF>
221+
<vCBS>88.00</vCBS>
222+
<vIBS>177.00</vIBS>
223+
<vIS>10.00</vIS>
224+
</ICMSTot>
225+
</total>
226+
```
227+
228+
## Regras de serializacao
229+
230+
- **CSTs 01, 02, 51**: Serializam `vBC`, aliquota e valor (campos completos)
231+
- **CSTs 03, 04, 05, 70**: Serializam apenas o `CST` (sem valores)
232+
- **IS CSTs 01, 02**: Serializam campos completos; demais apenas `CST`
233+
- **`cMunDest`** (IBS): Serializado apenas quando informado
234+
- **Totais**: Emitidos apenas quando o valor e maior que zero
235+
- **`impostoMisto`**: Omitido completamente se nenhum dos tres impostos for informado
236+
237+
## Notas importantes
238+
239+
- Os nomes das tags XML (`impostoMisto`, `CBS`, `IBS`, `IS`) sao baseados na especificacao preliminar. Podem ser renomeados quando a SEFAZ publicar a Nota Tecnica oficial.
240+
- A validacao XSD e ignorada para os novos grupos, pois os schemas oficiais ainda nao existem.
241+
- Durante a fase de transicao (2026-2032), os impostos legados e os novos coexistem no mesmo XML.
242+
- O calculo dos valores (base de calculo, aliquota, valor) deve ser feito pela aplicacao consumidora. PyNFe apenas serializa os valores informados.

pynfe/entidades/notafiscal.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ class NotaFiscal(Entidade):
302302
# - Valor total do ICMS monofásico sujeito a retenção
303303
totais_icms_v_icms_mono_reten = Decimal()
304304

305+
# Reforma Tributaria - Totais IVA Dual
306+
totais_cbs = Decimal()
307+
totais_ibs = Decimal()
308+
totais_is = Decimal()
309+
305310
# Transporte
306311
# - Modalidade do Frete (obrigatorio - seleciona de lista) - MODALIDADES_FRETE
307312
# 0=Contratação do Frete por conta do Remetente (CIF);
@@ -464,6 +469,11 @@ def adicionar_produto_servico(self, **kwargs):
464469
self.totais_icms_q_bc_mono_ret += obj.icms_q_bc_mono_ret
465470
self.totais_icms_v_icms_mono_ret += obj.icms_v_icms_mono_ret
466471

472+
# Reforma Tributaria - IVA Dual
473+
self.totais_cbs += obj.cbs_valor
474+
self.totais_ibs += obj.ibs_valor
475+
self.totais_is += obj.is_valor
476+
467477
# TODO calcular impostos aproximados
468478
# self.totais_tributos_aproximado += obj.tributos
469479

@@ -477,6 +487,9 @@ def adicionar_produto_servico(self, **kwargs):
477487
+ obj.imposto_importacao_valor
478488
+ obj.ipi_valor_ipi
479489
+ obj.ipi_valor_ipi_dev
490+
+ obj.ibs_valor
491+
+ obj.cbs_valor
492+
+ obj.is_valor
480493
- obj.desconto
481494
- obj.icms_desonerado
482495
)
@@ -1002,6 +1015,29 @@ class NotaFiscalProduto(Entidade):
10021015
# - Valor imposto de importacao
10031016
imposto_importacao_valor = Decimal()
10041017

1018+
# =============================================
1019+
# Reforma Tributaria - IVA Dual (EC 132/2023)
1020+
# =============================================
1021+
1022+
# CBS (Contribuicao sobre Bens e Servicos) - Federal
1023+
cbs_situacao_tributaria = str()
1024+
cbs_valor_base_calculo = Decimal()
1025+
cbs_aliquota = Decimal()
1026+
cbs_valor = Decimal()
1027+
1028+
# IBS (Imposto sobre Bens e Servicos) - Estadual/Municipal
1029+
ibs_situacao_tributaria = str()
1030+
ibs_valor_base_calculo = Decimal()
1031+
ibs_aliquota = Decimal()
1032+
ibs_valor = Decimal()
1033+
ibs_codigo_municipio_destino = str() # cMunDest - IBGE code
1034+
1035+
# IS (Imposto Seletivo) - Federal
1036+
is_situacao_tributaria = str()
1037+
is_valor_base_calculo = Decimal()
1038+
is_aliquota = Decimal()
1039+
is_valor = Decimal()
1040+
10051041
# - Informacoes Adicionais
10061042
# - Texto livre de informacoes adicionais
10071043
informacoes_adicionais = str()

pynfe/entidades/notafiscal_map.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
# Source Map: `notafiscal.py` (1253 lines)
1+
# Source Map: `notafiscal.py` (1280 lines)
22

33
Entity models for NF-e/NFC-e invoices and related objects (products, taxes, payments, transport, etc.).
44

55
## Classes Overview
66

77
| Class | Lines | Purpose |
88
|-------|-------|---------|
9-
| `NotaFiscal` | 14-572 | Main invoice entity |
10-
| `NotaFiscalReferenciada` | 575-603 | Referenced invoice |
11-
| `NotaFiscalProduto` | 606-1019 | Product/service item with all tax fields |
12-
| `NotaFiscalDeclaracaoImportacao` | 1022-1067 | Import declaration |
13-
| `NotaFiscalDeclaracaoImportacaoAdicao` | 1070-1082 | Import declaration addition |
14-
| `NotaFiscalTransporteVolume` | 1084-1113 | Transport volume |
15-
| `NotaFiscalTransporteVolumeLacre` | 1116-1118 | Volume seal |
16-
| `NotaFiscalCobrancaDuplicata` | 1121-1129 | Billing duplicate |
17-
| `NotaFiscalObservacaoContribuinte` | 1132-1137 | Taxpayer note |
18-
| `NotaFiscalProcessoReferenciado` | 1140-1150 | Referenced process |
19-
| `NotaFiscalEntregaRetirada` | 1153-1190 | Delivery/withdrawal address |
20-
| `NotaFiscalServico` | 1192-1220 | NFS-e service invoice |
21-
| `NotaFiscalResponsavelTecnico` | 1223-1229 | Technical responsible (NT2018/003) |
22-
| `AutorizadosBaixarXML` | 1232-1233 | Authorized XML downloaders |
23-
| `NotaFiscalPagamentos` | 1236-1253 | Payment details |
9+
| `NotaFiscal` | 14-580 | Main invoice entity |
10+
| `NotaFiscalReferenciada` | 583-611 | Referenced invoice |
11+
| `NotaFiscalProduto` | 614-1046 | Product/service item with all tax fields |
12+
| `NotaFiscalDeclaracaoImportacao` | 1049-1094 | Import declaration |
13+
| `NotaFiscalDeclaracaoImportacaoAdicao` | 1097-1109 | Import declaration addition |
14+
| `NotaFiscalTransporteVolume` | 1111-1140 | Transport volume |
15+
| `NotaFiscalTransporteVolumeLacre` | 1143-1145 | Volume seal |
16+
| `NotaFiscalCobrancaDuplicata` | 1148-1156 | Billing duplicate |
17+
| `NotaFiscalObservacaoContribuinte` | 1159-1164 | Taxpayer note |
18+
| `NotaFiscalProcessoReferenciado` | 1167-1177 | Referenced process |
19+
| `NotaFiscalEntregaRetirada` | 1180-1217 | Delivery/withdrawal address |
20+
| `NotaFiscalServico` | 1219-1247 | NFS-e service invoice |
21+
| `NotaFiscalResponsavelTecnico` | 1250-1256 | Technical responsible (NT2018/003) |
22+
| `AutorizadosBaixarXML` | 1259-1260 | Authorized XML downloaders |
23+
| `NotaFiscalPagamentos` | 1263-1280 | Payment details |
2424

2525
---
2626

@@ -34,7 +34,8 @@ Entity models for NF-e/NFC-e invoices and related objects (products, taxes, paym
3434
| Read-only fields | 128-144 | digest_value, valor_total_nota, valor_icms_nota, valor_icms_st_nota, protocolo, data |
3535
| Relationships | 146-173 | notas_fiscais_referenciadas, emitente, destinatario_remetente, entrega, retirada, autorizados_baixar_xml, produtos_e_servicos |
3636
| ICMS totals | 175-303 | totais_icms_base_calculo, totais_icms_total, totais_icms_desonerado, totais_icms_st_*, totais_icms_total_*, totais_fcp_*, totais_icms_inter_*, totais_icms_*_mono_* |
37-
| Transport | 305-361 | transporte_modalidade_frete, transporte_transportadora, transporte_retencao_icms_*, transporte_veiculo_*, transporte_reboque_*, transporte_volumes |
37+
| Reforma Tributaria totals | 305-311 | totais_cbs, totais_ibs, totais_is — IVA Dual totals (EC 132/2023) |
38+
| Transport | 313-369 | transporte_modalidade_frete, transporte_transportadora, transporte_retencao_icms_*, transporte_veiculo_*, transporte_reboque_*, transporte_volumes |
3839
| Billing | 363-378 | fatura_numero, fatura_valor_original, fatura_valor_desconto, fatura_valor_liquido, duplicatas |
3940
| Additional info | 380-397 | informacoes_adicionais_*, observacoes_contribuinte, processos_referenciados, pagamentos, valor_troco |
4041

@@ -70,7 +71,8 @@ Entity models for NF-e/NFC-e invoices and related objects (products, taxes, paym
7071
| COFINS fields | 925-969 | cofins_modalidade, cofins_valor_base_calculo, cofins_aliquota_percentual, cofins_aliquota_reais, cofins_valor, cofins_st_* |
7172
| ISSQN fields | 971-990 | issqn_valor_base_calculo, issqn_aliquota, issqn_lista_servico, issqn_uf, issqn_municipio, issqn_valor |
7273
| Import tax fields | 992-1003 | imposto_importacao_valor_base_calculo, imposto_importacao_valor_despesas_aduaneiras, imposto_importacao_valor_iof, imposto_importacao_valor |
73-
| Additional info | 1005-1019 | informacoes_adicionais, declaracoes_importacao |
74+
| Reforma Tributaria fields | 1005-1028 | cbs_situacao_tributaria, cbs_valor_base_calculo, cbs_aliquota, cbs_valor, ibs_situacao_tributaria, ibs_valor_base_calculo, ibs_aliquota, ibs_valor, ibs_codigo_municipio_destino, is_situacao_tributaria, is_valor_base_calculo, is_aliquota, is_valor |
75+
| Additional info | 1030-1046 | informacoes_adicionais, declaracoes_importacao |
7476

7577
---
7678

0 commit comments

Comments
 (0)