Files
aurum/backend/app/schemas/dashboard.py
ZProger 140f58d33f fix: restrict transaction splits to one parent category, show subcategory breakdown
Раньше сплит позволял смешивать вообще любые категории. Реальная задача —
разложить одну покупку по подкатегориям ОДНОЙ базовой категории (100 € на
продукты: сколько на сладости, сколько на уход). А раз Dashboard и рейтинг
категорий сворачивают подкатегории в родителя, эта разбивка нигде не была
видна.

- _build_splits() требует, чтобы все категории сплита были одной родительской
  категорией или её прямыми подкатегориями.
- category_rollup.py отдаёт для каждого родительского тотала список
  category-источников, которые в него скинулись (children) — пусто, если
  источник один.
- Dashboard и рейтинг категорий: строка с непустым children раскрывается по
  клику, показывая вклад каждой подкатегории.
- Форма транзакции: выбор категории при сплите — сначала базовая (верхний
  уровень), затем строки сплита выбирают саму базовую или её подкатегорию.
2026-08-30 19:06:29 +03:00

39 lines
1.0 KiB
Python

from decimal import Decimal
from pydantic import BaseModel, Field
class CategoryBreakdownChildItem(BaseModel):
"""One subcategory's (or the parent's own direct, un-subcategorized)
share of a CategoryBreakdownItem's total — see
services/category_rollup.py's CategoryRollupChildItem."""
category_id: int
name: str
color: str
icon: str | None
amount: Decimal
class CategoryBreakdownItem(BaseModel):
category_id: int | None
name: str
color: str
icon: str | None
amount: Decimal
percent: float
# Populated only when this slice's spend came from more than one
# distinct category (subcategories, or a mix of the parent itself and
# its children) — e.g. a receipt split across "Groceries" subcategories.
children: list[CategoryBreakdownChildItem] = Field(default_factory=list)
class DashboardSummary(BaseModel):
year: int
month: int
real_income: Decimal
spent: Decimal
net: Decimal
transferred_out: Decimal
spending_by_category: list[CategoryBreakdownItem]