# ER-диаграмма базы данных Finance App ```mermaid erDiagram roles { int id PK varchar(50) name UK text description timestamptz created_at } users { int id PK varchar(100) username UK varchar(255) email UK varchar(255) password_hash int role_id FK boolean is_active timestamptz created_at timestamptz updated_at } currencies { int id PK varchar(3) code UK "ISO 4217" varchar(100) name varchar(10) symbol boolean is_active timestamptz created_at } exchange_rates { int id PK int currency_from_id FK int currency_to_id FK numeric(20_6) rate date rate_date varchar(100) source timestamptz created_at } locations { int id PK int user_id FK "NULL = системное" varchar(200) name varchar(50) type "store|bank|atm|online|other" text address varchar(100) city varchar(100) country numeric(9_6) latitude numeric(9_6) longitude int parent_id FK "самоссылка" timestamptz created_at } account_types { int id PK varchar(100) name UK varchar(50) icon text description } accounts { int id PK int user_id FK varchar(200) name int account_type_id FK int currency_id FK numeric(20_2) balance numeric(20_2) initial_balance boolean is_active numeric(20_2) credit_limit text description varchar(50) icon varchar(7) color "hex #RRGGBB" timestamptz created_at timestamptz updated_at } categories { int id PK int user_id FK "NULL = системная" varchar(200) name varchar(20) type "income|expense|transfer" int parent_id FK "иерархия" varchar(50) icon varchar(7) color timestamptz created_at } budgets { int id PK int user_id FK int category_id FK varchar(200) name numeric(20_2) amount int currency_id FK varchar(20) period_type "monthly|weekly|yearly|custom" date start_date date end_date boolean is_active timestamptz created_at } operation_types { int id PK varchar(50) name UK "income|expense|transfer" text description } operations { int id PK int user_id FK int account_id FK int category_id FK int operation_type_id FK numeric(20_2) amount int currency_id FK numeric(20_2) amount_converted "в валюте счёта" numeric(20_6) exchange_rate timestamptz date text description int location_id FK boolean is_planned timestamptz created_at timestamptz updated_at } operation_relations { int id PK int operation_from_id FK int operation_to_id FK varchar(50) relation_type "transfer|split|correction" timestamptz created_at } calendar_events { int id PK int user_id FK varchar(200) title text description date event_date time event_time boolean is_recurring varchar(50) recurrence_pattern "daily|weekly|monthly|yearly" date recurrence_end_date int related_operation_id FK int category_id FK numeric(20_2) amount int currency_id FK int reminder_days boolean is_completed timestamptz created_at timestamptz updated_at } %% ── Связи ────────────────────────────────────────────────────── roles ||--o{ users : "назначается" users ||--o{ accounts : "владеет" users ||--o{ operations : "создаёт" users ||--o{ budgets : "планирует" users ||--o{ calendar_events : "назначает" users ||--o{ categories : "определяет" users ||--o{ locations : "добавляет" currencies ||--o{ accounts : "деноминирует" currencies ||--o{ exchange_rates : "исходная" currencies ||--o{ exchange_rates : "целевая" currencies ||--o{ operations : "валюта операции" currencies ||--o{ budgets : "валюта бюджета" currencies ||--o{ calendar_events : "валюта события" account_types ||--o{ accounts : "классифицирует" accounts ||--o{ operations : "содержит" categories ||--o{ operations : "классифицирует" categories ||--o{ budgets : "ограничивает" categories ||--o{ calendar_events : "ассоциирует" categories ||--o{ categories : "родитель→ребёнок" operation_types ||--o{ operations : "определяет тип" locations ||--o{ operations : "место проведения" locations ||--o{ locations : "родитель→дочернее" operations ||--o{ operation_relations : "от (from)" operations ||--o{ operation_relations : "к (to)" operations ||--o{ calendar_events : "привязанная операция" ``` --- ## Описание сущностей | Таблица | Назначение | |---|---| | **roles** | Роли доступа: `admin`, `accountant`, `user`, `viewer` | | **users** | Учётные записи пользователей | | **currencies** | Справочник валют (ISO 4217: RUB, USD, EUR…) | | **exchange_rates** | Ежедневные курсы между парами валют | | **locations** | Места проведения операций (магазины, банки, банкоматы) с иерархией | | **account_types** | Типы счетов: наличные, банковский счёт, кредитная карта, вклад, инвест., крипто | | **accounts** | Финансовые счета пользователя с балансом и валютой | | **categories** | Иерархические категории доходов/расходов (системные + пользовательские) | | **budgets** | Лимиты расходов по категориям за период | | **operation_types** | Типы операций: `income`, `expense`, `transfer` | | **operations** | Финансовые операции — транзакции по счетам | | **operation_relations** | Связи операций: перевод (debit ↔ credit), разделение, коррекция | | **calendar_events** | Плановые события с напоминанием (разовые и повторяющиеся) | ## Разграничение прав доступа (RBAC) | Роль | Описание | Права | |---|---|---| | **admin** | Администратор | Полный доступ + управление пользователями | | **accountant** | Бухгалтер | Все финансовые операции, без управления пользователями | | **user** | Пользователь | CRUD своих данных (счета, операции, бюджеты) | | **viewer** | Наблюдатель | Только чтение своих данных | Изоляция данных обеспечивается на уровне приложения: каждый запрос фильтруется по `user_id`. При необходимости — PostgreSQL Row Level Security (RLS). ## Безопасность подключения к БД - **SSL/TLS**: `sslmode=prefer` (может быть переключён на `require` для продакшена) - **Переменные окружения**: учётные данные никогда не хранятся в коде - **Connection pooling**: SQLAlchemy pool (size=10, max_overflow=20, recycle=3600s) - **Nginx**: HTTPS терминация + rate limiting на auth-эндпоинтах (10 req/min) - **JWT**: access token (30 мин) + refresh token (7 дней) - **Пароли**: bcrypt с salt