mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 02:56:39 +07:00
Раньше сплит позволял смешивать вообще любые категории. Реальная задача — разложить одну покупку по подкатегориям ОДНОЙ базовой категории (100 € на продукты: сколько на сладости, сколько на уход). А раз Dashboard и рейтинг категорий сворачивают подкатегории в родителя, эта разбивка нигде не была видна. - _build_splits() требует, чтобы все категории сплита были одной родительской категорией или её прямыми подкатегориями. - category_rollup.py отдаёт для каждого родительского тотала список category-источников, которые в него скинулись (children) — пусто, если источник один. - Dashboard и рейтинг категорий: строка с непустым children раскрывается по клику, показывая вклад каждой подкатегории. - Форма транзакции: выбор категории при сплите — сначала базовая (верхний уровень), затем строки сплита выбирают саму базовую или её подкатегорию.
57 lines
1.4 KiB
Python
57 lines
1.4 KiB
Python
from datetime import date as date_
|
|
from decimal import Decimal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class CategoryRankingChildItem(BaseModel):
|
|
"""One subcategory's (or the parent's own direct, un-subcategorized)
|
|
share of a CategoryRankingItem's total — see
|
|
services/category_rollup.py's CategoryRollupChildItem."""
|
|
|
|
category_id: int
|
|
name: str
|
|
color: str
|
|
icon: str | None
|
|
amount: Decimal
|
|
|
|
|
|
class CategorySpendingPoint(BaseModel):
|
|
year: int
|
|
month: int
|
|
amount: Decimal
|
|
|
|
|
|
class CategorySpendingReport(BaseModel):
|
|
category_id: int
|
|
category_name: str
|
|
category_color: str
|
|
category_icon: str | None
|
|
start_date: date_ | None
|
|
end_date: date_ | None
|
|
total_amount: Decimal
|
|
transaction_count: int
|
|
average_per_month: Decimal
|
|
series: list[CategorySpendingPoint]
|
|
|
|
|
|
class CategoryRankingItem(BaseModel):
|
|
category_id: int
|
|
name: str
|
|
color: str
|
|
icon: str | None
|
|
amount: Decimal
|
|
percent: float
|
|
transaction_count: int
|
|
# Populated only when this category's spend came from more than one
|
|
# distinct category (subcategories, or a mix of itself and its
|
|
# children) — e.g. a receipt split across "Groceries" subcategories.
|
|
children: list[CategoryRankingChildItem] = Field(default_factory=list)
|
|
|
|
|
|
class CategoryRankingReport(BaseModel):
|
|
start_date: date_ | None
|
|
end_date: date_ | None
|
|
total_amount: Decimal
|
|
items: list[CategoryRankingItem]
|