diff --git a/projects/coulomb-pricing/README.md b/projects/coulomb-pricing/README.md index 336b6d7..12f8a11 100644 --- a/projects/coulomb-pricing/README.md +++ b/projects/coulomb-pricing/README.md @@ -28,5 +28,6 @@ python3 -m observatory --period 2026-06 python3 -m observatory --period 2026-06 --output reports/economics-2026-06.md ``` -Seed data is used until Bubble (Sprint 2) and Stripe (Sprint 3) importers -replace manual entries. \ No newline at end of file +**Current registry state:** one active member (founder), €8.99/month revenue, no +running costs recorded. Bubble (Sprint 2) and Stripe (Sprint 3) importers will +replace manual entries when integrations land. \ No newline at end of file diff --git a/projects/coulomb-pricing/data/costs.json b/projects/coulomb-pricing/data/costs.json index 0139597..a84a5d8 100644 --- a/projects/coulomb-pricing/data/costs.json +++ b/projects/coulomb-pricing/data/costs.json @@ -1,64 +1,9 @@ { "version": 1, "period": "2026-06", - "entries": [ - { - "id": "bubble-subscription", - "name": "Bubble.io platform", - "category": "fixed", - "amount": "35.00", - "currency": "USD", - "cadence": "monthly", - "allocation": "flat" - }, - { - "id": "domains", - "name": "Domains", - "category": "fixed", - "amount": "15.00", - "currency": "EUR", - "cadence": "monthly", - "allocation": "flat" - }, - { - "id": "operational-overhead", - "name": "Operational overhead", - "category": "fixed", - "amount": "25.00", - "currency": "EUR", - "cadence": "monthly", - "allocation": "flat" - }, - { - "id": "stripe-percentage", - "name": "Stripe percentage fee", - "category": "variable", - "amount": "0.015", - "currency": "ratio", - "cadence": "per_transaction", - "allocation": "percent_of_gross_revenue" - }, - { - "id": "stripe-fixed", - "name": "Stripe fixed fee", - "category": "variable", - "amount": "0.25", - "currency": "EUR", - "cadence": "per_transaction", - "allocation": "per_active_member" - }, - { - "id": "openrouter-ai", - "name": "OpenRouter AI consumption", - "category": "variable", - "amount": "0.00", - "currency": "EUR", - "cadence": "monthly", - "allocation": "flat", - "note": "Populated in Sprint 4 after usage import" - } - ], + "entries": [], "fx_rates": { "USD/EUR": "0.92" - } + }, + "note": "No running costs at present. Future fixed/variable lines (Bubble, Stripe, OpenRouter) added as they become payable." } \ No newline at end of file diff --git a/projects/coulomb-pricing/data/membership.json b/projects/coulomb-pricing/data/membership.json index 3d66d3c..c2af85a 100644 --- a/projects/coulomb-pricing/data/membership.json +++ b/projects/coulomb-pricing/data/membership.json @@ -1,40 +1,16 @@ { "version": 1, - "snapshot_date": "2026-06-21", + "snapshot_date": "2026-06-22", "members": [ { - "id": "member-001", + "id": "member-founder", "external_id": null, "status": "active", "joined_at": "2025-11-03", "plan_id": "flat-899-eur-monthly", - "source": "seed" - }, - { - "id": "member-002", - "external_id": null, - "status": "active", - "joined_at": "2026-01-15", - "plan_id": "flat-899-eur-monthly", - "source": "seed" - }, - { - "id": "member-003", - "external_id": null, - "status": "active", - "joined_at": "2026-03-28", - "plan_id": "flat-899-eur-monthly", - "source": "seed" - }, - { - "id": "member-004", - "external_id": null, - "status": "churned", - "joined_at": "2025-08-10", - "churned_at": "2026-02-01", - "plan_id": "flat-899-eur-monthly", - "source": "seed" + "source": "manual", + "note": "Sole active member (founder)" } ], - "note": "Seed data for Sprint 1; replaced by Bubble importer in Sprint 2" + "note": "Current reality: one active member. Bubble importer (Sprint 2) will sync live data." } \ No newline at end of file diff --git a/projects/coulomb-pricing/data/revenue.json b/projects/coulomb-pricing/data/revenue.json index b4e8934..d125a52 100644 --- a/projects/coulomb-pricing/data/revenue.json +++ b/projects/coulomb-pricing/data/revenue.json @@ -2,15 +2,15 @@ "version": 1, "entries": [ { - "id": "rev-2026-06-estimate", + "id": "rev-2026-06-founder", "period": "2026-06", - "gross_amount": "80.91", - "fees_amount": "2.46", + "gross_amount": "8.99", + "fees_amount": "0.00", "refunds_amount": "0.00", - "net_amount": "78.45", + "net_amount": "8.99", "currency": "EUR", - "source": "manual_estimate", - "note": "Seed estimate for Sprint 1; replaced by Stripe sync in Sprint 3" + "source": "manual", + "note": "Single-member subscription; Stripe sync in Sprint 3" } ] } \ No newline at end of file diff --git a/projects/coulomb-pricing/reports/economics-2026-06.md b/projects/coulomb-pricing/reports/economics-2026-06.md index c2a2e6f..05e8bc6 100644 --- a/projects/coulomb-pricing/reports/economics-2026-06.md +++ b/projects/coulomb-pricing/reports/economics-2026-06.md @@ -8,14 +8,14 @@ | Metric | Value | |--------|------:| -| Active members | 3 | -| Monthly revenue | 80.91 EUR | -| Monthly cost | 74.16 EUR | -| Cost per member | 24.72 EUR | -| Gross margin | 6.75 EUR | -| Gross margin % | 8.3% | +| Active members | 1 | +| Monthly revenue | 8.99 EUR | +| Monthly cost | 0.00 EUR | +| Cost per member | 0.00 EUR | +| Gross margin | 8.99 EUR | +| Gross margin % | 100.0% | -_Revenue source: manual_estimate_ +_Revenue source: manual_ ## Pricing Model Registry diff --git a/projects/coulomb-pricing/tests/test_economics.py b/projects/coulomb-pricing/tests/test_economics.py index 5b9a892..42ce7c6 100644 --- a/projects/coulomb-pricing/tests/test_economics.py +++ b/projects/coulomb-pricing/tests/test_economics.py @@ -17,10 +17,10 @@ DATA_DIR = Path(__file__).resolve().parent.parent / "data" def test_active_members_counts_only_active_status() -> None: members = load_membership(DATA_DIR) - assert active_members(members) == 3 + assert active_members(members) == 1 -def test_build_snapshot_uses_seed_revenue_for_period() -> None: +def test_build_snapshot_reflects_sole_member_and_zero_costs() -> None: product = load_product(DATA_DIR) models = load_pricing_models(DATA_DIR) members = load_membership(DATA_DIR) @@ -29,23 +29,20 @@ def test_build_snapshot_uses_seed_revenue_for_period() -> None: snapshot = build_snapshot("2026-06", product, models, members, revenue, costs, fx_rates) - assert snapshot.active_members == 3 - assert snapshot.monthly_revenue == Decimal("80.91") - assert snapshot.revenue_source == "manual_estimate" + 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") - assert snapshot.cost_per_member == (snapshot.monthly_cost / 3).quantize(Decimal("0.01")) - assert snapshot.gross_margin == (snapshot.monthly_revenue - snapshot.monthly_cost).quantize( - Decimal("0.01") - ) + 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") -def test_monthly_cost_includes_fixed_and_variable_components() -> None: +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("80.91"), 3) - # fixed: 35 USD -> 32.20 EUR + 15 EUR + 25 EUR = 72.20 - # variable: 1.5% of 80.91 + 0.25 * 3 = 1.21 + 0.75 = 1.96 - assert total == Decimal("74.16") + total = monthly_cost_total(costs, fx_rates, Decimal("8.99"), 1) + assert total == Decimal("0.00") def test_dashboard_module_renders_markdown() -> None: @@ -54,4 +51,5 @@ def test_dashboard_module_renders_markdown() -> None: 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 \ No newline at end of file + assert "flat-899-eur-monthly" in report + assert "Active members | 1" in report \ No newline at end of file