Skip to content

feat(danfe): leiaute da Reforma Tributária no DANFE da NF-e (NT 2026.010) - #55

Merged
rhfranzoni merged 5 commits into
mainfrom
feat/nt-2026-010-danfe-rtc
Oct 27, 2026
Merged

rhfranzoni merged 5 commits into
mainfrom
feat/nt-2026-010-danfe-rtc

Conversation

@rhfranzoni

@rhfranzoni rhfranzoni commented Oct 20, 2026 •

Copy link
Copy Markdown

Resumo

Leiaute do DANFE da NF-e (modelo 55) para a Reforma Tributária, conforme a NT 2026.010 v1.00 (produção em 01/12/2026). O leiaute é escolhido pelo consumidor: DanfeViewModel.UsarLeiauteReformaTributaria (padrão false, leiaute anterior). A biblioteca não tem regra de vigência. A data da NT e a condição de presença de IBS/CBS/IS ficam no nfe/dfetech-product-invoice-api#832 (DanfeTaxReformLayout).

Item da NT O que muda
4.1 Bloco "Total do IBS / CBS / IS" logo após o "Cálculo do Imposto": vCBS (W56), vIBSUF (W41), vIBSMun (W46) e vIS (W33). A linha da monofasia (vIBSMono, vCBSMono, vIBSMonoReten, vCBSMonoReten) só sai com valor maior que zero (o emissor manda o gMono zerado)
4.2 Código do Regime Tributário (CRT, C21) no quadro do emitente, com a descrição ("3 - REGIME NORMAL"). O "Tipo de Regime de Apuração do IBS e da CBS" não tem tag publicada, então o campo reservado não é impresso (4.4)
4.3 Quadro de produtos no modelo de referência: NCM e cClassTrib na descrição, CST e CFOP na mesma célula, e colunas Bases de cálculo / Alíquotas / Valor dos tributos, com dois tributos informados por linha, na ordem do modelo (ICMS, CBS, IBS UF, IPI, IBS Município, IS); sem ICMS ST por item, como no modelo da NT. Com gRed, a alíquota impressa é a efetiva (pAliqEfet)
4.4 Nada é inferido: tributo ausente no XML não ganha linha, e a linha da monofasia depende do gMono

Leitura do XML

ProcNFe passa a ler imposto/IBSCBS (CST, cClassTrib, gIBSCBS com gIBSUF/gIBSMun/gCBS e gRed), imposto/IS, total/IBSCBSTot (gIBS, gCBS, gMono) e total/ISTot, com os campos impressos e os de identificação/totalização (ver summaries).

Fora do escopo

  • QR Code no DANFE modelo 55 (4.5): a NT diz que a regra será publicada em alteração futura.
  • Conteúdo do "Tipo de Regime de Apuração do IBS e da CBS": sem tag publicada.

Validação

  • Unidade, neste repositório: DanfeSharp.Test/ReformaTributariaTests.cs com 19 testes:

    • FormatarCrt (1/2/3/4, com espaços, desconhecido e nulo);
    • pares de tributos na ordem da NT e item sem ICMS;
    • PossuiIcms por Csosn e descrição com e sem NCM/cClassTrib;
    • PossuiMonofasia zerada, só por retenção e sem retenção;
    • gRed por grupo e item só com IS;
    • IS/ISTot e base do IPI lidos de XML.

    Execução local (net461/MSTest v1, sem CI): nuget restore + dotnet build + vstest.console. Resultado: 19/19 dos novos e 147 aprovados no total. As 21 falhas que já existiam são tratadas no fix: destrava 21 testes pre-existentes do DanfeSharp.Test #44. Follow-up de CI: DanfeSharp.Test: projeto SDK-style e CI para os testes rodarem em PR #56.

  • Integração e paridade, no product-invoice#832: retrato e paisagem, alíquota efetiva, monofasia, IS, caminho do agregado, nota sem IBS/CBS no leiaute anterior e colunas do item na mesma linha (Y via TextExtractor). As larguras do quadro do emitente foram conferidas manualmente no PDF com CRT 2.

Review — rodada 2 (2b5c29b)

