From ff26ea1a141f749a2ab23f41985df52c4f5e2ade Mon Sep 17 00:00:00 2001 From: willian Date: Wed, 21 Oct 2026 22:29:26 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20DANFE=20HTML=20no=20leiaute=20da=20NT?= =?UTF-8?q?=202026.010=20(Reforma=20Tribut=C3=A1ria)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Novo leiaute opcional do DANFE NF-e em HTML, escolhido por LeiauteDanfe.ReformaTributaria no construtor do DanfeNFe. O construtor anterior continua gerando o leiaute atual, sem alteração. - Quadro "Total do IBS/CBS/IS" (W56, W41, W46, W33 e monofásicos W58-W59b) - CRT no quadro do emitente e campo reservado do regime de apuração - Por item: CST, cClassTrib, bases, alíquotas (pAliqEfet quando há gRed) e valores de ICMS, IBS UF, IBS Município, CBS, IS e IPI - Quadros facultativos (fatura, FCP/DIFAL, ICMS monofásico, IBS/CBS monofásico, ISSQN e transporte) só impressos quando há informação no XML - Paginação por altura fixa de item, aferida no Chromium em A4 O NFe.Danfe.Html passa a referenciar o NFe.Classes do repositório no lugar do pacote Zeus.Net.NFe.NFCe 2024, e ganha o pacote Hercules.NET.NFe.Danfe.Html no workflow de build. Testes: o leiaute atual é comparado byte a byte com o HTML gerado pelo master anterior; renderização no Chromium com RUN_PLAYWRIGHT_DANFE_TESTS=1. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ZeusFiscal_build.yml | 6 + .../DanfeNfeHtmlLeiauteAtualTestes.cs | 83 + .../DanfeNfeHtmlReformaTributariaTestes.cs | 182 ++ .../DanfeNfeHtmlRenderizacaoTestes.cs | 80 + .../Golden/danfe-leiaute-atual-3-itens.html | 921 +++++++++ .../Golden/danfe-leiaute-atual-40-itens.html | 1671 +++++++++++++++++ .../Fixtures/NFeFixture.ReformaTributaria.cs | 103 + NFe.Danfe.Html.Testes/Fixtures/NFeFixture.cs | 219 +++ .../NFe.Danfe.Html.Testes.csproj | 26 + NFe.Danfe.Html/CrossCutting/Enumeradores.cs | 19 +- .../DanfeNfeHtml2.ReformaTributaria.cs | 346 ++++ NFe.Danfe.Html/DanfeNfeHtml2.cs | 4 +- NFe.Danfe.Html/Dominio/DanfeNFe.cs | 116 +- NFe.Danfe.Html/Dominio/Emitente.cs | 5 + .../Dominio/ImpostoReformaTributaria.cs | 97 + NFe.Danfe.Html/Dominio/Produto.cs | 5 + .../Dominio/ProdutoReformaTributaria.cs | 77 + NFe.Danfe.Html/NFe.Danfe.Html.csproj | 5 +- NFe.Danfe.Html/Resource.Designer.cs | 36 + NFe.Danfe.Html/Resource.resx | 12 + .../danfe-model-55-nfe-rtc-cabecalho.html | 218 +++ .../danfe-model-55-nfe-rtc-page-next.html | 20 + .../danfe-model-55-nfe-rtc-page-one.html | 843 +++++++++ .../danfe-model-55-nfe-rtc-produtos.html | 31 + .../Hercules.NET.NFe.Danfe.Html.csproj | 12 + .../Hercules.NET.NFe.Danfe.Html.nuspec | 27 + ZeusFiscal.sln | 11 + 27 files changed, 5170 insertions(+), 5 deletions(-) create mode 100644 NFe.Danfe.Html.Testes/DanfeNfeHtmlLeiauteAtualTestes.cs create mode 100644 NFe.Danfe.Html.Testes/DanfeNfeHtmlReformaTributariaTestes.cs create mode 100644 NFe.Danfe.Html.Testes/DanfeNfeHtmlRenderizacaoTestes.cs create mode 100644 NFe.Danfe.Html.Testes/Fixtures/Golden/danfe-leiaute-atual-3-itens.html create mode 100644 NFe.Danfe.Html.Testes/Fixtures/Golden/danfe-leiaute-atual-40-itens.html create mode 100644 NFe.Danfe.Html.Testes/Fixtures/NFeFixture.ReformaTributaria.cs create mode 100644 NFe.Danfe.Html.Testes/Fixtures/NFeFixture.cs create mode 100644 NFe.Danfe.Html.Testes/NFe.Danfe.Html.Testes.csproj create mode 100644 NFe.Danfe.Html/DanfeNfeHtml2.ReformaTributaria.cs create mode 100644 NFe.Danfe.Html/Dominio/ImpostoReformaTributaria.cs create mode 100644 NFe.Danfe.Html/Dominio/ProdutoReformaTributaria.cs create mode 100644 NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-cabecalho.html create mode 100644 NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-next.html create mode 100644 NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-one.html create mode 100644 NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-produtos.html create mode 100644 NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.csproj create mode 100644 NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.nuspec diff --git a/.github/workflows/ZeusFiscal_build.yml b/.github/workflows/ZeusFiscal_build.yml index f54a00cbb..82216ba30 100644 --- a/.github/workflows/ZeusFiscal_build.yml +++ b/.github/workflows/ZeusFiscal_build.yml @@ -82,6 +82,10 @@ jobs: run: | dotnet build -p:Version=${{ steps.date.outputs.date }} ".\NFe.Danfe.QuestPdf\NFe.Danfe.QuestPdf.csproj" -c Release + - name: Build Impressão DANFE HTML + run: | + dotnet build -p:Version=${{ steps.date.outputs.date }} ".\NFe.Danfe.Html\NFe.Danfe.Html.csproj" -c Release + #- name: Test # run: dotnet test --no-build --verbosity normal @@ -91,6 +95,7 @@ jobs: dotnet pack -o ${{ github.workspace }} -v minimal -c Release -p:NuspecProperties=version=${{ steps.date.outputs.date }} -p:PackageVersion=${{ steps.date.outputs.date }} NuGet\Hercules.NET.MDFe\Hercules.NET.MDFe.csproj dotnet pack -o ${{ github.workspace }} -v minimal -c Release -p:NuspecProperties=version=${{ steps.date.outputs.date }} -p:PackageVersion=${{ steps.date.outputs.date }} NuGet\Hercules.NET.CTe\Hercules.NET.CTe.csproj dotnet pack -o ${{ github.workspace }} -v minimal -c Release -p:NuspecProperties=version=${{ steps.date.outputs.date }} -p:PackageVersion=${{ steps.date.outputs.date }} NuGet\Hercules.NET.Impressao.NFCe.QuestPdf\Hercules.NET.Impressao.NFCe.QuestPdf.csproj + dotnet pack -o ${{ github.workspace }} -v minimal -c Release -p:NuspecProperties=version=${{ steps.date.outputs.date }} -p:PackageVersion=${{ steps.date.outputs.date }} NuGet\Hercules.NET.NFe.Danfe.Html\Hercules.NET.NFe.Danfe.Html.csproj - name: Upload Artifacts uses: actions/upload-artifact@v4 @@ -154,6 +159,7 @@ jobs: - Hercules.NET.MDFe - Hercules.NET.CTe - Hercules.NET.Impressao.NFCe.QuestPdf + - Hercules.NET.NFe.Danfe.Html files: | ${{ github.workspace }}/*.nupkg diff --git a/NFe.Danfe.Html.Testes/DanfeNfeHtmlLeiauteAtualTestes.cs b/NFe.Danfe.Html.Testes/DanfeNfeHtmlLeiauteAtualTestes.cs new file mode 100644 index 000000000..84e1b14ec --- /dev/null +++ b/NFe.Danfe.Html.Testes/DanfeNfeHtmlLeiauteAtualTestes.cs @@ -0,0 +1,83 @@ +using System.Globalization; +using System.IO; +using System.Threading.Tasks; +using NFe.Danfe.Html.CrossCutting; +using NFe.Danfe.Html.Dominio; +using NFe.Danfe.Html.Testes.Fixtures; +using Xunit; + +namespace NFe.Danfe.Html.Testes +{ + /// + /// Garante que o leiaute atual continua idêntico ao gerado antes da NT 2026.010. + /// Os arquivos em Fixtures/Golden foram gerados a partir do master anterior a esta alteração, com a cultura pt-BR. + /// + public class DanfeNfeHtmlLeiauteAtualTestes + { + private const string Protocolo = "135261000001234 - 21/10/2026 10:31:00"; + private const string Creditos = "Hercules.NET"; + + public DanfeNfeHtmlLeiauteAtualTestes() + { + //a formatação do leiaute atual depende da cultura corrente + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("pt-BR"); + } + + private static string LerGolden(int quantidadeProdutos) + { + return File.ReadAllText(Path.Combine("Fixtures", "Golden", $"danfe-leiaute-atual-{quantidadeProdutos}-itens.html")); + } + + private static async Task GerarHtmlAsync(DanfeNFe danfe) + { + return (await new DanfeNfeHtml2(danfe).ObterDocHtmlAsync()).Html; + } + + [Theory] + [InlineData(3)] + [InlineData(40)] + public async Task ConstrutorAnterior_GeraHtmlIdenticoAoLeiauteAtual(int quantidadeProdutos) + { + // Arrange + var danfe = new DanfeNFe(NFeFixture.CriarNfe(quantidadeProdutos), Status.Autorizada, Protocolo, Creditos); + + // Act + var html = await GerarHtmlAsync(danfe); + + // Assert + Assert.Equal(LeiauteDanfe.Atual, danfe.Leiaute); + Assert.Equal(LerGolden(quantidadeProdutos), html); + } + + [Theory] + [InlineData(3)] + [InlineData(40)] + public async Task LeiauteAtualExplicito_GeraHtmlIdenticoAoLeiauteAtual(int quantidadeProdutos) + { + // Arrange + var danfe = new DanfeNFe(NFeFixture.CriarNfe(quantidadeProdutos), Status.Autorizada, Protocolo, Creditos, LeiauteDanfe.Atual); + + // Act + var html = await GerarHtmlAsync(danfe); + + // Assert + Assert.Equal(LerGolden(quantidadeProdutos), html); + } + + [Theory] + [InlineData(3)] + [InlineData(40)] + public async Task LeiauteAtual_ComXmlDaReformaTributaria_IgnoraOsGruposNovos(int quantidadeProdutos) + { + // Arrange + var nfe = NFeFixture.CriarNfeReformaTributaria(quantidadeProdutos, comQuadrosFacultativos: true); + var danfe = new DanfeNFe(nfe, Status.Autorizada, Protocolo, Creditos); + + // Act + var html = await GerarHtmlAsync(danfe); + + // Assert + Assert.Equal(LerGolden(quantidadeProdutos), html); + } + } +} diff --git a/NFe.Danfe.Html.Testes/DanfeNfeHtmlReformaTributariaTestes.cs b/NFe.Danfe.Html.Testes/DanfeNfeHtmlReformaTributariaTestes.cs new file mode 100644 index 000000000..eafbb7039 --- /dev/null +++ b/NFe.Danfe.Html.Testes/DanfeNfeHtmlReformaTributariaTestes.cs @@ -0,0 +1,182 @@ +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using NFe.Danfe.Html.CrossCutting; +using NFe.Danfe.Html.Dominio; +using NFe.Danfe.Html.Testes.Fixtures; +using Xunit; + +namespace NFe.Danfe.Html.Testes +{ + /// + /// Leiaute do DANFE NF-e da NT 2026.010 (Reforma Tributária) + /// + public class DanfeNfeHtmlReformaTributariaTestes + { + private static async Task GerarHtmlAsync(int quantidadeProdutos, bool comQuadrosFacultativos = true, Issqn issqn = null) + { + var nfe = NFeFixture.CriarNfeReformaTributaria(quantidadeProdutos, comQuadrosFacultativos); + var danfe = new DanfeNFe(nfe, Status.Autorizada, "135261000001234 - 21/10/2026 10:31:00", "Hercules.NET", + LeiauteDanfe.ReformaTributaria, issqn); + return (await new DanfeNfeHtml2(danfe).ObterDocHtmlAsync()).Html; + } + + private static int ContarPaginas(string html) + { + return Regex.Matches(html, "class=\"page nfeArea rtc\"").Count; + } + + [Fact] + public async Task GerarHtml_ImprimeOsQuadrosDaNt2026010() + { + // Act + var html = await GerarHtmlAsync(3); + + // Assert + Assert.Contains("Total do IBS / CBS / IS", html); + Assert.Contains("CÓDIGO DO REGIME TRIBUTÁRIO", html); + Assert.Contains("3 - REGIME NORMAL", html); + Assert.Contains("TIPO DE REGIME DE APURAÇÃO DO IBS E DA CBS", html); + Assert.Contains("BASES DE CÁLCULO", html); + Assert.Contains("ALÍQUOTAS", html); + Assert.Contains("VALOR DOS TRIBUTOS", html); + Assert.Contains("[NCM 27101921] [cClassTrib 000001]", html); + Assert.Contains("CST 000", html); + } + + [Fact] + public async Task GerarHtml_PreencheOsTotaisDeIbsCbsIsEMonofasia() + { + // Act + var html = await GerarHtmlAsync(3); + + // Assert + Assert.Contains("VALOR DA CBS\n 2,16", html); + Assert.Contains("VALOR DO IBS UF\n 0,24", html); + Assert.Contains("VALOR DO IMPOSTO SELETIVO\n 0,25", html); + Assert.Contains("VALOR DO IBS MONOFÁSICO\n 12,30", html); + Assert.Contains("VALOR DA CBS MONOFÁSICA\n 110,70", html); + Assert.Contains("BC DO ICMS MONOFÁSICO\n 1.000,00", html); + } + + [Fact] + public async Task GerarHtml_ItemComGRed_ImprimeAAliquotaEfetiva() + { + // Act + var html = await GerarHtmlAsync(3); + var item2 = Regex.Match(html, "
]*>00002.*?").Value; + + // Assert + Assert.Contains("[cClassTrib 200003]", item2); + Assert.Contains("IBS UF0,04%", item2); + Assert.Contains("CBS0,36%", item2); + Assert.DoesNotContain("0,10%", item2); + Assert.DoesNotContain("0,90%", item2); + } + + [Fact] + public async Task GerarHtml_ItemSemIsOuIpi_DeixaOsCamposEmBranco() + { + // Act + var html = await GerarHtmlAsync(3); + var item1 = Regex.Match(html, "
]*>00001.*?").Value; + var item3 = Regex.Match(html, "
]*>00003.*?").Value; + + // Assert + Assert.Contains("IS", item1); + Assert.Contains("IPI", item1); + Assert.Contains("IS0,25%", item3); + Assert.Contains("IPI5,00", item3); + } + + [Fact] + public async Task GerarHtml_SemInformacaoNoXml_OmiteOsQuadrosFacultativos() + { + // Act + var html = await GerarHtmlAsync(3, comQuadrosFacultativos: false); + + // Assert + Assert.DoesNotContain("Fatura / Duplicatas", html); + Assert.DoesNotContain("VALOR DO FCP RETIDO POR ST", html); + Assert.DoesNotContain("BC DO ICMS MONOFÁSICO", html); + Assert.DoesNotContain("VALOR DO IBS MONOFÁSICO", html); + Assert.DoesNotContain("Cálculo do ISSQN", html); + Assert.DoesNotContain("Transportador / volumes transportados", html); + Assert.Contains("Total do IBS / CBS / IS", html); + } + + [Fact] + public async Task GerarHtml_ComInformacaoNoXml_ImprimeOsQuadrosFacultativos() + { + // Act + var html = await GerarHtmlAsync(3, issqn: new Issqn { Im = "123456", ValorTotServ = 50m, BaseCalculo = 50m, ValorIssqn = 2.5m }); + + // Assert + Assert.Contains("Fatura / Duplicatas", html); + Assert.Contains("VALOR DO FCP RETIDO POR ST", html); + Assert.Contains("BC DO ICMS MONOFÁSICO", html); + Assert.Contains("VALOR DO IBS MONOFÁSICO", html); + Assert.Contains("Cálculo do ISSQN", html); + Assert.Contains("Transportador / volumes transportados", html); + Assert.Contains("0 - Remetente", html); + } + + [Theory] + [InlineData(1)] + [InlineData(40)] + public async Task GerarHtml_NaoDeixaMarcadoresDoTemplate(int quantidadeProdutos) + { + // Act + var html = await GerarHtmlAsync(quantidadeProdutos); + + // Assert + Assert.DoesNotContain(" + + + + + + +
+ +
+ + + + + + + + + + + +
+ Recebemos de POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA os produtos e serviços + constantes na nota fiscal indicada ao lado + + NF-e + Nº 1234 + Série 1 +
+ Data de recebimento + + Identificação de assinatura do Recebedor +
+
+ + + + + + + + + + + + + + + +
+ + + POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA + Avenida das Bombas 1500 + + Centro - 01001000 + + + Sao Paulo - SP- Fone: + (11) 3333-4444 + + +

