Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/********************************************************************************/
/* Projeto: Biblioteca ZeusNFe */
/* Biblioteca C# para emissão de Nota Fiscal Eletrônica - NFe e Nota Fiscal de */
/* Consumidor Eletrônica - NFC-e (http://www.nfe.fazenda.gov.br) */
/* */
/* Esta biblioteca é software livre; você pode redistribuí-la e/ou modificá-la */
/* sob os termos da Licença Pública Geral Menor do GNU conforme publicada pela */
/* Free Software Foundation; tanto a versão 2.1 da Licença, ou (a seu critério) */
/* qualquer versão posterior. */
/********************************************************************************/

using DFe.Classes;
using System.Xml.Serialization;

namespace NFe.Classes.Informacoes.Detalhe.Tributacao.Compartilhado.InformacoesIbsCbs.InformacoesCbs
{
/// <summary>
/// UB66a - Grupo de operações em áreas incentivadas (ALC/ZFM) com alíquota zero da CBS.
/// Conforme arts. 451 e 466 da LC 214/2025 (NT 2025.002-RTC), quando fornecedor e
/// destinatário estiverem nessas áreas.
/// </summary>
public class gALCZFMCBS
{
private decimal _pAliqEfetRegCbs;
private decimal _vTribRegCbs;

/// <summary>
/// UB66c - Alíquota efetiva do regime da CBS (em percentual)
/// </summary>
[XmlElement(Order = 1)]
public decimal pAliqEfetRegCBS
{
get => _pAliqEfetRegCbs.Arredondar(4);
set => _pAliqEfetRegCbs = value.Arredondar(4);
}

/// <summary>
/// UB66e - Valor do tributo do regime da CBS
/// </summary>
[XmlElement(Order = 2)]
public decimal vTribRegCBS
{
get => _vTribRegCbs.Arredondar(2);
set => _vTribRegCbs = value.Arredondar(2);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,17 @@ public decimal pCBS
/// </summary>
[XmlElement(Order = 4)]
public gRed gRed { get; set; }

/// <summary>
/// UB67 - Valor da CBS
/// UB66a - Grupo de operações em áreas incentivadas (ALC/ZFM) - CBS alíquota zero
/// </summary>
[XmlElement(Order = 5)]
public gALCZFMCBS gALCZFMCBS { get; set; }

/// <summary>
/// UB67 - Valor da CBS
/// </summary>
[XmlElement(Order = 6)]
public decimal vCBS
{
get => _vCbs.Arredondar(2);
Expand Down
9 changes: 9 additions & 0 deletions NFe.Classes/Informacoes/Identificacao/gCompraGov.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
/* Rua Comendador Francisco josé da Cunha, 111 - Itabaiana - SE - 49500-000 */
/********************************************************************************/

using System.Collections.Generic;
using NFe.Classes.Informacoes.Identificacao.Tipos;

namespace NFe.Classes.Informacoes.Identificacao
Expand All @@ -57,5 +58,13 @@ public decimal pRedutor
/// B34 - Tipo de operação com o ente governamental
/// </summary>
public TpOperGov tpOperGov { get; set; }

/// <summary>
/// BB05 - Chave(s) de acesso do(s) DF-e referenciado(s) anterior(es) em compra
/// governamental (até 99). NT 2025.002-RTC.
/// </summary>
public List<string> refDFeAnt { get; set; }

public bool ShouldSerializerefDFeAnt() => refDFeAnt != null && refDFeAnt.Count > 0;
}
}
8 changes: 8 additions & 0 deletions NFe.Classes/Informacoes/Identificacao/ide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ public bool indIntermedSpecified
get { return indIntermed.HasValue; }
}

/// <summary>
/// B25d - Código indicador do local da operação de fornecimento (modelo 55;
/// vedado NFC-e). NT 2025.002-RTC.
/// </summary>
public string cIndOp { get; set; }

public bool ShouldSerializecIndOp() => !string.IsNullOrEmpty(cIndOp);

/// <summary>
/// B26 - Processo de emissão utilizado com a seguinte codificação:
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Design — Classes RTC (PL_010e_v1.01) no DFe.NET

## Fonte da verdade
Schema `PL_010e_v1.01`:
- `NFe/DFeTiposBasicos_v1.00.xsd` — tipos RTC (`TIS`, `TChDFeRTC`, `gALCZFMCBS`, decimais `TDec*RTC`).
- `NFe/leiauteNFe_v4.00.xsd` — `cIndOp` no produto; `IS`/`IBSCBS` em `imposto`.

## Decisões

### D1 — Mapear 1:1 o XSD, no padrão da lib
Cada grupo vira POCO em `NFe.Classes/Informacoes/...` com propriedades anotadas
(`[XmlElement("<tag>")]`), na **ordem do XSD**, e `ShouldSerialize<Prop>()` para campos
`minOccurs=0` (não emitir tag quando nulo) — mesmo padrão de `gIBSCBS`/`gIBSCBSMono` já existentes.
Decimais usam os tipos/format já convencionados na lib (string formatada por cultura invariante),
espelhando `IBSCBS.cs`.

### D2 — Colocação das classes
- **IS (TIS):** `Informacoes/Detalhe/Tributacao/Compartilhado/IS/IS.cs`, referenciado por
`imposto.cs` como irmão de `IBSCBS` (`det/imposto/IS`). Campos: `CSTIS`, `cClassTribIS?`,
`vBCIS`, `pIS`, `adRemIS?`, `uTrib?`, `qTrib`, `vIS`.
- **gALCZFMCBS:** sob `.../InformacoesIbsCbs/`, referenciado pelo grupo IBS/CBS (CBS).
Campos: `tpALCZFMCBS`, `nProcSUFRAMA`, `pAliqEfetRegCBS`, `vTribRegCBS`.
- **cIndOp:** propriedade no `produto` (`prod`), opcional.
- **refDFeAnt:** no grupo de Compras Governamentais (`gCompraGov`), tipo `TChDFeRTC` (string 44).

### D3 — Escopo limitado ao PL_010e_v1.01 (nível v1.40)
O XSD fornecido **não** contém o monofásico reformulado v1.50 (Ad Rem × Ad Valorem,
`gpBioDiferenca`) nem `ISUFemit`. Estes ficam **fora** — modelá-los exigiria elementos
inexistentes no schema. Serão tratados numa change futura quando o PL v1.50 oficial chegar.

### D4 — Não quebrar serialização atual
Todos os campos novos são `minOccurs=0`. Com `ShouldSerialize*` retornando `false` quando nulo,
notas sem RTC produzem XML idêntico ao atual. Validar via round-trip de serialização.

## Riscos
- ⚠️ Tipos decimais RTC (`TDec1302RTC`, `TDec_0302_04RTC`, `TDec_1104OpRTC`) — usar o mesmo
padrão de formatação já aplicado nas classes IBS/CBS existentes; conferir casas decimais.
- ⚠️ Ordem dos elementos no XML deve seguir o XSD (serialização posicional).
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## Why

A NF-e da Reforma Tributária (RTC — NT 2025.002) introduz grupos e campos novos no leiaute
que a biblioteca **DFe.NET (Zeus)** ainda não modela. O consumidor `dfetech-product-invoice-api`
(PR nfe/dfetech-product-invoice-api#265) precisa dessas classes para emitir os grupos na
conversão XML.

Escopo desta change é limitado ao que **está presente no schema fornecido** — `PL_010e_v1.01`
(`DFeTiposBasicos_v1.00.xsd` + `leiauteNFe_v4.00.xsd`), nível RTC **v1.40**. Ficam **de fora**
(não existem neste XSD): o **monofásico reformulado v1.50** (Ad Rem × Ad Valorem, `gpBioDiferenca`)
e o **`ISUFemit`** — serão tratados quando o pacote v1.50 oficial estiver disponível.

## What Changes

Adicionar ao Zeus as classes/campos abaixo, mapeando 1:1 o XSD do PL_010e_v1.01, com os
atributos de serialização XML no padrão da lib:

### 1. Grupo Imposto Seletivo — `IS` (tipo `TIS`) — ⚠️ JÁ EXISTE no Zeus
Após inspeção, o grupo `IS` **já está implementado** (`Federal/IS.cs`, com `CSTIS`,
`cClassTribIS`, `vBCIS`, `pIS`, `pISEspec`≈adRemIS, `uTrib`, `qTrib`, `vIS`) e **já encaixado** em
`imposto.cs`. **Removido do escopo** desta change — nada a fazer.

### 2. `cIndOp` — código indicador do local da operação de fornecimento
Campo opcional no produto/item (`prod`), modelo 55 (vedado NFC-e).

### 3. `refDFeAnt` — referência a DF-e anterior (Compras Governamentais, BB05)
Campo (`TChDFeRTC`) no grupo de Compras Governamentais.

### 4. `gALCZFMCBS` — ALC/ZFM alíquota zero CBS (UB66a)
Grupo sob `gCBS`: `pAliqEfetRegCBS` + `vTribRegCBS` (o `TALCZFMCBS` do PL_010e tem **só esses 2
campos**; não há `tpALCZFMCBS`/`nProcSUFRAMA` neste XSD).

Cada item inclui: classe(s) de domínio, propriedades com `[XmlElement]`/`ShouldSerialize*` no
padrão Zeus, e o encaixe no agregado pai (imposto/prod/IBSCBS/CompraGov). Sem quebrar a
serialização atual (campos novos são opcionais / `minOccurs=0`).

## Capabilities

### New Capabilities
- `nfe-rtc-schema-classes`: classes de domínio + serialização dos grupos RTC do PL_010e_v1.01
(IS, cIndOp, refDFeAnt, gALCZFMCBS) ausentes no Zeus.

### Modified Capabilities
_Nenhuma (adição de campos opcionais; não altera grupos existentes além do encaixe)._

## Impact

**Código (DFe.NET / NFe.Classes):**
- Novo: `Informacoes/Detalhe/Tributacao/Compartilhado/IS/*` (grupo IS/TIS).
- Novo: `gALCZFMCBS` sob `Informacoes/Detalhe/Tributacao/Compartilhado/InformacoesIbsCbs/`.
- `prod` (produto) — campo `cIndOp`.
- Grupo de Compras Governamentais — campo `refDFeAnt`.
- `imposto.cs` — encaixe do grupo `IS`.

**Compatibilidade:** aditivo; todos os campos são opcionais (`minOccurs=0`) e não aparecem no
XML quando nulos (`ShouldSerialize*`). Não altera a serialização de notas sem RTC.

**Fora de escopo:** monofásico reformulado v1.50, `gpBioDiferenca`, `ISUFemit` (ausentes no
PL_010e_v1.01). Ver nfe/dfetech-product-invoice-api#265 (Fase 3 e tarefa 2.3).

## Rastreabilidade
NT 2025.002-RTC · schema `PL_010e_v1.01` (`DFeTiposBasicos_v1.00.xsd`, `leiauteNFe_v4.00.xsd`).
Consumidor: nfe/dfetech-product-invoice-api#265.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## ADDED Requirements

### Requirement: grupo Imposto Seletivo (IS)
A biblioteca SHALL modelar o grupo `IS` (tipo `TIS`) do schema PL_010e_v1.01 dentro de
`det/imposto`, com os campos na ordem do XSD: `CSTIS`, `cClassTribIS` (opcional), `vBCIS`,
`pIS`, `adRemIS` (opcional), `uTrib` (opcional), `qTrib`, `vIS`. Campos `minOccurs=0` SHALL usar
`ShouldSerialize*` e não emitir a tag quando nulos.

#### Scenario: emissão do grupo IS
- **GIVEN** um item com Imposto Seletivo preenchido (`CSTIS`, `vBCIS`, `pIS`, `qTrib`, `vIS`)
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `det/imposto/IS` com os campos preenchidos, na ordem do XSD
- **AND** `cClassTribIS`/`adRemIS`/`uTrib` só aparecem quando preenchidos

### Requirement: campo cIndOp no produto
O `produto` (`prod`) SHALL expor o campo opcional `cIndOp` (código indicador do local da
operação de fornecimento), emitido apenas quando preenchido.

#### Scenario: cIndOp opcional
- **GIVEN** um produto sem `cIndOp`
- **WHEN** a NF-e é serializada
- **THEN** a tag `cIndOp` não aparece no XML

### Requirement: campo refDFeAnt em Compras Governamentais
O grupo de Compras Governamentais SHALL expor o campo opcional `refDFeAnt` (`TChDFeRTC`),
emitido apenas quando preenchido.

#### Scenario: refDFeAnt opcional
- **GIVEN** uma operação de compra governamental com `refDFeAnt` preenchido
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `refDFeAnt` no grupo de Compras Governamentais

### Requirement: grupo gALCZFMCBS (ALC/ZFM alíquota zero CBS)
A biblioteca SHALL modelar o grupo `gALCZFMCBS` sob IBS/CBS, com `tpALCZFMCBS`, `nProcSUFRAMA`,
`pAliqEfetRegCBS`, `vTribRegCBS`, emitido apenas quando aplicável.

#### Scenario: emissão do gALCZFMCBS
- **GIVEN** uma operação ALC/ZFM com alíquota zero de CBS e `gALCZFMCBS` preenchido
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `gALCZFMCBS` com os campos na ordem do XSD

### Requirement: não regressão da serialização atual
Notas fiscais **sem** os grupos novos SHALL produzir XML idêntico ao anterior a esta change
(nenhuma tag nova emitida quando os campos são nulos).

#### Scenario: nota sem grupos RTC novos
- **GIVEN** uma NF-e sem IS, sem `cIndOp`, sem `refDFeAnt` e sem `gALCZFMCBS`
- **WHEN** a NF-e é serializada
- **THEN** o XML não contém nenhuma dessas tags novas
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Plano — Classes RTC (PL_010e_v1.01) no DFe.NET

> Padrão: propriedades na ordem do XSD (`[XmlElement(Order)]` onde a classe já usa; ordem de
> declaração onde não usa) + `ShouldSerialize*`/`*Specified` para `minOccurs=0`. Decimais via
> `.Arredondar(n)`. Fonte: `PL_010e_v1.01`. Comentários pt-BR.

## 1. Grupo Imposto Seletivo (IS / TIS) — ✅ JÁ EXISTIA
- [x] 1.1 `IS.cs` **já existe** em `NFe.Classes/Informacoes/Detalhe/Tributacao/Federal/IS.cs`
(`CSTIS`, `cClassTribIS`, `vBCIS`, `pIS`, `pISEspec`≈adRemIS, `uTrib`, `qTrib`, `vIS`) e já está
**encaixado** em `imposto.cs` (`public IS IS`). **Nada a implementar** — escopo removido após
inspeção do código. (Consumidor product-invoice#265 Fase 4.1 pode emitir gIS sem mudança no Zeus.)

## 2. cIndOp — ✅ FEITO
- [x] 2.1 `cIndOp` adicionado ao grupo **`ide`** (`ide.cs`, B25d — entre `indIntermed` e `procEmi`),
opcional, com `ShouldSerializecIndOp()`. (Correção de escopo: é do `ide`, não do `prod`.)

## 3. refDFeAnt — ✅ FEITO
- [x] 3.1 `refDFeAnt` (`List<string>`, até 99) adicionado ao `gCompraGov.cs` (tipo XSD
`TCompraGovReduzido`: tpEnteGov/pRedutor/tpOperGov/**refDFeAnt**), com `ShouldSerializerefDFeAnt()`.

## 4. gALCZFMCBS — ✅ FEITO
- [x] 4.1 `gALCZFMCBS.cs` criado com **`pAliqEfetRegCBS`** + **`vTribRegCBS`** (o `TALCZFMCBS` do
PL_010e tem só esses 2 campos — correção de escopo; não há tpALCZFMCBS/nProcSUFRAMA neste XSD).
- [x] 4.2 Encaixado no `gCBS.cs` (Order 5, entre `gRed` e `vCBS`; `vCBS` renumerado para Order 6).

## 5. Testes / validação
- [x] 5.3 Build do `NFe.Classes` (Release) sem erros.
- [ ] 5.1/5.2 Round-trip de serialização (nota sem grupos = XML idêntico; com grupos = ordem correta)
— recomendado adicionar ao projeto de testes do Zeus (follow-up).

## 6. OpenSpec
- [x] 6.1 `openspec validate add-nt2025-002-rtc-schema-classes --strict` sem erros.
6 changes: 6 additions & 0 deletions openspec/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
schema: spec-driven

context: |
Language: Portuguese (pt-BR)
Biblioteca .NET (Zeus / DFe.NET) de classes e serialização XML da NF-e.
Classes de domínio mapeiam 1:1 o schema XSD oficial (PL/NT da SEFAZ).
53 changes: 53 additions & 0 deletions openspec/specs/nfe-rtc-schema-classes/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# nfe-rtc-schema-classes Specification

## Purpose
TBD - created by archiving change add-nt2025-002-rtc-schema-classes. Update Purpose after archive.
## Requirements
### Requirement: grupo Imposto Seletivo (IS)
A biblioteca SHALL modelar o grupo `IS` (tipo `TIS`) do schema PL_010e_v1.01 dentro de
`det/imposto`, com os campos na ordem do XSD: `CSTIS`, `cClassTribIS` (opcional), `vBCIS`,
`pIS`, `adRemIS` (opcional), `uTrib` (opcional), `qTrib`, `vIS`. Campos `minOccurs=0` SHALL usar
`ShouldSerialize*` e não emitir a tag quando nulos.

#### Scenario: emissão do grupo IS
- **GIVEN** um item com Imposto Seletivo preenchido (`CSTIS`, `vBCIS`, `pIS`, `qTrib`, `vIS`)
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `det/imposto/IS` com os campos preenchidos, na ordem do XSD
- **AND** `cClassTribIS`/`adRemIS`/`uTrib` só aparecem quando preenchidos

### Requirement: campo cIndOp no produto
O `produto` (`prod`) SHALL expor o campo opcional `cIndOp` (código indicador do local da
operação de fornecimento), emitido apenas quando preenchido.

#### Scenario: cIndOp opcional
- **GIVEN** um produto sem `cIndOp`
- **WHEN** a NF-e é serializada
- **THEN** a tag `cIndOp` não aparece no XML

### Requirement: campo refDFeAnt em Compras Governamentais
O grupo de Compras Governamentais SHALL expor o campo opcional `refDFeAnt` (`TChDFeRTC`),
emitido apenas quando preenchido.

#### Scenario: refDFeAnt opcional
- **GIVEN** uma operação de compra governamental com `refDFeAnt` preenchido
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `refDFeAnt` no grupo de Compras Governamentais

### Requirement: grupo gALCZFMCBS (ALC/ZFM alíquota zero CBS)
A biblioteca SHALL modelar o grupo `gALCZFMCBS` sob IBS/CBS, com `tpALCZFMCBS`, `nProcSUFRAMA`,
`pAliqEfetRegCBS`, `vTribRegCBS`, emitido apenas quando aplicável.

#### Scenario: emissão do gALCZFMCBS
- **GIVEN** uma operação ALC/ZFM com alíquota zero de CBS e `gALCZFMCBS` preenchido
- **WHEN** a NF-e é serializada
- **THEN** o XML contém `gALCZFMCBS` com os campos na ordem do XSD

### Requirement: não regressão da serialização atual
Notas fiscais **sem** os grupos novos SHALL produzir XML idêntico ao anterior a esta change
(nenhuma tag nova emitida quando os campos são nulos).

#### Scenario: nota sem grupos RTC novos
- **GIVEN** uma NF-e sem IS, sem `cIndOp`, sem `refDFeAnt` e sem `gALCZFMCBS`
- **WHEN** a NF-e é serializada
- **THEN** o XML não contém nenhuma dessas tags novas