122 lines
5.2 KiB
Python
122 lines
5.2 KiB
Python
"""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()
|