Danfe

+

Documento auxiliar da Nota Fiscal Eletrônica

+

+ + 1 + + + 0 - Entrada + 1 - Saída + +

+

+ + Nº + 1234 + + + SÉRIE: + 1 + + + Página + 1 + de + 1 + +

+
+ Controle do Fisco + + + +
+ CHAVE DE ACESSO + 3526 1012 3456 7800 0199 5500 1000 0012 3410 0001 2340 +
+ + Consulta de autenticidade no portal nacional da NF-e + + www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizada. +
+ + + + + + + + +
+ NATUREZA DA OPERAÇÃO + VENDA DE MERCADORIA ADQUIRIDA OU RECEBIDA DE TERCEIROS + + PROTOCOLO DE AUTORIZAÇÃO DE USO + 135261000001234 - 21/10/2026 10:31:00 +
+ + + + + + + + + + +
+ INSCRIÇÃO ESTADUAL + 110042490114 + + INSCRIÇÃO ESTADUAL DO SUBST. TRIB. + + + CNPJ + 12.345.678/0001-99 +
+ + +

Destinatário/Emitente

+ + + + + + + + + + + + + + + +
+ + + + + + + +
+ NOME/RAZÃO SOCIAL + TRANSPORTADORA CLIENTE S/A + + CNPJ/CPF + 98.765.432/0001-88 +
+
+ DATA DE EMISSÃO + 21/10/2026 +
+ + + + + + + + +
+ ENDEREÇO + Rodovia Exemplo km 10 S/N + + BAIRRO/DISTRITO + Distrito Industrial + + CEP + 01002000 +
+
+ DATA DE ENTR./SAÍDA + 21/10/2026 +
+ + + + + + + + + +
+ MUNICÍPIO + Sao Paulo + + FONE/FAX + (11) 4444-5555 + + UF + SP + + INSCRIÇÃO ESTADUAL + 110042490115 +
+
+ HORA ENTR./SAÍDA + 11:00:00 +
+ +
+

Fatura

+ + + + + + +
+ N Fat.º: 001   Vencimento: 20/11/2026   Valor: 60,000   | N Fat.º: 002   Vencimento: 20/12/2026   Valor: 52,500   | +
+
+ + +

Calculo do imposto

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ BASE DE CÁLC. DO ICMS + 300,000 + + VALOR DO ICMS + 54,000 + + BASE DE CÁLC. DO ICMS ST + 0,000 + + VALOR DO ICMS ST + 0,000 + + V. IMP. IMPORTAÇÃO + + + V. ICMS UF REMET. + + + VALOR DO FCP + 0 + + VALOR DO PIS + 4,950 + + V. TOTAL DE PRODUTOS + 300,000 +
+ VALOR DO FRETE + 15,000 + + VALOR DO SEGURO + 0,000 + + DESCONTO + 2,500 + + OUTRAS DESP. + 0,000 + + VALOR DO IPI + 5,000 + + V. ICMS UF DEST. + + + V. APROX. DO TRIBUTO + 0,000 + + VALOR DA CONFINS + 22,800 + + V. TOTAL DA NOTA + 317,500 +
+
+ +

Transportador/volumes transportados

+ + + + + + + + + + + +
+ RAZÃO SOCIAL + Transportadora Exemplo + + FRETE POR CONTA +
+ 1 +
+

0 - Emitente

+

1 - Destinatário

+
+ CÓDIGO ANTT + + + PLACA + + + UF + SP + + CNPJ/CPF + 22.222.222/0001-22 +
+ + + + + + + + + + +
+ ENDEREÇO + Rod. Exemplo, km 10 + + MUNICÍPIO + Campinas + + UF + SP + + INSC. ESTADUAL + 333333333 +
+ + + + + + + + + + + +
+ QUANTIDADE + 1 + + ESPÉCIE + Volume + + MARCA + + + NUMERAÇÃO + 001 + + PESO BRUTO + 12,500 + + PESO LÍQUIDO + 11,900 +
+ +

Dados do produto/serviço

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CÓDIGO + DESCRIÇÃO DO PRODUTO/SERVIÇO + NCMSHCSTCFOPUNQTD.VLR.UNITVLR.TOTALBC ICMSVLR.ICMSVLR.IPIALIQ.ICMSALIQ.IPI
00001Produto teste 00127101921005102UN1,000100.00100.00100.0018.0018.00
00002Produto teste 00227101921005102UN1,000100.00100.00100.0018.0018.00
00003Produto teste 00327101921005102UN1,000100.00100.00100.0018.005.0018.005.00
+
+ + +

Calculo do issqn

+ + + + + + + + + +
+ INSCRIÇÃO MUNICIPAL + + + VALOR TOTAL DOS SERVIÇOS + + + BASE DE CÁLCULO DO ISSQN + + + VALOR DO ISSQN + +
+ + +

Dados adicionais

+ + + + + + + +
+ INFORMAÇÕES COMPLEMENTARES + Documento emitido para teste do leiaute do DANFE HTML. + + RESERVA AO FISCO + +
+ +
+ + + + + + +
+ Hercules.NET +
+
+
+ +
+ \ No newline at end of file diff --git a/NFe.Danfe.Html.Testes/Fixtures/Golden/danfe-leiaute-atual-40-itens.html b/NFe.Danfe.Html.Testes/Fixtures/Golden/danfe-leiaute-atual-40-itens.html new file mode 100644 index 000000000..a62781ab2 --- /dev/null +++ b/NFe.Danfe.Html.Testes/Fixtures/Golden/danfe-leiaute-atual-40-itens.html @@ -0,0 +1,1671 @@ + + + + + + + +
+ +
+ + + + + + + + + + + +
+ Recebemos de POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA os produtos e serviços + constantes na nota fiscal indicada ao lado + + NF-e + Nº 1234 + Série 1 +
+ Data de recebimento + + Identificação de assinatura do Recebedor +
+
+ + + + + + + + + + + + + + + +
+ + + POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA + Avenida das Bombas 1500 + + Centro - 01001000 + + + Sao Paulo - SP- Fone: + (11) 3333-4444 + + +

Danfe

+

Documento auxiliar da Nota Fiscal Eletrônica

+

+ + 1 + + + 0 - Entrada + 1 - Saída + +

+

+ + Nº + 1234 + + + SÉRIE: + 1 + + + Página + 1 + de + 2 + +

