Обновление приложения
This commit is contained in:
121
backend/seed.py
Normal file
121
backend/seed.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user