generated from coulomb/repo-seed
Record actual Stripe payment costs for tegwick membership
Update payment_records to 8.99 EUR gross, 0.44 EUR fees, 8.55 EUR net payout to binky-hedgehog. Link member tegwick in membership ledger and add Stripe reference catalog.
This commit is contained in:
@@ -24,7 +24,8 @@ computes all totals programmatically (`ledger.py` → `economics.py`).
|
|||||||
|
|
||||||
**Current reality:** infrastructure from January 2025 — domains **€6.75/mo**,
|
**Current reality:** infrastructure from January 2025 — domains **€6.75/mo**,
|
||||||
coulombcore hosting **€13.99/mo** (from Jan 2025), railiance01 hosting
|
coulombcore hosting **€13.99/mo** (from Jan 2025), railiance01 hosting
|
||||||
**€8.99/mo** (from Mar 2026). Sole member payments from November 2025. Customer
|
**€8.99/mo** (from Mar 2026). Member **tegwick** pays **€8.99/mo** (Stripe fee
|
||||||
|
**€0.44**, net payout **€8.55** to binky-hedgehog) from November 2025. Customer
|
||||||
cost-pass-through billing is not active.
|
cost-pass-through billing is not active.
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|||||||
13
projects/coulomb-pricing/data/infrastructure/stripe.json
Normal file
13
projects/coulomb-pricing/data/infrastructure/stripe.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"currency": "EUR",
|
||||||
|
"payout_account": "binky-hedgehog",
|
||||||
|
"membership": {
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"gross_monthly_eur": "8.99",
|
||||||
|
"fee_monthly_eur": "0.44",
|
||||||
|
"net_payout_monthly_eur": "8.55",
|
||||||
|
"member_username": "tegwick"
|
||||||
|
},
|
||||||
|
"note": "Reference from actual Stripe payouts. Payment rows live in payment_records.json."
|
||||||
|
}
|
||||||
@@ -3,14 +3,15 @@
|
|||||||
"snapshot_date": "2026-06-22",
|
"snapshot_date": "2026-06-22",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"id": "member-founder",
|
"id": "member-tegwick",
|
||||||
|
"username": "tegwick",
|
||||||
"external_id": null,
|
"external_id": null,
|
||||||
"status": "active",
|
"status": "active",
|
||||||
"joined_at": "2025-11-03",
|
"joined_at": "2025-11-03",
|
||||||
"plan_id": "flat-899-eur-monthly",
|
"plan_id": "flat-899-eur-monthly",
|
||||||
"source": "manual",
|
"source": "stripe",
|
||||||
"note": "Sole paying member; payments from November 2025"
|
"note": "Sole paying member; coulomb.social membership 8.99 EUR/mo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"note": "Infrastructure costs run from January 2025; member payments from November 2025."
|
"note": "Infrastructure costs from January 2025; member payments from November 2025."
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,118 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 2,
|
||||||
"records": [
|
"records": [
|
||||||
{"id": "pay-2025-11", "period": "2025-11", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
{
|
||||||
{"id": "pay-2025-12", "period": "2025-12", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"id": "pay-2025-11",
|
||||||
{"id": "pay-2026-01", "period": "2026-01", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"period": "2025-11",
|
||||||
{"id": "pay-2026-02", "period": "2026-02", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"gross_amount": "8.99",
|
||||||
{"id": "pay-2026-03", "period": "2026-03", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"fees_amount": "0.44",
|
||||||
{"id": "pay-2026-04", "period": "2026-04", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"refunds_amount": "0.00",
|
||||||
{"id": "pay-2026-05", "period": "2026-05", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1},
|
"net_amount": "8.55",
|
||||||
{"id": "pay-2026-06", "period": "2026-06", "gross_amount": "8.99", "fees_amount": "0.38", "refunds_amount": "0.00", "net_amount": "8.61", "currency": "EUR", "source": "manual", "member_count": 1}
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2025-12",
|
||||||
|
"period": "2025-12",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-01",
|
||||||
|
"period": "2026-01",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-02",
|
||||||
|
"period": "2026-02",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-03",
|
||||||
|
"period": "2026-03",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-04",
|
||||||
|
"period": "2026-04",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-05",
|
||||||
|
"period": "2026-05",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pay-2026-06",
|
||||||
|
"period": "2026-06",
|
||||||
|
"gross_amount": "8.99",
|
||||||
|
"fees_amount": "0.44",
|
||||||
|
"refunds_amount": "0.00",
|
||||||
|
"net_amount": "8.55",
|
||||||
|
"currency": "EUR",
|
||||||
|
"source": "stripe",
|
||||||
|
"member_count": 1,
|
||||||
|
"member_username": "tegwick",
|
||||||
|
"product": "coulomb.social-membership",
|
||||||
|
"payout_account": "binky-hedgehog"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"note": "Member payment ledger from November 2025. Stripe sync replaces manual entries in Sprint 3."
|
"note": "Stripe payment ledger for tegwick coulomb.social membership (8.99 EUR gross, 0.44 EUR fees, 8.55 EUR net payout to binky-hedgehog)."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ _Revenue source: {snapshot.revenue_source}_
|
|||||||
- Product model (`data/product.json`)
|
- Product model (`data/product.json`)
|
||||||
- Budget (`data/budget.json`)
|
- Budget (`data/budget.json`)
|
||||||
- Expense records (`data/expense_records.json`) — source of truth for costs
|
- Expense records (`data/expense_records.json`) — source of truth for costs
|
||||||
- Infrastructure catalog (`data/infrastructure/`) — domain and VPS reference data
|
- Infrastructure catalog (`data/infrastructure/`) — domain, VPS, and Stripe reference data
|
||||||
- Payment records (`data/payment_records.json`)
|
- Payment records (`data/payment_records.json`)
|
||||||
- Membership (`data/membership.json`)
|
- Membership (`data/membership.json`)
|
||||||
- Requirements (`REQUIREMENTS.md`)
|
- Requirements (`REQUIREMENTS.md`)
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ def load_payment_records(data_dir: Path | None = None) -> list[PaymentRecord]:
|
|||||||
currency=item["currency"],
|
currency=item["currency"],
|
||||||
source=item["source"],
|
source=item["source"],
|
||||||
member_count=item.get("member_count", 0),
|
member_count=item.get("member_count", 0),
|
||||||
|
member_username=item.get("member_username"),
|
||||||
|
payout_account=item.get("payout_account"),
|
||||||
)
|
)
|
||||||
for item in items
|
for item in items
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ class PaymentRecord:
|
|||||||
currency: str
|
currency: str
|
||||||
source: str
|
source: str
|
||||||
member_count: int = 0
|
member_count: int = 0
|
||||||
|
member_username: str | None = None
|
||||||
|
payout_account: str | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
|||||||
@@ -16,27 +16,27 @@
|
|||||||
| Active members | 1 |
|
| Active members | 1 |
|
||||||
| Member payments (gross) | 8.99 EUR |
|
| Member payments (gross) | 8.99 EUR |
|
||||||
| Infrastructure cost | 29.73 EUR |
|
| Infrastructure cost | 29.73 EUR |
|
||||||
| Payment processing cost | 0.38 EUR |
|
| Payment processing cost | 0.44 EUR |
|
||||||
| Total platform cost | 30.11 EUR |
|
| Total platform cost | 30.17 EUR |
|
||||||
| Platform cost per member | 30.11 EUR |
|
| Platform cost per member | 30.17 EUR |
|
||||||
| Period gross margin | -21.12 EUR |
|
| Period gross margin | -21.18 EUR |
|
||||||
| Period gross margin % | -234.9% |
|
| Period gross margin % | -235.6% |
|
||||||
| Period net liquidity | -21.12 EUR (burning) |
|
| Period net liquidity | -21.18 EUR (burning) |
|
||||||
|
|
||||||
_Period net liquidity = net member payments − infrastructure cost (processing fees already netted from payments)._
|
_Period net liquidity = net member payments − infrastructure cost (processing fees already netted from payments)._
|
||||||
_Revenue source: manual_
|
_Revenue source: stripe_
|
||||||
|
|
||||||
## Liquidity & Budget (through 2026-06)
|
## Liquidity & Budget (through 2026-06)
|
||||||
|
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
|--------|------:|
|
|--------|------:|
|
||||||
| Initial budget | 1000.00 EUR |
|
| Initial budget | 1000.00 EUR |
|
||||||
| Cumulative member payments (net) | 68.88 EUR |
|
| Cumulative member payments (net) | 68.40 EUR |
|
||||||
| Cumulative infrastructure cost | 409.28 EUR |
|
| Cumulative infrastructure cost | 409.28 EUR |
|
||||||
| Cumulative payment processing | 3.04 EUR |
|
| Cumulative payment processing | 3.52 EUR |
|
||||||
| Cumulative total platform cost | 412.32 EUR |
|
| Cumulative total platform cost | 412.80 EUR |
|
||||||
| Cumulative net liquidity | -340.40 EUR (burning) |
|
| Cumulative net liquidity | -340.88 EUR (burning) |
|
||||||
| Remaining budget | 659.60 EUR (within budget) |
|
| Remaining budget | 659.12 EUR (within budget) |
|
||||||
| Months tracked | 18 |
|
| Months tracked | 18 |
|
||||||
|
|
||||||
## Monthly History
|
## Monthly History
|
||||||
@@ -53,14 +53,14 @@ _Revenue source: manual_
|
|||||||
| 2025-08 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
| 2025-08 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
||||||
| 2025-09 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
| 2025-09 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
||||||
| 2025-10 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
| 2025-10 | 0 | 0.00 | 20.74 | 0.00 | 20.74 | -20.74 |
|
||||||
| 2025-11 | 1 | 8.99 | 20.74 | 0.38 | 21.12 | -12.13 |
|
| 2025-11 | 1 | 8.99 | 20.74 | 0.44 | 21.18 | -12.19 |
|
||||||
| 2025-12 | 1 | 8.99 | 20.74 | 0.38 | 21.12 | -12.13 |
|
| 2025-12 | 1 | 8.99 | 20.74 | 0.44 | 21.18 | -12.19 |
|
||||||
| 2026-01 | 1 | 8.99 | 20.74 | 0.38 | 21.12 | -12.13 |
|
| 2026-01 | 1 | 8.99 | 20.74 | 0.44 | 21.18 | -12.19 |
|
||||||
| 2026-02 | 1 | 8.99 | 20.74 | 0.38 | 21.12 | -12.13 |
|
| 2026-02 | 1 | 8.99 | 20.74 | 0.44 | 21.18 | -12.19 |
|
||||||
| 2026-03 | 1 | 8.99 | 29.73 | 0.38 | 30.11 | -21.12 |
|
| 2026-03 | 1 | 8.99 | 29.73 | 0.44 | 30.17 | -21.18 |
|
||||||
| 2026-04 | 1 | 8.99 | 29.73 | 0.38 | 30.11 | -21.12 |
|
| 2026-04 | 1 | 8.99 | 29.73 | 0.44 | 30.17 | -21.18 |
|
||||||
| 2026-05 | 1 | 8.99 | 29.73 | 0.38 | 30.11 | -21.12 |
|
| 2026-05 | 1 | 8.99 | 29.73 | 0.44 | 30.17 | -21.18 |
|
||||||
| 2026-06 | 1 | 8.99 | 29.73 | 0.38 | 30.11 | -21.12 |
|
| 2026-06 | 1 | 8.99 | 29.73 | 0.44 | 30.17 | -21.18 |
|
||||||
|
|
||||||
## Pricing Model Registry
|
## Pricing Model Registry
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ _Revenue source: manual_
|
|||||||
- Product model (`data/product.json`)
|
- Product model (`data/product.json`)
|
||||||
- Budget (`data/budget.json`)
|
- Budget (`data/budget.json`)
|
||||||
- Expense records (`data/expense_records.json`) — source of truth for costs
|
- Expense records (`data/expense_records.json`) — source of truth for costs
|
||||||
- Infrastructure catalog (`data/infrastructure/`) — domain and VPS reference data
|
- Infrastructure catalog (`data/infrastructure/`) — domain, VPS, and Stripe reference data
|
||||||
- Payment records (`data/payment_records.json`)
|
- Payment records (`data/payment_records.json`)
|
||||||
- Membership (`data/membership.json`)
|
- Membership (`data/membership.json`)
|
||||||
- Requirements (`REQUIREMENTS.md`)
|
- Requirements (`REQUIREMENTS.md`)
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ def test_monthly_ledger_starts_january_2025() -> None:
|
|||||||
assert march.infrastructure_cost == Decimal("20.74")
|
assert march.infrastructure_cost == Decimal("20.74")
|
||||||
assert march.payment_processing_cost == Decimal("0.00")
|
assert march.payment_processing_cost == Decimal("0.00")
|
||||||
assert june.infrastructure_cost == Decimal("29.73")
|
assert june.infrastructure_cost == Decimal("29.73")
|
||||||
assert june.payment_processing_cost == Decimal("0.38")
|
assert june.payment_processing_cost == Decimal("0.44")
|
||||||
assert june.gross_revenue == Decimal("8.99")
|
assert june.gross_revenue == Decimal("8.99")
|
||||||
|
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ def test_build_snapshot_june_2026_domain_only_infrastructure() -> None:
|
|||||||
snapshot = build_snapshot("2026-06", product, models, members, payments, ledger)
|
snapshot = build_snapshot("2026-06", product, models, members, payments, ledger)
|
||||||
|
|
||||||
assert snapshot.monthly_infrastructure_cost == Decimal("29.73")
|
assert snapshot.monthly_infrastructure_cost == Decimal("29.73")
|
||||||
assert snapshot.monthly_payment_processing_cost == Decimal("0.38")
|
assert snapshot.monthly_payment_processing_cost == Decimal("0.44")
|
||||||
assert snapshot.monthly_total_platform_cost == Decimal("30.11")
|
assert snapshot.monthly_total_platform_cost == Decimal("30.17")
|
||||||
assert snapshot.period_net_liquidity == Decimal("-21.12")
|
assert snapshot.period_net_liquidity == Decimal("-21.18")
|
||||||
assert snapshot.liquidity_status == "burning"
|
assert snapshot.liquidity_status == "burning"
|
||||||
|
|
||||||
|
|
||||||
@@ -74,11 +74,11 @@ def test_liquidity_summary_with_actual_domain_costs() -> None:
|
|||||||
summary = build_liquidity_summary(budget, payments, ledger, "2026-06")
|
summary = build_liquidity_summary(budget, payments, ledger, "2026-06")
|
||||||
|
|
||||||
assert summary.cumulative_infrastructure_cost == Decimal("409.28")
|
assert summary.cumulative_infrastructure_cost == Decimal("409.28")
|
||||||
assert summary.cumulative_payment_processing_cost == Decimal("3.04")
|
assert summary.cumulative_payment_processing_cost == Decimal("3.52")
|
||||||
assert summary.cumulative_total_platform_cost == Decimal("412.32")
|
assert summary.cumulative_total_platform_cost == Decimal("412.80")
|
||||||
assert summary.cumulative_member_payments == Decimal("68.88")
|
assert summary.cumulative_member_payments == Decimal("68.40")
|
||||||
assert summary.cumulative_net_liquidity == Decimal("-340.40")
|
assert summary.cumulative_net_liquidity == Decimal("-340.88")
|
||||||
assert summary.remaining_budget == Decimal("659.60")
|
assert summary.remaining_budget == Decimal("659.12")
|
||||||
assert summary.liquidity_status == "burning"
|
assert summary.liquidity_status == "burning"
|
||||||
assert summary.months_tracked == 18
|
assert summary.months_tracked == 18
|
||||||
|
|
||||||
@@ -95,11 +95,23 @@ def test_build_monthly_ledger_matches_loader() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_payment_records_match_stripe_actuals_for_tegwick() -> None:
|
||||||
|
payments = load_payment_records(DATA_DIR)
|
||||||
|
nov = next(p for p in payments if p.period == "2025-11")
|
||||||
|
|
||||||
|
assert nov.gross_amount == Decimal("8.99")
|
||||||
|
assert nov.fees_amount == Decimal("0.44")
|
||||||
|
assert nov.net_amount == Decimal("8.55")
|
||||||
|
assert nov.member_username == "tegwick"
|
||||||
|
assert nov.payout_account == "binky-hedgehog"
|
||||||
|
assert nov.source == "stripe"
|
||||||
|
|
||||||
|
|
||||||
def test_dashboard_notes_expense_record_source() -> None:
|
def test_dashboard_notes_expense_record_source() -> None:
|
||||||
from observatory.dashboard import generate_dashboard
|
from observatory.dashboard import generate_dashboard
|
||||||
|
|
||||||
report = generate_dashboard(DATA_DIR, "2026-06")
|
report = generate_dashboard(DATA_DIR, "2026-06")
|
||||||
assert "expense and payment record ledgers" in report
|
assert "expense and payment record ledgers" in report
|
||||||
assert "409.28" in report
|
assert "409.28" in report
|
||||||
assert "659.60" in report
|
assert "659.12" in report
|
||||||
assert "coulomb.social" not in report # dashboard shows aggregates, not domain names
|
assert "coulomb.social" not in report # dashboard shows aggregates, not domain names
|
||||||
Reference in New Issue
Block a user