generated from coulomb/repo-seed
Add liquidity tracking, budget, and platform cost history
Restore operator platform costs (Bubble, domains, Stripe) with monthly history from March 2025 and member payments from November 2025. Track €1,000 starting budget, cumulative burn, and remaining liquidity in the economics dashboard. Document LQ requirements in REQUIREMENTS.md.
This commit is contained in:
@@ -3,10 +3,17 @@ from __future__ import annotations
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
from observatory.economics import active_members, build_snapshot, monthly_cost_total
|
||||
from observatory.economics import (
|
||||
active_members,
|
||||
build_liquidity_summary,
|
||||
build_snapshot,
|
||||
monthly_cost_from_rate_card,
|
||||
)
|
||||
from observatory.load import (
|
||||
load_costs,
|
||||
load_budget,
|
||||
load_cost_rate_card,
|
||||
load_membership,
|
||||
load_monthly_platform_costs,
|
||||
load_pricing_models,
|
||||
load_product,
|
||||
load_revenue,
|
||||
@@ -20,36 +27,58 @@ def test_active_members_counts_only_active_status() -> None:
|
||||
assert active_members(members) == 1
|
||||
|
||||
|
||||
def test_build_snapshot_reflects_sole_member_and_zero_costs() -> None:
|
||||
def test_rate_card_matches_documented_platform_cost_without_revenue() -> None:
|
||||
rate_card, fx_rates = load_cost_rate_card(DATA_DIR)
|
||||
total = monthly_cost_from_rate_card(rate_card, fx_rates, Decimal("0"), 0)
|
||||
assert total == Decimal("72.20")
|
||||
|
||||
|
||||
def test_rate_card_matches_platform_cost_with_one_member() -> None:
|
||||
rate_card, fx_rates = load_cost_rate_card(DATA_DIR)
|
||||
total = monthly_cost_from_rate_card(rate_card, fx_rates, Decimal("8.99"), 1)
|
||||
assert total == Decimal("72.58")
|
||||
|
||||
|
||||
def test_build_snapshot_june_2026_shows_liquidity_burn() -> None:
|
||||
product = load_product(DATA_DIR)
|
||||
models = load_pricing_models(DATA_DIR)
|
||||
members = load_membership(DATA_DIR)
|
||||
revenue = load_revenue(DATA_DIR)
|
||||
_, costs, fx_rates = load_costs(DATA_DIR)
|
||||
monthly_costs = load_monthly_platform_costs(DATA_DIR)
|
||||
|
||||
snapshot = build_snapshot("2026-06", product, models, members, revenue, costs, fx_rates)
|
||||
snapshot = build_snapshot("2026-06", product, models, members, revenue, monthly_costs)
|
||||
|
||||
assert snapshot.active_members == 1
|
||||
assert snapshot.monthly_revenue == Decimal("8.99")
|
||||
assert snapshot.revenue_source == "manual"
|
||||
assert snapshot.pricing_model_count == 3
|
||||
assert snapshot.monthly_cost == Decimal("0.00")
|
||||
assert snapshot.cost_per_member == Decimal("0.00")
|
||||
assert snapshot.gross_margin == Decimal("8.99")
|
||||
assert snapshot.gross_margin_pct == Decimal("100.0")
|
||||
assert snapshot.monthly_platform_cost == Decimal("72.58")
|
||||
assert snapshot.period_net_liquidity == Decimal("-63.97")
|
||||
assert snapshot.liquidity_status == "burning"
|
||||
assert snapshot.gross_margin == Decimal("-63.59")
|
||||
|
||||
|
||||
def test_monthly_cost_is_zero_with_empty_registry() -> None:
|
||||
_, costs, fx_rates = load_costs(DATA_DIR)
|
||||
total = monthly_cost_total(costs, fx_rates, Decimal("8.99"), 1)
|
||||
assert total == Decimal("0.00")
|
||||
def test_liquidity_summary_tracks_budget_burn_through_june_2026() -> None:
|
||||
budget = load_budget(DATA_DIR)
|
||||
revenue = load_revenue(DATA_DIR)
|
||||
monthly_costs = load_monthly_platform_costs(DATA_DIR)
|
||||
|
||||
summary = build_liquidity_summary(budget, revenue, monthly_costs, "2026-06")
|
||||
|
||||
assert summary.initial_budget == Decimal("1000.00")
|
||||
assert summary.cumulative_platform_cost == Decimal("1158.24")
|
||||
assert summary.cumulative_member_payments == Decimal("68.88")
|
||||
assert summary.cumulative_net_liquidity == Decimal("-1089.36")
|
||||
assert summary.remaining_budget == Decimal("-89.36")
|
||||
assert summary.liquidity_status == "burning"
|
||||
assert summary.months_tracked == 16
|
||||
|
||||
|
||||
def test_dashboard_module_renders_markdown() -> None:
|
||||
def test_dashboard_renders_liquidity_sections() -> None:
|
||||
from observatory.dashboard import generate_dashboard
|
||||
|
||||
report = generate_dashboard(DATA_DIR, "2026-06")
|
||||
assert "# Economics Dashboard v1" in report
|
||||
assert "Pricing Model Registry" in report
|
||||
assert "flat-899-eur-monthly" in report
|
||||
assert "Active members | 1" in report
|
||||
assert "Liquidity & Budget" in report
|
||||
assert "Monthly History" in report
|
||||
assert "2025-03" in report
|
||||
assert "2025-11" in report
|
||||
assert "remaining budget" not in report.lower() or "Remaining budget" in report
|
||||
assert "-89.36" in report
|
||||
Reference in New Issue
Block a user