feat: add corrected business case page with TEI-styled charts

This commit is contained in:
2026-07-07 11:48:52 -04:00
parent 483bbe61dc
commit 0fa2091a25
4 changed files with 1268 additions and 447 deletions

View File

@@ -0,0 +1,108 @@
"""Appendix-4 corrected business case — hand-check acceptance numbers."""
from __future__ import annotations
import datetime as dt
import math
import pytest
from tokencalc import appendix4 as a4
from tokencalc.defaults import CTM_DEFAULT_SITES, DEFAULT_METERS, DEFAULT_PRICING
SITES = list(CTM_DEFAULT_SITES)
def test_verbatim_crossfoots_to_slide_totals():
df = a4.verbatim_dataframe()
for r, expect in a4.SLIDE_TOTALS["regional_3yr"].items():
got = df.loc[df.region == r, "three_yr"].sum()
assert abs(got - expect) <= a4.crossfoot_tolerance(expect), r
for c, expect in a4.SLIDE_TOTALS["capability_3yr"].items():
got = df.loc[df.capability == c, "three_yr"].sum()
assert abs(got - expect) <= a4.crossfoot_tolerance(expect), c
assert abs(df["three_yr"].sum() - a4.SLIDE_TOTALS["total_3yr"]) <= \
a4.crossfoot_tolerance(a4.SLIDE_TOTALS["total_3yr"])
def test_benefits_phase_on_the_deck_schedule():
_, _, benefit_rollout = a4.build_rollouts(SITES)
long = a4.benefits_by_year(benefit_rollout)
by_year = long.groupby("year")["benefit"].sum()
assert by_year[2026] == 0.0, "2026 must be $0 under Genesys's own schedule"
# Scaling at the finest grain reproduces every verbatim 3-yr value exactly.
for (region, cap), (_, three_yr) in a4.VERBATIM_BENEFITS.items():
got = long.query("region == @region and capability == @cap")["benefit"].sum()
assert got == pytest.approx(three_yr)
def test_ramp_zeroes_year_one_licences():
assert a4.licence_costs_by_year(12) == {2026: 0.0, 2027: 4_300_000.0,
2028: 4_300_000.0}
assert a4.licence_costs_by_year(0)[2026] == 4_300_000.0
assert a4.licence_costs_by_year(18)[2027] == pytest.approx(4_300_000 * 6 / 12)
def test_current_state_run_off():
cs = a4.current_state_inputs(SITES)
assert cs["annual_cost"].sum() == pytest.approx(7_300_000)
by_year = a4.current_costs_by_year(cs)
assert by_year == {2026: pytest.approx(7_300_000),
2027: pytest.approx(7_300_000), 2028: 0.0}
cs.loc["NA", "contract_termination"] = dt.date(2028, 6, 30)
assert a4.current_costs_by_year(cs)[2028] == pytest.approx(
cs.loc["NA", "annual_cost"] * 6 / 12)
def test_token_hand_checks():
token_ro, email_ro, _ = a4.build_rollouts(SITES)
core, email = a4.build_scopes(SITES, copilot_includes_asia=False)
meters = {**DEFAULT_METERS, "Email AI (Auto-Respond)": a4.autorespond_meter(0.05)}
long = a4.token_costs_by_year(SITES, meters, DEFAULT_PRICING,
a4.claim_scenario(0.255), core, email,
token_ro, email_ro)
# STA 2028: NAM/AUZ/EMEA × 12 months + ASIA × 10 months, by hand.
sta = long.query("cost_line == 'Speech & Text Analytics [named]'")
assert sta.query("year == 2028")["annual_cost"].sum() == pytest.approx(715_800)
# Agent Copilot 2028 (ASIA off): 1,490 users × 40 tokens × 12 months.
cp = long.query("cost_line == 'Agent Copilot [named]' and year == 2028")
assert cp["annual_cost"].sum() == pytest.approx(1_490 * 40 * 12)
# Rule 1: Copilot covers AI Summary at Copilot sites.
assert (long.query("cost_line == 'AI Summary & Insights'")["annual_cost"] == 0).all()
# Nothing is live in 2026.
assert long.query("year == 2026")["annual_cost"].sum() == 0
# PR NAM steady-month tokens.
assert math.ceil(
1_214_358 * DEFAULT_METERS["Predictive Routing"].tokens_per_unit) == 71_433
def test_impl_costs_reconcile_with_v2_doc():
_, impl_y, kb_y, steady_y = a4.build_impl_costs(SITES, "mid", 225.0,
include_kb=True)
assert sum(impl_y.values()) == pytest.approx(5_850 * 225) # V2's "$1.3M"
assert sum(kb_y.values()) == pytest.approx(1_000 * 225)
assert steady_y == {2026: 0.0, 2027: pytest.approx(700 * 225),
2028: pytest.approx(700 * 225)}
# Impl spend is fully booked by each region's implementation month.
assert a4.impl_year_fractions(18) == pytest.approx([12 / 18, 6 / 18, 0.0])
assert a4.impl_year_fractions(27) == pytest.approx([12 / 27, 12 / 27, 3 / 27])
def test_case_flows_and_kpis():
benefits = {2026: 0.0, 2027: 2_000_000.0, 2028: 12_000_000.0}
costs = {2026: 10_000_000.0, 2027: 13_000_000.0, 2028: 8_000_000.0}
inc, net = a4.case_flows(costs, benefits)
assert inc == {2026: pytest.approx(2_700_000),
2027: pytest.approx(5_700_000),
2028: pytest.approx(700_000)}
for y in a4.YEARS:
assert net[y] == pytest.approx(benefits[y] - inc[y])
kpis = a4.case_kpis(inc, net)
assert kpis["benefits_3yr"] == pytest.approx(sum(benefits.values()))
assert kpis["net_3yr"] == pytest.approx(sum(net.values()))
assert kpis["roi"] == pytest.approx(kpis["net_3yr"] / kpis["incremental_cost_3yr"])
assert kpis["discount_rate"] == 0.135
# Net cost saving → ROI undefined.
inc2 = {y: -1.0 for y in a4.YEARS}
net2 = {y: benefits[y] + 1.0 for y in a4.YEARS}
assert a4.case_kpis(inc2, net2)["roi"] is None