| 
									
										
										
										
											2025-06-20 19:04:23 -03:00
										 |  |  | using GestionIntegral.Api.Dtos.Reportes.ViewModels; | 
					
						
							|  |  |  | using QuestPDF.Fluent; | 
					
						
							|  |  |  | using QuestPDF.Helpers; | 
					
						
							|  |  |  | using QuestPDF.Infrastructure; | 
					
						
							|  |  |  | using System.Linq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Usamos una clase parcial para organizar mejor el código, aunque no es estrictamente necesario aquí. | 
					
						
							|  |  |  |     public class ExistenciaPapelDocument : IDocument | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Usamos una propiedad pública con 'init' en lugar de un campo privado. | 
					
						
							|  |  |  |         // Esto es más limpio y funciona mejor con el análisis de código. | 
					
						
							|  |  |  |         public ExistenciaPapelViewModel Model { get; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public ExistenciaPapelDocument(ExistenciaPapelViewModel model) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Model = model; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public DocumentMetadata GetMetadata() => DocumentMetadata.Default; | 
					
						
							|  |  |  |         public DocumentSettings GetSettings() => DocumentSettings.Default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public void Compose(IDocumentContainer container) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             container | 
					
						
							|  |  |  |                 .Page(page => | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2025-06-24 12:52:37 -03:00
										 |  |  |                     page.Margin(1, Unit.Centimetre); | 
					
						
							| 
									
										
										
										
											2025-06-20 19:04:23 -03:00
										 |  |  |                     page.PageColor(Colors.White); | 
					
						
							|  |  |  |                     page.DefaultTextStyle(x => x.FontFamily("Roboto").FontSize(10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     page.Header().Element(ComposeHeader); | 
					
						
							|  |  |  |                     page.Content().Element(ComposeContent); | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                     page.Footer() | 
					
						
							|  |  |  |                         .AlignCenter() | 
					
						
							|  |  |  |                         .Text(x => | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             x.Span("Página "); | 
					
						
							|  |  |  |                             x.CurrentPageNumber(); | 
					
						
							|  |  |  |                         }); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Ahora los métodos usan 'Model' (la propiedad pública) en lugar de '_model'. | 
					
						
							|  |  |  |         void ComposeHeader(IContainer container) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             container.Column(column => | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 column.Spacing(5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 column.Item().AlignCenter().Text("Reporte de Existencias de Papel").SemiBold().FontSize(14); | 
					
						
							|  |  |  |                 column.Item().AlignCenter().Text($"Planta: {Model.NombrePlanta}").FontSize(12); | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 column.Item().PaddingTop(2, Unit.Millimetre).Row(row => | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     row.RelativeItem().Column(col => | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         col.Item().Text(text => | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             text.Span("Fecha del Reporte: ").SemiBold(); | 
					
						
							|  |  |  |                             text.Span(Model.FechaReporte); | 
					
						
							|  |  |  |                         }); | 
					
						
							|  |  |  |                          col.Item().Text($"Periodo Consultado: Desde {Model.FechaDesde} Hasta {Model.FechaHasta}"); | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void ComposeContent(IContainer container) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             container.PaddingTop(1, Unit.Centimetre).Table(table => | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 table.ColumnsDefinition(columns => | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     columns.RelativeColumn();  | 
					
						
							|  |  |  |                     columns.ConstantColumn(65); | 
					
						
							|  |  |  |                     columns.ConstantColumn(70); | 
					
						
							|  |  |  |                     columns.ConstantColumn(85);  | 
					
						
							|  |  |  |                     columns.ConstantColumn(65);  | 
					
						
							|  |  |  |                     columns.ConstantColumn(80);  | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 table.Header(header => | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).Text("Tipo de Bobina"); | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Stock"); | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Kg. Stock"); | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Consumo (Kg)"); | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Días Disp."); | 
					
						
							|  |  |  |                     header.Cell().Background(Colors.Grey.Lighten3).Padding(4).AlignCenter().Text("Fin Estimado"); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 foreach (var item in Model.Existencias) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).Text(item.TipoBobina); | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(item.BobinasEnStock?.ToString("N0") ?? "0"); | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(item.TotalKilosEnStock?.ToString("N0") ?? "0"); | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(item.ConsumoAcumulado?.ToString("N0") ?? "0"); | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(item.PromedioDiasDisponibles?.ToString("N0") ?? "N/A"); | 
					
						
							|  |  |  |                     table.Cell().BorderBottom(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignCenter().Text(item.FechaEstimacionFinStock?.ToString("dd/MM/yyyy") ?? "N/A"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 var totalBobinas = Model.Existencias.Sum(e => e.BobinasEnStock ?? 0); | 
					
						
							|  |  |  |                 var totalKilos = Model.Existencias.Sum(e => e.TotalKilosEnStock ?? 0); | 
					
						
							|  |  |  |                 var totalConsumo = Model.Existencias.Sum(e => e.ConsumoAcumulado ?? 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 table.Cell().BorderTop(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(t => t.Span("Totales").SemiBold()); | 
					
						
							|  |  |  |                 table.Cell().BorderTop(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(t => t.Span(totalBobinas.ToString("N0")).SemiBold()); | 
					
						
							|  |  |  |                 table.Cell().BorderTop(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(t => t.Span(totalKilos.ToString("N0")).SemiBold()); | 
					
						
							|  |  |  |                 table.Cell().BorderTop(1).BorderColor(Colors.Grey.Lighten2).Padding(4).AlignRight().Text(t => t.Span(totalConsumo.ToString("N0")).SemiBold()); | 
					
						
							|  |  |  |                 table.Cell().ColumnSpan(2).BorderTop(1).BorderColor(Colors.Grey.Lighten2); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |