Files
finance_app/backend/seed.py

122 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Seed initial reference data. Run once after migrations: python seed.py"""
import os
from dotenv import load_dotenv
load_dotenv()
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from app.auth.security import hash_password
from app.models import Role, User, Currency, AccountType, OperationType, Category
engine = create_engine(os.environ["DATABASE_URL"])
ROLES = [
("admin", "Full access — manages users, all financial data"),
("accountant", "Manages all financial data, cannot manage users"),
("user", "Manages own financial data"),
("viewer", "Read-only access to own data"),
]
CURRENCIES = [
("RUB", "Российский рубль", "₽"),
("USD", "Доллар США", "$"),
("EUR", "Евро", "€"),
("GBP", "Фунт стерлингов", "£"),
("CNY", "Китайский юань", "¥"),
("BTC", "Биткоин", "₿"),
]
ACCOUNT_TYPES = [
("Наличные", "wallet", "Наличные деньги"),
("Банковский счёт", "bank", "Текущий/расчётный счёт"),
("Кредитная карта", "credit-card", "Кредитная карта"),
("Накопительный", "piggy-bank", "Вклад / накопительный счёт"),
("Инвестиционный", "chart-line", "Брокерский или инвест. счёт"),
("Криптовалюта", "bitcoin", "Криптовалютный кошелёк"),
("Другое", "dots", "Прочий тип счёта"),
]
OPERATION_TYPES = [
("income", "Доход — пополнение счёта"),
("expense", "Расход — списание со счёта"),
("transfer", "Перевод между счетами"),
]
CATEGORIES = [
# (name, type, icon, color)
# --- Доходы ---
("Зарплата", "income", "briefcase", "#4CAF50"),
("Фриланс", "income", "laptop", "#8BC34A"),
("Инвестиции", "income", "chart-line", "#00BCD4"),
("Подарки", "income", "gift", "#E91E63"),
("Прочие доходы", "income", "plus-circle", "#9E9E9E"),
# --- Расходы ---
("Продукты", "expense", "shopping-cart","#FF5722"),
("Транспорт", "expense", "car", "#FF9800"),
("ЖКХ", "expense", "home", "#795548"),
("Здоровье", "expense", "heart", "#F44336"),
("Рестораны и кафе", "expense", "utensils", "#E91E63"),
("Развлечения", "expense", "gamepad", "#9C27B0"),
("Одежда", "expense", "tshirt", "#3F51B5"),
("Образование", "expense", "book", "#2196F3"),
("Путешествия", "expense", "plane", "#03A9F4"),
("Связь и интернет", "expense", "wifi", "#009688"),
("Подписки", "expense", "repeat", "#607D8B"),
("Прочие расходы", "expense", "minus-circle", "#9E9E9E"),
# --- Переводы ---
("Переводы", "transfer", "arrows-h", "#607D8B"),
]
def seed():
with Session(engine) as db:
# Roles
role_map: dict[str, Role] = {}
for name, desc in ROLES:
role = db.query(Role).filter(Role.name == name).first()
if not role:
role = Role(name=name, description=desc)
db.add(role)
db.flush()
role_map[name] = role
# Admin user
if not db.query(User).filter(User.username == "admin").first():
admin_pwd = os.getenv("ADMIN_PASSWORD", "Admin1234!")
admin = User(
username="admin",
email="admin@finance.local",
password_hash=hash_password(admin_pwd),
role_id=role_map["admin"].id,
)
db.add(admin)
print(f"[seed] Admin user created. Password from ADMIN_PASSWORD env (default: Admin1234!)")
# Currencies
for code, name, symbol in CURRENCIES:
if not db.query(Currency).filter(Currency.code == code).first():
db.add(Currency(code=code, name=name, symbol=symbol))
# Account types
for name, icon, desc in ACCOUNT_TYPES:
if not db.query(AccountType).filter(AccountType.name == name).first():
db.add(AccountType(name=name, icon=icon, description=desc))
# Operation types
for name, desc in OPERATION_TYPES:
if not db.query(OperationType).filter(OperationType.name == name).first():
db.add(OperationType(name=name, description=desc))
# System categories (user_id=None)
for name, ctype, icon, color in CATEGORIES:
if not db.query(Category).filter(Category.name == name, Category.user_id == None).first():
db.add(Category(name=name, type=ctype, icon=icon, color=color, user_id=None))
db.commit()
print("[seed] Done.")
if __name__ == "__main__":
seed()