+
+ Controle do Fisco + + + +
+ CHAVE DE ACESSO + 3526 1012 3456 7800 0199 5500 1000 0012 3410 0001 2340 +
+ + Consulta de autenticidade no portal nacional da NF-e + + www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizada. +
+ + + + + + + + +
+ NATUREZA DA OPERAÇÃO + VENDA DE MERCADORIA ADQUIRIDA OU RECEBIDA DE TERCEIROS + + PROTOCOLO DE AUTORIZAÇÃO DE USO + 135261000001234 - 21/10/2026 10:31:00 +
+ + + + + + + + + + +
+ INSCRIÇÃO ESTADUAL + 110042490114 + + INSCRIÇÃO ESTADUAL DO SUBST. TRIB. + + + CNPJ + 12.345.678/0001-99 +
+ + +

Destinatário/Emitente

+ + + + + + + + + + + + + + + +
+ + + + + + + +
+ NOME/RAZÃO SOCIAL + TRANSPORTADORA CLIENTE S/A + + CNPJ/CPF + 98.765.432/0001-88 +
+
+ DATA DE EMISSÃO + 21/10/2026 +
+ + + + + + + + +
+ ENDEREÇO + Rodovia Exemplo km 10 S/N + + BAIRRO/DISTRITO + Distrito Industrial + + CEP + 01002000 +
+
+ DATA DE ENTR./SAÍDA + 21/10/2026 +
+ + + + + + + + + +
+ MUNICÍPIO + Sao Paulo + + FONE/FAX + (11) 4444-5555 + + UF + SP + + INSCRIÇÃO ESTADUAL + 110042490115 +
+
+ HORA ENTR./SAÍDA + 11:00:00 +
+ +
+

Fatura

+ + + + + + +
+ N Fat.º: 001   Vencimento: 20/11/2026   Valor: 60,000   | N Fat.º: 002   Vencimento: 20/12/2026   Valor: 52,500   | +
+
+ + +

Calculo do imposto

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ BASE DE CÁLC. DO ICMS + 4.000,000 + + VALOR DO ICMS + 720,000 + + BASE DE CÁLC. DO ICMS ST + 0,000 + + VALOR DO ICMS ST + 0,000 + + V. IMP. IMPORTAÇÃO + + + V. ICMS UF REMET. + + + VALOR DO FCP + 0 + + VALOR DO PIS + 66,000 + + V. TOTAL DE PRODUTOS + 4.000,000 +
+ VALOR DO FRETE + 15,000 + + VALOR DO SEGURO + 0,000 + + DESCONTO + 2,500 + + OUTRAS DESP. + 0,000 + + VALOR DO IPI + 70,000 + + V. ICMS UF DEST. + + + V. APROX. DO TRIBUTO + 0,000 + + VALOR DA CONFINS + 304,000 + + V. TOTAL DA NOTA + 4.082,500 +
+
+ +

Transportador/volumes transportados

+ + + + + + + + + + + +
+ RAZÃO SOCIAL + Transportadora Exemplo + + FRETE POR CONTA +
+ 1 +
+

0 - Emitente

+

1 - Destinatário

+
+ CÓDIGO ANTT + + + PLACA + + + UF + SP + + CNPJ/CPF + 22.222.222/0001-22 +
+ + + + + + + + + + +
+ ENDEREÇO + Rod. Exemplo, km 10 + + MUNICÍPIO + Campinas + + UF + SP + + INSC. ESTADUAL + 333333333 +
+ + + + + + + + + + + +
+ QUANTIDADE + 1 + + ESPÉCIE + Volume + + MARCA + + + NUMERAÇÃO + 001 + + PESO BRUTO + 12,500 + + PESO LÍQUIDO + 11,900 +
+ +

Dados do produto/serviço

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CÓDIGO + DESCRIÇÃO DO PRODUTO/SERVIÇO + NCMSHCSTCFOPUNQTD.VLR.UNITVLR.TOTALBC ICMSVLR.ICMSVLR.IPIALIQ.ICMSALIQ.IPI
00001Produto teste 00127101921005102UN1,000100.00100.00100.0018.0018.00
00002Produto teste 00227101921005102UN1,000100.00100.00100.0018.0018.00
00003Produto teste 00327101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00004Produto teste 004 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00005Produto teste 00527101921005102UN1,000100.00100.00100.0018.0018.00
00006Produto teste 00627101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00007Produto teste 00727101921005102UN1,000100.00100.00100.0018.0018.00
00008Produto teste 008 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00009Produto teste 00927101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00010Produto teste 01027101921005102UN1,000100.00100.00100.0018.0018.00
00011Produto teste 01127101921005102UN1,000100.00100.00100.0018.0018.00
00012Produto teste 012 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.005.0018.005.00
+
+ + +

Calculo do issqn

+ + + + + + + + + +
+ INSCRIÇÃO MUNICIPAL + + + VALOR TOTAL DOS SERVIÇOS + + + BASE DE CÁLCULO DO ISSQN + + + VALOR DO ISSQN + +
+ + +

Dados adicionais

+ + + + + + + +
+ INFORMAÇÕES COMPLEMENTARES + Documento emitido para teste do leiaute do DANFE HTML. + + RESERVA AO FISCO + +
+ +
+ + + + + + +
+ Hercules.NET +
+
+
+
+ +
+ + + + + + + + + + + + + + + +
+ + + POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA + Avenida das Bombas 1500 + + Centro - 01001000 + + + Sao Paulo - SP- Fone: + (11) 3333-4444 + + +

Danfe

+

Documento auxiliar da Nota Fiscal Eletrônica

+

+ + 1 + + + 0 - Entrada + 1 - Saída + +

+

+ + Nº + 1234 + + + SÉRIE: + 1 + + + Página + 2 + de + 2 + +

+
+ Controle do Fisco + + + +
+ CHAVE DE ACESSO + 3526 1012 3456 7800 0199 5500 1000 0012 3410 0001 2340 +
+ + Consulta de autenticidade no portal nacional da NF-e + + www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizada. +
+ + + + + + + + +
+ NATUREZA DA OPERAÇÃO + VENDA DE MERCADORIA ADQUIRIDA OU RECEBIDA DE TERCEIROS + + PROTOCOLO DE AUTORIZAÇÃO DE USO + 135261000001234 - 21/10/2026 10:31:00 +
+ + + + + + + + + + +
+ INSCRIÇÃO ESTADUAL + 110042490114 + + INSCRIÇÃO ESTADUAL DO SUBST. TRIB. + + + CNPJ + 12.345.678/0001-99 +
+ +

