267 lines
13 KiB
C#
267 lines
13 KiB
C#
// ══════════════════════════════════════════════════════════════════════════════
|
|
// DEPENDÊNCIA — adicionar no TLL.csproj:
|
|
// <PackageReference Include="QuestPDF" Version="2024.3.0" />
|
|
//
|
|
// 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
|
|
{
|
|
/// <summary>
|
|
/// Gera a ficha cadastral da empresa em PDF.
|
|
/// Uso: FichaEmpresaPDF.Gerar(empresa, @"C:\LevelCode\LevelOS\Fichas");
|
|
/// </summary>
|
|
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; }
|
|
}
|
|
} |