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