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:
2026-06-22 02:36:42 +02:00
parent bb3f152846
commit 7b84d34ea6
9 changed files with 183 additions and 48 deletions

View File

@@ -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

View 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."
}

View File

@@ -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."
} }

View File

@@ -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)."
} }

View File

@@ -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`)

View File

@@ -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
] ]

View File

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

View File

@@ -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`)

View File

@@ -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