Files
finance_app/docs/ER_diagram.md

231 lines
8.6 KiB
Markdown
Raw 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.
# 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