Resumen

Transformar datos en decisiones es una de las habilidades más valiosas en el desarrollo de software. Cuando trabajamos con un sistema de inventario, no basta con almacenar productos: necesitamos respuestas claras sobre el valor total, los productos que se agotan y cuáles generan más ingresos. Aquí se muestra cómo LINQ y StringBuilder se combinan en C# para construir un generador de reportes profesional que produce resúmenes ejecutivos, alertas de stock bajo, rankings y exportaciones a CSV y JSON.

¿Cómo se estructura la clase GeneradorReportes?

La clase GeneradorReportes se ubica dentro de la carpeta SRC/Infrastructure y actúa como el componente responsable de analizar y presentar los datos del inventario [00:56]. Para que funcione correctamente, se necesitan las siguientes importaciones:

  • using System y using System.Collections.Generic para las colecciones.
  • using System.Linq para las consultas declarativas.
  • using System.Text para StringBuilder.
  • using System.Text.Json para la serialización JSON.
  • using InventarioApp.Models para acceder al modelo de producto.

El namespace corresponde a InventarioApp.Infrastructure. Dentro de la clase, se declara un campo readonly de tipo IEnumerable<Producto> llamado _productos [01:42]. El constructor recibe esta colección y la almacena, lo que permite ofrecer múltiples vistas de los mismos datos sin modificarlos.

¿Qué hace el método generar resumen?

Este método crea una instancia de StringBuilder y utiliza AppendLine para construir el reporte línea por línea [02:17]. Primero imprime el total de productos usando .Count() y luego el valor total del inventario con .Sum(), que recorre cada producto y acumula su valor total.

Para desglosar los productos por categoría, se usa GroupBy, que agrupa cada producto según su categoría [02:55]. Después, con Select, se crea un objeto anónimo con la categoría y la cantidad usando g.Count(). Un foreach recorre el resultado y lo imprime con interpolación de cadenas. Finalmente, el método retorna sb.ToString().

¿Cómo se detectan productos con stock bajo?

El método GenerarReporteStockBajo recibe un parámetro entero con valor mínimo de cinco [03:31]. Utiliza el operador Where de LINQ para filtrar productos cuya cantidad sea menor al umbral y OrderBy para ordenarlos por cantidad ascendente.

Si la colección resultante está vacía, imprime "No hay productos con stock bajo". De lo contrario, un foreach recorre cada producto e imprime su ID, nombre, cantidad y precio usando StringBuilder.

¿Cómo se generan rankings y exportaciones?

El método GenerarTopProductos también recibe un entero con valor cinco [04:21]. Aquí se aplica OrderByDescending para ordenar los productos según su valor total de manera descendente y Take para limitar la cantidad de resultados. Una variable posición se incrementa dentro del foreach para numerar cada producto en el ranking.

Para la exportación a CSV, el método ExportarCSV establece los encabezados con AppendLine: ID, nombre, precio, cantidad, categoría y valor total [05:09]. Luego ordena los productos por ID con OrderBy y escribe cada fila en el mismo orden.

¿Cómo se exporta el resumen a JSON?

El método ExportarResumenJSON construye un objeto anónimo con [05:37]:

  • Total de productos calculado con .Count().
  • Valor total del inventario con .Sum().
  • Productos por categoría usando GroupBy y Select.
  • Top cinco productos con OrderByDescending, Take(5) y Select.

Todo se serializa con JsonSerializer.Serialize, pasando JsonSerializerOptions con WriteIndented = true para una salida legible.

¿Cómo se prueba todo en Program.cs?

En Program.cs se crean seis productos mediante ProductoFactory.Crear: laptop, camisa, arroz, lámpara, balón y mesa, cada uno con precio, cantidad y categoría [06:25]. Se instancia GeneradorReportes y se imprimen los cinco métodos en consola.

La salida muestra:

  • Seis productos en total con su valor de inventario.
  • Un producto por categoría en este ejemplo.
  • Lámpara, laptop y mesa como productos con stock bajo (menos de cinco unidades).
  • Laptop en primer lugar del ranking con valor de 3600, seguida de camisa con 675, confirmando el orden descendente.
  • El CSV y el JSON con todos los campos correctamente formateados.

LINQ es declarativo: expresa qué queremos obtener (filtrar, ordenar, sumar, agrupar) sin detallar cómo hacerlo paso a paso [08:27]. Esto produce código más legible y mantenible en comparación con loops manuales. Combinado con StringBuilder, que concatena cadenas de forma eficiente, se logran cinco métodos que responden preguntas reales sobre el inventario: métricas, alertas, rankings y exportación. ¿Qué otro reporte agregarías a este generador?