generated from coulomb/repo-seed
Implement comparable LTV engine and close WP-0005
This commit is contained in:
@@ -24,6 +24,10 @@ def test_dashboard_payload_contains_live_ledger_totals() -> None:
|
||||
assert payload["membership_analytics"]["active_members"] == 1
|
||||
assert payload["usage"]["record_count"] == 1
|
||||
assert len(payload["pricing_simulations"]["scenarios"]) == 3
|
||||
assert len(payload["pricing_simulations"]["profile_comparisons"]) == 2
|
||||
assert payload["pricing_simulations"]["primary_profile_id"] == "solo-builder"
|
||||
assert payload["pricing_simulations"]["required_improvement_factor"] == "1.05"
|
||||
assert payload["pricing_simulations"]["reference_model_id"] is not None
|
||||
assert len(payload["boundary_validation"]["model_results"]) == 3
|
||||
assert payload["boundary_validation"]["policy"]["target_margin_pct"] == "15"
|
||||
assert any(
|
||||
|
||||
69
projects/coulomb-pricing/tests/test_comparable_ltv.py
Normal file
69
projects/coulomb-pricing/tests/test_comparable_ltv.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from observatory.economics import build_snapshot
|
||||
from observatory.load import (
|
||||
load_ltv_scenarios,
|
||||
load_membership,
|
||||
load_monthly_ledger,
|
||||
load_payment_records,
|
||||
load_pricing_models,
|
||||
load_product,
|
||||
)
|
||||
from observatory.simulator import build_pricing_simulations
|
||||
from observatory.usage import load_usage_records
|
||||
|
||||
DATA_DIR = Path(__file__).resolve().parent.parent / "data"
|
||||
|
||||
|
||||
def _snapshot(period: str = "2026-06"):
|
||||
product = load_product(DATA_DIR)
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
members = load_membership(DATA_DIR)
|
||||
payments = load_payment_records(DATA_DIR)
|
||||
ledger = load_monthly_ledger(DATA_DIR)
|
||||
return build_snapshot(period, product, models, members, payments, ledger)
|
||||
|
||||
|
||||
def test_simulations_include_reference_model_and_profile_comparisons() -> None:
|
||||
snapshot = _snapshot()
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
simulations = build_pricing_simulations(
|
||||
snapshot,
|
||||
models,
|
||||
snapshot.cost_per_member,
|
||||
usage_records=load_usage_records(DATA_DIR),
|
||||
scenario_catalog=load_ltv_scenarios(DATA_DIR),
|
||||
)
|
||||
|
||||
assert simulations["primary_profile_id"] == "solo-builder"
|
||||
assert simulations["reference_model_id"] is not None
|
||||
assert simulations["best_ltv_scenario_id"] is not None
|
||||
assert len(simulations["profile_comparisons"]) == 2
|
||||
assert simulations["scenarios"][0]["average_comparable_customer_lifetime_value"] is not None
|
||||
assert simulations["scenarios"][0]["sensitivity"]
|
||||
|
||||
|
||||
def test_small_team_profile_has_reference_and_non_passing_candidates() -> None:
|
||||
snapshot = _snapshot()
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
simulations = build_pricing_simulations(
|
||||
snapshot,
|
||||
models,
|
||||
snapshot.cost_per_member,
|
||||
usage_records=load_usage_records(DATA_DIR),
|
||||
scenario_catalog=load_ltv_scenarios(DATA_DIR),
|
||||
)
|
||||
|
||||
small_team = next(
|
||||
item for item in simulations["profile_comparisons"] if item["profile"]["id"] == "small-team"
|
||||
)
|
||||
|
||||
assert small_team["reference_model_id"] is not None
|
||||
assert small_team["best_valid_model_id"] is not None
|
||||
assert any(
|
||||
not comparison["passes_required_improvement"]
|
||||
for comparison in small_team["comparisons"]
|
||||
if comparison["model_id"] != small_team["reference_model_id"]
|
||||
)
|
||||
@@ -8,6 +8,7 @@ from observatory.api import build_dashboard_payload
|
||||
from observatory.credits import build_credit_summary, load_credit_wallets
|
||||
from observatory.economics import build_snapshot
|
||||
from observatory.load import (
|
||||
load_ltv_scenarios,
|
||||
load_membership,
|
||||
load_monthly_ledger,
|
||||
load_payment_records,
|
||||
@@ -58,10 +59,18 @@ def test_cost_allocation_includes_ai_variable_cost() -> None:
|
||||
def test_pricing_simulator_compares_candidate_models() -> None:
|
||||
snapshot = _snapshot()
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
simulations = build_pricing_simulations(snapshot, models, Decimal("0.06"))
|
||||
simulations = build_pricing_simulations(
|
||||
snapshot,
|
||||
models,
|
||||
Decimal("0.06"),
|
||||
usage_records=load_usage_records(DATA_DIR),
|
||||
scenario_catalog=load_ltv_scenarios(DATA_DIR),
|
||||
)
|
||||
|
||||
assert len(simulations["scenarios"]) == 3
|
||||
assert simulations["active_scenario_id"] == "flat-899-eur-monthly"
|
||||
assert simulations["best_ltv_scenario_id"] is not None
|
||||
assert simulations["reference_model_id"] is not None
|
||||
|
||||
|
||||
def test_credit_summary_tracks_remaining_allowance() -> None:
|
||||
@@ -93,4 +102,4 @@ def test_dashboard_payload_includes_mvp_sections() -> None:
|
||||
assert "cost_allocation" in payload
|
||||
assert "pricing_simulations" in payload
|
||||
assert "credit_wallets" in payload
|
||||
assert "recommendations" in payload
|
||||
assert "recommendations" in payload
|
||||
|
||||
Reference in New Issue
Block a user