mirror of
https://github.com/Zproger/Aurum.git
synced 2026-10-13 02:56:39 +07:00
Aurum — a self-hosted personal finance operating system: cash flow, net worth tracking, budgets, goals, recurring payments, reports, proactive alerts, and a compound-interest returns calculator, all bilingual (RU/EN) and mobile-first. Ships as a three-container Docker Compose stack (Postgres + FastAPI + nginx-served React frontend). See README.md for setup and CONTRIBUTING.md for development.
87 lines
3.2 KiB
Python
87 lines
3.2 KiB
Python
"""Seeds the default category set on first boot.
|
|
|
|
The expense categories are assigned hues from the dataviz skill's validated
|
|
8-slot categorical palette, in the palette's fixed slot order (never
|
|
reordered/cycled) so the dashboard donut chart is colorblind-safe out of the
|
|
box. See CLAUDE.md-adjacent design notes in UPDATES.md for the source.
|
|
"""
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.config import get_settings
|
|
from app.models.account import Account
|
|
from app.models.category import Category
|
|
from app.models.enums import AccountType, CategoryKind
|
|
from app.models.settings import AppSettings
|
|
|
|
# (name, icon, color) — order doubles as sort_order / palette slot index.
|
|
DEFAULT_EXPENSE_CATEGORIES = [
|
|
("Housing & Utilities", "home", "#2a78d6"), # slot 1 blue
|
|
("Groceries", "shopping-basket", "#1baf7a"), # slot 3 aqua
|
|
("Dining Out", "utensils", "#eb6834"), # slot 2 orange
|
|
("Transportation", "car", "#4a3aa7"), # slot 7 violet
|
|
("Health & Fitness", "heart-pulse", "#e34948"), # slot 8 red
|
|
("Shopping", "shopping-bag", "#eda100"), # slot 4 yellow
|
|
("Entertainment", "clapperboard", "#e87ba4"), # slot 5 magenta
|
|
("Subscriptions", "repeat", "#008300"), # slot 6 green
|
|
]
|
|
|
|
DEFAULT_INCOME_CATEGORIES = [
|
|
("Salary", "banknote", "#2a78d6"),
|
|
("Freelance", "briefcase", "#1baf7a"),
|
|
("Investments", "trending-up", "#4a3aa7"),
|
|
("Gifts", "gift", "#e87ba4"),
|
|
("Other Income", "plus-circle", "#898781"),
|
|
]
|
|
|
|
|
|
async def seed_default_categories(session: AsyncSession) -> None:
|
|
existing = await session.execute(select(Category.id).limit(1))
|
|
if existing.first() is not None:
|
|
return
|
|
|
|
order = 0
|
|
for name, icon, color in DEFAULT_EXPENSE_CATEGORIES:
|
|
session.add(
|
|
Category(name=name, kind=CategoryKind.EXPENSE, icon=icon, color=color, sort_order=order, is_default=True)
|
|
)
|
|
order += 1
|
|
for name, icon, color in DEFAULT_INCOME_CATEGORIES:
|
|
session.add(
|
|
Category(name=name, kind=CategoryKind.INCOME, icon=icon, color=color, sort_order=order, is_default=True)
|
|
)
|
|
order += 1
|
|
|
|
await session.commit()
|
|
|
|
|
|
async def seed_default_account(session: AsyncSession) -> None:
|
|
"""Creates one starter account so the Transactions form always has a
|
|
destination to post to, even before the (future) accounts management UI
|
|
ships."""
|
|
existing = await session.execute(select(Account.id).limit(1))
|
|
if existing.first() is not None:
|
|
return
|
|
|
|
session.add(
|
|
Account(
|
|
name="Main Account",
|
|
type=AccountType.CHECKING,
|
|
currency=get_settings().default_currency,
|
|
color="#2a78d6",
|
|
)
|
|
)
|
|
await session.commit()
|
|
|
|
|
|
async def seed_default_app_settings(session: AsyncSession) -> None:
|
|
"""Ensures the singleton app_settings row (id=1) exists — the migration
|
|
already inserts it, but this makes app boot self-healing if that row is
|
|
ever missing (e.g. a DB restored from a pre-currency-setting backup)."""
|
|
existing = await session.get(AppSettings, 1)
|
|
if existing is not None:
|
|
return
|
|
|
|
session.add(AppSettings(id=1, currency=get_settings().default_currency))
|
|
await session.commit()
|