# Документация базы данных интернет-магазина ## Описание проекта База данных для интернет-магазина на PostgreSQL, включающая систему управления пользователями с ролями и правами доступа, каталог товаров, систему заказов, корзину покупок, отзывы и платежи. ## Структура файлов Проект состоит из четырех SQL-файлов, которые должны выполняться в следующем порядке: 1. **schema.sql** - Создание структуры базы данных (таблицы, функции) 2. **indexes.sql** - Создание индексов для оптимизации запросов 3. **triggers.sql** - Создание триггеров для автоматизации процессов 4. **seed_data.sql** - Заполнение начальными данными ## Порядок установки ```sql -- 1. Создание структуры \i schema.sql -- 2. Создание индексов \i indexes.sql -- 3. Создание триггеров \i triggers.sql -- 4. Заполнение данными \i seed_data.sql ``` ## Архитектура базы данных ### Система авторизации и прав доступа База данных использует гибкую систему ролей и прав доступа (RBAC - Role-Based Access Control): - **Ресурсы (resources)** - объекты системы (товары, заказы, категории и т.д.) - **Действия (actions)** - операции над ресурсами (просмотр, создание, редактирование, удаление) - **Права доступа (permissions)** - комбинация ресурса и действия - **Роли (roles)** - наборы прав доступа - **Пользователи (users)** - привязаны к ролям ### Основные модули 1. **Управление товарами** - категории, товары, изображения 2. **Управление заказами** - заказы, элементы заказов, статусы 3. **Корзина покупок** - временное хранение товаров перед оформлением заказа 4. **Отзывы и рейтинги** - система отзывов с автоматическим расчетом рейтинга 5. **Платежи** - управление платежами по заказам 6. **Адреса доставки** - адреса пользователей --- ## Описание таблиц ### 1. Система авторизации #### `resources` - Ресурсы системы Хранит список ресурсов (объектов), к которым можно предоставить доступ. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название ресурса | | slug | VARCHAR(50) | Уникальный идентификатор (URL-friendly) | | description | TEXT | Описание ресурса | | is_active | BOOLEAN | Активен ли ресурс | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Примеры ресурсов:** products, orders, categories, reviews, cart, users #### `actions` - Действия над ресурсами Хранит список действий, которые можно выполнять над ресурсами. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название действия | | slug | VARCHAR(50) | Уникальный идентификатор | | description | TEXT | Описание действия | | is_active | BOOLEAN | Активно ли действие | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Примеры действий:** view, create, edit, delete, moderate, manage #### `permissions` - Права доступа Комбинация ресурса и действия. Определяет конкретное право доступа. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название права | | slug | VARCHAR(100) | Уникальный идентификатор (формат: resource.action) | | resource_id | INTEGER | Ссылка на ресурс | | action_id | INTEGER | Ссылка на действие | | description | TEXT | Описание права | | is_active | BOOLEAN | Активно ли право | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** UNIQUE(resource_id, action_id) - одна комбинация ресурса и действия #### `roles` - Роли пользователей Роли, которые могут быть назначены пользователям. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название роли | | slug | VARCHAR(50) | Уникальный идентификатор | | description | TEXT | Описание роли | | is_active | BOOLEAN | Активна ли роль | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Предустановленные роли:** - `admin` - Администратор (полные права) - `owner` - Владелец магазина - `employee` - Сотрудник - `manager` - Менеджер - `customer` - Клиент (покупатель) #### `role_permissions` - Связь ролей и прав Связывает роли с правами доступа (многие-ко-многим). | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | role_id | INTEGER | Ссылка на роль | | permission_id | INTEGER | Ссылка на право доступа | | created_at | TIMESTAMP | Дата создания | **Ограничения:** UNIQUE(role_id, permission_id) #### `users` - Пользователи системы Пользователи системы (покупатели и администраторы). | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | email | VARCHAR(255) | Email (уникальный) | | password_hash | VARCHAR(255) | Хеш пароля | | first_name | VARCHAR(100) | Имя | | last_name | VARCHAR(100) | Фамилия | | phone | VARCHAR(20) | Телефон | | telegram_id | BIGINT | ID в Telegram (уникальный) | | role_id | INTEGER | Ссылка на роль | | is_active | BOOLEAN | Активен ли пользователь | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Особенности:** - Поддержка авторизации через email или Telegram - Связь с ролью через `role_id` --- ### 2. Каталог товаров #### `categories` - Категории товаров Иерархическая структура категорий товаров. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(255) | Название категории | | slug | VARCHAR(255) | Уникальный идентификатор (URL-friendly) | | description | TEXT | Описание категории | | parent_id | INTEGER | Ссылка на родительскую категорию (для иерархии) | | image_url | VARCHAR(500) | URL изображения категории | | is_active | BOOLEAN | Активна ли категория | | sort_order | INTEGER | Порядок сортировки | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Особенности:** - Поддержка вложенных категорий через `parent_id` - Возможность сортировки через `sort_order` #### `products` - Товары Основная информация о товарах магазина. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(255) | Название товара | | slug | VARCHAR(255) | Уникальный идентификатор (URL-friendly) | | description | TEXT | Полное описание | | short_description | TEXT | Краткое описание | | sku | VARCHAR(100) | Артикул товара (уникальный) | | price | DECIMAL(10, 2) | Цена продажи | | compare_at_price | DECIMAL(10, 2) | Старая цена (для отображения скидки) | | cost_price | DECIMAL(10, 2) | Себестоимость | | category_id | INTEGER | Ссылка на категорию | | stock_quantity | INTEGER | Количество на складе | | weight | DECIMAL(8, 2) | Вес товара | | dimensions | VARCHAR(100) | Размеры товара | | is_active | BOOLEAN | Активен ли товар | | is_featured | BOOLEAN | Рекомендуемый товар | | rating | DECIMAL(3, 2) | Средний рейтинг (0-5) | | review_count | INTEGER | Количество одобренных отзывов | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** - `price >= 0` - `compare_at_price >= 0` - `cost_price >= 0` - `stock_quantity >= 0` - `rating >= 0 AND rating <= 5` **Особенности:** - Рейтинг и количество отзывов обновляются автоматически через триггеры #### `product_images` - Изображения товаров Изображения товаров с поддержкой множественных изображений. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | product_id | INTEGER | Ссылка на товар | | image_url | VARCHAR(500) | URL изображения | | alt_text | VARCHAR(255) | Альтернативный текст для изображения | | is_primary | BOOLEAN | Основное изображение | | sort_order | INTEGER | Порядок сортировки | | created_at | TIMESTAMP | Дата создания | **Особенности:** - Поддержка нескольких изображений на товар - Одно изображение может быть помечено как основное (`is_primary = TRUE`) --- ### 3. Система заказов #### `order_statuses` - Статусы заказов Предустановленные статусы заказов. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название статуса | | slug | VARCHAR(50) | Уникальный идентификатор | | description | TEXT | Описание статуса | | color | VARCHAR(20) | Цвет для отображения в интерфейсе | | sort_order | INTEGER | Порядок сортировки | | is_active | BOOLEAN | Активен ли статус | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Предустановленные статусы:** - `pending` - Ожидает обработки - `processing` - В обработке - `shipped` - Отправлен - `delivered` - Доставлен - `cancelled` - Отменен - `refunded` - Возвращен #### `payment_methods` - Способы оплаты Справочник способов оплаты. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название способа оплаты | | slug | VARCHAR(50) | Уникальный идентификатор | | description | TEXT | Описание способа оплаты | | is_active | BOOLEAN | Активен ли способ оплаты | | sort_order | INTEGER | Порядок сортировки | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Предустановленные способы оплаты:** - `card` - Банковская карта - `e-wallet` - Электронный кошелек - `cash_on_delivery` - Наличные при получении - `bank_transfer` - Банковский перевод - `crypto` - Криптовалюта #### `payment_statuses` - Статусы платежей Справочник статусов платежей. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | name | VARCHAR(100) | Название статуса | | slug | VARCHAR(50) | Уникальный идентификатор | | description | TEXT | Описание статуса | | color | VARCHAR(20) | Цвет для отображения в интерфейсе | | sort_order | INTEGER | Порядок сортировки | | is_active | BOOLEAN | Активен ли статус | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Предустановленные статусы:** - `pending` - Ожидает оплаты - `paid` - Оплачен - `completed` - Завершен - `failed` - Ошибка оплаты - `refunded` - Возвращен #### `orders` - Заказы Основная информация о заказах покупателей. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | user_id | INTEGER | Ссылка на пользователя | | order_number | VARCHAR(50) | Уникальный номер заказа | | status_id | INTEGER | Ссылка на статус заказа | | subtotal | DECIMAL(10, 2) | Сумма товаров | | tax_amount | DECIMAL(10, 2) | Сумма налогов | | shipping_cost | DECIMAL(10, 2) | Стоимость доставки | | discount_amount | DECIMAL(10, 2) | Сумма скидки | | total_amount | DECIMAL(10, 2) | Итоговая сумма | | shipping_address_id | INTEGER | Ссылка на адрес доставки | | billing_address_id | INTEGER | Ссылка на адрес для выставления счета | | payment_method_id | INTEGER | Ссылка на способ оплаты | | payment_status_id | INTEGER | Ссылка на статус платежа | | notes | TEXT | Примечания к заказу | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** - `subtotal >= 0` - `tax_amount >= 0` - `shipping_cost >= 0` - `discount_amount >= 0` - `total_amount >= 0` **Особенности:** - Номер заказа генерируется автоматически через триггер в формате: `ORD-YYYYMMDD-XXXXXX` #### `order_items` - Элементы заказа Товары, входящие в заказ. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | order_id | INTEGER | Ссылка на заказ | | product_id | INTEGER | Ссылка на товар | | product_name | VARCHAR(255) | Название товара на момент заказа | | product_sku | VARCHAR(100) | Артикул товара на момент заказа | | quantity | INTEGER | Количество | | price | DECIMAL(10, 2) | Цена за единицу на момент заказа | | subtotal | DECIMAL(10, 2) | Сумма по позиции | | created_at | TIMESTAMP | Дата создания | **Ограничения:** - `quantity > 0` - `price >= 0` - `subtotal >= 0` **Особенности:** - Сохраняет название, артикул и цену товара на момент заказа (на случай изменения товара в будущем) --- ### 4. Корзина покупок #### `cart_items` - Корзина покупок Временное хранение товаров перед оформлением заказа. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | user_id | INTEGER | Ссылка на пользователя | | product_id | INTEGER | Ссылка на товар | | quantity | INTEGER | Количество | | created_at | TIMESTAMP | Дата добавления | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** - `quantity > 0` - UNIQUE(user_id, product_id) - один товар может быть в корзине только один раз --- ### 5. Отзывы и рейтинги #### `reviews` - Отзывы на товары Отзывы покупателей на товары. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | product_id | INTEGER | Ссылка на товар | | user_id | INTEGER | Ссылка на пользователя | | rating | INTEGER | Оценка (1-5) | | title | VARCHAR(255) | Заголовок отзыва | | comment | TEXT | Текст отзыва | | is_approved | BOOLEAN | Одобрен ли отзыв модератором | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** - `rating >= 1 AND rating <= 5` - UNIQUE(product_id, user_id) - один пользователь может оставить только один отзыв на товар **Особенности:** - Отзывы требуют модерации (`is_approved = FALSE` по умолчанию) - Рейтинг товара обновляется автоматически при одобрении/изменении отзывов --- ### 6. Платежи #### `payments` - Платежи по заказам Информация о платежах по заказам. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | order_id | INTEGER | Ссылка на заказ | | payment_method_id | INTEGER | Ссылка на способ оплаты | | transaction_id | VARCHAR(255) | ID транзакции в платежной системе (уникальный) | | amount | DECIMAL(10, 2) | Сумма платежа | | status_id | INTEGER | Ссылка на статус платежа | | payment_date | TIMESTAMP | Дата платежа | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | **Ограничения:** - `amount >= 0` --- ### 7. Адреса доставки #### `addresses` - Адреса пользователей Адреса доставки пользователей. | Поле | Тип | Описание | |------|-----|----------| | id | SERIAL | Первичный ключ | | user_id | INTEGER | Ссылка на пользователя | | first_name | VARCHAR(100) | Имя получателя | | last_name | VARCHAR(100) | Фамилия получателя | | phone | VARCHAR(20) | Телефон | | country | VARCHAR(100) | Страна | | city | VARCHAR(100) | Город | | street | VARCHAR(255) | Улица | | building | VARCHAR(50) | Номер дома | | apartment | VARCHAR(50) | Номер квартиры | | postal_code | VARCHAR(20) | Почтовый индекс | | is_default | BOOLEAN | Адрес по умолчанию | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | --- ## Функции базы данных ### `update_updated_at_column()` Автоматически обновляет поле `updated_at` при изменении записи. **Использование:** Применяется через триггеры на всех таблицах с полем `updated_at`. ### `update_product_rating()` Автоматически пересчитывает рейтинг и количество отзывов товара при изменении отзывов. **Логика:** - Рассчитывает средний рейтинг из одобренных отзывов - Подсчитывает количество одобренных отзывов - Обновляет поля `rating` и `review_count` в таблице `products` **Триггеры:** - Срабатывает при INSERT, UPDATE и DELETE в таблице `reviews` ### `generate_order_number()` Автоматически генерирует уникальный номер заказа. **Формат:** `ORD-YYYYMMDD-XXXXXX` **Пример:** `ORD-20240115-000001` **Триггер:** Срабатывает перед INSERT в таблицу `orders`, если `order_number` не указан. ### `get_order_status_id(status_slug VARCHAR)` Вспомогательная функция для получения ID статуса заказа по его slug. **Возвращает:** INTEGER (ID статуса) или NULL ### `get_payment_status_id(status_slug VARCHAR)` Вспомогательная функция для получения ID статуса платежа по его slug. **Возвращает:** INTEGER (ID статуса) или NULL ### `get_payment_method_id(method_slug VARCHAR)` Вспомогательная функция для получения ID способа оплаты по его slug. **Возвращает:** INTEGER (ID способа оплаты) или NULL --- ## Триггеры ### Триггеры обновления `updated_at` Автоматически обновляют поле `updated_at` при изменении записи в следующих таблицах: - `resources` - `actions` - `permissions` - `roles` - `users` - `categories` - `order_statuses` - `products` - `addresses` - `orders` - `cart_items` - `reviews` - `payments` ### Триггеры обновления рейтинга товара - **`update_product_rating_on_review_insert`** - после добавления отзыва (если он одобрен) - **`update_product_rating_on_review_update`** - после изменения отзыва (если изменился рейтинг или статус одобрения) - **`update_product_rating_on_review_delete`** - после удаления отзыва ### Триггер генерации номера заказа - **`generate_order_number_trigger`** - перед вставкой нового заказа генерирует номер, если он не указан --- ## Индексы Индексы созданы для оптимизации наиболее частых запросов: ### Индексы по slug - `resources.slug` - `actions.slug` - `permissions.slug` - `roles.slug` - `categories.slug` - `products.slug` - `order_statuses.slug` ### Индексы по внешним ключам - `permissions.resource_id`, `permissions.action_id` - `role_permissions.role_id`, `role_permissions.permission_id` - `users.role_id` - `categories.parent_id` - `products.category_id` - `product_images.product_id` - `addresses.user_id` - `orders.user_id`, `orders.status_id`, `orders.payment_method_id`, `orders.payment_status_id` - `order_items.order_id`, `order_items.product_id` - `cart_items.user_id`, `cart_items.product_id` - `reviews.product_id`, `reviews.user_id` - `payments.order_id`, `payments.payment_method_id`, `payments.status_id` ### Индексы по статусам и флагам - `resources.is_active` - `actions.is_active` - `permissions.is_active` - `roles.is_active` - `users.is_active` - `categories.is_active` - `products.is_active`, `products.is_featured` - `order_statuses.is_active` - `payment_methods.is_active` - `payment_statuses.is_active` - `reviews.is_approved` ### Индексы по уникальным полям - `users.email` - `users.telegram_id` - `products.sku` - `orders.order_number` - `payments.transaction_id` ### Индексы для сортировки и фильтрации - `products.price` - `orders.created_at` - `orders.payment_status_id` - `reviews.rating` --- ## Начальные данные (seed_data.sql) ### Ресурсы - products, orders, categories, reviews, cart, users - payments, addresses, roles, permissions - * (все ресурсы для администратора) ### Действия - view, create, edit, delete - moderate, manage, view_own - * (все действия для администратора) ### Права доступа Создаются комбинации ресурсов и действий, например: - `products.view`, `products.create`, `products.edit`, `products.delete` - `orders.view`, `orders.create`, `orders.edit`, `orders.view_own` - `categories.view`, `categories.create`, `categories.edit`, `categories.delete` - `reviews.view`, `reviews.create`, `reviews.moderate`, `reviews.delete` - `cart.manage` - `users.view`, `users.edit`, `users.delete` - `admin.all` (полные права) ### Роли и их права #### Администратор (admin) - Все права доступа (`admin.all`) #### Владелец (owner) - Все права, кроме управления ролями и правами доступа #### Сотрудник (employee) - Просмотр, создание, редактирование, удаление товаров - Просмотр и редактирование заказов - Полное управление категориями - Просмотр, модерация и удаление отзывов - Просмотр пользователей #### Менеджер (manager) - Те же права, что и у сотрудника #### Клиент (customer) - Просмотр товаров и категорий - Создание заказов и просмотр своих заказов - Управление корзиной - Создание отзывов ### Статусы заказов 1. **pending** - Ожидает обработки (#FFA500) 2. **processing** - В обработке (#4169E1) 3. **shipped** - Отправлен (#32CD32) 4. **delivered** - Доставлен (#228B22) 5. **cancelled** - Отменен (#DC143C) 6. **refunded** - Возвращен (#8B0000) ### Способы оплаты 1. **card** - Банковская карта 2. **e-wallet** - Электронный кошелек 3. **cash_on_delivery** - Наличные при получении 4. **bank_transfer** - Банковский перевод 5. **crypto** - Криптовалюта ### Статусы платежей 1. **pending** - Ожидает оплаты (#FFA500) 2. **paid** - Оплачен (#32CD32) 3. **completed** - Завершен (#228B22) 4. **failed** - Ошибка оплаты (#DC143C) 5. **refunded** - Возвращен (#8B0000) --- ## Диаграмма связей ``` users ──┬──> roles ──> role_permissions ──> permissions ──┬──> resources │ └──> actions │ ├──> addresses ├──> cart_items ──> products ──> categories ├──> orders ──> order_statuses │ └──> order_items ──> products │ └──> payments └──> reviews ──> products ``` --- ## Примеры использования ### Получение всех прав пользователя ```sql SELECT p.slug, p.name FROM users u JOIN roles r ON u.role_id = r.id JOIN role_permissions rp ON r.id = rp.role_id JOIN permissions p ON rp.permission_id = p.id WHERE u.id = 1 AND p.is_active = TRUE; ``` ### Получение товаров с рейтингом ```sql SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.id WHERE p.is_active = TRUE ORDER BY p.rating DESC, p.review_count DESC; ``` ### Получение заказов пользователя ```sql SELECT o.*, os.name as status_name, os.color as status_color, pm.name as payment_method_name, ps.name as payment_status_name, ps.color as payment_status_color FROM orders o JOIN order_statuses os ON o.status_id = os.id LEFT JOIN payment_methods pm ON o.payment_method_id = pm.id LEFT JOIN payment_statuses ps ON o.payment_status_id = ps.id WHERE o.user_id = 1 ORDER BY o.created_at DESC; ``` ### Получение элементов заказа ```sql SELECT oi.*, p.name as current_product_name, p.price as current_price FROM order_items oi LEFT JOIN products p ON oi.product_id = p.id WHERE oi.order_id = 1; ``` ### Получение корзины пользователя ```sql SELECT ci.*, p.name, p.price, p.stock_quantity, pi.image_url FROM cart_items ci JOIN products p ON ci.product_id = p.id LEFT JOIN product_images pi ON p.id = pi.product_id AND pi.is_primary = TRUE WHERE ci.user_id = 1; ``` --- ## Рекомендации по использованию 1. **Безопасность:** - Всегда проверяйте права доступа перед выполнением операций - Используйте параметризованные запросы для предотвращения SQL-инъекций - Храните пароли только в виде хешей 2. **Производительность:** - Используйте индексы для часто запрашиваемых полей - При больших объемах данных рассмотрите партиционирование таблиц `orders` и `order_items` - Регулярно анализируйте и оптимизируйте медленные запросы 3. **Целостность данных:** - Используйте транзакции при создании заказов (заказ + элементы заказа) - Проверяйте наличие товара на складе перед добавлением в корзину - Обновляйте количество товара на складе при создании заказа 4. **Масштабирование:** - Рассмотрите возможность добавления таблицы для истории изменений заказов - Для больших каталогов товаров используйте полнотекстовый поиск (PostgreSQL tsvector) - Кэшируйте часто запрашиваемые данные (категории, популярные товары) --- ## Версия **Версия базы данных:** 1.0 **СУБД:** PostgreSQL **Дата создания:** 2024 --- ## Лицензия Данная схема базы данных предоставляется "как есть" для использования в проектах интернет-магазинов.