adaptive-pricing/projects/coulomb-pricing/observatory/dashboard.py

107 lines
3.1 KiB
Python
Raw Normal View History

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())