// ══════════════════════════════════════════════════════════════════════════════
// DEPENDÊNCIA — adicionar no TLL.csproj:
//
//
// Ou via Package Manager Console:
// Install-Package QuestPDF
// ══════════════════════════════════════════════════════════════════════════════
using System;
using System.IO;
using MLL;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using Color = QuestPDF.Infrastructure.Color;
namespace TLL
{
///
/// Gera a ficha cadastral da empresa em PDF.
/// Uso: FichaEmpresaPDF.Gerar(empresa, @"C:\LevelCode\LevelOS\Fichas");
///
public static class FichaEmpresaPDF
{
static FichaEmpresaPDF()
{
// Licença community (gratuita para projetos não comerciais ou até $1M receita)
QuestPDF.Settings.License = LicenseType.Community;
}
// ══════════════════════════════════════════════════════════════════════
// GERAR PDF
// ══════════════════════════════════════════════════════════════════════
public static FichaPDFResultado Gerar(ModeloEmpresa empresa, string? pastaDestino = null)
{
try
{
pastaDestino ??= @"C:\LevelCode\LevelOS\Docs";
Directory.CreateDirectory(pastaDestino);
string cnpjLimpo = empresa.CNPJ?
.Replace(".", "").Replace("/", "").Replace("-", "") ?? "empresa";
string caminho = Path.Combine(pastaDestino,
$"Ficha_{cnpjLimpo}_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.DefaultTextStyle(x => x.FontSize(10).FontFamily("Arial"));
// ── CABEÇALHO ──────────────────────────────────────────
page.Header().Column(col =>
{
col.Item().Row(row =>
{
row.RelativeItem().Column(c =>
{
c.Item().Text("FICHA CADASTRAL DA EMPRESA")
.FontSize(16).Bold()
.FontColor(Color.FromHex("#2563EB"));
c.Item().Text(empresa.Nome ?? "")
.FontSize(12).Bold()
.FontColor(Color.FromHex("#1E293B"));
c.Item().Text($"CNPJ: {empresa.CNPJ ?? ""}")
.FontSize(10)
.FontColor(Color.FromHex("#64748B"));
});
row.ConstantItem(120).AlignRight().Column(c =>
{
c.Item().Text($"Emitido em:")
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
c.Item().Text(DateTime.Now.ToString("dd/MM/yyyy HH:mm"))
.FontSize(8).Bold()
.FontColor(Color.FromHex("#64748B"));
c.Item().Text($"Situação:")
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
c.Item().Text(empresa.Ativo ? "ATIVA" : "INATIVA")
.FontSize(9).Bold()
.FontColor(empresa.Ativo
? Color.FromHex("#16A34A")
: Color.FromHex("#DC2626"));
});
});
col.Item().PaddingTop(6).LineHorizontal(2)
.LineColor(Color.FromHex("#2563EB"));
});
// ── CONTEÚDO ───────────────────────────────────────────
page.Content().PaddingTop(12).Column(col =>
{
// 1. IDENTIFICAÇÃO
Secao(col, "IDENTIFICAÇÃO DA EMPRESA");
Grade(col, new[]
{
("Tipo de Empresa", empresa.TipoEmpresa, "Regime Tributário", empresa.RegimeTributario),
("CNAE", empresa.CNAE, "Inscrição Estadual", empresa.InscricaoEstadual),
("Inscrição Municipal", empresa.InscricaoMunicipal, "", ""),
});
// 2. ENDEREÇO
col.Item().PaddingTop(10);
Secao(col, "ENDEREÇO");
Grade(col, new[]
{
("CEP", empresa.Cep, "Logradouro", empresa.Endereco),
("Número", empresa.Numero.ToString(), "Complemento", empresa.Complemento),
("Bairro", empresa.Bairro, "Cidade", empresa.Cidade),
("UF", empresa.UF, "País", empresa.Pais),
});
// 3. CONTATOS
col.Item().PaddingTop(10);
Secao(col, "CONTATOS E COMUNICAÇÃO");
Grade(col, new[]
{
("Telefone 1", empresa.Telefone1, "Telefone 2", empresa.Telefone2),
("Celular", empresa.Celular, "WhatsApp", empresa.Whatsapp),
("E-mail", empresa.Email, "Site", empresa.Site),
});
// 4. CONTADOR
col.Item().PaddingTop(10);
Secao(col, "DADOS DO CONTADOR");
Grade(col, new[]
{
("CPF/CNPJ do Contador", empresa.CNPJCPF_Contador, "Nome do Contador", empresa.Nome_Contador),
});
// 5. OUTROS
if (!string.IsNullOrWhiteSpace(empresa.TextoParaRecibo))
{
col.Item().PaddingTop(10);
Secao(col, "TEXTO PARA RECIBO");
col.Item().PaddingTop(4)
.Border(0.5f).BorderColor(Color.FromHex("#E2E8F0"))
.Padding(8)
.Text(empresa.TextoParaRecibo)
.FontSize(9).FontColor(Color.FromHex("#475569"));
}
// 6. INFORMAÇÕES DO REGISTRO
col.Item().PaddingTop(10);
Secao(col, "INFORMAÇÕES DO REGISTRO");
Grade(col, new[]
{
("ID", empresa.Id.ToString(), "Criado Em", empresa.CriadoEm.ToString("dd/MM/yyyy")),
("Atualizado Em",empresa.AtualizadoEm.ToString("dd/MM/yyyy"), "", ""),
});
});
// ── RODAPÉ ─────────────────────────────────────────────
page.Footer().AlignCenter().Text(text =>
{
text.Span("LevelOS — Documento gerado automaticamente em ")
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
text.Span(DateTime.Now.ToString("dd/MM/yyyy HH:mm"))
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
text.Span(" — Página ")
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
text.CurrentPageNumber()
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
text.Span(" de ")
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
text.TotalPages()
.FontSize(8).FontColor(Color.FromHex("#94A3B8"));
});
});
}).GeneratePdf(caminho);
return new FichaPDFResultado
{
Sucesso = true,
Caminho = caminho,
Mensagem = "Ficha gerada com sucesso!"
};
}
catch (Exception ex)
{
return new FichaPDFResultado
{
Sucesso = false,
Mensagem = $"Erro ao gerar ficha: {ex.Message}"
};
}
}
// ══════════════════════════════════════════════════════════════════════
// GERAR E ABRIR AUTOMATICAMENTE
// ══════════════════════════════════════════════════════════════════════
public static FichaPDFResultado GerarEAbrir(ModeloEmpresa empresa, string? pastaDestino = null)
{
var resultado = Gerar(empresa, pastaDestino);
if (resultado.Sucesso && resultado.Caminho != null)
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = resultado.Caminho,
UseShellExecute = true
});
}
return resultado;
}
// ── HELPERS INTERNOS ──────────────────────────────────────────────────
private static void Secao(ColumnDescriptor col, string titulo)
{
col.Item().Column(c =>
{
c.Item().Text(titulo)
.FontSize(9).Bold()
.FontColor(Color.FromHex("#2563EB"));
c.Item().LineHorizontal(0.5f)
.LineColor(Color.FromHex("#E2E8F0"));
});
}
private static void Grade(ColumnDescriptor col,
(string label1, string? val1, string label2, string? val2)[] linhas)
{
foreach (var (label1, val1, label2, val2) in linhas)
{
col.Item().PaddingTop(4).Row(row =>
{
// Coluna esquerda
row.RelativeItem().Column(c =>
{
c.Item().Text(label1)
.FontSize(7.5f).FontColor(Color.FromHex("#94A3B8"));
c.Item().Text(val1 ?? "—")
.FontSize(9).FontColor(Color.FromHex("#1E293B"));
});
// Coluna direita
if (!string.IsNullOrEmpty(label2))
{
row.RelativeItem().Column(c =>
{
c.Item().Text(label2)
.FontSize(7.5f).FontColor(Color.FromHex("#94A3B8"));
c.Item().Text(val2 ?? "—")
.FontSize(9).FontColor(Color.FromHex("#1E293B"));
});
}
});
}
}
}
// ── MODELO DE RETORNO ─────────────────────────────────────────────────────
public class FichaPDFResultado
{
public bool Sucesso { get; set; }
public string Mensagem { get; set; } = string.Empty;
public string? Caminho { get; set; }
}
}