mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 11:06:40 +07:00
fix: restrict transaction splits to one parent category, show subcategory breakdown
Раньше сплит позволял смешивать вообще любые категории. Реальная задача — разложить одну покупку по подкатегориям ОДНОЙ базовой категории (100 € на продукты: сколько на сладости, сколько на уход). А раз Dashboard и рейтинг категорий сворачивают подкатегории в родителя, эта разбивка нигде не была видна. - _build_splits() требует, чтобы все категории сплита были одной родительской категорией или её прямыми подкатегориями. - category_rollup.py отдаёт для каждого родительского тотала список category-источников, которые в него скинулись (children) — пусто, если источник один. - Dashboard и рейтинг категорий: строка с непустым children раскрывается по клику, показывая вклад каждой подкатегории. - Форма транзакции: выбор категории при сплите — сначала базовая (верхний уровень), затем строки сплита выбирают саму базовую или её подкатегорию.
This commit is contained in:
@@ -1,6 +1,18 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel
|
||||
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):
|
||||
@@ -10,6 +22,10 @@ class CategoryBreakdownItem(BaseModel):
|
||||
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):
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
from datetime import date as date_
|
||||
from decimal import Decimal
|
||||
|
||||
from pydantic import BaseModel
|
||||
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):
|
||||
@@ -31,6 +43,10 @@ class CategoryRankingItem(BaseModel):
|
||||
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):
|
||||
|
||||
Reference in New Issue
Block a user