# Budget Phase 1.11 — Migros auto-booking and monthly budget analytics

Use this reference when the user asks to make Migros expenses authoritative in Budget/Cashflow and to enhance Budgetstatus with monthly category analytics.

## Scope boundaries

- No new import sources, OCR, camera, provider calls, large rule engine, duplicate engine, forecast models, Sankey/Sunburst/FIRE analytics.
- Migros CSV/Cumulus/receipt rows are the source of truth for Migros expenses.
- Credit-card Migros rows stay `covered_by_migros`; they must not become extra expense transactions.
- Real source files, runtime DBs, backups, build artifacts and secrets stay outside Git.
- Never print real amounts in chat reports; aggregate counts/statuses only.
- Before productive runtime mutation, create and verify an external runtime DB backup.

## Migros rule

The old threshold rule is obsolete:

- Do **not** use `under 50 CHF auto / over 50 CHF review` as the primary decision.
- Every Migros receipt/bon candidate for the active budget year maps to `Essen & Haushalt`.
- Receipt candidates may be `auto_categorized` before booking and `confirmed` after the write boundary.
- Article rows are detail data in `budget_import_line_items`, never main `budget_transactions`.
- Productive booking is at receipt/bon level only.

## Runtime flow

1. Create runtime DB backup outside repo and verify checksum/existence.
2. Dry-run counts only:
   - Migros receipt candidates for active year
   - already confirmed receipts
   - open receipts
   - credit-card `covered_by_migros`
   - line item count
   - old article candidate count
3. Supersede old open article-level candidates if present, with audit.
4. Confirm open `source_type='migros_receipt'` candidates for active year to category `Essen & Haushalt`, using an existing active budget account.
5. Verify aggregate-only:
   - open receipt count is zero
   - confirmed receipt count increased as expected
   - wrong Migros category count is zero
   - line-item transaction count is zero
   - covered-card transaction count is zero
   - audit events exist
6. Verify Budgetstatus contains `Essen & Haushalt` with actuals and `monthly_analysis` length 12.

## Budgetstatus monthly analytics

Backend category status rows should include:

- `monthly_actuals` for `01` through `12`
- `monthly_analysis`: list of month DTOs with `month`, `month_label`, `actual_chf`, `budget_chf`, `difference_chf`, `status`, `bar_color`
- Money strings must be formatted to two decimals.

Add an endpoint such as:

```text
GET /api/budget/status/categories/{category_id}/months/{YYYY-MM}
```

Monthly detail DTO should include:

- category, month, budget month, actual, absolute difference, percent difference, status/color
- breakdown grouped by merchant/payee if available, otherwise source/account
- confirmed transactions for that category/month
- receipt line-item count and `article_rows_detail_only` flag for Migros receipt-backed transactions
- link to Effective Expenses filtered by year/month/category

## Frontend pattern

- Preserve desktop Budgetstatus table.
- Row click opens category detail drawer with a simple monthly bar chart.
- Bar color: green under budget, yellow near budget, red over budget, slate/no-budget where no meaningful comparison.
- Chart click loads monthly detail drawer/panel.
- Monthly detail includes a compact donut/progress breakdown, transaction table, and link to Effective Expenses with query filters.
- Migros receipt detail should visibly explain that article rows are detail data only.

## Tests

Backend tests:

- Migros receipts always map to `Essen & Haushalt`, including above old threshold.
- Confirm creates receipt-level transactions only and writes audit.
- Article rows do not create main transactions.
- Credit-card Migros remains `covered_by_migros` and unbooked.
- Budgetstatus monthly analysis marks over-budget red and under-budget green.
- Monthly detail includes budget/actual/difference/percent, breakdown, transactions and expense filter link.

Frontend tests:

- Row click opens monthly chart.
- Chart has budget-line copy and red/green classes.
- Month click opens detail drawer.
- Detail drawer shows difference percent, breakdown/donut, transactions and filter link.

## Verification gates

- Python compile
- full pytest
- full frontend Vitest
- `npm run build`
- source secret scan
- frontend build secret scan
- remove `frontend/dist`, `frontend/node_modules`, `.pytest_cache`, `__pycache__` before Git-safety
- Git-safety scan
- `git diff --check`
- commit/push/remote hash
- reinstall frontend deps if node_modules was removed and a dashboard restart is required
- restart dashboard with browser-visible Tailscale API base and verify `/api/runtime/status` plus Budgetstatus route