Achado Tratamento
Vigência dentro da lib (calendário, fase 0) UsarLeiauteReformaTributaria preenchido pelo consumidor; vigência no fuso da UF no product-invoice
DanfeViewModel.cs acima de 500 linhas 497 linhas: a regra saiu
DanfeViewModelCreator.cs +60 linhas ReformaTributariaViewModelMapper (internal static); no creator ficam só as chamadas
Gatilho exige IBS/CBS/IS e a NT não exige Condição no consumidor; pergunta para fiscal/produto na nfe/dfetech-product-invoice-api#760
Sem teste no repositório 19 testes em DanfeSharp.Test; CI no follow-up #56
IS/ISTot sem fixture Teste com XML, mais item só com IS
Linhas* no ProdutoViewModel Blocos/LinhasTributosReformaTributaria
Ramos sem teste (Csosn, descrição, gRed por grupo, IPI) Testes de unidade
ICMS ST só nas bases Removido (modelo da NT não tem ST por item)
Segundo modelo de totais (TributosIbsCbsViewModel) Não consolidado: no Tipo 2, instância não nula liga o bloco daquele leiaute. Nomes alinhados (ValorIbsUF, ValorIS, AliquotaIS)
FormatarCrt só com "3"; fallback sem Trim DataRows 1–4/desconhecido/nulo; crt?.Trim()
CFOP com separador de milhar Formatar("0") no leiaute novo (anterior mantém "N0")
Alias g, banners // ----, doc "uma linha por tributo", summaries do ProcNFe, campo estático, linha em branco Corrigidos
Posição/largura sem checagem automática Colunas do item: teste por coordenada no #832. Emitente: conferência manual

Merge

⚠️ Mergear com merge commit (como #53/#54): o nfe/dfetech-product-invoice-api#832 aponta o submódulo para 2b5c29b, e squash/rebase mudaria o SHA. Se for necessário squash, atualizar o ponteiro no #832 antes do merge de lá.

Relacionados

🤖 Generated with Claude Code

…010)

NT 2026.010 v1.00 (DANFE Reforma Tributária, produção 01/12/2026), aplicado só à nota que tem
IBS/CBS/IS — a nota sem esses grupos continua no leiaute anterior (DanfeViewModel.ExibirReformaTributaria).

- 4.1: bloco "Total do IBS / CBS / IS" logo após o "Cálculo do Imposto" (vCBS, vIBSUF, vIBSMun, vIS);
  linha da monofasia (vIBSMono, vCBSMono, vIBSMonoReten, vCBSMonoReten) só com o grupo gMono.
- 4.2: Código do Regime Tributário (CRT com descrição) no quadro do emitente. O "Tipo de Regime de
  Apuração do IBS e da CBS" não tem tag publicada: campo reservado, não impresso (4.4).
- 4.3: quadro de produtos no modelo de referência — NCM e cClassTrib na descrição, CST e CFOP numa
  célula, e colunas de bases, alíquotas e valores com uma linha por tributo informado (ICMS, ICMS ST,
  IBS UF, IBS Município, CBS, IS, IPI). Alíquota efetiva (gRed/pAliqEfet) quando há redução.
- Leitura do XML: IBSCBS/IS do item e IBSCBSTot/ISTot do total no ProcNFe (só os campos impressos).

Refs nfe/dfetech-product-invoice-api#760

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rhfranzoni

Copy link
Copy Markdown
Author

Consumido por nfe/dfetech-product-invoice-api#832 (issue nfe/dfetech-product-invoice-api#760).

… 2026.010)

- Leiaute novo só para dhEmi a partir de 01/12/2026 (produção da NT): nota anterior segue no leiaute em
  que foi emitida, também quando o DANFE é regerado, e o deploy não antecipa o leiaute.
- Monofasia pelo VALOR (> 0), não pela presença do gMono: o emissor manda gMono zerado em toda nota com
  IBS/CBS. Campos "por Retenção" só com retenção (4.4).
- Linha de ICMS só quando o item tem o grupo (Nota de Crédito/Débito do RTC pode vir só com IBS/CBS).
- Tributos aos pares por linha, na ordem do modelo da NT (ICMS/CBS, IBS UF/IPI, IBS MUN/IS), com as
  colunas de tributos mais largas: o item não triplica de altura (item 3 da NT).
- Quadro do emitente com larguras próprias para os 4 campos; CRT 2 abreviado ("EXC. SUBLIMITE").

Refs nfe/dfetech-product-invoice-api#760

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@john182 john182 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revisão de código (Gate 8, 10 perspectivas) — resultado: REJEITADO

O que o PR faz: leiaute do DANFE da NF-e para a Reforma Tributária (NT 2026.010): bloco "Total do IBS/CBS/IS", CRT no quadro do emitente, quadro de produtos com cClassTrib e colunas de bases/alíquotas/valores por tributo, e leitura de IBSCBS/IS/IBSCBSTot/ISTot no ProcNFe. Revisado junto com nfe/dfetech-product-invoice-api#832 (mesma entrega, issue #760).

