Этот проект реализует схему БД, SQL‑запросы и REST‑сервис для работы с заказами и номенклатурой.
-
Реляционная БД (PostgreSQL):
- Категории товаров с неограниченной вложенностью (Adjacency List);
- Товары (номенклатура) с количеством и ценой;
- Клиенты;
- Заказы и состав заказов.
-
SQL‑запросы:
- 2.1. Сумма товаров по каждому клиенту;
- 2.2. Подсчёт дочерних категорий первого уровня;
- 2.3. Отчёт «Топ‑5 товаров за последний месяц» (view).
-
REST‑сервис (DRF):
- Метод
POST /orders/{order_id}/items
для добавления товара в заказ. - Проверка остатков на складе.
- Если товар уже есть в заказе — количество увеличивается.
- Метод
-
Контейнеризация (Docker + docker‑compose).
git clone <url> test_task
cd test_task
docker compose up --build
Поднимутся два контейнера:
- db — PostgreSQL 16
- api — DRF‑сервис
/api/schema/
/api/docs/
/api/redo/
GET /api/products/
GET /api/orders/
POST api/orders/{order_id}/items
order_id
— ID заказа (в URL)
{
"product_id": 123,
"quantity": 2
}
{
"order_id": 1,
"product_id": 123,
"quantity": 5,
"price": 19990.00
}
404
— заказ или товар не найден;409
— недостаточно товара на складе.
- Таблицы:
category
,product
,client
,orders
,order_item
. order_item
хранит цену товара на момент покупки.- В
category
используется полеparent_id
для дерева категорий. - Ограничения (
CONSTRAINT
) и индексы обеспечивают целостность и скорость работы.
docker compose exec db psql -U postgres -d shop
SELECT c.name AS client_name,
COALESCE(SUM(oi.quantity * oi.price), 0) AS total_amount
FROM mainapp_client c
LEFT JOIN mainapp_order o ON o.client_id = c.id
LEFT JOIN mainapp_orderitem oi ON oi.order_id = o.id
GROUP BY c.id, c.name
ORDER BY total_amount DESC;
SELECT p.id AS category_id,
p.name AS category_name,
COUNT(c.id) AS child_count
FROM mainapp_category p
LEFT JOIN mainapp_category c ON c.parent_id = p.id
GROUP BY p.id, p.name
ORDER BY category_id;
CREATE OR REPLACE VIEW top5_products_last_month AS
WITH period AS (
SELECT (CURRENT_DATE - INTERVAL '1 month') AS dt_from,
CURRENT_DATE AS dt_to
)
SELECT p.name AS product_name,
c.name AS category_name,
SUM(oi.quantity) AS total_qty
FROM mainapp_order o
JOIN period t ON o.order_date >= t.dt_from AND o.order_date < t.dt_to
JOIN mainapp_orderitem oi ON oi.order_id = o.id
JOIN mainapp_product p ON p.id = oi.product_id
JOIN mainapp_category c ON c.id = p.category_id
GROUP BY p.name, c.name
ORDER BY total_qty DESC
LIMIT 5;
- Индексы по
order_date
,order_id
,product_id
. - Денормализация: хранить
root_category_id
вproduct
. - Материализованные view для агрегаций.
- Партиционирование таблиц
orders
иorder_item
по дате. - Closure Table или Materialized Path для оптимизации запросов по дереву категорий.
- Backend: Python 3.12, Django, DRF
- Database: PostgreSQL 16
- Infra: Docker, docker‑compose
- Unit‑тесты (pytest + httpx).
- CI/CD (GitHub Actions).
- Redis‑кэш для отчётных запросов.