studies/202602_AmazonConnect -> studies/202602_TEI_Amazon_Connect, rebuilt as pattern Variant 4 (TEI composite reproduction): - teicalc/ self-contained engine (stdlib-only): Forrester's tables as the never-edited verbatim anchor, NPV/ROI/payback + risk adjustment transplanted from core/calculations, ClientDrivers overlay (contacts/ agents/fixed driver map, growth re-base, identity at composite scale), scenario stress with core-identical semantics - one deliverable notebook (business_case.ipynb): widget-pair sidebar drivers, published-vs-overlay KPI columns, cash-flow/waterfall/scenario charts, verification gate, backstage JSON data appendix - gate + tests reproduce the published totals within PDF rounding: NPV $78.7M / ROI 342% / payback <6 months (engine $78,713,492 / 342.48% / 0.7 months); 27 study tests, headless nbconvert green, stage simulation leak-free, exports carry the appendix - old Athena workflow (00_provision..04_export, config.py, seed_data.py) deleted; git history preserves it; root test fixture repointed to teicalc.anchor - docs: study README rewritten; root README points new studies at template/MercuryNotebook; pattern doc stale ctm-token-calculator paths now cite studies/202607_CTM_GenesysCX; Variant 4 cites this study as its realized reference Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
"""The verbatim anchor is Forrester's published record — pinned value by
|
|
value, and proven immutable under every engine code path."""
|
|
|
|
from copy import deepcopy
|
|
|
|
from teicalc import (
|
|
ASSUMPTIONS,
|
|
BENEFITS_VERBATIM,
|
|
COMPOSITE,
|
|
COSTS_VERBATIM,
|
|
PUBLISHED,
|
|
ClientDrivers,
|
|
apply_scenario,
|
|
compute_summary,
|
|
overlay_rows,
|
|
)
|
|
|
|
|
|
def _row(rows, key):
|
|
return next(r for r in rows if r["field_key"] == key)
|
|
|
|
|
|
def test_benefit_rows_verbatim():
|
|
assert [r["field_key"] for r in BENEFITS_VERBATIM] == [
|
|
"ai_contact_resolution",
|
|
"ai_content_sentiment",
|
|
"ai_forecasting_supervision",
|
|
"data_driven_profit_lift",
|
|
"legacy_solution_savings",
|
|
]
|
|
expected = {
|
|
"ai_contact_resolution": ({"1": 13_911_040, "2": 23_932_480, "3": 37_797_760}, 0.15),
|
|
"ai_content_sentiment": ({"1": 4_586_620, "2": 5_358_412, "3": 6_291_680}, 0.15),
|
|
"ai_forecasting_supervision": ({"1": 6_651_680, "2": 9_133_760, "3": 12_391_712}, 0.15),
|
|
"data_driven_profit_lift": ({"1": 1_200_000, "2": 1_560_000, "3": 2_028_000}, 0.20),
|
|
"legacy_solution_savings": ({"1": 6_177_600, "2": 8_030_880, "3": 10_440_144}, 0.20),
|
|
}
|
|
for key, (years, rf) in expected.items():
|
|
row = _row(BENEFITS_VERBATIM, key)
|
|
assert row["year_values"] == years
|
|
assert row["risk_adjustment"] == rf
|
|
assert row["table"] == "benefits"
|
|
|
|
|
|
def test_cost_rows_verbatim():
|
|
expected = {
|
|
"amazon_connect_usage": ({"1": 6_456_448, "2": 7_951_164, "3": 9_832_961}, 0.05, 0),
|
|
"implementation_migration": ({"1": 188_333, "2": 188_333, "3": 0}, 0.10, 1_087_500),
|
|
"ongoing_management": ({"1": 256_200, "2": 187_200, "3": 187_200}, 0.15, 0),
|
|
}
|
|
for key, (years, rf, initial) in expected.items():
|
|
row = _row(COSTS_VERBATIM, key)
|
|
assert row["year_values"] == years
|
|
assert row["risk_adjustment"] == rf
|
|
assert row["initial"] == initial
|
|
assert row["table"] == "costs"
|
|
|
|
|
|
def test_assumptions_and_published():
|
|
assert ASSUMPTIONS["agents_fte"] == 2_000
|
|
assert ASSUMPTIONS["supervisors_fte"] == 200
|
|
assert ASSUMPTIONS["annual_contacts_y1"] == 20_000_000
|
|
assert ASSUMPTIONS["growth_rate"] == 0.30
|
|
assert ASSUMPTIONS["discount_rate"] == 0.10
|
|
assert ASSUMPTIONS["analysis_years"] == 3
|
|
|
|
assert PUBLISHED["benefits_pv"] == 101_696_791
|
|
assert PUBLISHED["costs_pv"] == 22_983_076
|
|
assert PUBLISHED["npv"] == 78_713_715
|
|
assert PUBLISHED["roi_pct"] == 342
|
|
assert PUBLISHED["payback_months_max"] == 6
|
|
|
|
# The composite drivers ARE the anchor assumptions.
|
|
assert COMPOSITE.agents_fte == ASSUMPTIONS["agents_fte"]
|
|
assert COMPOSITE.annual_contacts_y1 == ASSUMPTIONS["annual_contacts_y1"]
|
|
assert COMPOSITE.growth_rate == ASSUMPTIONS["growth_rate"]
|
|
assert COMPOSITE.discount_rate == ASSUMPTIONS["discount_rate"]
|
|
|
|
|
|
def test_anchor_is_never_mutated():
|
|
"""Exercise every engine code path, then prove the record unchanged."""
|
|
ben_snap = deepcopy(BENEFITS_VERBATIM)
|
|
cost_snap = deepcopy(COSTS_VERBATIM)
|
|
|
|
overlay_rows()
|
|
overlay_rows(ClientDrivers(agents_fte=137, annual_contacts_y1=1_000_000,
|
|
growth_rate=0.0))
|
|
for scenario in ("conservative", "moderate", "aggressive"):
|
|
apply_scenario(BENEFITS_VERBATIM, scenario)
|
|
apply_scenario(COSTS_VERBATIM, scenario)
|
|
compute_summary(BENEFITS_VERBATIM, COSTS_VERBATIM, 0.10)
|
|
compute_summary(BENEFITS_VERBATIM, COSTS_VERBATIM, 0.08)
|
|
|
|
assert BENEFITS_VERBATIM == ben_snap
|
|
assert COSTS_VERBATIM == cost_snap
|