Migrate Amazon Connect TEI study to the Mercury Notebook Pattern
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>
This commit is contained in:
75
studies/202602_TEI_Amazon_Connect/tests/test_scenarios.py
Normal file
75
studies/202602_TEI_Amazon_Connect/tests/test_scenarios.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Scenario pins — hand-checked composite results per scenario, clamp
|
||||
behaviour, and copy semantics."""
|
||||
|
||||
import pytest
|
||||
|
||||
from teicalc import (
|
||||
BENEFITS_VERBATIM,
|
||||
COSTS_VERBATIM,
|
||||
SCENARIOS,
|
||||
apply_scenario,
|
||||
compute_summary,
|
||||
)
|
||||
|
||||
|
||||
def _summary(scenario):
|
||||
return compute_summary(
|
||||
apply_scenario(BENEFITS_VERBATIM, scenario),
|
||||
apply_scenario(COSTS_VERBATIM, scenario),
|
||||
0.10,
|
||||
)
|
||||
|
||||
|
||||
def test_scenario_definitions():
|
||||
assert SCENARIOS == {
|
||||
"conservative": {"adoption": 0.80, "risk_delta": 0.10},
|
||||
"moderate": {"adoption": 1.00, "risk_delta": 0.00},
|
||||
"aggressive": {"adoption": 1.15, "risk_delta": -0.05},
|
||||
}
|
||||
|
||||
|
||||
def test_moderate_is_identity():
|
||||
got = _summary("moderate")
|
||||
want = compute_summary(BENEFITS_VERBATIM, COSTS_VERBATIM, 0.10)
|
||||
assert got["benefits_pv"] == pytest.approx(want["benefits_pv"], abs=0.01)
|
||||
assert got["costs_pv"] == pytest.approx(want["costs_pv"], abs=0.01)
|
||||
|
||||
|
||||
def test_conservative_pins():
|
||||
s = _summary("conservative")
|
||||
assert s["benefits_pv"] == pytest.approx(71_672_867.65, abs=1)
|
||||
assert s["costs_pv"] == pytest.approx(17_437_916.34, abs=1)
|
||||
assert s["npv"] == pytest.approx(54_234_951.31, abs=1)
|
||||
assert s["roi_pct"] == pytest.approx(311.02, abs=0.01)
|
||||
assert s["payback_months"] == pytest.approx(0.763, abs=0.001)
|
||||
|
||||
|
||||
def test_aggressive_pins():
|
||||
s = _summary("aggressive")
|
||||
assert s["benefits_pv"] == pytest.approx(123_911_705.40, abs=1)
|
||||
assert s["costs_pv"] == pytest.approx(27_682_368.61, abs=1)
|
||||
assert s["npv"] == pytest.approx(96_229_336.79, abs=1)
|
||||
assert s["roi_pct"] == pytest.approx(347.62, abs=0.01)
|
||||
assert s["payback_months"] == pytest.approx(0.705, abs=0.001)
|
||||
|
||||
|
||||
def test_risk_delta_clamps_at_zero():
|
||||
"""Conservative subtracts 0.10 from cost risk; usage (0.05) clamps to 0."""
|
||||
rows = apply_scenario(COSTS_VERBATIM, "conservative")
|
||||
usage = next(r for r in rows if r["field_key"] == "amazon_connect_usage")
|
||||
assert usage["risk_adjustment"] == 0.0
|
||||
impl = next(r for r in rows if r["field_key"] == "implementation_migration")
|
||||
assert impl["risk_adjustment"] == pytest.approx(0.0) # 0.10 − 0.10
|
||||
assert impl["initial"] == pytest.approx(1_087_500 * 0.80) # adoption scales initial
|
||||
|
||||
|
||||
def test_unknown_scenario_raises():
|
||||
with pytest.raises(KeyError):
|
||||
apply_scenario(BENEFITS_VERBATIM, "wildly_optimistic")
|
||||
|
||||
|
||||
def test_inputs_not_mutated():
|
||||
apply_scenario(BENEFITS_VERBATIM, "aggressive")
|
||||
apply_scenario(COSTS_VERBATIM, "conservative")
|
||||
assert BENEFITS_VERBATIM[0]["year_values"]["1"] == 13_911_040
|
||||
assert COSTS_VERBATIM[1]["initial"] == 1_087_500
|
||||
Reference in New Issue
Block a user