Dados do produto/serviço

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CÓDIGO + DESCRIÇÃO DO PRODUTO/SERVIÇO + NCMSHCSTCFOPUNQTD.VLR.UNITVLR.TOTALBC ICMSVLR.ICMSVLR.IPIALIQ.ICMSALIQ.IPI
00013Produto teste 01327101921005102UN1,000100.00100.00100.0018.0018.00
00014Produto teste 01427101921005102UN1,000100.00100.00100.0018.0018.00
00015Produto teste 01527101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00016Produto teste 016 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00017Produto teste 01727101921005102UN1,000100.00100.00100.0018.0018.00
00018Produto teste 01827101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00019Produto teste 01927101921005102UN1,000100.00100.00100.0018.0018.00
00020Produto teste 020 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00021Produto teste 02127101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00022Produto teste 02227101921005102UN1,000100.00100.00100.0018.0018.00
00023Produto teste 02327101921005102UN1,000100.00100.00100.0018.0018.00
00024Produto teste 024 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00025Produto teste 02527101921005102UN1,000100.00100.00100.0018.0018.00
00026Produto teste 02627101921005102UN1,000100.00100.00100.0018.0018.00
00027Produto teste 02727101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00028Produto teste 028 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00029Produto teste 02927101921005102UN1,000100.00100.00100.0018.0018.00
00030Produto teste 03027101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00031Produto teste 03127101921005102UN1,000100.00100.00100.0018.0018.00
00032Produto teste 032 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
00033Produto teste 03327101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00034Produto teste 03427101921005102UN1,000100.00100.00100.0018.0018.00
00035Produto teste 03527101921005102UN1,000100.00100.00100.0018.0018.00
00036Produto teste 036 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00037Produto teste 03727101921005102UN1,000100.00100.00100.0018.0018.00
00038Produto teste 03827101921005102UN1,000100.00100.00100.0018.0018.00
00039Produto teste 03927101921005102UN1,000100.00100.00100.0018.005.0018.005.00
00040Produto teste 040 com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do D27101921005102UN1,000100.00100.00100.0018.0018.00
+
+
+ + + + + + +
+ Empresa de Software www.empresa.com +
+
+
+ +
+ +
+ \ No newline at end of file diff --git a/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.ReformaTributaria.cs b/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.ReformaTributaria.cs new file mode 100644 index 000000000..a9d953743 --- /dev/null +++ b/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.ReformaTributaria.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using System.Linq; +using NFe.Classes.Informacoes.Detalhe.Tributacao; +using NFe.Classes.Informacoes.Total; +using NFe.Classes.Informacoes.Transporte; + +namespace NFe.Danfe.Html.Testes.Fixtures +{ + /// + /// NF-e modelo 55 com os grupos da Reforma Tributária (IBS/CBS/IS) usados pelo DANFE da NT 2026.010 + /// + public static partial class NFeFixture + { + /// Quantidade de itens + /// + /// true preenche fatura, FCP, ICMS monofásico, IBS/CBS monofásico e transporte; false omite todos + /// + public static Classes.NFe CriarNfeReformaTributaria(int quantidadeProdutos, bool comQuadrosFacultativos = true) + { + var nfe = CriarNfe(quantidadeProdutos); + var infNFe = nfe.infNFe; + + foreach (var det in infNFe.det) + { + var item = det.nItem; + det.imposto.IBSCBS = new IBSCBS + { + CST = CSTIBSCBS.cst000, + cClassTrib = "000001", + gIBSCBS = new gIBSCBS + { + vBC = 100m, + gIBSUF = new gIBSUF { pIBSUF = 0.1m, vIBSUF = 0.1m }, + gIBSMun = new gIBSMun { pIBSMun = 0m, vIBSMun = 0m }, + vIBS = 0.1m, + gCBS = new gCBS { pCBS = 0.9m, vCBS = 0.9m } + } + }; + + //item 2: redução de alíquota (gRed) - o DANFE deve imprimir a alíquota efetiva + if (item == 2) + { + var g = det.imposto.IBSCBS.gIBSCBS; + det.imposto.IBSCBS.CST = CSTIBSCBS.cst200; + det.imposto.IBSCBS.cClassTrib = "200003"; + g.gIBSUF = new gIBSUF { pIBSUF = 0.1m, gRed = new gRed { pRedAliq = 60m, pAliqEfet = 0.04m }, vIBSUF = 0.04m }; + g.gIBSMun = new gIBSMun { pIBSMun = 0m, gRed = new gRed { pRedAliq = 60m, pAliqEfet = 0m }, vIBSMun = 0m }; + g.gCBS = new gCBS { pCBS = 0.9m, gRed = new gRed { pRedAliq = 60m, pAliqEfet = 0.36m }, vCBS = 0.36m }; + g.vIBS = 0.04m; + } + + //item 3: Imposto Seletivo + if (item == 3) + { + det.imposto.IS = new IS + { + CSTIS = "000", + cClassTribIS = "000001", + vBCIS = 100m, + pIS = 0.25m, + vIS = 0.25m + }; + } + } + + var dets = infNFe.det; + infNFe.total.IBSCBSTot = new IBSCBSTot + { + vBCIBSCBS = dets.Sum(d => d.imposto.IBSCBS.gIBSCBS.vBC), + gIBS = new gIBSTotal + { + gIBSUF = new gIBSUFTotal { vIBSUF = dets.Sum(d => d.imposto.IBSCBS.gIBSCBS.gIBSUF.vIBSUF) }, + gIBSMun = new gIBSMunTotal { vIBSMun = 0m }, + vIBS = dets.Sum(d => d.imposto.IBSCBS.gIBSCBS.gIBSUF.vIBSUF) + }, + gCBS = new gCBSTotal { vCBS = dets.Sum(d => d.imposto.IBSCBS.gIBSCBS.gCBS.vCBS) } + }; + infNFe.total.ISTot = new ISTot { vIS = dets.Where(d => d.imposto.IS != null).Sum(d => d.imposto.IS.vIS) }; + + if (comQuadrosFacultativos) + { + infNFe.total.ICMSTot.vFCP = 2m; + infNFe.total.ICMSTot.vFCPST = 0m; + infNFe.total.ICMSTot.qBCMono = 1000m; + infNFe.total.ICMSTot.vICMSMono = 1470m; + infNFe.total.IBSCBSTot.gMono = new gMonoTotal + { + vIBSMono = 12.3m, + vCBSMono = 110.7m, + vIBSMonoReten = 0m, + vCBSMonoReten = 0m + }; + } + else + { + infNFe.cobr = null; + infNFe.transp = new transp { modFrete = ModalidadeFrete.mfSemFrete }; + } + + return nfe; + } + } +} diff --git a/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.cs b/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.cs new file mode 100644 index 000000000..1f908dcfb --- /dev/null +++ b/NFe.Danfe.Html.Testes/Fixtures/NFeFixture.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using DFe.Classes.Entidades; +using DFe.Classes.Flags; +using NFe.Classes.Informacoes; +using NFe.Classes.Informacoes.Cobranca; +using NFe.Classes.Informacoes.Destinatario; +using NFe.Classes.Informacoes.Detalhe; +using NFe.Classes.Informacoes.Detalhe.Tributacao; +using NFe.Classes.Informacoes.Detalhe.Tributacao.Estadual; +using NFe.Classes.Informacoes.Detalhe.Tributacao.Estadual.Tipos; +using NFe.Classes.Informacoes.Detalhe.Tributacao.Federal; +using NFe.Classes.Informacoes.Detalhe.Tributacao.Federal.Tipos; +using NFe.Classes.Informacoes.Emitente; +using NFe.Classes.Informacoes.Identificacao; +using NFe.Classes.Informacoes.Identificacao.Tipos; +using NFe.Classes.Informacoes.Observacoes; +using NFe.Classes.Informacoes.Total; +using NFe.Classes.Informacoes.Transporte; + +namespace NFe.Danfe.Html.Testes.Fixtures +{ + /// + /// NF-e modelo 55 com os campos do leiaute anterior à Reforma Tributária (sem IBS/CBS/IS) + /// + public static partial class NFeFixture + { + public const string Chave = "35261012345678000199550010000012341000012340"; + + public static Classes.NFe CriarNfe(int quantidadeProdutos) + { + var det = new List(); + for (var i = 1; i <= quantidadeProdutos; i++) + det.Add(CriarItem(i)); + + var vProd = quantidadeProdutos * 100m; + var vIcms = quantidadeProdutos * 18m; + var vIpi = Math.Ceiling(quantidadeProdutos / 3m) * 5m; + + return new Classes.NFe + { + infNFe = new infNFe + { + versao = "4.00", + Id = "NFe" + Chave, + ide = new ide + { + cUF = Estado.SP, + cNF = "00001234", + natOp = "VENDA DE MERCADORIA ADQUIRIDA OU RECEBIDA DE TERCEIROS", + mod = ModeloDocumento.NFe, + serie = 1, + nNF = 1234, + dhEmi = new DateTimeOffset(2026, 10, 21, 10, 30, 0, TimeSpan.FromHours(-3)), + dhSaiEnt = new DateTimeOffset(2026, 10, 21, 11, 0, 0, TimeSpan.FromHours(-3)), + tpNF = TipoNFe.tnSaida, + idDest = DestinoOperacao.doInterna, + cMunFG = 3550308, + tpImp = TipoImpressao.tiRetrato, + tpEmis = TipoEmissao.teNormal, + cDV = 0, + tpAmb = TipoAmbiente.Producao, + finNFe = FinalidadeNFe.fnNormal, + indFinal = ConsumidorFinal.cfNao, + indPres = PresencaComprador.pcPresencial, + procEmi = ProcessoEmissao.peAplicativoContribuinte, + verProc = "DanfeHtmlTestes" + }, + emit = new emit + { + CNPJ = "12345678000199", + xNome = "POSTO EXEMPLO COMERCIO DE COMBUSTIVEIS LTDA", + xFant = "POSTO EXEMPLO", + IE = "110042490114", + IEST = "", + CRT = CRT.RegimeNormal, + enderEmit = new enderEmit + { + xLgr = "Avenida das Bombas", + nro = "1500", + xBairro = "Centro", + cMun = 3550308, + xMun = "Sao Paulo", + UF = Estado.SP, + CEP = "01001000", + fone = 1133334444 + } + }, + dest = new dest(VersaoServico.Versao400) + { + CNPJ = "98765432000188", + xNome = "Transportadora Cliente S/A", + IE = "110042490115", + indIEDest = indIEDest.ContribuinteICMS, + enderDest = new enderDest + { + xLgr = "Rodovia Exemplo km 10", + nro = "S/N", + xBairro = "Distrito Industrial", + cMun = 3550308, + xMun = "Sao Paulo", + UF = "SP", + CEP = "01002000", + fone = 1144445555 + } + }, + det = det, + total = new total + { + ICMSTot = new ICMSTot + { + vBC = vProd, + vICMS = vIcms, + vBCST = 0m, + vST = 0m, + vProd = vProd, + vFrete = 15m, + vSeg = 0m, + vDesc = 2.5m, + vOutro = 0m, + vII = 0m, + vIPI = vIpi, + vPIS = 1.65m * quantidadeProdutos, + vCOFINS = 7.6m * quantidadeProdutos, + vNF = vProd + 15m - 2.5m + vIpi, + vTotTrib = 0m + } + }, + transp = new transp + { + modFrete = ModalidadeFrete.mfContaEmitenteOumfContaRemetente, + transporta = new transporta + { + CNPJ = "22222222000122", + xNome = "Transportadora Exemplo", + IE = "333333333", + xEnder = "Rod. Exemplo, km 10", + xMun = "Campinas", + UF = "SP" + }, + vol = new List + { + new vol { qVol = 1, esp = "Volume", marca = "", nVol = "001", pesoB = 12.5m, pesoL = 11.9m } + } + }, + cobr = new cobr + { + dup = new List + { + new dup { nDup = "001", dVenc = new DateTime(2026, 11, 20), vDup = 60m }, + new dup { nDup = "002", dVenc = new DateTime(2026, 12, 20), vDup = 52.5m } + } + }, + infAdic = new infAdic + { + infCpl = "Documento emitido para teste do leiaute do DANFE HTML." + } + } + }; + } + + private static det CriarItem(int nItem) + { + //itens alternam descrição curta/longa e com/sem IPI para exercitar a paginação + var descricao = nItem % 4 == 0 + ? $"Produto teste {nItem:000} com uma descricao bem mais longa que o normal para ocupar mais de uma linha no quadro de produtos do DANFE" + : $"Produto teste {nItem:000}"; + + var item = new det + { + nItem = nItem, + prod = new prod + { + cProd = nItem.ToString("00000"), + cEAN = "SEM GTIN", + xProd = descricao, + NCM = "27101921", + CFOP = 5102, + uCom = "UN", + qCom = 1m, + vUnCom = 100m, + vProd = 100m, + cEANTrib = "SEM GTIN", + uTrib = "UN", + qTrib = 1m, + vUnTrib = 100m, + indTot = IndicadorTotal.ValorDoItemCompoeTotalNF + }, + imposto = new imposto + { + ICMS = new ICMS + { + TipoICMS = new ICMS00 + { + orig = OrigemMercadoria.OmNacional, + CST = Csticms.Cst00, + modBC = DeterminacaoBaseIcms.DbiValorOperacao, + vBC = 100m, + pICMS = 18m, + vICMS = 18m + } + } + }, + infAdProd = nItem % 3 == 1 ? $"Lote L{nItem:0000}" : null + }; + + if (nItem % 3 == 0) + { + item.imposto.IPI = new IPI + { + cEnq = 999, + TipoIPI = new IPITrib { CST = CSTIPI.ipi50, vBC = 100m, pIPI = 5m, vIPI = 5m } + }; + } + + return item; + } + } +} diff --git a/NFe.Danfe.Html.Testes/NFe.Danfe.Html.Testes.csproj b/NFe.Danfe.Html.Testes/NFe.Danfe.Html.Testes.csproj new file mode 100644 index 000000000..a13133048 --- /dev/null +++ b/NFe.Danfe.Html.Testes/NFe.Danfe.Html.Testes.csproj @@ -0,0 +1,26 @@ + + + + net8.0 + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/NFe.Danfe.Html/CrossCutting/Enumeradores.cs b/NFe.Danfe.Html/CrossCutting/Enumeradores.cs index 464ca1261..41e5f1c70 100644 --- a/NFe.Danfe.Html/CrossCutting/Enumeradores.cs +++ b/NFe.Danfe.Html/CrossCutting/Enumeradores.cs @@ -11,5 +11,22 @@ public enum Status Contingencia, EsperandoAutorizacao } - + + /// + /// Leiaute de impressão do DANFE NF-e + /// + public enum LeiauteDanfe + { + /// + /// Leiaute anterior à Reforma Tributária, sem os quadros de IBS, CBS e IS + /// + Atual, + + /// + /// Leiaute da NT 2026.010 (Reforma Tributária), com o quadro "Total do IBS/CBS/IS", o CRT do emitente + /// e as bases, alíquotas e valores de IBS, CBS e IS por item. Obrigatório a partir de 01/12/2026 + /// + ReformaTributaria + } + } diff --git a/NFe.Danfe.Html/DanfeNfeHtml2.ReformaTributaria.cs b/NFe.Danfe.Html/DanfeNfeHtml2.ReformaTributaria.cs new file mode 100644 index 000000000..fac900958 --- /dev/null +++ b/NFe.Danfe.Html/DanfeNfeHtml2.ReformaTributaria.cs @@ -0,0 +1,346 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using NFe.Danfe.Html.CrossCutting; +using NFe.Danfe.Html.Dominio; + +namespace NFe.Danfe.Html +{ + /// + /// Leiaute do DANFE NF-e da NT 2026.010 (Reforma Tributária), usado quando DanfeNFe.Leiaute = ReformaTributaria + /// + public partial class DanfeNfeHtml2 + { + #region Dimensões do leiaute (mm) + + //medidas aferidas no Chromium (impressão A4, mesmas opções do PDF via Playwright); cada página fica abaixo de 285 mm. + //o item tem altura fixa (4 linhas: descrição, informações adicionais, NCM/cClassTrib e tributos), o que torna a paginação previsível + private const decimal AlturaLinhaProdutoRtc = 10.25m; + private const decimal AlturaCabecalhoTabelaProdutosRtc = 3.5m; + + //quadro de produtos na primeira página com todos os quadros facultativos impressos + private const decimal AlturaQuadroProdutosPrimeiraPaginaRtc = 41m; + private const decimal AlturaQuadroProdutosDemaisPaginasRtc = 185m; + private const decimal AlturaDadosAdicionaisRtc = 24m; + + //espaço devolvido ao quadro de produtos quando um quadro facultativo não é impresso + private static readonly Dictionary AlturaSecoesFacultativasRtc = new Dictionary + { + { "fatura", 8.12m }, + { "fcp", 6.44m }, + { "icms_mono", 6.44m }, + { "ibscbs_mono", 6.44m }, + { "issqn", 9.88m }, + { "transporte", 25.28m } + }; + + #endregion + + private static readonly CultureInfo CulturaBrasil = CultureInfo.GetCultureInfo("pt-BR"); + + private bool LeiauteReformaTributaria => _danfe.Leiaute == LeiauteDanfe.ReformaTributaria; + + private string MontarDanfeReformaTributaria(DanfeNFe danfeNfe) + { + var produtos = danfeNfe.Produtos.ToList(); + var secoes = ObterSecoesFacultativasRtc(danfeNfe); + + var alturaQuadroPrimeiraPagina = AlturaQuadroProdutosPrimeiraPaginaRtc + + secoes.Where(s => !s.Value).Sum(s => AlturaSecoesFacultativasRtc[s.Key]); + var itensPrimeiraPagina = ObterCapacidadeQuadroProdutosRtc(alturaQuadroPrimeiraPagina); + var itensDemaisPaginas = ObterCapacidadeQuadroProdutosRtc(AlturaQuadroProdutosDemaisPaginasRtc); + + var restantes = Math.Max(0, produtos.Count - itensPrimeiraPagina); + var totalPaginas = 1 + (int)Math.Ceiling((double)restantes / itensDemaisPaginas); + + var html = MontarPaginaInicialRtc(danfeNfe, produtos.Take(itensPrimeiraPagina), secoes, alturaQuadroPrimeiraPagina, + totalPaginas.ToString()); + html = MontarMarcaDagua(danfeNfe, html); + + var skip = itensPrimeiraPagina; + for (var pagina = 2; pagina <= totalPaginas; pagina++) + { + var proximaPagina = MontarPaginaSubsequenteRtc(danfeNfe, produtos.Skip(skip).Take(itensDemaisPaginas), + pagina.ToString(), totalPaginas.ToString()); + proximaPagina = MontarMarcaDagua(danfeNfe, proximaPagina); + html = AdicionarProximaPagina(html, proximaPagina); + skip += itensDemaisPaginas; + } + + return FinalizarProcesso(html); + } + + private static int ObterCapacidadeQuadroProdutosRtc(decimal alturaQuadro) + { + return Math.Max(1, (int)Math.Floor((alturaQuadro - AlturaCabecalhoTabelaProdutosRtc) / AlturaLinhaProdutoRtc)); + } + + /// + /// Quadros de exibição facultativa (NT 2026.010, item 4.4): só são impressos quando a informação existe no XML + /// + private static Dictionary ObterSecoesFacultativasRtc(DanfeNFe danfeNfe) + { + var imposto = danfeNfe.ImpostoReformaTributaria; + return new Dictionary + { + { "fatura", danfeNfe.Faturas != null && danfeNfe.Faturas.Any() }, + { "fcp", new[] { imposto.vFCP, imposto.vFCPST, imposto.vICMSUFDest, imposto.vFCPUFDest }.Any(v => v > 0) }, + { "icms_mono", new[] { imposto.qBCMono, imposto.vICMSMono, imposto.qBCMonoReten, imposto.vICMSMonoReten }.Any(v => v.HasValue) }, + { "ibscbs_mono", imposto.PossuiMonofasia }, + { "issqn", danfeNfe.ISsqn != null }, + { "transporte", danfeNfe.Transportadora != null || (danfeNfe.Volumes != null && danfeNfe.Volumes.Any()) } + }; + } + + private string MontarPaginaInicialRtc(DanfeNFe danfeNfe, IEnumerable produtos, Dictionary secoes, + decimal alturaQuadroProdutos, string qtdPaginasTotal) + { + var html = Resource.danfe_model_55_nfe_rtc_page_one; + foreach (var secao in secoes) + html = AplicarSecao(html, secao.Key, secao.Value); + + html = Substituir(html, new Dictionary + { + { "[cabecalho_rtc]", MontarCabecalhoRtc(danfeNfe, "1", qtdPaginasTotal) }, + { "[produtos_rtc]", MontarQuadroProdutosRtc(produtos, alturaQuadroProdutos) }, + { "[altura_dados_adicionais]", FormatarMilimetros(AlturaDadosAdicionaisRtc) }, + { "[altura_linha_produto]", FormatarMilimetros(AlturaLinhaProdutoRtc - 0.85m) } + }); + + html = MontarCanhotoRecibo(danfeNfe, html); + html = Substituir(html, new Dictionary { { "[ds_company_issuer_name]", danfeNfe.Emitente.Nome } }); + html = MontarFaturasRtc(danfeNfe, html); + html = MontarTotaisRtc(danfeNfe, html); + html = MontarTransportadoraRtc(danfeNfe, html); + html = MontarInformacoesAdicionais(danfeNfe, html); + html = MontarCreditos(danfeNfe, html); + return html; + } + + private string MontarPaginaSubsequenteRtc(DanfeNFe danfeNfe, IEnumerable produtos, string paginaAtual, + string qtdPaginasTotal) + { + var html = Substituir(Resource.danfe_model_55_nfe_rtc_page_next, new Dictionary + { + { "[cabecalho_rtc]", MontarCabecalhoRtc(danfeNfe, paginaAtual, qtdPaginasTotal) }, + { "[produtos_rtc]", MontarQuadroProdutosRtc(produtos, AlturaQuadroProdutosDemaisPaginasRtc) } + }); + return MontarCreditos(danfeNfe, html); + } + + private string MontarCabecalhoRtc(DanfeNFe danfeNfe, string paginaAtual, string qtdPaginasTotal) + { + var html = MontarCabecalho(danfeNfe, Resource.danfe_model_55_nfe_rtc_cabecalho, paginaAtual, qtdPaginasTotal); + html = MontarDestinatarioEmitente(danfeNfe, html); + return Substituir(html, new Dictionary { { "[ds_company_crt]", danfeNfe.Emitente.Crt } }); + } + + private string MontarQuadroProdutosRtc(IEnumerable produtos, decimal alturaQuadro) + { + var linhas = new StringBuilder(); + foreach (var produto in produtos) + linhas.Append(MontarLinhaTabelaProdutoRtc(produto)); + + return Substituir(Resource.danfe_model_55_nfe_rtc_produtos, new Dictionary + { + { "[altura_quadro_produtos]", FormatarMilimetros(alturaQuadro) }, + { "[itens_products]", linhas.ToString() } + }); + } + + /// + /// Linha do item no quadro "Dados dos produtos/serviços" (NT 2026.010, item 4.3) + /// + /// Alíquotas de IBS UF, IBS Município e CBS: a efetiva (pAliqEfet) quando houver gRed; caso contrário, a + /// vigente. Campos de grupos ausentes no XML ficam em branco + /// + /// + private string MontarLinhaTabelaProdutoRtc(Produto produto) + { + var rtc = produto.ReformaTributaria ?? new ProdutoReformaTributaria(); + var temInfAdic = !string.IsNullOrWhiteSpace(produto.InfAdic); + + var descricao = new StringBuilder(); + descricao.Append($"
"); + descricao.Append($"{Html(produto.Codigo)} {Html(produto.Descricao)}
"); + if (temInfAdic) + descricao.Append($"{Html(produto.InfAdic)}"); + var cClassTrib = string.IsNullOrEmpty(rtc.cClassTrib) ? string.Empty : $" [cClassTrib {Html(rtc.cClassTrib)}]"; + descricao.Append($"[NCM {Html(produto.Ncm)}]{cClassTrib}"); + + var bases = MontarTabelaTributosRtc( + ("ICMS", FormatarValorRtc(produto.BaseCalculo)), + ("IBS / CBS", FormatarValorRtc(rtc.vBCIBSCBS)), + ("IS", FormatarValorRtc(rtc.vBCIS)), + ("IPI", FormatarValorRtc(rtc.vBCIPI))); + + var aliquotas = MontarTabelaTributosParesRtc( + ("ICMS", FormatarAliquotaRtc(produto.PIcms), "CBS", FormatarAliquotaRtc(rtc.pCBS)), + ("IBS UF", FormatarAliquotaRtc(rtc.pIBSUF), "IPI", FormatarAliquotaRtc(produto.PIpi)), + ("IBS MUN", FormatarAliquotaRtc(rtc.pIBSMun), "IS", FormatarAliquotaRtc(rtc.pIS))); + + var valores = MontarTabelaTributosParesRtc( + ("ICMS", FormatarValorRtc(produto.VIcms), "CBS", FormatarValorRtc(rtc.vCBS)), + ("IBS UF", FormatarValorRtc(rtc.vIBSUF), "IPI", FormatarValorRtc(produto.ValorIpi)), + ("IBS MUN", FormatarValorRtc(rtc.vIBSMun), "IS", FormatarValorRtc(rtc.vIS))); + + var sb = new StringBuilder(); + sb.Append(""); + sb.Append($"{descricao}"); + sb.Append($"CST {Html(rtc.CstIcms ?? produto.Origem)}CFOP {Html(produto.Cfop)}"); + sb.Append($"{FormatarQuantidadeRtc(produto.Quantidade)}[{Html(produto.Unidade)}]"); + sb.Append($"{FormatarValorUnitarioRtc(produto.ValorUnitario)}"); + sb.Append($"{FormatarValorRtc(produto.ValorTotal)}"); + sb.Append($"{bases}"); + sb.Append($"{aliquotas}"); + sb.Append($"{valores}"); + sb.Append(""); + return sb.ToString(); + } + + private static string MontarTabelaTributosRtc(params (string rotulo, string valor)[] linhas) + { + var sb = new StringBuilder(""); + foreach (var (rotulo, valor) in linhas) + sb.Append($""); + sb.Append("
{rotulo}{valor}
"); + return sb.ToString(); + } + + private static string MontarTabelaTributosParesRtc(params (string rotulo1, string valor1, string rotulo2, string valor2)[] linhas) + { + var sb = new StringBuilder(""); + foreach (var (rotulo1, valor1, rotulo2, valor2) in linhas) + sb.Append($""); + sb.Append("
{rotulo1}{valor1}/{rotulo2}{valor2}
"); + return sb.ToString(); + } + + private string MontarFaturasRtc(DanfeNFe danfeNfe, string nfeHtml) + { + var faturas = (danfeNfe.Faturas ?? new List()) + .Select(f => $"Nº {Html(f.NumFatura)}  Venc. {f.DataVencimento:dd/MM/yyyy}  Valor {FormatarValorRtc(f.Valor)}"); + return Substituir(nfeHtml, new Dictionary { { "[duplicates]", string.Join("  |  ", faturas) } }); + } + + private string MontarTotaisRtc(DanfeNFe danfeNfe, string nfeHtml) + { + var imposto = danfeNfe.Imposto; + var rtc = danfeNfe.ImpostoReformaTributaria; + var issqn = danfeNfe.ISsqn; + return Substituir(nfeHtml, new Dictionary + { + { "[vl_total_prod]", FormatarValorRtc(imposto.vProd) }, + { "[vl_shipping]", FormatarValorRtc(imposto.vFrete) }, + { "[vl_insurance]", FormatarValorRtc(imposto.vSeg) }, + { "[vl_discount]", FormatarValorRtc(imposto.vDesc) }, + { "[vl_other_expense]", FormatarValorRtc(imposto.vOutro) }, + { "[vl_total]", FormatarValorRtc(imposto.vNF) }, + { "[tot_bc_icms]", FormatarValorRtc(imposto.vBCIMS) }, + { "[tot_icms]", FormatarValorRtc(imposto.vICMS) }, + { "[tot_bc_icms_st]", FormatarValorRtc(imposto.vBCICMSST ?? 0) }, + { "[tot_icms_st]", FormatarValorRtc(imposto.vICMSST ?? 0) }, + { "[tot_total_ipi_tax]", FormatarValorRtc(imposto.vIpi) }, + { "[tot_fcp]", FormatarValorRtc(rtc.vFCP) }, + { "[tot_fcp_st]", FormatarValorRtc(rtc.vFCPST) }, + { "[tot_icms_uf_dest]", FormatarValorRtc(rtc.vICMSUFDest) }, + { "[tot_fcp_uf_dest]", FormatarValorRtc(rtc.vFCPUFDest) }, + { "[tot_qbc_mono]", FormatarQuantidadeRtc(rtc.qBCMono) }, + { "[tot_icms_mono]", FormatarValorRtc(rtc.vICMSMono) }, + { "[tot_qbc_mono_reten]", FormatarQuantidadeRtc(rtc.qBCMonoReten) }, + { "[tot_icms_mono_reten]", FormatarValorRtc(rtc.vICMSMonoReten) }, + { "[tot_cbs]", FormatarValorRtc(rtc.vCBS) }, + { "[tot_ibs_uf]", FormatarValorRtc(rtc.vIBSUF) }, + { "[tot_ibs_mun]", FormatarValorRtc(rtc.vIBSMun) }, + { "[tot_is]", FormatarValorRtc(rtc.vIS) }, + { "[tot_ibs_mono]", FormatarValorRtc(rtc.vIBSMono) }, + { "[tot_cbs_mono]", FormatarValorRtc(rtc.vCBSMono) }, + { "[tot_ibs_mono_reten]", FormatarValorRtc(rtc.vIBSMonoReten) }, + { "[tot_cbs_mono_reten]", FormatarValorRtc(rtc.vCBSMonoReten) }, + { "[ds_company_im]", Html(issqn?.Im) }, + { "[vl_total_serv]", FormatarValorRtc(issqn?.ValorTotServ) }, + { "[tot_bc_issqn]", FormatarValorRtc(issqn?.BaseCalculo) }, + { "[tot_issqn]", FormatarValorRtc(issqn?.ValorIssqn) } + }); + } + + private string MontarTransportadoraRtc(DanfeNFe danfeNfe, string nfeHtml) + { + var transportadora = danfeNfe.Transportadora; + var volume = danfeNfe.Volumes?.FirstOrDefault(); + return Substituir(nfeHtml, new Dictionary + { + { "[ds_transport_carrier_name]", Html(transportadora?.Nome) }, + { "[ds_transport_shipping_type]", Html(danfeNfe.ModalidadeFreteDescricao) }, + { "[ds_transport_rntc]", Html(transportadora?.CodAntt) }, + { "[ds_transport_vehicle_plate]", Html(transportadora?.Placa) }, + { "[ds_transport_vehicle_uf]", string.IsNullOrEmpty(transportadora?.Placa) ? string.Empty : Html(transportadora?.Endereco?.Uf) }, + { "[nl_transport_cnpj_cpf]", CrossCutting.Utils.FormatarCnpjCpf(transportadora?.CnpjCpf) }, + { "[ds_transport_address]", Html($"{transportadora?.Endereco?.NomeEnd} {transportadora?.Endereco?.Num}".Trim()) }, + { "[ds_transport_city]", Html(transportadora?.Endereco?.Cidade) }, + { "[ds_transport_uf]", Html(transportadora?.Endereco?.Uf) }, + { "[ds_transport_ie]", Html(transportadora?.Ie) }, + { "[nu_transport_amount_transported_volumes]", volume?.Quantidade?.ToString("#,##0", CulturaBrasil) }, + { "[ds_transport_type_volumes_transported]", Html(volume?.Especie) }, + { "[ds_transport_mark_volumes_transported]", Html(volume?.Marca) }, + { "[ds_transport_number_volumes_transported]", Html(volume?.NumeroVolume) }, + { "[vl_transport_gross_weight]", volume == null ? string.Empty : $"{volume.PesoBruto.ToString("#,##0.000", CulturaBrasil)} kg" }, + { "[vl_transport_net_weight]", volume == null ? string.Empty : $"{volume.PesoLiq.ToString("#,##0.000", CulturaBrasil)} kg" } + }); + } + + /// + /// Mantém ou remove um trecho do template delimitado por <!--[secao:nome]--> e <!--[/secao:nome]--> + /// + private static string AplicarSecao(string html, string secao, bool exibir) + { + var inicio = $""; + var fim = $""; + var posInicio = html.IndexOf(inicio, StringComparison.Ordinal); + var posFim = html.IndexOf(fim, StringComparison.Ordinal); + if (posInicio < 0 || posFim < posInicio) return html; + + return exibir + ? html.Remove(posFim, fim.Length).Remove(posInicio, inicio.Length) + : html.Remove(posInicio, posFim + fim.Length - posInicio); + } + + private static string Html(string texto) + { + return string.IsNullOrEmpty(texto) ? string.Empty : WebUtility.HtmlEncode(texto); + } + + private static string FormatarValorRtc(decimal valor) + { + return valor.ToString("N2", CulturaBrasil); + } + + private static string FormatarValorRtc(decimal? valor) + { + return valor.HasValue ? FormatarValorRtc(valor.Value) : string.Empty; + } + + private static string FormatarValorUnitarioRtc(decimal valor) + { + return valor.ToString("#,##0.00########", CulturaBrasil); + } + + private static string FormatarQuantidadeRtc(decimal? valor) + { + return valor?.ToString("#,##0.00##", CulturaBrasil) ?? string.Empty; + } + + private static string FormatarAliquotaRtc(decimal? valor) + { + return valor.HasValue ? $"{valor.Value.ToString("0.00##", CulturaBrasil)}%" : string.Empty; + } + + private static string FormatarMilimetros(decimal valor) + { + return valor.ToString("0.##", CultureInfo.InvariantCulture); + } + } +} diff --git a/NFe.Danfe.Html/DanfeNfeHtml2.cs b/NFe.Danfe.Html/DanfeNfeHtml2.cs index e1e98a834..3af93afa2 100644 --- a/NFe.Danfe.Html/DanfeNfeHtml2.cs +++ b/NFe.Danfe.Html/DanfeNfeHtml2.cs @@ -24,7 +24,7 @@ namespace NFe.Danfe.Html { - public class DanfeNfeHtml2 : IDanfeHtml2 + public partial class DanfeNfeHtml2 : IDanfeHtml2 { #region Propriedades @@ -356,6 +356,8 @@ private int ObterQuantidadeMaximaPaginas(IList produtos) /// private string MontarDanfe(DanfeNFe danfeNfe) { + if (LeiauteReformaTributaria) return MontarDanfeReformaTributaria(danfeNfe); + var sbHtmlPage = new StringBuilder(); int paginaAtual = 1; var qtdLinhasPrimeiraPagina = ObterQuantidadeLinhasPrimeiraPagina(danfeNfe.Produtos.ToList()); diff --git a/NFe.Danfe.Html/Dominio/DanfeNFe.cs b/NFe.Danfe.Html/Dominio/DanfeNFe.cs index 18bc0ceaa..b32877458 100644 --- a/NFe.Danfe.Html/Dominio/DanfeNFe.cs +++ b/NFe.Danfe.Html/Dominio/DanfeNFe.cs @@ -12,7 +12,10 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; using DFe.Classes.Flags; +using NFe.Classes.Informacoes.Emitente; using NFe.Classes.Informacoes.Identificacao.Tipos; using NFe.Classes.Informacoes.Transporte; using NFe.Danfe.Html.CrossCutting; @@ -112,6 +115,21 @@ public class DanfeNFe /// public string Creditos { get; } + /// + /// Leiaute de impressão. O padrão é o leiaute atual; ReformaTributaria segue a NT 2026.010 + /// + public LeiauteDanfe Leiaute { get; } + + /// + /// Totais exibidos somente no leiaute da NT 2026.010 (IBS, CBS, IS, FCP e monofásicos). Nulo no leiaute atual + /// + public ImpostoReformaTributaria ImpostoReformaTributaria { get; private set; } + + /// + /// X02 - Modalidade do frete, já formatada para impressão (ex.: "0 - Remetente") + /// + public string ModalidadeFreteDescricao { get; private set; } + #endregion #region Construtor @@ -177,6 +195,20 @@ public class DanfeNFe /// Créditos /// ISSQN public DanfeNFe(Classes.NFe nfe, Status status,string protocolo, string creditos, Issqn issqn = null, string logo = "") + : this(nfe, status, protocolo, creditos, LeiauteDanfe.Atual, issqn, logo) + { + } + + /// + /// + /// + /// Status + /// Número do protocolo retornado pela SEFAZ + /// Créditos + /// Leiaute de impressão (atual ou NT 2026.010) + /// ISSQN + /// Imagem em base64 + public DanfeNFe(Classes.NFe nfe, Status status, string protocolo, string creditos, LeiauteDanfe leiaute, Issqn issqn = null, string logo = "") { if (nfe == null) throw new ArgumentNullException(nameof(nfe)); if(nfe.infNFe.ide.mod!=ModeloDocumento.NFe) throw new InvalidOperationException("Modelo da nota imcompatível com o esperado 55"); @@ -354,7 +386,7 @@ public DanfeNFe(Classes.NFe nfe, Status status,string protocolo, string creditos Imposto = new Imposto(nfe.infNFe.total.ICMSTot.vBC, nfe.infNFe.total.ICMSTot.vICMS, nfe.infNFe.total.ICMSTot.vBCST, nfe.infNFe.total.ICMSTot.vST, nfe.infNFe.total.ICMSTot.vProd, nfe.infNFe.total.ICMSTot.vFrete, nfe.infNFe.total.ICMSTot.vSeg, nfe.infNFe.total.ICMSTot.vDesc, nfe.infNFe.total.ICMSTot.vOutro, - nfe.infNFe.total.ICMSTot.vIPI, nfe.infNFe.total.ICMSTot.vNF,nfe.infNFe.total.ICMSTot.vTotTrib, + nfe.infNFe.total.ICMSTot.vIPI, nfe.infNFe.total.ICMSTot.vNF,nfe.infNFe.total.ICMSTot.vTotTrib ?? 0, nfe.infNFe.total.ICMSTot.vPIS, nfe.infNFe.total.ICMSTot.vCOFINS, nfe.infNFe.total.ICMSTot.vICMSUFRemet, nfe.infNFe.total.ICMSTot.vICMSUFDest); @@ -373,10 +405,90 @@ public DanfeNFe(Classes.NFe nfe, Status status,string protocolo, string creditos ValorTotNota = Imposto.vNF; NumNota = nfe.infNFe.ide.nNF.ToString(); SerieNota = nfe.infNFe.ide.serie.ToString(); - + + Leiaute = leiaute; + if (leiaute == LeiauteDanfe.ReformaTributaria) + PreencherReformaTributaria(nfe); } #endregion + + /// + /// Preenche o CRT, os totais e a tributação por item usados pelo leiaute da NT 2026.010 + /// Os grupos ausentes no XML ficam nulos e não são impressos + /// + private void PreencherReformaTributaria(Classes.NFe nfe) + { + var crt = nfe.infNFe.emit.CRT; + var descricaoCrt = typeof(CRT).GetField(crt.ToString())? + .GetCustomAttributes(typeof(DescriptionAttribute), false) + .OfType().FirstOrDefault()?.Description; + Emitente.Crt = $"{(int)crt} - {descricaoCrt?.ToUpper()}"; + + if (nfe.infNFe.transp != null) + { + var modFrete = nfe.infNFe.transp.modFrete; + string descricaoFrete; + switch (modFrete) + { + case ModalidadeFrete.mfContaEmitenteOumfContaRemetente: descricaoFrete = "Remetente"; break; + case ModalidadeFrete.mfContaDestinatario: descricaoFrete = "Destinatário"; break; + case ModalidadeFrete.mfContaTerceiros: descricaoFrete = "Terceiros"; break; + case ModalidadeFrete.mfProprioContaRemente: descricaoFrete = "Próprio Remetente"; break; + case ModalidadeFrete.mfProprioContaDestinatario: descricaoFrete = "Próprio Destinatário"; break; + default: descricaoFrete = "Sem Frete"; break; + } + ModalidadeFreteDescricao = $"{(int)modFrete} - {descricaoFrete}"; + } + + var icmsTot = nfe.infNFe.total.ICMSTot; + var ibscbsTot = nfe.infNFe.total.IBSCBSTot; + ImpostoReformaTributaria = new ImpostoReformaTributaria + { + vFCP = icmsTot.vFCP, + vFCPST = icmsTot.vFCPST, + vICMSUFDest = icmsTot.vICMSUFDest, + vFCPUFDest = icmsTot.vFCPUFDest, + qBCMono = icmsTot.qBCMono, + vICMSMono = icmsTot.vICMSMono, + qBCMonoReten = icmsTot.qBCMonoReten, + vICMSMonoReten = icmsTot.vICMSMonoReten, + vCBS = ibscbsTot?.gCBS?.vCBS ?? 0, + vIBSUF = ibscbsTot?.gIBS?.gIBSUF?.vIBSUF ?? 0, + vIBSMun = ibscbsTot?.gIBS?.gIBSMun?.vIBSMun ?? 0, + vIS = nfe.infNFe.total.ISTot?.vIS ?? 0, + PossuiMonofasia = ibscbsTot?.gMono != null, + vIBSMono = ibscbsTot?.gMono?.vIBSMono ?? 0, + vCBSMono = ibscbsTot?.gMono?.vCBSMono ?? 0, + vIBSMonoReten = ibscbsTot?.gMono?.vIBSMonoReten ?? 0, + vCBSMonoReten = ibscbsTot?.gMono?.vCBSMonoReten ?? 0 + }; + + //os produtos foram adicionados na mesma ordem dos itens (det) + var produtos = Produtos.ToList(); + for (var i = 0; i < nfe.infNFe.det.Count; i++) + { + var imposto = nfe.infNFe.det[i].imposto; + var gIBSCBS = imposto?.IBSCBS?.gIBSCBS; + produtos[i].ReformaTributaria = new ProdutoReformaTributaria + { + CstIcms = imposto?.ICMS?.TipoICMS == null ? null + : imposto.ICMS.TipoICMS.orig() + imposto.ICMS.TipoICMS.Cst() + imposto.ICMS.TipoICMS.Csosn(), + cClassTrib = imposto?.IBSCBS?.cClassTrib, + vBCIBSCBS = gIBSCBS?.vBC, + pIBSUF = gIBSCBS?.gIBSUF == null ? (decimal?)null : gIBSCBS.gIBSUF.gRed?.pAliqEfet ?? gIBSCBS.gIBSUF.pIBSUF, + vIBSUF = gIBSCBS?.gIBSUF?.vIBSUF, + pIBSMun = gIBSCBS?.gIBSMun == null ? (decimal?)null : gIBSCBS.gIBSMun.gRed?.pAliqEfet ?? gIBSCBS.gIBSMun.pIBSMun, + vIBSMun = gIBSCBS?.gIBSMun?.vIBSMun, + pCBS = gIBSCBS?.gCBS == null ? (decimal?)null : gIBSCBS.gCBS.gRed?.pAliqEfet ?? gIBSCBS.gCBS.pCBS, + vCBS = gIBSCBS?.gCBS?.vCBS, + vBCIS = imposto?.IS?.vBCIS, + pIS = imposto?.IS?.pIS, + vIS = imposto?.IS?.vIS, + vBCIPI = imposto?.IPI?.TipoIPI?.vBC() + }; + } + } } } diff --git a/NFe.Danfe.Html/Dominio/Emitente.cs b/NFe.Danfe.Html/Dominio/Emitente.cs index ff12601dd..79926b994 100644 --- a/NFe.Danfe.Html/Dominio/Emitente.cs +++ b/NFe.Danfe.Html/Dominio/Emitente.cs @@ -36,6 +36,11 @@ public class Emitente public Endereco Endereco { get; } + /// + /// C21 - Código do Regime Tributário, já formatado para impressão (ex.: "3 - REGIME NORMAL") + /// + public string Crt { get; internal set; } + #endregion #region Construtor diff --git a/NFe.Danfe.Html/Dominio/ImpostoReformaTributaria.cs b/NFe.Danfe.Html/Dominio/ImpostoReformaTributaria.cs new file mode 100644 index 000000000..4e437ba95 --- /dev/null +++ b/NFe.Danfe.Html/Dominio/ImpostoReformaTributaria.cs @@ -0,0 +1,97 @@ +namespace NFe.Danfe.Html.Dominio +{ + /// + /// Totais da nota exibidos somente no leiaute da NT 2026.010 (Reforma Tributária) + /// + public class ImpostoReformaTributaria + { + #region Propriedades + + /// + /// W04h - Valor do FCP + /// + public decimal? vFCP { get; set; } + + /// + /// W06a - Valor do FCP retido por ST + /// + public decimal? vFCPST { get; set; } + + /// + /// W04e - Valor do ICMS (DIFAL) na UF de destino + /// + public decimal? vICMSUFDest { get; set; } + + /// + /// W04c - Valor do FCP na UF de destino + /// + public decimal? vFCPUFDest { get; set; } + + /// + /// W06b.1 - BC (quantidade) do ICMS monofásico + /// + public decimal? qBCMono { get; set; } + + /// + /// W06c - Valor do ICMS monofásico + /// + public decimal? vICMSMono { get; set; } + + /// + /// W06c.1 - BC (quantidade) do ICMS monofásico por retenção + /// + public decimal? qBCMonoReten { get; set; } + + /// + /// W06d - Valor do ICMS monofásico por retenção + /// + public decimal? vICMSMonoReten { get; set; } + + /// + /// W56 - Valor da CBS + /// + public decimal vCBS { get; set; } + + /// + /// W41 - Valor do IBS UF + /// + public decimal vIBSUF { get; set; } + + /// + /// W46 - Valor do IBS Município + /// + public decimal vIBSMun { get; set; } + + /// + /// W33 - Valor do Imposto Seletivo + /// + public decimal vIS { get; set; } + + /// + /// Indica se o grupo de monofasia (gMono - W57) foi informado + /// + public bool PossuiMonofasia { get; set; } + + /// + /// W58 - Valor do IBS monofásico + /// + public decimal vIBSMono { get; set; } + + /// + /// W59 - Valor da CBS monofásica + /// + public decimal vCBSMono { get; set; } + + /// + /// W59a - Valor do IBS monofásico por retenção + /// + public decimal vIBSMonoReten { get; set; } + + /// + /// W59b - Valor da CBS monofásica por retenção + /// + public decimal vCBSMonoReten { get; set; } + + #endregion + } +} diff --git a/NFe.Danfe.Html/Dominio/Produto.cs b/NFe.Danfe.Html/Dominio/Produto.cs index 8d70e7c55..259ed92df 100644 --- a/NFe.Danfe.Html/Dominio/Produto.cs +++ b/NFe.Danfe.Html/Dominio/Produto.cs @@ -84,6 +84,11 @@ public class Produto /// public decimal? PIpi { get; } + /// + /// Tributação do item para o leiaute da NT 2026.010 (Reforma Tributária) + /// + public ProdutoReformaTributaria ReformaTributaria { get; internal set; } + /// /// Valor Total /// diff --git a/NFe.Danfe.Html/Dominio/ProdutoReformaTributaria.cs b/NFe.Danfe.Html/Dominio/ProdutoReformaTributaria.cs new file mode 100644 index 000000000..8ddf75421 --- /dev/null +++ b/NFe.Danfe.Html/Dominio/ProdutoReformaTributaria.cs @@ -0,0 +1,77 @@ +namespace NFe.Danfe.Html.Dominio +{ + /// + /// Tributação do item exibida somente no leiaute da NT 2026.010 (Reforma Tributária) + /// + public class ProdutoReformaTributaria + { + #region Propriedades + + /// + /// Origem + CST (ou CSOSN) do ICMS, como impresso no DANFE (ex.: "000") + /// + public string CstIcms { get; set; } + + /// + /// UB14 - Classificação Tributária do IBS/CBS + /// + public string cClassTrib { get; set; } + + /// + /// UB16 - Base de cálculo do IBS/CBS + /// + public decimal? vBCIBSCBS { get; set; } + + /// + /// UB18 (pIBSUF) ou UB28 (pAliqEfet) quando houver gRed + /// + public decimal? pIBSUF { get; set; } + + /// + /// UB35 - Valor do IBS UF + /// + public decimal? vIBSUF { get; set; } + + /// + /// UB37 (pIBSMun) ou UB47 (pAliqEfet) quando houver gRed + /// + public decimal? pIBSMun { get; set; } + + /// + /// UB54 - Valor do IBS Município + /// + public decimal? vIBSMun { get; set; } + + /// + /// UB56 (pCBS) ou UB66 (pAliqEfet) quando houver gRed + /// + public decimal? pCBS { get; set; } + + /// + /// UB67 - Valor da CBS + /// + public decimal? vCBS { get; set; } + + /// + /// UB05 - Base de cálculo do IS + /// + public decimal? vBCIS { get; set; } + + /// + /// UB06 - Alíquota do IS + /// + public decimal? pIS { get; set; } + + /// + /// UB11 - Valor do IS + /// + public decimal? vIS { get; set; } + + /// + /// O10 - Base de cálculo do IPI + /// + public decimal? vBCIPI { get; set; } + + #endregion + } +} diff --git a/NFe.Danfe.Html/NFe.Danfe.Html.csproj b/NFe.Danfe.Html/NFe.Danfe.Html.csproj index a660375bd..70ea43605 100644 --- a/NFe.Danfe.Html/NFe.Danfe.Html.csproj +++ b/NFe.Danfe.Html/NFe.Danfe.Html.csproj @@ -6,7 +6,10 @@ - + + + + diff --git a/NFe.Danfe.Html/Resource.Designer.cs b/NFe.Danfe.Html/Resource.Designer.cs index 954ccf63a..8629f2dae 100644 --- a/NFe.Danfe.Html/Resource.Designer.cs +++ b/NFe.Danfe.Html/Resource.Designer.cs @@ -121,5 +121,41 @@ internal static string danfe_model_55_nfe_page_one { return ResourceManager.GetString("danfe_model_55_nfe_page_one", resourceCulture); } } + + /// + /// Cabeçalho, emitente, regime tributário e destinatário do leiaute da NT 2026.010. + /// + internal static string danfe_model_55_nfe_rtc_cabecalho { + get { + return ResourceManager.GetString("danfe_model_55_nfe_rtc_cabecalho", resourceCulture); + } + } + + /// + /// Páginas subsequentes do leiaute da NT 2026.010. + /// + internal static string danfe_model_55_nfe_rtc_page_next { + get { + return ResourceManager.GetString("danfe_model_55_nfe_rtc_page_next", resourceCulture); + } + } + + /// + /// Primeira página do leiaute da NT 2026.010. + /// + internal static string danfe_model_55_nfe_rtc_page_one { + get { + return ResourceManager.GetString("danfe_model_55_nfe_rtc_page_one", resourceCulture); + } + } + + /// + /// Quadro de produtos/serviços do leiaute da NT 2026.010. + /// + internal static string danfe_model_55_nfe_rtc_produtos { + get { + return ResourceManager.GetString("danfe_model_55_nfe_rtc_produtos", resourceCulture); + } + } } } diff --git a/NFe.Danfe.Html/Resource.resx b/NFe.Danfe.Html/Resource.resx index f3e6df90a..368741a01 100644 --- a/NFe.Danfe.Html/Resource.resx +++ b/NFe.Danfe.Html/Resource.resx @@ -124,4 +124,16 @@ Resources\danfe-model-55-nfe-page-one.html;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + Resources\danfe-model-55-nfe-rtc-cabecalho.html;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + Resources\danfe-model-55-nfe-rtc-page-next.html;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + Resources\danfe-model-55-nfe-rtc-page-one.html;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + Resources\danfe-model-55-nfe-rtc-produtos.html;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + \ No newline at end of file diff --git a/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-cabecalho.html b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-cabecalho.html new file mode 100644 index 000000000..456d2353d --- /dev/null +++ b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-cabecalho.html @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + +
+ + + [ds_company_issuer_name] + [ds_company_address] + + [ds_company_neighborhood] - [nu_company_cep] + + + [ds_company_city_name] - [ds_company_uf]- Fone: + [nl_company_phone_number] + + +

Danfe

+

Documento auxiliar da Nota Fiscal Eletrônica

+

+ + [ds_code_operation_type] + + + 0 - Entrada + 1 - Saída + +

+

+ + Nº + [nl_invoice] + + + SÉRIE: + [ds_invoice_serie] + + + Folha + [actual_page] + / + [total_pages] + +

+
+ Controle do Fisco + + + +
+ CHAVE DE ACESSO + [ds_danfe] +
+ + Consulte a autenticidade no portal nacional da NF-e + + www.nfe.fazenda.gov.br/portal ou no site da SEFAZ autorizadora +
+ + + + + + + + +
+ NATUREZA DA OPERAÇÃO + [_ds_transaction_nature] + + PROTOCOLO DE AUTORIZAÇÃO DE USO + [ds_protocol] +
+ + + + + + + + + + +
+ INSCRIÇÃO ESTADUAL + [nl_company_ie] + + INSCRIÇÃO ESTADUAL DO SUBST. TRIB. + [nl_company_ie_st] + + CNPJ / CPF + [nl_company_cnpj_cpf] +
+ + + + + + + + + +
+ CÓDIGO DO REGIME TRIBUTÁRIO + [ds_company_crt] + + TIPO DE REGIME DE APURAÇÃO DO IBS E DA CBS + +
+ + +

Destinatário / Remetente

+ + + + + + + + + + + + + + + +
+ + + + + + + +
+ NOME / RAZÃO SOCIAL + [ds_client_receiver_name] + + CNPJ / CPF + [nl_client_cnpj_cpf] +
+
+ DATA DE EMISSÃO + [dt_invoice_issue] +
+ + + + + + + + +
+ ENDEREÇO + [ds_client_address] + + BAIRRO / DISTRITO + [ds_client_neighborhood] + + CEP + [nu_client_cep] +
+
+ DATA DE ENTRADA / SAÍDA + [dt_input_output] +
+ + + + + + + + + +
+ MUNICÍPIO + [ds_client_city_name] + + FONE / FAX + [nl_client_phone_number] + + UF + [ds_client_uf] + + INSCRIÇÃO ESTADUAL + [ds_client_ie] +
+
+ HORA DE ENTRADA / SAÍDA + [hr_input_output] +
diff --git a/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-next.html b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-next.html new file mode 100644 index 000000000..0f1dd19ec --- /dev/null +++ b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-next.html @@ -0,0 +1,20 @@ +
+ [marca_dagua] +
+[cabecalho_rtc] +[produtos_rtc] + +
+ + + + + + +
+ [credits] +
+
+
+ [next-page] +
diff --git a/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-one.html b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-one.html new file mode 100644 index 000000000..71dc77917 --- /dev/null +++ b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-page-one.html @@ -0,0 +1,843 @@ + + + + + + + +
+ [marca_dagua] +
+ + + + + + + + + + + +
+ Recebemos de [ds_company_issuer_name] os produtos/serviços + constantes da nota fiscal eletrônica indicada ao lado + + NF-e + Nº [nl_invoice] + Série [ds_invoice_serie] +
+ Data de recebimento + + Identificação e assinatura do recebedor +
+
+[cabecalho_rtc] + +
+

Fatura / Duplicatas

+ + + + + + +
+ [duplicates] +
+
+ + + +

Total dos produtos e total da nota

+ + + + + + + + + + + + + + +
+ VALOR TOTAL DOS PRODUTOS + [vl_total_prod] + + VALOR DO FRETE + [vl_shipping] + + VALOR DO SEGURO + [vl_insurance] + + DESCONTO + [vl_discount] + + OUTRAS DESPESAS ACESSÓRIAS + [vl_other_expense] +
+ VALOR TOTAL DA NOTA + [vl_total] +
+ + +

Total do ICMS / IPI

+ + + + + + + + + + +
+ BASE DE CÁLCULO DO ICMS + [tot_bc_icms] + + VALOR DO ICMS + [tot_icms] + + BASE DE CÁLCULO DO ICMS ST + [tot_bc_icms_st] + + VALOR DO ICMS ST + [tot_icms_st] + + VALOR DO IPI + [tot_total_ipi_tax] +
+ + + + + + + + + + +
+ VALOR DO FCP + [tot_fcp] + + VALOR DO FCP RETIDO POR ST + [tot_fcp_st] + + VALOR DO DIFAL NA UF DE DESTINO + [tot_icms_uf_dest] + + VALOR DO FCP NA UF DE DESTINO + [tot_fcp_uf_dest] +
+ + + + + + + + + + + +
+ BC DO ICMS MONOFÁSICO + [tot_qbc_mono] + + VALOR DO ICMS MONOFÁSICO + [tot_icms_mono] + + BC DO ICMS MONOFÁSICO POR RETENÇÃO + [tot_qbc_mono_reten] + + VALOR DO ICMS MONOFÁSICO POR RETENÇÃO + [tot_icms_mono_reten] +
+ + + +

Total do IBS / CBS / IS

+ + + + + + + + + +
+ VALOR DA CBS + [tot_cbs] + + VALOR DO IBS UF + [tot_ibs_uf] + + VALOR DO IBS MUNICÍPIO + [tot_ibs_mun] + + VALOR DO IMPOSTO SELETIVO + [tot_is] +
+ + + + + + + + + + +
+ VALOR DO IBS MONOFÁSICO + [tot_ibs_mono] + + VALOR DA CBS MONOFÁSICA + [tot_cbs_mono] + + VALOR DO IBS MONOFÁSICO POR RETENÇÃO + [tot_ibs_mono_reten] + + VALOR DA CBS MONOFÁSICA POR RETENÇÃO + [tot_cbs_mono_reten] +
+ + + +

Cálculo do ISSQN

+ + + + + + + + + +
+ INSCRIÇÃO MUNICIPAL + [ds_company_im] + + VALOR TOTAL DOS SERVIÇOS + [vl_total_serv] + + BASE DE CÁLCULO DO ISSQN + [tot_bc_issqn] + + VALOR DO ISSQN + [tot_issqn] +
+ + + +

Transportador / volumes transportados

+ + + + + + + + + + + +
+ RAZÃO SOCIAL + [ds_transport_carrier_name] + + FRETE POR CONTA + [ds_transport_shipping_type] + + CÓDIGO ANTT + [ds_transport_rntc] + + PLACA DO VEÍCULO + [ds_transport_vehicle_plate] + + UF + [ds_transport_vehicle_uf] + + CNPJ / CPF + [nl_transport_cnpj_cpf] +
+ + + + + + + + + +
+ ENDEREÇO + [ds_transport_address] + + MUNICÍPIO + [ds_transport_city] + + UF + [ds_transport_uf] + + INSCRIÇÃO ESTADUAL + [ds_transport_ie] +
+ + + + + + + + + + + +
+ QUANTIDADE + [nu_transport_amount_transported_volumes] + + ESPÉCIE + [ds_transport_type_volumes_transported] + + MARCA + [ds_transport_mark_volumes_transported] + + NUMERAÇÃO + [ds_transport_number_volumes_transported] + + PESO BRUTO + [vl_transport_gross_weight] + + PESO LÍQUIDO + [vl_transport_net_weight] +
+ + +[produtos_rtc] + + +

Dados adicionais

+ + + + + + + +
+ INFORMAÇÕES COMPLEMENTARES + [ds_additional_information] + + RESERVADO AO FISCO + +
+ +
+ + + + + + +
+ [credits] +
+
+
+ [next-page] +
+ diff --git a/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-produtos.html b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-produtos.html new file mode 100644 index 000000000..73cca3415 --- /dev/null +++ b/NFe.Danfe.Html/Resources/danfe-model-55-nfe-rtc-produtos.html @@ -0,0 +1,31 @@ + +

Dados dos produtos / serviços

+
+ + + + + + + + + + + + + + + + + + + + + + + + + [itens_products] + +
DESCRIÇÃO DO PRODUTO / SERVIÇOCST / CFOPQTD / UNVLR UNITVLR TOTALBASES DE CÁLCULOALÍQUOTASVALOR DOS TRIBUTOS
+
diff --git a/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.csproj b/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.csproj new file mode 100644 index 000000000..a544993e7 --- /dev/null +++ b/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + AnyCpu + Release + true + false + Hercules.NET.NFe.Danfe.Html.nuspec + + + diff --git a/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.nuspec b/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.nuspec new file mode 100644 index 000000000..cefbb20c1 --- /dev/null +++ b/NuGet/Hercules.NET.NFe.Danfe.Html/Hercules.NET.NFe.Danfe.Html.nuspec @@ -0,0 +1,27 @@ + + + + Hercules.NET.NFe.Danfe.Html + $version$ + Hercules.NET DANFE NF-e em HTML + Hercules.NET + Hercules.NET + https://github.com/Hercules-NET/ZeusFiscal + https://avatars.githubusercontent.com/u/165974473 + false + Biblioteca para geração do DANFE da NF-e em HTML, sem dependências de Windows. Inclui o leiaute da NT 2026.010 (Reforma Tributária). + + Hercules.NET + pt-BR + danfe html nf-e nfe + + + + + + + + + + + diff --git a/ZeusFiscal.sln b/ZeusFiscal.sln index 43394ef38..6cbe774f7 100644 --- a/ZeusFiscal.sln +++ b/ZeusFiscal.sln @@ -126,6 +126,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFe.Danfe.PdfClown", "NFe.D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFe.Danfe.QuestPdf", "NFe.Danfe.QuestPdf\NFe.Danfe.QuestPdf.csproj", "{D868005D-1F35-43E0-BE57-7914D5BA1583}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFe.Danfe.Html.Testes", "NFe.Danfe.Html.Testes\NFe.Danfe.Html.Testes.csproj", "{CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -502,6 +504,14 @@ Global {D868005D-1F35-43E0-BE57-7914D5BA1583}.Release|Any CPU.Build.0 = Release|Any CPU {D868005D-1F35-43E0-BE57-7914D5BA1583}.Release|x86.ActiveCfg = Release|Any CPU {D868005D-1F35-43E0-BE57-7914D5BA1583}.Release|x86.Build.0 = Release|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Debug|x86.ActiveCfg = Debug|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Debug|x86.Build.0 = Debug|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Release|Any CPU.Build.0 = Release|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Release|x86.ActiveCfg = Release|Any CPU + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -561,6 +571,7 @@ Global {18429710-19E2-480F-8B3A-39FB6FC7AF19} = {3AC1A3D4-91D0-471A-AF9C-5EF8442F3F27} {1A057DFD-016C-4308-AE11-1E90AD809621} = {003B008B-F388-4FB5-A081-12C0FBA84B57} {D868005D-1F35-43E0-BE57-7914D5BA1583} = {003B008B-F388-4FB5-A081-12C0FBA84B57} + {CD0FD170-28E2-4ABD-96F6-D0BD3E7C0B11} = {164EF13E-7F27-4BC8-92A4-A82B1696B279} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C8C4D9F7-EF86-49A2-83AF-13FA5D4E8DBB}