// ══════════════════════════════════════════════════════════════════════════════ // 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; } } }