Files
BeyondCXAnalytics-Demo/backend/tests/test_economy_cost.py
2026-02-04 11:08:21 +01:00

129 lines
3.5 KiB
Python

import math
from datetime import datetime
import matplotlib
import pandas as pd
from beyond_metrics.dimensions.EconomyCost import EconomyCostMetrics, EconomyConfig
matplotlib.use("Agg")
def _sample_df() -> pd.DataFrame:
data = [
{
"interaction_id": "id1",
"datetime_start": datetime(2024, 1, 1, 10, 0),
"queue_skill": "ventas",
"channel": "voz",
"duration_talk": 600,
"hold_time": 60,
"wrap_up_time": 30,
},
{
"interaction_id": "id2",
"datetime_start": datetime(2024, 1, 1, 10, 5),
"queue_skill": "ventas",
"channel": "voz",
"duration_talk": 300,
"hold_time": 30,
"wrap_up_time": 20,
},
{
"interaction_id": "id3",
"datetime_start": datetime(2024, 1, 1, 11, 0),
"queue_skill": "soporte",
"channel": "chat",
"duration_talk": 400,
"hold_time": 20,
"wrap_up_time": 30,
},
]
return pd.DataFrame(data)
def test_init_and_required_columns():
df = _sample_df()
cfg = EconomyConfig(labor_cost_per_hour=20.0, overhead_rate=0.1, tech_costs_annual=10000.0)
em = EconomyCostMetrics(df, cfg)
assert not em.is_empty
# Falta de columna obligatoria -> ValueError
df_missing = df.drop(columns=["duration_talk"])
import pytest
with pytest.raises(ValueError):
EconomyCostMetrics(df_missing, cfg)
def test_metrics_without_config_do_not_crash():
df = _sample_df()
em = EconomyCostMetrics(df, None)
assert em.cpi_by_skill_channel().empty
assert em.annual_cost_by_skill_channel().empty
assert em.cost_breakdown() == {}
assert em.inefficiency_cost_by_skill_channel().empty
assert em.potential_savings() == {}
def test_basic_cpi_and_annual_cost():
df = _sample_df()
cfg = EconomyConfig(labor_cost_per_hour=20.0, overhead_rate=0.1)
em = EconomyCostMetrics(df, cfg)
cpi = em.cpi_by_skill_channel()
assert not cpi.empty
# Debe haber filas para ventas/voz y soporte/chat
assert ("ventas", "voz") in cpi.index
assert ("soporte", "chat") in cpi.index
annual = em.annual_cost_by_skill_channel()
assert "annual_cost" in annual.columns
# costes positivos
assert (annual["annual_cost"] > 0).any()
def test_cost_breakdown_and_potential_savings():
df = _sample_df()
cfg = EconomyConfig(
labor_cost_per_hour=20.0,
overhead_rate=0.1,
tech_costs_annual=5000.0,
automation_cpi=0.2,
automation_volume_share=0.5,
automation_success_rate=0.8,
)
em = EconomyCostMetrics(df, cfg)
breakdown = em.cost_breakdown()
assert "labor_pct" in breakdown
assert "overhead_pct" in breakdown
assert "tech_pct" in breakdown
total_pct = (
breakdown["labor_pct"]
+ breakdown["overhead_pct"]
+ breakdown["tech_pct"]
)
# Permitimos pequeño error por redondeo a 2 decimales
assert abs(total_pct - 100.0) < 0.2
savings = em.potential_savings()
assert "annual_savings" in savings
assert savings["annual_savings"] >= 0.0
def test_plot_methods_return_axes():
from matplotlib.axes import Axes
df = _sample_df()
cfg = EconomyConfig(labor_cost_per_hour=20.0, overhead_rate=0.1)
em = EconomyCostMetrics(df, cfg)
ax1 = em.plot_cost_waterfall()
ax2 = em.plot_cpi_by_channel()
assert isinstance(ax1, Axes)
assert isinstance(ax2, Axes)