feat: enterprise questpdf reports
- EmpresaReportService with 4 enterprise PDF reports - ContratoAbierto: contract header, course detail, schedules, students - ContratoCerrado: proposal info, courses, student list - CotizacionCursoCerrado: quote header, course detail table - CotizacionPlanCentral: company info, payment plan, course schedule - EmpresaReportController with download endpoints - All using ModuloEmpresa_PropuestaCrystalReport SP via Dapper
This commit is contained in:
+3
-1
@@ -60,7 +60,9 @@
|
|||||||
- [x] Claims → cookies HttpOnly
|
- [x] Claims → cookies HttpOnly
|
||||||
- [x] **1.7 Reportes QuestPDF** (~2-3 sem)
|
- [x] **1.7 Reportes QuestPDF** (~2-3 sem)
|
||||||
- [x] ReportService.cs (Contrato, Cotización, Arqueo en QuestPDF)
|
- [x] ReportService.cs (Contrato, Cotización, Arqueo en QuestPDF)
|
||||||
- [ ] 14 reportes restantes (Anexo, ContratoBlack, Presupuesto, CAEMP, CC_EMP, etc.)
|
- [x] EmpresaReportService.cs (ContratoAbierto, ContratoCerrado, CotizacionCC, CotizacionPC)
|
||||||
|
- [x] EmpresaReportController.cs (endpoints para reportes empresa)
|
||||||
|
- [ ] 10 reportes restantes (Anexo, ContratoBlack, Presupuesto, CAEMP variants, etc.)
|
||||||
- [ ] Dockerfile Backend
|
- [ ] Dockerfile Backend
|
||||||
|
|
||||||
### FASE 2: SERVICES EXTERNOS API (~2-3 semanas)
|
### FASE 2: SERVICES EXTERNOS API (~2-3 semanas)
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ventas.Services;
|
||||||
|
|
||||||
|
namespace Ventas.API.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/reportes/empresa")]
|
||||||
|
[Authorize]
|
||||||
|
public class EmpresaReportController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly EmpresaReportService _empresaReportService;
|
||||||
|
|
||||||
|
public EmpresaReportController(EmpresaReportService empresaReportService)
|
||||||
|
{
|
||||||
|
_empresaReportService = empresaReportService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("contrato-abierto/{id}")]
|
||||||
|
public async Task<IActionResult> ContratoAbiertoPdf(int id)
|
||||||
|
{
|
||||||
|
var pdf = await _empresaReportService.ContratoAbiertoPdfAsync(id);
|
||||||
|
return File(pdf, "application/pdf", $"contrato_abierto_{id}.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("contrato-cerrado/{prop}/{cont}")]
|
||||||
|
public async Task<IActionResult> ContratoCerradoPdf(int prop, int cont)
|
||||||
|
{
|
||||||
|
var pdf = await _empresaReportService.ContratoCerradoPdfAsync(prop, cont);
|
||||||
|
return File(pdf, "application/pdf", $"contrato_cerrado_{cont}.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("cotizacion-curso-cerrado/{prop}")]
|
||||||
|
public async Task<IActionResult> CotizacionCursoCerradoPdf(int prop)
|
||||||
|
{
|
||||||
|
var pdf = await _empresaReportService.CotizacionCursoCerradoPdfAsync(prop);
|
||||||
|
return File(pdf, "application/pdf", $"cotizacion_cc_{prop}.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("cotizacion-plan-central/{id}")]
|
||||||
|
public async Task<IActionResult> CotizacionPlanCentralPdf(int id)
|
||||||
|
{
|
||||||
|
var pdf = await _empresaReportService.CotizacionPlanCentralPdfAsync(id);
|
||||||
|
return File(pdf, "application/pdf", $"cotizacion_pc_{id}.pdf");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,8 @@ builder.Services.AddScoped<AlumnoService>(sp =>
|
|||||||
builder.Services.AddScoped<InformeService>(sp =>
|
builder.Services.AddScoped<InformeService>(sp =>
|
||||||
new InformeService(connectionString));
|
new InformeService(connectionString));
|
||||||
builder.Services.AddScoped<ReportService>();
|
builder.Services.AddScoped<ReportService>();
|
||||||
|
builder.Services.AddScoped<EmpresaReportService>(sp =>
|
||||||
|
new EmpresaReportService(connectionString));
|
||||||
|
|
||||||
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
|
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
|
||||||
var jwtExpiration = int.Parse(builder.Configuration["Jwt:ExpirationMinutes"] ?? "30");
|
var jwtExpiration = int.Parse(builder.Configuration["Jwt:ExpirationMinutes"] ?? "30");
|
||||||
|
|||||||
@@ -0,0 +1,437 @@
|
|||||||
|
using Dapper;
|
||||||
|
using Npgsql;
|
||||||
|
using QuestPDF.Fluent;
|
||||||
|
using QuestPDF.Helpers;
|
||||||
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
|
namespace Ventas.Services;
|
||||||
|
|
||||||
|
public class EmpresaReportService
|
||||||
|
{
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
|
public EmpresaReportService(string connectionString)
|
||||||
|
{
|
||||||
|
_connectionString = connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<Dictionary<string, object>>> EjecutarCrystalSpAsync(string tipo, int prop, int cotz, int cont)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"ModuloEmpresa_PropuestaCrystalReport",
|
||||||
|
new { tipo, prop, cotz, cont },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<Dictionary<string, object>>> EjecutarContratoCrysAsync(string tipo, int cont)
|
||||||
|
{
|
||||||
|
using var connection = new NpgsqlConnection(_connectionString);
|
||||||
|
var rows = await connection.QueryAsync(
|
||||||
|
"Empresa_ContratoCrys",
|
||||||
|
new { tipo, cont },
|
||||||
|
commandType: System.Data.CommandType.StoredProcedure);
|
||||||
|
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetString(Dictionary<string, object> row, string key) =>
|
||||||
|
row.GetValueOrDefault(key)?.ToString() ?? "";
|
||||||
|
|
||||||
|
public async Task<byte[]> ContratoAbiertoPdfAsync(int contratoId)
|
||||||
|
{
|
||||||
|
var dt01 = await EjecutarContratoCrysAsync("CONTRATOREIMPRESION", contratoId);
|
||||||
|
var dt02 = await EjecutarContratoCrysAsync("DETALLECURSO", contratoId);
|
||||||
|
var dt03 = await EjecutarContratoCrysAsync("HORARIO", contratoId);
|
||||||
|
var dt04 = await EjecutarContratoCrysAsync("ALUMNO", contratoId);
|
||||||
|
|
||||||
|
var header = dt01.FirstOrDefault();
|
||||||
|
if (header == null) return [];
|
||||||
|
|
||||||
|
return Document.Create(container =>
|
||||||
|
{
|
||||||
|
container.Page(page =>
|
||||||
|
{
|
||||||
|
page.Size(PageSizes.A4);
|
||||||
|
page.Margin(57);
|
||||||
|
page.DefaultTextStyle(x => x.FontSize(9));
|
||||||
|
|
||||||
|
page.Header().Element(c => ComposeEmpHeader(c, GetString(header, "NombreEmp"), contratoId.ToString()));
|
||||||
|
page.Content().Element(c => ComposeEmpContent(c, header, dt02, dt03, dt04));
|
||||||
|
page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); });
|
||||||
|
});
|
||||||
|
}).GeneratePdf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]> ContratoCerradoPdfAsync(int propuestaId, int contratoId)
|
||||||
|
{
|
||||||
|
var infoPropuesta = await EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, contratoId);
|
||||||
|
var infoCursos = await EjecutarCrystalSpAsync("CONTRATOCURSO", propuestaId, 0, contratoId);
|
||||||
|
var infoAlumnos = await EjecutarCrystalSpAsync("CONTRATOALUMNO", propuestaId, 0, contratoId);
|
||||||
|
|
||||||
|
var header = infoPropuesta.FirstOrDefault();
|
||||||
|
if (header == null) return [];
|
||||||
|
|
||||||
|
return Document.Create(container =>
|
||||||
|
{
|
||||||
|
container.Page(page =>
|
||||||
|
{
|
||||||
|
page.Size(PageSizes.A4);
|
||||||
|
page.Margin(57);
|
||||||
|
page.DefaultTextStyle(x => x.FontSize(9));
|
||||||
|
|
||||||
|
page.Header().Element(c => ComposeContratoCerradoHeader(c, GetString(header, "EMPRESA"), contratoId.ToString()));
|
||||||
|
page.Content().Element(c => ComposeContratoCerradoContent(c, header, infoCursos, infoAlumnos));
|
||||||
|
page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); });
|
||||||
|
});
|
||||||
|
}).GeneratePdf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]> CotizacionCursoCerradoPdfAsync(int propuestaId)
|
||||||
|
{
|
||||||
|
var data = await EjecutarCrystalSpAsync("PROPUESTA", propuestaId, 0, 0);
|
||||||
|
var detalle = await EjecutarCrystalSpAsync("PROPUESTADET", propuestaId, 0, 0);
|
||||||
|
|
||||||
|
var header = data.FirstOrDefault();
|
||||||
|
if (header == null) return [];
|
||||||
|
|
||||||
|
return Document.Create(container =>
|
||||||
|
{
|
||||||
|
container.Page(page =>
|
||||||
|
{
|
||||||
|
page.Size(PageSizes.A4);
|
||||||
|
page.Margin(57);
|
||||||
|
page.DefaultTextStyle(x => x.FontSize(9));
|
||||||
|
|
||||||
|
page.Header().Element(c => ComposeCotizacionCCHeader(c, GetString(header, "EMPRESA"), propuestaId.ToString()));
|
||||||
|
page.Content().Element(c => ComposeCotizacionCCContent(c, header, detalle));
|
||||||
|
page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); });
|
||||||
|
});
|
||||||
|
}).GeneratePdf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<byte[]> CotizacionPlanCentralPdfAsync(int cotizacionId)
|
||||||
|
{
|
||||||
|
var data = await EjecutarCrystalSpAsync("COTIZACIONV2", 0, cotizacionId, 0);
|
||||||
|
var detalle = await EjecutarCrystalSpAsync("COTIZACIONDETV2", 0, cotizacionId, 0);
|
||||||
|
|
||||||
|
var header = data.FirstOrDefault();
|
||||||
|
if (header == null) return [];
|
||||||
|
|
||||||
|
return Document.Create(container =>
|
||||||
|
{
|
||||||
|
container.Page(page =>
|
||||||
|
{
|
||||||
|
page.Size(PageSizes.A4);
|
||||||
|
page.Margin(57);
|
||||||
|
page.DefaultTextStyle(x => x.FontSize(9));
|
||||||
|
|
||||||
|
page.Header().Element(c => ComposePlanCentralHeader(c, GetString(header, "Razon Social"), cotizacionId.ToString()));
|
||||||
|
page.Content().Element(c => ComposePlanCentralContent(c, header, detalle));
|
||||||
|
page.Footer().AlignCenter().Text(t => { t.Span("Página "); t.CurrentPageNumber(); });
|
||||||
|
});
|
||||||
|
}).GeneratePdf();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeEmpHeader(IContainer container, string empresa, string numContrato)
|
||||||
|
{
|
||||||
|
container.Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold();
|
||||||
|
col.Item().Text("Módulo Empresa").FontSize(8);
|
||||||
|
});
|
||||||
|
row.ConstantItem(140).AlignRight().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text($"Contrato N° {numContrato}").FontSize(14).Bold();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeEmpContent(IContainer container, Dictionary<string, object> header,
|
||||||
|
IEnumerable<Dictionary<string, object>> cursos, IEnumerable<Dictionary<string, object>> horarios,
|
||||||
|
IEnumerable<Dictionary<string, object>> alumnos)
|
||||||
|
{
|
||||||
|
container.Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); });
|
||||||
|
table.Cell().Text("Empresa:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "NombreEmp"));
|
||||||
|
table.Cell().Text("RUT:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "idEmpresa"));
|
||||||
|
table.Cell().Text("Dirección:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "DireccionEmp"));
|
||||||
|
table.Cell().Text("Representante:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "Representante"));
|
||||||
|
table.Cell().Text("Vendedor:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "Vendedor"));
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c =>
|
||||||
|
{
|
||||||
|
c.ConstantColumn(30);
|
||||||
|
c.RelativeColumn();
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
c.ConstantColumn(70);
|
||||||
|
c.ConstantColumn(70);
|
||||||
|
});
|
||||||
|
|
||||||
|
table.Header(h =>
|
||||||
|
{
|
||||||
|
h.Cell().Text("#").Bold();
|
||||||
|
h.Cell().Text("Curso").Bold();
|
||||||
|
h.Cell().Text("Duración").Bold();
|
||||||
|
h.Cell().Text("Inicio").Bold();
|
||||||
|
h.Cell().Text("Término").Bold();
|
||||||
|
});
|
||||||
|
|
||||||
|
int idx = 1;
|
||||||
|
foreach (var c in cursos)
|
||||||
|
{
|
||||||
|
table.Cell().Text(idx++.ToString());
|
||||||
|
table.Cell().Text(GetString(c, "Curso"));
|
||||||
|
table.Cell().Text(GetString(c, "Duracion"));
|
||||||
|
table.Cell().Text(GetString(c, "FechaInicio"));
|
||||||
|
table.Cell().Text(GetString(c, "FechaTermino"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(10).Text("Horarios:").Bold();
|
||||||
|
foreach (var h in horarios)
|
||||||
|
{
|
||||||
|
col.Item().PaddingLeft(10).Text(GetString(h, "Horario"));
|
||||||
|
}
|
||||||
|
|
||||||
|
col.Item().PaddingTop(10).Text("Alumnos:").Bold();
|
||||||
|
foreach (var a in alumnos)
|
||||||
|
{
|
||||||
|
col.Item().PaddingLeft(10).Text(GetString(a, "Alumno"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeContratoCerradoHeader(IContainer container, string empresa, string numContrato)
|
||||||
|
{
|
||||||
|
container.Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold();
|
||||||
|
col.Item().Text("Módulo Empresa - Contrato Cerrado").FontSize(8);
|
||||||
|
});
|
||||||
|
row.ConstantItem(140).AlignRight().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text($"Contrato N° {numContrato}").FontSize(14).Bold();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeContratoCerradoContent(IContainer container, Dictionary<string, object> header,
|
||||||
|
IEnumerable<Dictionary<string, object>> cursos, IEnumerable<Dictionary<string, object>> alumnos)
|
||||||
|
{
|
||||||
|
container.Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); });
|
||||||
|
table.Cell().Text("Empresa:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "EMPRESA"));
|
||||||
|
table.Cell().Text("RUT:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "RUT"));
|
||||||
|
table.Cell().Text("Dirección:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "DIRECCION"));
|
||||||
|
table.Cell().Text("Vendedor:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "VENDEDOR"));
|
||||||
|
table.Cell().Text("Total:").Bold();
|
||||||
|
table.Cell().Text("$" + GetString(header, "TOTAL"));
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c =>
|
||||||
|
{
|
||||||
|
c.ConstantColumn(25);
|
||||||
|
c.RelativeColumn();
|
||||||
|
c.ConstantColumn(50);
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
table.Header(h =>
|
||||||
|
{
|
||||||
|
h.Cell().Text("#").Bold();
|
||||||
|
h.Cell().Text("Curso").Bold();
|
||||||
|
h.Cell().Text("Horas").Bold();
|
||||||
|
h.Cell().Text("Inicio").Bold();
|
||||||
|
h.Cell().Text("Valor").Bold();
|
||||||
|
});
|
||||||
|
|
||||||
|
int idx = 1;
|
||||||
|
foreach (var c in cursos)
|
||||||
|
{
|
||||||
|
table.Cell().Text(idx++.ToString());
|
||||||
|
table.Cell().Text(GetString(c, "CURSO"));
|
||||||
|
table.Cell().Text(GetString(c, "Duracion"));
|
||||||
|
table.Cell().Text(GetString(c, "FechaInicio"));
|
||||||
|
table.Cell().Text("$" + GetString(c, "ValorGrupal"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c => { c.ConstantColumn(25); c.RelativeColumn(); });
|
||||||
|
table.Header(h =>
|
||||||
|
{
|
||||||
|
h.Cell().Text("#").Bold();
|
||||||
|
h.Cell().Text("Alumno").Bold();
|
||||||
|
});
|
||||||
|
int idx = 1;
|
||||||
|
foreach (var a in alumnos)
|
||||||
|
{
|
||||||
|
table.Cell().Text(idx++.ToString());
|
||||||
|
table.Cell().Text(GetString(a, "Alumnos"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeCotizacionCCHeader(IContainer container, string empresa, string numProp)
|
||||||
|
{
|
||||||
|
container.Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold();
|
||||||
|
col.Item().Text("Cotización Curso Cerrado").FontSize(8);
|
||||||
|
});
|
||||||
|
row.ConstantItem(140).AlignRight().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text($"Cotización N° {numProp}").FontSize(14).Bold();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposeCotizacionCCContent(IContainer container, Dictionary<string, object> header,
|
||||||
|
IEnumerable<Dictionary<string, object>> detalle)
|
||||||
|
{
|
||||||
|
container.Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c => { c.ConstantColumn(100); c.RelativeColumn(); });
|
||||||
|
table.Cell().Text("Empresa:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "EMPRESA"));
|
||||||
|
table.Cell().Text("RUT:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "RUT"));
|
||||||
|
table.Cell().Text("Vendedor:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "VENDEDOR"));
|
||||||
|
table.Cell().Text("Total:").Bold();
|
||||||
|
table.Cell().Text("$" + GetString(header, "TOTAL"));
|
||||||
|
table.Cell().Text("Vigencia:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "VALIDEZ"));
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c =>
|
||||||
|
{
|
||||||
|
c.ConstantColumn(25);
|
||||||
|
c.RelativeColumn();
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
table.Header(h =>
|
||||||
|
{
|
||||||
|
h.Cell().Text("#").Bold();
|
||||||
|
h.Cell().Text("Curso").Bold();
|
||||||
|
h.Cell().Text("Jornada").Bold();
|
||||||
|
h.Cell().Text("Valor").Bold();
|
||||||
|
});
|
||||||
|
|
||||||
|
int idx = 1;
|
||||||
|
foreach (var d in detalle)
|
||||||
|
{
|
||||||
|
table.Cell().Text(idx++.ToString());
|
||||||
|
table.Cell().Text(GetString(d, "CURSO"));
|
||||||
|
table.Cell().Text(GetString(d, "JORNADA"));
|
||||||
|
table.Cell().Text("$" + GetString(d, "VALOR CURSO"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposePlanCentralHeader(IContainer container, string empresa, string numCotizacion)
|
||||||
|
{
|
||||||
|
container.Row(row =>
|
||||||
|
{
|
||||||
|
row.RelativeItem().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text("Instituto Chileno Norteamericano").FontSize(12).Bold();
|
||||||
|
col.Item().Text("Cotización Plan Central").FontSize(8);
|
||||||
|
});
|
||||||
|
row.ConstantItem(140).AlignRight().Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().Text($"Cotización N° {numCotizacion}").FontSize(14).Bold();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ComposePlanCentralContent(IContainer container, Dictionary<string, object> header,
|
||||||
|
IEnumerable<Dictionary<string, object>> detalle)
|
||||||
|
{
|
||||||
|
container.Column(col =>
|
||||||
|
{
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c => { c.ConstantColumn(110); c.RelativeColumn(); });
|
||||||
|
table.Cell().Text("Empresa:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "Razon Social"));
|
||||||
|
table.Cell().Text("RUT:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "R.U.T."));
|
||||||
|
table.Cell().Text("Ejecutivo:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "Ejecutivo"));
|
||||||
|
table.Cell().Text("Total:").Bold();
|
||||||
|
table.Cell().Text("$" + GetString(header, "Total con descuento"));
|
||||||
|
table.Cell().Text("Vigencia:").Bold();
|
||||||
|
table.Cell().Text(GetString(header, "Vigencia"));
|
||||||
|
});
|
||||||
|
|
||||||
|
col.Item().PaddingTop(15).Table(table =>
|
||||||
|
{
|
||||||
|
table.ColumnsDefinition(c =>
|
||||||
|
{
|
||||||
|
c.ConstantColumn(25);
|
||||||
|
c.RelativeColumn();
|
||||||
|
c.ConstantColumn(50);
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
c.ConstantColumn(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
table.Header(h =>
|
||||||
|
{
|
||||||
|
h.Cell().Text("#").Bold();
|
||||||
|
h.Cell().Text("Curso").Bold();
|
||||||
|
h.Cell().Text("Periodo").Bold();
|
||||||
|
h.Cell().Text("Inicio").Bold();
|
||||||
|
h.Cell().Text("Valor").Bold();
|
||||||
|
});
|
||||||
|
|
||||||
|
int idx = 1;
|
||||||
|
foreach (var d in detalle)
|
||||||
|
{
|
||||||
|
table.Cell().Text(idx++.ToString());
|
||||||
|
table.Cell().Text(GetString(d, "NombreCurso"));
|
||||||
|
table.Cell().Text(GetString(d, "Periodo"));
|
||||||
|
table.Cell().Text(GetString(d, "FechaInicio"));
|
||||||
|
table.Cell().Text("$" + GetString(d, "ValorCurso"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user