fix: Consistent CPI calculations and correct benchmark data

1. DimensionAnalysisTab: Changed CPI fallback from 2.33 to 0 to match
   ExecutiveSummaryTab calculation

2. ExecutiveSummaryTab: Fixed benchmark data for inverted metrics (CPI, Abandono)
   - Values must be in ASCENDING order (p25 < p50 < p75 < p90)
   - p25 = best performers (lowest CPI/abandono)
   - p90 = worst performers (highest CPI/abandono)
   - This fixes the visual comparison and gap calculation

Before: cpi { p25: 4.50, p50: 3.50, p75: 2.80, p90: 2.20 } (DESCENDING - wrong)
After:  cpi { p25: 2.20, p50: 3.50, p75: 4.50, p90: 5.50 } (ASCENDING - correct)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
sujucu70
2026-01-23 11:09:40 +01:00
parent 0063d299c9
commit 5df79d436f
2 changed files with 16 additions and 15 deletions

View File

@@ -62,16 +62,17 @@ function generateCausalAnalysis(
} }
// v3.11: CPI consistente con Executive Summary // v3.11: CPI consistente con Executive Summary
const CPI_TCO = 2.33; const CPI_TCO = 2.33; // Benchmark para cálculos de impacto cuando no hay CPI real
// Usar CPI pre-calculado de heatmapData si existe, sino calcular desde annual_cost/cost_volume // Usar CPI pre-calculado de heatmapData si existe, sino calcular desde annual_cost/cost_volume
// IMPORTANTE: Mismo cálculo que ExecutiveSummaryTab para consistencia
const totalCostVolume = heatmapData.reduce((sum, h) => sum + (h.cost_volume || h.volume), 0); const totalCostVolume = heatmapData.reduce((sum, h) => sum + (h.cost_volume || h.volume), 0);
const totalAnnualCost = heatmapData.reduce((sum, h) => sum + (h.annual_cost || 0), 0); const totalAnnualCost = heatmapData.reduce((sum, h) => sum + (h.annual_cost || 0), 0);
const hasCpiField = heatmapData.some(h => h.cpi !== undefined && h.cpi > 0); const hasCpiField = heatmapData.some(h => h.cpi !== undefined && h.cpi > 0);
const CPI = hasCpiField const CPI = hasCpiField
? (totalCostVolume > 0 ? (totalCostVolume > 0
? heatmapData.reduce((sum, h) => sum + (h.cpi || 0) * (h.cost_volume || h.volume), 0) / totalCostVolume ? heatmapData.reduce((sum, h) => sum + (h.cpi || 0) * (h.cost_volume || h.volume), 0) / totalCostVolume
: CPI_TCO) : 0)
: (totalCostVolume > 0 ? totalAnnualCost / totalCostVolume : CPI_TCO); : (totalCostVolume > 0 ? totalAnnualCost / totalCostVolume : 0);
// Calcular métricas agregadas // Calcular métricas agregadas
const avgCVAHT = totalVolume > 0 const avgCVAHT = totalVolume > 0

View File