Por que rejeitado: bloqueio mecânico de tamanho de arquivo (regra categórica >500 linhas; a correção é extração cirúrgica do código novo, sem mudar comportamento):

  • Modelo/DanfeViewModel.cs passou de 489 para 506 linhas por causa deste diff.
  • Modelo/DanfeViewModelCreator.cs (666 → 726) recebeu 60 linhas de lógica nova.

Não há bloqueio comportamental. O ponto de negócio mais relevante é o ALTO do gatilho do leiaute (linha 495): a NT 2026.010 não condiciona o leiaute novo à presença de IBS/CBS/IS — precisa de confirmação de fiscal/produto.

Requisitos (NT 2026.010 v1.00, lida em docs/notas-tecnicas do product-invoice): 4.1, 4.2 e 4.3 entregues; 4.4 respeitado (nada inferido); 4.5 (QR Code) corretamente fora do escopo.

Testes: o PR não traz teste no próprio repositório. dotnet test DanfeSharp.sln termina com EXIT=0 sem executar teste nenhum (DanfeSharp.Test é net461/MSTest). A cobertura vem só de DanfeServiceTaxReformTests do product-invoice#832 (3378/3378 lá), e o product-invoice exclui lib/** da cobertura. Ver o ALTO de testabilidade abaixo.

Perspectivas: Arquitetura ❌ (2 BLOQUEANTE, 2 MÉDIO) · Segurança ✅ · Performance ✅ · Testabilidade ✅ (2 ALTO, 2 MÉDIO, 2 BAIXO) · Observabilidade ✅ · Resiliência ✅ · Conformidade ✅ (8 BAIXO) · Nulidade ✅ · Código Órfão ✅ · Completude ✅ (1 ALTO, 1 BAIXO).

Merge: o product-invoice#832 aponta o submódulo para fd1847cd. A main (8d93674) é ancestral dele: mergear este PR com merge commit (como #53/#54) preserva o SHA; squash/rebase exige atualizar o ponteiro no #832 antes do merge de lá.

Fora do diff (pré-existente, só registro): XmlSerializer.Deserialize(TextReader) em DanfeViewModelCreator.cs:65/84/170/190 (CA5369, DTD); laço de paginação em Danfe.cs:153-194 sem saída se uma única linha for mais alta que a página.

