Files
adaptive-pricing/projects/coulomb-pricing/observatory/dashboard.py
tegwick a1a4aa972f Implement ADAPTIVE-WP-0002 Sprint 1 economic foundations
Add Coulomb observatory package with JSON registries (product, pricing
models, costs, revenue, membership), economics snapshot engine, Economics
Dashboard v1 CLI, sample report, and pytest coverage. Complete T01 and
queue Sprint 2 Bubble.io integration.
2026-06-22 01:32:48 +02:00

107 lines
3.1 KiB
Python

from __future__ import annotations
import argparse
from pathlib import Path
from .economics import build_snapshot
from .load import (
default_data_dir,
load_costs,
load_membership,
load_pricing_models,
load_product,
load_revenue,
)
from .models import EconomicsSnapshot, PricingModel, Product
def render_dashboard(
product: Product,
models: list[PricingModel],
snapshot: EconomicsSnapshot,
) -> str:
active = next(m for m in models if m.id == product.active_pricing_model_id)
registry_lines = "\n".join(
f"| {model.id} | {model.name} | {model.model_type} | {model.status} |"
for model in models
)
return f"""# Economics Dashboard v1 — {product.name}
**Period:** {snapshot.period}
**Lifecycle phase:** {product.lifecycle_phase}
**Active pricing model:** {active.name} ({active.access_fee_amount} {active.currency}/{active.access_fee_cadence})
## Key Metrics
| Metric | Value |
|--------|------:|
| Active members | {snapshot.active_members} |
| Monthly revenue | {snapshot.monthly_revenue} {snapshot.currency} |
| Monthly cost | {snapshot.monthly_cost} {snapshot.currency} |
| Cost per member | {snapshot.cost_per_member} {snapshot.currency} |
| Gross margin | {snapshot.gross_margin} {snapshot.currency} |
| Gross margin % | {snapshot.gross_margin_pct}% |
_Revenue source: {snapshot.revenue_source}_
## Pricing Model Registry
| ID | Name | Type | Status |
|----|------|------|--------|
{registry_lines}
## Registries Loaded
- Product model (`data/product.json`)
- Pricing model registry (`data/pricing-models.json`)
- Cost registry (`data/costs.json`)
- Revenue registry (`data/revenue.json`)
- Membership registry (`data/membership.json`)
"""
def generate_dashboard(data_dir: Path | None = None, period: str | None = None) -> str:
root = data_dir or default_data_dir()
product = load_product(root)
models = load_pricing_models(root)
members = load_membership(root)
revenue = load_revenue(root)
cost_period, costs, fx_rates = load_costs(root)
target_period = period or cost_period
snapshot = build_snapshot(
target_period,
product,
models,
members,
revenue,
costs,
fx_rates,
)
return render_dashboard(product, models, snapshot)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Coulomb Social Economics Dashboard v1")
parser.add_argument("--data-dir", type=Path, default=None, help="Registry data directory")
parser.add_argument("--period", default=None, help="Reporting period (YYYY-MM)")
parser.add_argument(
"--output",
type=Path,
default=None,
help="Write Markdown report to this path (default: stdout only)",
)
args = parser.parse_args(argv)
report = generate_dashboard(args.data_dir, args.period)
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(report, encoding="utf-8")
print(f"Wrote {args.output}")
else:
print(report)
return 0
if __name__ == "__main__":
raise SystemExit(main())