@@ -57,8 +57,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 320, p50: 380, p75: 450, p90: 520, unidad: 's', invertida: true }, aht: { p25: 320, p50: 380, p75: 450, p90: 520, unidad: 's', invertida: true },
fcr: { p25: 55, p50: 68, p75: 78, p90: 85, unidad: '%', invertida: false }, fcr: { p25: 55, p50: 68, p75: 78, p90: 85, unidad: '%', invertida: false },
abandono: { p25: 8, p50: 5, p75: 3, p90: 2, unidad: '%', invertida: true }, abandono: { p25: 2, p50: 5, p75: 8, p90: 12, unidad: '%', invertida: true },
cpi: { p25: 4.50, p50: 3.50, p75: 2.80, p90: 2.20, unidad: '€', invertida: true } cpi: { p25: 2.20, p50: 3.50, p75: 4.50, p90: 5.50, unidad: '€', invertida: true }
} }
}, },
telecomunicaciones: { telecomunicaciones: {
@@ -67,8 +67,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 380, p50: 420, p75: 500, p90: 600, unidad: 's', invertida: true }, aht: { p25: 380, p50: 420, p75: 500, p90: 600, unidad: 's', invertida: true },
fcr: { p25: 50, p50: 65, p75: 75, p90: 82, unidad: '%', invertida: false }, fcr: { p25: 50, p50: 65, p75: 75, p90: 82, unidad: '%', invertida: false },
abandono: { p25: 10, p50: 6, p75: 4, p90: 2, unidad: '%', invertida: true }, abandono: { p25: 2, p50: 6, p75: 10, p90: 15, unidad: '%', invertida: true },
cpi: { p25: 5.00, p50: 4.00, p75: 3.20, p90: 2.50, unidad: '€', invertida: true } cpi: { p25: 2.50, p50: 4.00, p75: 5.00, p90: 6.00, unidad: '€', invertida: true }
} }
}, },
banca: { banca: {
@@ -77,8 +77,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 280, p50: 340, p75: 420, p90: 500, unidad: 's', invertida: true }, aht: { p25: 280, p50: 340, p75: 420, p90: 500, unidad: 's', invertida: true },
fcr: { p25: 58, p50: 72, p75: 82, p90: 88, unidad: '%', invertida: false }, fcr: { p25: 58, p50: 72, p75: 82, p90: 88, unidad: '%', invertida: false },
abandono: { p25: 6, p50: 4, p75: 2, p90: 1, unidad: '%', invertida: true }, abandono: { p25: 1, p50: 4, p75: 6, p90: 10, unidad: '%', invertida: true },
cpi: { p25: 6.00, p50: 4.50, p75: 3.50, p90: 2.80, unidad: '€', invertida: true } cpi: { p25: 2.80, p50: 4.50, p75: 6.00, p90: 7.50, unidad: '€', invertida: true }
} }
}, },
utilities: { utilities: {
@@ -87,8 +87,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 350, p50: 400, p75: 480, p90: 560, unidad: 's', invertida: true }, aht: { p25: 350, p50: 400, p75: 480, p90: 560, unidad: 's', invertida: true },
fcr: { p25: 52, p50: 67, p75: 77, p90: 84, unidad: '%', invertida: false }, fcr: { p25: 52, p50: 67, p75: 77, p90: 84, unidad: '%', invertida: false },
abandono: { p25: 9, p50: 6, p75: 4, p90: 2, unidad: '%', invertida: true }, abandono: { p25: 2, p50: 6, p75: 9, p90: 14, unidad: '%', invertida: true },
cpi: { p25: 4.20, p50: 3.30, p75: 2.60, p90: 2.00, unidad: '€', invertida: true } cpi: { p25: 2.00, p50: 3.30, p75: 4.20, p90: 5.20, unidad: '€', invertida: true }
} }
}, },
retail: { retail: {
@@ -97,8 +97,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 240, p50: 300, p75: 380, p90: 450, unidad: 's', invertida: true }, aht: { p25: 240, p50: 300, p75: 380, p90: 450, unidad: 's', invertida: true },
fcr: { p25: 60, p50: 73, p75: 82, p90: 89, unidad: '%', invertida: false }, fcr: { p25: 60, p50: 73, p75: 82, p90: 89, unidad: '%', invertida: false },
abandono: { p25: 7, p50: 4, p75: 2, p90: 1, unidad: '%', invertida: true }, abandono: { p25: 1, p50: 4, p75: 7, p90: 12, unidad: '%', invertida: true },
cpi: { p25: 3.80, p50: 2.80, p75: 2.10, p90: 1.60, unidad: '€', invertida: true } cpi: { p25: 1.60, p50: 2.80, p75: 3.80, p90: 4.80, unidad: '€', invertida: true }
} }
}, },
general: { general: {
@@ -107,8 +107,8 @@ const BENCHMARKS_INDUSTRIA: Record<IndustryKey, IndustryBenchmarks> = {
metricas: { metricas: {
aht: { p25: 320, p50: 380, p75: 460, p90: 540, unidad: 's', invertida: true }, aht: { p25: 320, p50: 380, p75: 460, p90: 540, unidad: 's', invertida: true },
fcr: { p25: 55, p50: 70, p75: 80, p90: 87, unidad: '%', invertida: false }, fcr: { p25: 55, p50: 70, p75: 80, p90: 87, unidad: '%', invertida: false },
abandono: { p25: 8, p50: 5, p75: 3, p90: 2, unidad: '%', invertida: true }, abandono: { p25: 2, p50: 5, p75: 8, p90: 12, unidad: '%', invertida: true },
cpi: { p25: 4.50, p50: 3.50, p75: 2.80, p90: 2.20, unidad: '€', invertida: true } cpi: { p25: 2.20, p50: 3.50, p75: 4.50, p90: 5.50, unidad: '€', invertida: true }
} }
} }
}; };