Files
dating-app-backend/database-schema.md
2026-06-02 15:52:22 +03:00

248 lines
7.9 KiB
Markdown
Raw Permalink 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.
# Схема базы данных
## Обзор
Все идентификаторы — `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)
```