first commit
This commit is contained in:
247
database-schema.md
Normal file
247
database-schema.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# Схема базы данных
|
||||
|
||||
## Обзор
|
||||
|
||||
Все идентификаторы — `uuid`. Схема разбита на домены: авторизация, профиль, гео, тарифы, социальные действия, чат, встречи, модерация.
|
||||
|
||||
---
|
||||
|
||||
## Таблицы
|
||||
|
||||
### `user`
|
||||
Авторизационные данные. Намеренно отделены от профиля — публичная анкета живёт в `profile`.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| phone | string | номер телефона |
|
||||
| password | string | хешированный пароль |
|
||||
| status | string | `active` / `banned` / `pending` |
|
||||
| role_id | uuid FK → role | роль пользователя |
|
||||
| tariff_id | uuid FK → tariff | текущий тариф |
|
||||
| payment_id | uuid FK → payment | способ оплаты |
|
||||
| active_chat_id | uuid FK → chat | активный чат (один пользователь — один чат одновременно) |
|
||||
| fcm_token | string | токен для push-уведомлений (FCM) |
|
||||
|
||||
---
|
||||
|
||||
### `profile`
|
||||
Публичная анкета пользователя. Это то, что видят другие в ленте.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| user_id | uuid FK → user | |
|
||||
| name | string | |
|
||||
| birth_date | date | вместо `age` — возраст вычисляется на лету |
|
||||
| city_id | uuid FK → city | |
|
||||
| district_id | uuid FK → city_district | район / метро, опционально |
|
||||
| description | string | текст анкеты |
|
||||
| nation | string | национальность |
|
||||
| height | float | опционально |
|
||||
| weight | float | опционально |
|
||||
|
||||
---
|
||||
|
||||
### `media`
|
||||
Фотографии и видео пользователя в анкете. Файлы хранятся в MinIO, здесь только путь.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| user_id | uuid FK → user | |
|
||||
| path | string | URL в MinIO |
|
||||
| type | string | `photo` / `video` |
|
||||
|
||||
---
|
||||
|
||||
### `tag`
|
||||
Справочник интересов / тегов.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| value | string |
|
||||
|
||||
### `profile_tag`
|
||||
Связь M:M между профилем и тегами.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| profile_id | uuid FK → profile |
|
||||
| tag_id | uuid FK → tag |
|
||||
|
||||
---
|
||||
|
||||
### `city`
|
||||
Справочник городов.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| name | string | |
|
||||
| lat | decimal | широта центра города |
|
||||
| lng | decimal | долгота центра города |
|
||||
|
||||
### `city_district`
|
||||
Районы и станции метро внутри города.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| city_id | uuid FK → city |
|
||||
| name | string |
|
||||
|
||||
---
|
||||
|
||||
### `tariff`
|
||||
Тарифные планы подписки.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| name | string |
|
||||
| price_per_month | decimal |
|
||||
| price_per_year | decimal |
|
||||
|
||||
### `payment`
|
||||
Платёжные данные пользователя.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| user_id | uuid FK → user | |
|
||||
| provider | string | название платёжной системы |
|
||||
| credentials | string | токен / идентификатор в платёжной системе |
|
||||
|
||||
---
|
||||
|
||||
### `role`
|
||||
Роли пользователей: `user`, `moderator`, `admin`.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| name | string |
|
||||
|
||||
### `permission`
|
||||
Права доступа, привязанные к роли. Используется для логики AdminPanel.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| role_id | uuid FK → role |
|
||||
| name | string |
|
||||
|
||||
---
|
||||
|
||||
### `like`
|
||||
Лайк или дизлайк от одного пользователя другому. При взаимном лайке создаётся `match`.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| source_user | uuid FK → user | |
|
||||
| target_user | uuid FK → user | |
|
||||
| type | enum | `like` / `dislike` |
|
||||
| created_at | timestamp | |
|
||||
|
||||
### `match`
|
||||
Взаимный лайк. После создания открывается возможность чата.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| user1_id | uuid FK → user |
|
||||
| user2_id | uuid FK → user |
|
||||
| created_at | timestamp |
|
||||
|
||||
---
|
||||
|
||||
### `chat`
|
||||
Чат между двумя профилями. Один пользователь может иметь только один активный чат одновременно (`user.active_chat_id`).
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| profile1_id | uuid FK → profile | |
|
||||
| profile2_id | uuid FK → profile | |
|
||||
| status | string | `active` / `closed` |
|
||||
|
||||
### `message`
|
||||
Сообщения внутри чата. Доставка в реальном времени через Socket.io. Поддерживает текст и медиавложения.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| chat_id | uuid FK → chat | |
|
||||
| user_id | uuid FK → user | |
|
||||
| text | string | текст сообщения, опционально |
|
||||
| media_url | string | URL файла в MinIO, опционально |
|
||||
| media_type | enum | `photo` / `voice` / `video`, опционально |
|
||||
| created_at | timestamp | |
|
||||
|
||||
### `greetings`
|
||||
Справочник готовых приветственных фраз. Пользователь выбирает из списка при открытии нового чата. Не привязан ни к чату, ни к пользователю — это просто набор текстов.
|
||||
|
||||
| Поле | Тип |
|
||||
|---|---|
|
||||
| id | uuid PK |
|
||||
| text | string |
|
||||
|
||||
---
|
||||
|
||||
### `report`
|
||||
Жалобы пользователей. `entity_type` указывает на что именно жалоба.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| source_user | uuid FK → user | кто подал жалобу |
|
||||
| entity_id | uuid | id объекта жалобы |
|
||||
| entity_type | enum | `profile` / `message` |
|
||||
| description | string | текст жалобы |
|
||||
|
||||
---
|
||||
|
||||
### `date`
|
||||
Реальная офлайн-встреча двух пользователей. Создаётся по договорённости в чате.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| user1_id | uuid FK → user | |
|
||||
| user2_id | uuid FK → user | |
|
||||
| lat | decimal | координаты места встречи |
|
||||
| lng | decimal | |
|
||||
| time | timestamp | дата и время встречи |
|
||||
| status_id | uuid FK → date_status | |
|
||||
|
||||
### `date_status`
|
||||
Справочник статусов встречи.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
| id | uuid PK | |
|
||||
| text | string | `pending` / `confirmed` / `cancelled` / `rescheduled` |
|
||||
|
||||
---
|
||||
|
||||
## Связи
|
||||
|
||||
```
|
||||
user ──────────── profile (1:1)
|
||||
user ──────────── media (1:N)
|
||||
user ──────────── role (N:1)
|
||||
user ──────────── tariff (N:1)
|
||||
user ──────────── payment (1:1)
|
||||
user ──────────── chat (активный чат, 1:1)
|
||||
profile ────────── tag (M:M через profile_tag)
|
||||
profile ────────── city (N:1)
|
||||
profile ────────── city_district (N:1, опционально)
|
||||
city ───────────── city_district (1:N)
|
||||
role ───────────── permission (1:N)
|
||||
chat ───────────── message (1:N)
|
||||
date ───────────── date_status (N:1)
|
||||
report ─────────── user (N:1)
|
||||
```
|
||||
Reference in New Issue
Block a user