Files
diploma-server/docs/db-structure.md
Evgenii Saenko ea390b1533 Add docker
2025-12-17 11:52:18 +03:00

120 lines
9.2 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.
# Структура БД и модель данных
Документ описывает схемы PostgreSQL, которые используются приложением, а также слой абстракции на базе Ktorm ORM.
## Технологический стек
- **PostgreSQL** основная СУБД. Подключение выполняется через HikariCP (см. `app/Database.kt`), параметры берутся из переменных окружения `DB_*`.
- **Ktorm ORM** легковесная ORM, которая:
- предоставляет интерфейсы `Entity` для объектного представления строк;
- описывает таблицы через `object Table<T>` (например, `object NewsT : Table<News>("t_news")`);
- дает `Database.sequenceOf(Table)` для CRUD-операций и построения SQL через DSL.
Каждая доменная сущность имеет:
1. `interface <Entity> : Entity<<Entity>>` декларация полей.
2. `object <Table> : Table<<Entity>>("table_name")` описание колонок/ключей и связей через `bindTo`/`references`.
3. DTO для сериализации в API.
## Таблицы
### `t_admins`
| Колонка | Тип | Описание |
|----------------|------------------|---------------------------------------|
| `id` | `bigint` (PK) | Идентификатор администратора |
| `username` | `varchar` | Уникальное имя пользователя |
| `password_hash`| `varchar` | Хеш пароля (bcrypt) |
| `created_at` | `timestamp` | Дата регистрации |
| `last_login_at`| `timestamp` nul. | Время последней авторизации |
Сущность: `AdminEntity`, таблица: `AdminUsers`. Используется модулем `admin` для регистрации, логина, смены паролей и удаления аккаунтов.
### `t_news`
| Колонка | Тип | Описание |
|----------------|------------------|--------------------------------------------------|
| `id` | `bigint` (PK) | Идентификатор новости |
| `title` | `varchar` | Заголовок |
| `slug` | `varchar` | Уникальный slug для ссылок |
| `summary` | `varchar` | Краткое описание |
| `content` | `text` | Основной текст |
| `status` | `varchar` | `DRAFT` \| `PUBLISHED` \| `ARCHIVED` |
| `published_at` | `timestamp` nul. | Дата публикации |
| `image_url` | `varchar` nul. | Ссылка на изображение |
| `created_at` | `timestamp` | Дата создания |
| `updated_at` | `timestamp` | Дата последнего обновления |
Сущность: `News`, таблица: `NewsT`. Репозиторий использует фильтры по статусу и slug для публичных и админских запросов.
### `t_service_categories`
| Колонка | Тип | Описание |
|---------|---------------|-------------------------|
| `id` | `bigint` (PK) | Идентификатор категории |
| `name` | `varchar` | Название |
| `slug` | `varchar` | Уникальный slug |
Сущность: `ServiceCategoryEntity`, таблица: `ServiceCategories`. Используется как справочник категорий услуг.
### `t_services`
| Колонка | Тип | Описание |
|--------------|-------------------|----------------------------------------------------|
| `id` | `bigint` (PK) | Идентификатор услуги |
| `title` | `varchar` | Название |
| `slug` | `varchar` | Уникальный slug |
| `description`| `text` | Подробное описание |
| `price_from` | `decimal` nul. | Нижняя граница стоимости |
| `image_url` | `varchar` nul. | Изображение |
| `status` | `varchar` | `PUBLISHED` \| `DRAFT` \| `ARCHIVED` |
| `category_id`| `bigint` FK | Ссылка на `t_service_categories.id` (может быть `NULL`) |
| `created_at` | `timestamp` | Дата создания |
| `updated_at` | `timestamp` | Дата обновления |
Сущность: `ServiceEntity`, таблица: `Services`. Поле `category` смоделировано через `references(ServiceCategories)` и возвращает `ServiceCategoryEntity?`. Сервис объединяет услуги и категории для публичного и админского API.
### `t_users` (лиды)
| Колонка | Тип | Описание |
|-------------|-----------------|------------------------------------------|
| `id` | `bigint` (PK) | Идентификатор лида |
| `full_name` | `varchar` | Имя и фамилия |
| `email` | `varchar` | Контактный email |
| `phone` | `varchar` nul. | Телефон |
| `created_at`| `timestamp` | Дата поступления заявки |
Сущность: `LeadEntity`, таблица: `Leads`. Несмотря на название таблицы `t_users`, фактически хранит только заявки. Админский модуль использует пагинацию и поиск по `full_name`/`email`.
## Связи между сущностями
- **Service → ServiceCategory (многие к одному)**: `Services.category_id` ссылается на `ServiceCategories.id`. Ktorm позволяет навигировать через `ServiceEntity.category`. При выборе услуг можно жадно загружать категорию и формировать вложенный DTO.
- **Admin, News, Leads** независимые сущности без внешних ключей на другие таблицы (в текущей версии).
- **Status/enum поля** находятся в бизнес-логике: нет отдельных таблиц для статусов, их значения валидируются сервисами.
## Использование Ktorm
- **Entity интерфейсы** объявляют свойства и их типы. Экземпляры создаются через `Entity.Factory`.
- **Table объекты** задают имя таблицы, колонки и связи. Пример:
```kotlin
object Services : Table<ServiceEntity>("t_services") {
val title = varchar("title").bindTo { it.title }
val category = long("category_id").references(ServiceCategories) { it.category }
}
```
- **Расширения Database** в каждом модуле есть свой `val Database.<entities>` (например, `Database.news`) для получения `sequenceOf(Table)`:
```kotlin
val Database.news get() = this.sequenceOf(NewsT)
```
Это скрывает детали доступа к данным и дает типобезопасные операции (`filter`, `sortedBy`, `take`, `drop`, `insert`, `update` и т.д.).
- **DTO слой** отделяет Ktorm-entity от сериализуемых объектов (например, `NewsDTO`, `ServiceDTO`). Преобразование выполняется в сервисах.
## Итог
База данных состоит из пяти основных таблиц, объединенных единым пулом соединений и общими практиками (таймстемпы, статусы, slug). Слабое связывание между сущностями делает схему гибкой, а Ktorm обеспечивает лаконичный и типобезопасный доступ к данным без тяжелых ORM-схем. Диаграмма CRUD-слоя (`docs/crud-model.svg`) дополняет данное описание визуальным представлением потока данных.