Achados fora das linhas do diff

  • [ALTO][Testabilidade] Nenhum teste no próprio repositório e a cobertura do DanfeSharp não é medida em lugar nenhum (DanfeSharp.Test/DanfeSharp.Test.csproj:62): O PR não toca DanfeSharp.Test. O DanfeSharp não tem CI e dotnet test DanfeSharp.sln não executa teste; no product-invoice, pr.yml:226 (-**/lib/**) e o coverage.runsettings excluem a lib. Um PR futuro que quebre o leiaute RTC passa aqui sem sinal. Trazer para DanfeSharp.Test os testes de unidade pura (FormatarCrt, Linhas*, PossuiMonofasia*, Mapear* com fragmento XML), mantendo no #832 os de integração/paridade.

Comment thread DanfeSharp/Modelo/DanfeViewModel.cs Resolved
Comment thread DanfeSharp/Modelo/DanfeViewModel.cs Resolved
Comment thread DanfeSharp/Esquemas/ProcNFe.cs Resolved
Comment thread DanfeSharp/Modelo/DanfeViewModel.cs Resolved
@john182

john182 commented Oct 21, 2026

Copy link
Copy Markdown

Vigência de NT: a biblioteca de renderização não deveria decidir a data de corte

InicioLeiauteReformaTributaria = new DateTime(2026, 12, 1) (Modelo/DanfeViewModel.cs:504) põe uma regra fiscal de vigência dentro do DanfeSharp. Adiar a NT 2026.010 passaria a exigir release da lib e bump do submódulo no product-invoice. A comparação também é feita com DateTime sem fuso.

Proposta: o DanfeSharp recebe a decisão pronta. Por exemplo, uma propriedade UsarLeiauteReformaTributaria no DanfeViewModel, preenchida pelo consumidor, no lugar de ExibirReformaTributaria calculado com a data fixa. A regra de vigência, avaliada no fuso da UF, fica no product-invoice#832. Isso também resolve o BLOQUEANTE de tamanho deste arquivo, porque a data e o cálculo saem daqui.

Contexto: proposta de Calendário Fiscal compartilhado para NF-e/NFS-e em https://github.com/nfe/dfetech-product-invoice-api/pull/831#issuecomment-6306171450

…utos e mapeamento em classes próprias (NT 2026.010)

Ajustes da segunda rodada de review do #55:
- DanfeViewModel.UsarLeiauteReformaTributaria (bool) substitui a regra de vigência
  dentro da biblioteca: a data da NT e a condição de presença ficam no consumidor
  (product-invoice), que compara pela data no fuso da UF.
- LinhasTributosReformaTributaria (Descricao/Bases/Aliquotas/Valores) sai do
  ProdutoViewModel; ReformaTributariaViewModelMapper sai do DanfeViewModelCreator.
- Nomes alinhados (ValorIbsUF, AliquotaIbsUF, BaseIS/AliquotaIS/ValorIS) e regions.
- FormatarCrt devolve o código recebido quando não reconhece o valor.
- CFOP "0" só no leiaute novo; leiaute anterior mantém "N0".
- Summaries do ProcNFe (IS, IBSCBS, IBSCBSTot) descrevem os campos usados.
- DanfeSharp.Test/ReformaTributariaTests: 19 testes (FormatarCrt, pares de
  tributos, item sem ICMS, monofasia, gRed por grupo, IS/ISTot e base do IPI do XML).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rhfranzoni

Copy link
Copy Markdown
Author

Respostas à revisão (Gate 8) — correções em 2b5c29b. Todas as conversas inline foram respondidas e resolvidas.

@rhfranzoni

Copy link
Copy Markdown
Author

Aplicado em 2b5c29b:

  • ExibirReformaTributaria e InicioLeiauteReformaTributaria foram removidos. No lugar entrou UsarLeiauteReformaTributaria (get; set;, padrão false), preenchido pelo consumidor. A lib só renderiza.
  • No product-invoice#832, a vigência está em Nt2026010.Production (DateOnly) e DanfeTaxReformLayout.ShouldUse. A comparação é pela data no fuso da UF, nos dois caminhos.
  • Adiar a NT agora é um PR no product-invoice, sem release da lib e sem bump do submódulo.

@john182

john182 commented Oct 22, 2026

Copy link
Copy Markdown

Re-revisão (head 2b5c29b5): BLOQUEANTES sanados

Conferi as 18 conversas.

Corrigido:

  • DanfeViewModel ficou com 497 linhas, DanfeViewModelCreator com 670 e ProdutoViewModel com 266.
  • A regra de vigência saiu da lib. Agora UsarLeiauteReformaTributaria é preenchido pelo consumidor (fase 0 do calendário).
  • Os testes de IS/ISTot, de FormatarCrt e dos demais ramos foram para o DanfeSharp.Test.

Reaberto:

  • DanfeViewModel.cs:496: a parte técnica está ok, mas a decisão de fiscal/produto sobre o gatilho (presença de IBS/CBS/IS) ainda está aberta na nfe/dfetech-product-invoice-api#760. Produção em 01/12/2026.

Ainda pendente (achado fora do diff, DanfeSharp.Test.csproj:62):

  • Os testes novos existem, mas nada os executa. O DanfeSharp.Test é MSTest/net461, dotnet test DanfeSharp.sln termina sem executar nenhum teste e o repositório não tem CI. Parte da cobertura só existe aqui: gRed de IBS Município e CBS, Csosn e FormatarCrt 1 e 4. Sugestão: um workflow mínimo (windows-latest + vstest/dotnet test com net461 instalado) ou migrar o projeto de teste para SDK-style com net8.0 + net461. Sem isso, um PR futuro que quebre o leiaute passa sem sinal.

Merge: o #832 aponta o submódulo para 2b5c29b5. Mergear com merge commit preserva o SHA.

rhfranzoni and others added 2 commits October 26, 2026 17:47
…condicionado, linha do CRT com regime de apuração reservado e totais divididos

- Quadro "QR Code" ao lado dos dados adicionais, só no leiaute RTC e com infNFeSupl/qrCode no XML (itens 4.4/4.5)
- CRT em linha própria com a área reservada do Tipo de Regime de Apuração do IBS/CBS (item 4.2)
- "Total dos Produtos e Total da Nota" + "Total do ICMS/IPI" com linhas de FCP/DIFAL e ICMS monofásico condicionadas
- Geração do XObject do QR Code compartilhada com o Simplificado Tipo 2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… RTC (NT 2026.010)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rhfranzoni
rhfranzoni merged commit 11ca249 into main Oct 27, 2026
2 checks passed
@rhfranzoni
rhfranzoni deleted the feat/nt-2026-010-danfe-rtc branch October 27, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants