# Схема базы данных ## Обзор Все идентификаторы — `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) ```