Документация базы данных интернет-магазина
Описание проекта
База данных для интернет-магазина на PostgreSQL, включающая систему управления пользователями с ролями и правами доступа, каталог товаров, систему заказов, корзину покупок, отзывы и платежи.
Структура файлов
Проект состоит из четырех SQL-файлов, которые должны выполняться в следующем порядке:
- schema.sql - Создание структуры базы данных (таблицы, функции)
- indexes.sql - Создание индексов для оптимизации запросов
- triggers.sql - Создание триггеров для автоматизации процессов
- seed_data.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. Система авторизации
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 | Первичный ключ |
| 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 >= 0compare_at_price >= 0cost_price >= 0stock_quantity >= 0rating >= 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 >= 0tax_amount >= 0shipping_cost >= 0discount_amount >= 0total_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 > 0price >= 0subtotal >= 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 при изменении записи в следующих таблицах:
resourcesactionspermissionsrolesuserscategoriesorder_statusesproductsaddressesorderscart_itemsreviewspayments
Триггеры обновления рейтинга товара
update_product_rating_on_review_insert- после добавления отзыва (если он одобрен)update_product_rating_on_review_update- после изменения отзыва (если изменился рейтинг или статус одобрения)update_product_rating_on_review_delete- после удаления отзыва
Триггер генерации номера заказа
generate_order_number_trigger- перед вставкой нового заказа генерирует номер, если он не указан
Индексы
Индексы созданы для оптимизации наиболее частых запросов:
Индексы по slug
resources.slugactions.slugpermissions.slugroles.slugcategories.slugproducts.slugorder_statuses.slug
Индексы по внешним ключам
permissions.resource_id,permissions.action_idrole_permissions.role_id,role_permissions.permission_idusers.role_idcategories.parent_idproducts.category_idproduct_images.product_idaddresses.user_idorders.user_id,orders.status_id,orders.payment_method_id,orders.payment_status_idorder_items.order_id,order_items.product_idcart_items.user_id,cart_items.product_idreviews.product_id,reviews.user_idpayments.order_id,payments.payment_method_id,payments.status_id
Индексы по статусам и флагам
resources.is_activeactions.is_activepermissions.is_activeroles.is_activeusers.is_activecategories.is_activeproducts.is_active,products.is_featuredorder_statuses.is_activepayment_methods.is_activepayment_statuses.is_activereviews.is_approved
Индексы по уникальным полям
users.emailusers.telegram_idproducts.skuorders.order_numberpayments.transaction_id
Индексы для сортировки и фильтрации
products.priceorders.created_atorders.payment_status_idreviews.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.deleteorders.view,orders.create,orders.edit,orders.view_owncategories.view,categories.create,categories.edit,categories.deletereviews.view,reviews.create,reviews.moderate,reviews.deletecart.manageusers.view,users.edit,users.deleteadmin.all(полные права)
Роли и их права
Администратор (admin)
- Все права доступа (
admin.all)
Владелец (owner)
- Все права, кроме управления ролями и правами доступа
Сотрудник (employee)
- Просмотр, создание, редактирование, удаление товаров
- Просмотр и редактирование заказов
- Полное управление категориями
- Просмотр, модерация и удаление отзывов
- Просмотр пользователей
Менеджер (manager)
- Те же права, что и у сотрудника
Клиент (customer)
- Просмотр товаров и категорий
- Создание заказов и просмотр своих заказов
- Управление корзиной
- Создание отзывов
Статусы заказов
- pending - Ожидает обработки (#FFA500)
- processing - В обработке (#4169E1)
- shipped - Отправлен (#32CD32)
- delivered - Доставлен (#228B22)
- cancelled - Отменен (#DC143C)
- refunded - Возвращен (#8B0000)
Способы оплаты
- card - Банковская карта
- e-wallet - Электронный кошелек
- cash_on_delivery - Наличные при получении
- bank_transfer - Банковский перевод
- crypto - Криптовалюта
Статусы платежей
- pending - Ожидает оплаты (#FFA500)
- paid - Оплачен (#32CD32)
- completed - Завершен (#228B22)
- failed - Ошибка оплаты (#DC143C)
- refunded - Возвращен (#8B0000)
Диаграмма связей
users ──┬──> roles ──> role_permissions ──> permissions ──┬──> resources
│ └──> actions
│
├──> addresses
├──> cart_items ──> products ──> categories
├──> orders ──> order_statuses
│ └──> order_items ──> products
│ └──> payments
└──> reviews ──> products
Примеры использования
Получение всех прав пользователя
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;
Получение товаров с рейтингом
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;
Получение заказов пользователя
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;
Получение элементов заказа
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;
Получение корзины пользователя
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;
Рекомендации по использованию
-
Безопасность:
- Всегда проверяйте права доступа перед выполнением операций
- Используйте параметризованные запросы для предотвращения SQL-инъекций
- Храните пароли только в виде хешей
-
Производительность:
- Используйте индексы для часто запрашиваемых полей
- При больших объемах данных рассмотрите партиционирование таблиц
ordersиorder_items - Регулярно анализируйте и оптимизируйте медленные запросы
-
Целостность данных:
- Используйте транзакции при создании заказов (заказ + элементы заказа)
- Проверяйте наличие товара на складе перед добавлением в корзину
- Обновляйте количество товара на складе при создании заказа
-
Масштабирование:
- Рассмотрите возможность добавления таблицы для истории изменений заказов
- Для больших каталогов товаров используйте полнотекстовый поиск (PostgreSQL tsvector)
- Кэшируйте часто запрашиваемые данные (категории, популярные товары)
Версия
Версия базы данных: 1.0
СУБД: PostgreSQL
Дата создания: 2024
Лицензия
Данная схема базы данных предоставляется "как есть" для использования в проектах интернет-магазинов.