feat(Reportes): Ajusta cálculo de promedios en Listado de Distribución
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 3m58s
All checks were successful
Optimized Build and Deploy / remote-build-and-deploy (push) Successful in 3m58s
Se modifica la lógica de cálculo para la fila "General" en la tabla de promedios del reporte de Listado de Distribución para distribuidores.
**Motivación:**
Por requerimiento explícito del usuario final, el cálculo de los promedios generales (Llevados, Devueltos, Ventas y % Devolución) debe ser un promedio aritmético simple de los valores de los días de la semana mostrados en la tabla (ej. Viernes, Sábado, Domingo), en lugar del promedio ponderado que se calculaba anteriormente basado en los totales generales.
**Cambios Realizados:**
1. **Backend (`ListadoDistribucionDistribuidoresViewModel.cs`):**
* Se actualizó la propiedad `PromedioGeneral` para que calcule sus valores (Promedio\_Llevados, Promedio\_Devueltos, etc.) promediando directamente los valores de la colección `PromediosPorDia`.
2. **PDF (`ListadoDistribucionDistribuidoresDocument.cs`):**
* Se ajustó la lógica de renderizado de la fila "General" para que el porcentaje de devolución también se calcule como el promedio de los porcentajes de los días individuales, asegurando consistencia con el ViewModel.
3. **Frontend (`ReporteListadoDistribucionPage.tsx`):**
* Se modificó el cálculo del estado `totalesPromedios` dentro de la función `handleGenerarReporte`. Ahora, en lugar de usar los totales de la tabla de detalle, suma los valores de la tabla de promedios y los divide por la cantidad de días para obtener un promedio simple.
**Resultado:**
Tanto la interfaz web como el PDF generado ahora muestran en la fila "General" un promedio simple de las filas de promedios diarios, alineándose con la lógica solicitada por el usuario.
This commit is contained in:
@@ -161,16 +161,16 @@ namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
|
|||||||
if (general != null)
|
if (general != null)
|
||||||
{
|
{
|
||||||
var boldStyle = TextStyle.Default.SemiBold();
|
var boldStyle = TextStyle.Default.SemiBold();
|
||||||
var llevadosGeneral = general.Llevados ?? 0; // Usamos el total para el %
|
var avgPercentage = Model.PromediosPorDia
|
||||||
var devueltosGeneral = general.Devueltos ?? 0; // Usamos el total para el %
|
.Where(p => p.Dia != "General" && (p.Promedio_Llevados ?? 0) > 0)
|
||||||
var porcDevolucionGeneral = llevadosGeneral > 0 ? (decimal)devueltosGeneral * 100 / llevadosGeneral : 0;
|
.Average(p => (decimal)(p.Promedio_Devueltos ?? 0) * 100 / (p.Promedio_Llevados ?? 1));
|
||||||
|
|
||||||
table.Cell().Border(1).Padding(3).Text(t => t.Span(general.Dia).Style(boldStyle));
|
table.Cell().Border(1).Padding(3).Text(t => t.Span(general.Dia).Style(boldStyle));
|
||||||
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Cant?.ToString("N0")).Style(boldStyle));
|
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Cant?.ToString("N0")).Style(boldStyle));
|
||||||
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Llevados?.ToString("N0")).Style(boldStyle));
|
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Llevados?.ToString("N0")).Style(boldStyle));
|
||||||
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Devueltos?.ToString("N0")).Style(boldStyle));
|
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Devueltos?.ToString("N0")).Style(boldStyle));
|
||||||
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Ventas?.ToString("N0")).Style(boldStyle));
|
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Ventas?.ToString("N0")).Style(boldStyle));
|
||||||
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(porcDevolucionGeneral.ToString("F2") + "%").Style(boldStyle));
|
table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(avgPercentage.ToString("F2") + "%").Style(boldStyle));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,26 +20,26 @@ namespace GestionIntegral.Api.Dtos.Reportes.ViewModels
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (DetalleDiario == null || !DetalleDiario.Any())
|
if (PromediosPorDia == null || !PromediosPorDia.Any())
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
var promediosValidos = PromediosPorDia.Where(p => p.Dia != "General").ToList();
|
||||||
var diasConDatos = DetalleDiario.Count(d => (d.Llevados ?? 0) > 0);
|
if (!promediosValidos.Any()) return null;
|
||||||
if (diasConDatos == 0) return null;
|
var countPromedios = promediosValidos.Count;
|
||||||
|
var sumPromLlevados = promediosValidos.Sum(p => p.Promedio_Llevados ?? 0);
|
||||||
var totalLlevados = DetalleDiario.Sum(d => d.Llevados ?? 0);
|
var sumPromDevueltos = promediosValidos.Sum(p => p.Promedio_Devueltos ?? 0);
|
||||||
var totalDevueltos = DetalleDiario.Sum(d => d.Devueltos ?? 0);
|
var sumPromVentas = promediosValidos.Sum(p => p.Promedio_Ventas ?? 0);
|
||||||
|
|
||||||
return new ListadoDistribucionDistPromedioDiaDto
|
return new ListadoDistribucionDistPromedioDiaDto
|
||||||
{
|
{
|
||||||
Dia = "General",
|
Dia = "General",
|
||||||
Cant = diasConDatos,
|
Cant = promediosValidos.Sum(p => p.Cant ?? 0),
|
||||||
Promedio_Llevados = totalLlevados / diasConDatos,
|
Promedio_Llevados = (int)Math.Round((decimal)sumPromLlevados / countPromedios, MidpointRounding.AwayFromZero),
|
||||||
Promedio_Devueltos = totalDevueltos / diasConDatos,
|
Promedio_Devueltos = (int)Math.Round((decimal)sumPromDevueltos / countPromedios, MidpointRounding.AwayFromZero),
|
||||||
Promedio_Ventas = (totalLlevados - totalDevueltos) / diasConDatos,
|
Promedio_Ventas = (int)Math.Round((decimal)sumPromVentas / countPromedios, MidpointRounding.AwayFromZero),
|
||||||
Llevados = totalLlevados, // Guardamos el total para el cálculo del %
|
Llevados = (int)Math.Round((decimal)sumPromLlevados / countPromedios, MidpointRounding.AwayFromZero),
|
||||||
Devueltos = totalDevueltos // Guardamos el total para el cálculo del %
|
Devueltos = (int)Math.Round((decimal)sumPromDevueltos / countPromedios, MidpointRounding.AwayFromZero)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ builder.Services.AddCors(options =>
|
|||||||
policy =>
|
policy =>
|
||||||
{
|
{
|
||||||
policy.WithOrigins(
|
policy.WithOrigins(
|
||||||
"http://localhost:5173", // Para desarrollo local
|
"http://localhost:5175", // Para desarrollo local
|
||||||
"https://gestion.eldiaservicios.com" // Para producción
|
"https://gestion.eldiaservicios.com" // Para producción
|
||||||
)
|
)
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
|
|||||||
@@ -121,20 +121,24 @@ const ReporteListadoDistribucionPage: React.FC = () => {
|
|||||||
porcentajeDevolucion: item.promedio_Llevados > 0 ? (item.promedio_Devueltos / item.promedio_Llevados) * 100 : 0,
|
porcentajeDevolucion: item.promedio_Llevados > 0 ? (item.promedio_Devueltos / item.promedio_Llevados) * 100 : 0,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Calcular totales para la tabla de promedios (ponderados por Cant. Días)
|
|
||||||
const totalDiasPromedios = promediosConCalculos.reduce((sum, item) => sum + (item.cant || 0), 0);
|
const totalDiasPromedios = promediosConCalculos.reduce((sum, item) => sum + (item.cant || 0), 0);
|
||||||
const totalPonderadoLlevados = promediosConCalculos.reduce((sum, item) => sum + ((item.promedio_Llevados || 0) * (item.cant || 0)), 0);
|
const countPromedios = promediosConCalculos.length;
|
||||||
const totalPonderadoDevueltos = promediosConCalculos.reduce((sum, item) => sum + ((item.promedio_Devueltos || 0) * (item.cant || 0)), 0);
|
|
||||||
const totalPonderadoVentas = promediosConCalculos.reduce((sum, item) => sum + ((item.promedio_Ventas || 0) * (item.cant || 0)), 0);
|
// LÓGICA DE PROMEDIO DE PROMEDIOS
|
||||||
|
if (countPromedios > 0) {
|
||||||
|
const sumPromLlevados = promediosConCalculos.reduce((sum, item) => sum + (item.promedio_Llevados || 0), 0);
|
||||||
|
const sumPromDevueltos = promediosConCalculos.reduce((sum, item) => sum + (item.promedio_Devueltos || 0), 0);
|
||||||
|
const sumPromVentas = promediosConCalculos.reduce((sum, item) => sum + (item.promedio_Ventas || 0), 0);
|
||||||
|
const sumPorcDevolucion = promediosConCalculos.reduce((sum, item) => sum + (item.porcentajeDevolucion || 0), 0);
|
||||||
|
|
||||||
setTotalesPromedios({
|
setTotalesPromedios({
|
||||||
cantDias: totalDiasPromedios,
|
cantDias: totalDiasPromedios,
|
||||||
promLlevados: totalDiasPromedios > 0 ? totalPonderadoLlevados / totalDiasPromedios : 0,
|
promLlevados: sumPromLlevados / countPromedios,
|
||||||
promDevueltos: totalDiasPromedios > 0 ? totalPonderadoDevueltos / totalDiasPromedios : 0,
|
promDevueltos: sumPromDevueltos / countPromedios,
|
||||||
promVentas: totalDiasPromedios > 0 ? totalPonderadoVentas / totalDiasPromedios : 0,
|
promVentas: sumPromVentas / countPromedios,
|
||||||
porcentajeDevolucionGeneral: totalPonderadoLlevados > 0 ? (totalPonderadoDevueltos / totalPonderadoLlevados) * 100 : 0,
|
porcentajeDevolucionGeneral: sumPorcDevolucion / countPromedios,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setReportData({ detalleSimple: detalleConCalculos, promediosPorDia: promediosConCalculos });
|
setReportData({ detalleSimple: detalleConCalculos, promediosPorDia: promediosConCalculos });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user