diff --git a/operations/runbook-budget-from-csv.md b/operations/runbook-budget-from-csv.md index fe016d9..61e4e0e 100644 --- a/operations/runbook-budget-from-csv.md +++ b/operations/runbook-budget-from-csv.md @@ -11,77 +11,116 @@ summarised into targets and fixed costs. - `yuvomi-mcp` is running on LXC 129 and connected as an MCP server in Claude. - The CSV is an N26 export (columns: Booking Date, Value Date, Partner Name, Partner Iban, Type, Payment Reference, Account Name, Amount (EUR), …). +- API token: `homelab secret yuvomi-api-token` (decrypts on any enrolled client). +- Direct API base: `https://house.hubris.network/api/v1` + +--- + +## API quirks (Yuvomi ≤ 0.77.x) + +- **Subscriptions live under `/budget/subscriptions`**, NOT `/subscriptions/`. + A top-level `/subscriptions` route returns 404. +- `GET /budget/subscriptions` → `{ data: { subscriptions: [...], summary: {...} } }` +- `GET /budget/subscriptions/meta` → `{ data: { categories: [...], payment_methods: [...] } }` +- `POST /budget/subscriptions` → create a subscription (name, amount, billing_cycle, + cycle_interval, next_payment_date, currency, category_id, payment_method_id required) +- `GET /budget/` (no month) → returns only **non-recurring** base entries. + Use `GET /budget/?month=YYYY-MM` to get all entries (recurring + one-time) for a month. +- `GET /budget/categories` → expense category keys + income category names (German keys + like `"Erwerbseinkommen"`, `"Sozialleistungen"`, `"Geschenke & Transfers"`). +- Budget entries: `amount` positive = income, negative = expense. +- Recurring entries: set `is_recurring: 1` + `recurrence_interval: "monthly"`. + The `date` field sets the start month. +- `recurrence_virtual: 1` smooths non-monthly amounts across all months in the summary + (e.g. 55.08 € quarterly → shows as ~18.36 €/month). +- Custom RRULE strings (`recurrence_rule`) are **not accepted** by the API — use + `cycle_interval` on the subscription instead, or `recurrence_interval` on budget entries. + +--- + +## Subscription category IDs (as of 2026-06-26) + +| id | name | budget_subcategory_key | +|---|---|---| +| 1 | Entertainment | subscription_entertainment | +| 2 | Productivity | subscription_productivity | +| 3 | Utilities | subscription_utilities | +| 4 | Health | subscription_health | +| 5 | Education | subscription_education | +| 6 | Other | subscription_other | + +## Payment method IDs + +| id | name | +|---|---| +| 1 | Credit Card | +| 2 | Debit Card | +| 3 | PayPal | +| 6 | Bank Transfer / SEPA | +| 7 | Other | --- ## Step 1 — Categorise the transactions -Ask Claude to read the CSV and group rows into: +Skip these as internal/already-covered: +- Fixed costs you'll enter as **subscriptions** (Miete, SWM, SYNVIA, Hundefutter, + Netflix, Grover, Rundfunk ARD, KuKita, Lillydoo) +- Internal transfers (The Joy Pot ↔ Cookie, Hauptkonto, Tagesgeldkonto splits) +- Identified income (Cookie Share, Kindergeld, Pocket Money credits, Distributor) +- Fun Money pass-throughs (in and out same month → net zero) -| Category | Examples | -|---|---| -| **Subscriptions** | Miete, SWM, SYNVIA, Carmen Muller (Hundefutter), Netflix, Grover, Rundfunk ARD, KuKita, Lillydoo | -| **Recurring income** | Kindergeld, Cookie Share (Stefanie Müller), Pocket Money | -| **Groceries** | E-Center, Knuspr, EDEKA, Tegut, VollCorner, Lidl, Netto, REWE, Bakeries | -| **Drugstore** | DM, Rossmann | -| **Pharmacy / Health** | Apotheke, Dermatologist | -| **Transport** | Uber, RYD GMBH, MVG, Handyparken | -| **Dining & restaurants** | Restaurant names, Lieferando | -| **Children** | Baby products, toys, PEKiP/courses | -| **Clothing** | Zalando, Ernsting's, Schuhmair, Thalia | -| **Amazon / Online** | Amazon, AMZN | -| **Home & Furniture** | IKEA, furniture invoices, Sostrene Grene | -| **Internal transfers** | The Joy Pot ↔ Cookie, Hauptkonto splits — **exclude from budgets** | +**Variable expense taxonomy:** + +| Category key | Subcategory key | Examples | +|---|---|---| +| `food` | `groceries` | E-Center, Knuspr, EDEKA, Tegut, VollCorner, Lidl, Netto, REWE, KoRo, Roast Market | +| `food` | `restaurants_bars` | Restaurants, Lieferando, Cafes, Zeit für Brot, Baobab, Höflinger | +| `personal_health` | `beauty_cosmetics` | DM, Rossmann | +| `personal_health` | `pharmacy` | Apotheke, MVZ Dermatologie | +| `transport` | `apps_taxi` | Uber, RYD GMBH, MVG, Handyparken | +| `shopping_clothing` | `gifts` | Children products: Schlummersack, Catchy Kids, SP EVERY., Dukal, Berger-Lernwelt | +| `shopping_clothing` | `clothes_shoes` | Zalando, Ernsting's, Schuhmair, Thalia, Vinted, Airbnb, Hotel at Booking.com | +| `shopping_clothing` | `electronics` | Amazon, AMZN Mktp DE | +| `housing` | `renovation_maintenance` | IKEA, Markus Festl, Granit, Sostrene Grene, Mol* tischdecken, Gaertnerei, Dehner | +| `education` | `courses_college` | Kathrin Orlob (PEKiP), Nerina Aupperle | +| `leisure` | `streaming` | WOW wowtv.de | +| `financial_other` | `bank_fees` | Unidentified PayPal, Ratepay, N26 fees | +| `Geschenke & Transfers` | *(income)* | One-off incoming transfers | --- -## Step 2 — Discover existing category & payment-method IDs +## Step 2 — Create subscriptions ``` -list_budget_categories() → note the key strings (e.g. 'housing', 'food') -get_subscriptions_meta() → note category_id and payment_method_id values +get_subscriptions_meta() ← get category_id and payment_method_id ``` +**Standard Cookie household subscriptions (as of 2026-07):** + +| Name | Amount | billing_cycle | cycle_interval | category_id | payment_method_id | +|---|---|---|---|---|---| +| Miete | 1080.00 | monthly | 1 | 6 (Other) | 6 (Bank Transfer) | +| Strom (SWM) | 79.00 | monthly | 1 | 3 (Utilities) | 6 | +| Internet / TV / Telefon | 29.99 | monthly | 1 | 3 (Utilities) | 6 | +| Hundefutter | 75.00 | monthly | 1 | 6 (Other) | 6 | +| Netflix | 8.00 | monthly | 1 | 1 (Entertainment) | 6 | +| Grover | 16.90 | monthly | 1 | 6 (Other) | 2 (Debit Card) | +| Rundfunk ARD / ZDF | 55.08 | monthly | 3 | 1 (Entertainment) | 6 | +| KuKita Daycare (Leon) | 503.00 | monthly | 1 | 5 (Education) | 6 | +| Lillydoo diapers | 56.70 | monthly | 2 | 4 (Health) | 3 (PayPal) | + +Monthly equivalent total: **1,838.60 €** (Yuvomi applies cycle_interval to prorate). + --- -## Step 3 — Create subscriptions - -For each fixed recurring cost, call: -``` -stage_create_subscription( - name="...", - amount=..., - billing_cycle="monthly", # or "yearly" with cycle_interval - cycle_interval=1, # 3 for quarterly - next_payment_date="YYYY-MM-DD", - category_id=..., # from get_subscriptions_meta() -) -commit_pending(pending_id) -``` - -**Standard subscriptions (as of Jun 2026):** - -| Name | Amount | billing_cycle | cycle_interval | -|---|---|---|---| -| Miete | 1080.00 | monthly | 1 | -| Strom (SWM) | 79.00 | monthly | 1 | -| Internet/TV/Telefon (SYNVIA) | 29.99 | monthly | 1 | -| Hundefutter | 75.00 | monthly | 1 | -| Netflix | 8.00 | monthly | 1 | -| Grover | 16.90 | monthly | 1 | -| Rundfunk ARD | 55.08 | monthly | 3 | -| KuKita Daycare (Leon) | 503.00 | monthly | 1 | -| Lillydoo diapers | 56.70 | monthly | 2 | - ---- - -## Step 4 — Add recurring income entries +## Step 3 — Add recurring income entries ``` stage_add_budget_entry( title="Kindergeld", amount=55.00, - category="", + category="Sozialleistungen", date="YYYY-MM-01", is_recurring=True, recurrence_interval="monthly", @@ -94,40 +133,70 @@ commit_pending(pending_id) | Title | Amount | category | |---|---|---| | Kindergeld | +55.00 | Sozialleistungen | -| Cookie Share | +1600.00 | Erwerbseinkommen (adjust to actual amount) | +| Cookie Share | +2650.00 | Erwerbseinkommen *(see recommended amount below)* | --- -## Step 5 — Set budget targets (monthly spending categories) +## Step 4 — Post variable transactions -**From the Jan–Jun 2026 6-month averages:** - -| Category | Monthly target | -|---|---| -| Groceries | 600 € | -| Children products & activities | 150 € | -| Dining & restaurants | 100 € | -| Transport | 70 € | -| Drugstore | 55 € | -| Clothing | 40 € | -| Amazon / Online | 40 € | -| Home & furniture | 100 € | -| Pharmacy & health | 15 € | +For each non-skipped CSV row, call `stage_add_budget_entry` with the mapped +category/subcategory and the actual transaction amount and date. Use the Partner +Name + Payment Reference as the title (truncate to 100 chars). --- -## Step 6 — Verify +## Step 5 — Verify ``` get_budget_summary("YYYY-MM") list_subscriptions() ``` -Expected fixed costs total: ~1848 €/month (before KuKita; ~2351 € after). +Expected for a full month with KuKita: +- Fixed expenses ≥ 1,838 € (subscriptions) +- Variable expenses ≥ 500 € (groceries alone) + +--- + +## Cookie Share: how much to transfer monthly + +Calculated from Jan–Jun 2026 data (Cookie account, one-offs stripped): + +| | €/month | +|---|---| +| **Fixed costs (subscriptions)** | **1,839** | +| Miete | 1,080 | +| KuKita *(permanent from Jul 2026)* | 503 | +| Strom + SYNVIA + Rundfunk + Netflix + Grover + Hundefutter + Lillydoo | 256 | +| **Variable (6-month averages)** | **1,032** | +| Groceries | 595 | +| Children products | 142 | +| Dining & cafes | 100 | +| Transport | 66 | +| Drugstore | 52 | +| Clothing, Amazon, Pharmacy | 77 | +| **Total monthly spend** | **≈ 2,871** | +| Minus Kindergeld (fixed income) | −55 | +| Minus Pocket Money (conservative ~600 €) | −600 | +| **→ Recommended Cookie Share** | **≈ 2,650 €** | +| With 200 € buffer | **≈ 2,850 €** | + +**Current Cookie Share (Jun 2026): 1,995 € — shortfall ~655 €.** + +The gap was covered by irregular Pocket Money top-ups (avg 962 €/mo over 6 months, but +highly variable: 121 €–3,000 €). KuKita starting in June is the biggest step-up; raising +Cookie Share to **2,650 €** makes the budget self-sufficient without relying on top-ups. --- ## Changelog +### 2026-06-29 — Corrections from first real import +- Subscriptions endpoint is `/budget/subscriptions`, NOT `/subscriptions/` (404). +- `recurrence_rule` RRULE strings are rejected by the API; use `cycle_interval` instead. +- `GET /budget/` (no filter) returns only non-recurring entries; use `?month=` for full view. +- Added Cookie Share recommendation (2,650 €/month) based on 6-month expense analysis. +- Added full category taxonomy table. + ### 2026-06-29 — Initial runbook Created from Jan–Jun 2026 N26 Cookie account analysis.