63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
"""Toy-model acceptance pins — hand-checked, like every study must have.
|
|
|
|
Every number here was computed by hand before it was pinned. When you
|
|
replace the toy domain, replace these with hand-checks of YOUR math;
|
|
the in-notebook verification gate is the second layer, not a substitute.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from studylib import model as m
|
|
|
|
|
|
def test_contracted_overlays_verbatim():
|
|
assert m.anchor("platform_annual") == 500_000 # signed contract
|
|
assert m.ANCHOR_VERBATIM["platform_annual"] == 600_000 # pitch record intact
|
|
assert m.anchor("baseline_annual") == m.ANCHOR_VERBATIM["baseline_annual"]
|
|
|
|
|
|
def test_ramp_mechanics():
|
|
assert m.platform_costs_by_year() == {2026: 300_000, 2027: 600_000,
|
|
2028: 600_000}
|
|
assert m.platform_costs_by_year(12)[2026] == 0.0
|
|
assert m.platform_costs_by_year(0)[2026] == 600_000.0
|
|
assert m.platform_costs_by_year(annual=m.anchor("platform_annual")) == \
|
|
{2026: 250_000, 2027: 500_000, 2028: 500_000}
|
|
|
|
|
|
def test_benefits_phase_on_the_schedule():
|
|
ben = m.benefits_by_year()
|
|
assert ben[2026] == 0.0 # nothing lands in year 1
|
|
assert ben[2027] == pytest.approx(900_000 * 6 / 18) # months 19-24
|
|
assert ben[2028] == pytest.approx(900_000 * 12 / 18)
|
|
assert sum(ben.values()) == pytest.approx(m.anchor("benefit_3yr"))
|
|
|
|
|
|
def _frame(annual):
|
|
plat = m.platform_costs_by_year(annual=annual)
|
|
total = {y: m.current_costs_by_year()[y] + plat[y] + m.services_by_year()[y]
|
|
for y in m.YEARS}
|
|
return m.case_flows(total, m.benefits_by_year())
|
|
|
|
|
|
def test_contracted_frame_kpis():
|
|
inc, net = _frame(m.anchor("platform_annual"))
|
|
assert sum(net.values()) == pytest.approx(400_000)
|
|
kpi = m.case_kpis(inc, net)
|
|
assert kpi["roi"] == pytest.approx(0.8)
|
|
assert kpi["npv"] == pytest.approx(206_612, abs=1) # @10%, hand-checked
|
|
assert kpi["payback"] == "32 months (~Aug 2028)"
|
|
|
|
|
|
def test_vendor_frame_kpis():
|
|
inc, net = _frame(None) # verbatim pitch rate
|
|
assert sum(net.values()) == pytest.approx(150_000)
|
|
assert m.case_kpis(inc, net)["payback"] == "35 months (~Nov 2028)"
|
|
|
|
|
|
def test_payback_edges():
|
|
assert m.payback_label({2026: 1.0, 2027: 0.0, 2028: 0.0}) == "immediate"
|
|
assert m.payback_label({2026: -1.0, 2027: -1.0, 2028: -1.0}) == "beyond 2028"
|