Дипломный проект представляет собой каталог интернет-магазина. Ваша задача заключается в создании работающего бэкэнд-приложения, всеми основными функциями которого можно пользоваться.
-
В каталоге хранятся продукты, категории продуктов, цены на продукты, магазины (под магазинами подразумеваются физические магазины, где забираем заказ).
-
Каталог должен отдавать продукты с ценами, по магазину, по категории и давать возможность поиска по названию товара.
-
Необходимо реализовать бизнес-логику получения данных по заданным маршрутам, также необходимо реализовать кеширование (например, можно закешировать ответ поисковый запрос или запрос магазинов, кеширование цен возможно только, если внешние сервисы отдают ответы с разной периодичностью).
-
Реализовать аутентификацию входящих запросов (рекомендуется делать это через использование jwt токена и middleware).
-
Необходимо предусмотреть, что пользователь может быть администратором, то есть иметь возможность добавлять и изменять данные (можно указать в настройках токен администратора и в middleware проверять тип запроса).
-
Товары без цен возможны, в таком случае в реальном магазине рисуется кнопка
Узнать цену
. -
В каталог может обращаться два типа пользователей: пользователь и администратор.
- получать продукты;
- получать список категорий;
- получать список магазинов;
- получать продукты по категории или магазину;
- выполнять поиск по наименованию продукта.
- добавлять продукт;
- добавлять цену;
- изменять продукт;
- изменять цену;
- добавлять категорию;
- добавлять магазин;
- изменять магазин и категорию.
Разработку Backend-сервиса рекомендуется разделить на следующие этапы:
Этап 1 - Создание модели данных Этап 2 - Создание бизнес логики и обработчиков
Настоятельно рекомендуется сдавать вашу работу на этих промежуточных этапах вашему дипломному руководителю. Старайтесь делать это как можно чаще для того, чтобы избежать лишнего переписывания кода в процессе хождения не в ту сторону.
Разберём подробно каждый этап.
На данном этапе мы реализуем модели в storage и физически в БД.
Данные объявлений должны храниться в PostgreSql.
В моделях заданы поля для даты и времени создания записи, для даты и времени обновления. Нужно, чтобы они заполнялись автоматически.
Необходимо реализовать модель для продукта, категорий, цен и магазинов.
Категории нужны для правильного отображения товара в интернет-магазине. Для простоты считаем, что все категории активны:
название | тип | обязательное | уникальное |
---|---|---|---|
id | int |
да | да |
name | varchar |
да | да |
create_at | timestamp |
да | нет |
updated_at | timestamp |
да | нет |
uri_name | varchar |
да | нет |
Связка с товаром:
название | тип | обязательное | уникальное |
---|---|---|---|
category_id | int |
да | да |
product_id | uuid |
да | да |
В данной таблице уникальность создается составным первичным ключом из 2х полей.
название | тип | обязательное | уникальное |
---|---|---|---|
id | int |
да | да |
name | varchar |
да | нет |
create_at | timestamp |
да | нет |
updated_at | timestamp |
да | нет |
address | varchar |
да | нет |
lon | varchar |
нет | нет |
lat | varchar |
нет | нет |
working_hours | varchar |
нет | нет |
Связка с товаром:
название | тип | обязательное | уникальное |
---|---|---|---|
shop_id | int |
да | да |
product_id | uuid |
да | да |
В данной таблице уникальность создается составным первичным ключом из 2х полей.
В нашем случае цена, как правило, будет одна, но мы предусмотрим модель на случай расширение функционала, (например, если цена будет зависеть от города или если мы захотим проследить динамику цен).
название | тип | обязательное | уникальное |
---|---|---|---|
id | int |
да | да |
sale_price | int |
да | нет |
factory_price | int |
да | нет |
discount_price | int |
да | нет |
create_at | timestamp |
нет | нет |
updated_at | timestamp |
нет | нет |
is_active | bool |
да | нет |
product_id | uuid |
да | нет |
название | тип | обязательное | уникальное |
---|---|---|---|
id | uuid |
да | да |
sku | varchar |
да | нет |
name | varchar |
да | нет |
type | varchar |
да | нет |
uri | varchar |
да | нет |
description | varchar |
да | нет |
is_active | bool |
да | нет |
create_at | timestamp |
да | нет |
updated_at | timestamp |
да | нет |
- GET /api/v1/products
- POST /api/v1/products
- PUT /api/v1/products
- GET /api/v1/search
- GET /api/v1/categories
- POST /api/v1/categories
- PUT /api/v1/categories
- GET /api/v1/shops
- POST /api/v1/shops
- PUT /api/v1/shops
- GET /api/v1/categories/:category_id/products
- GET /api/v1/shops/:shop/products
- POST /api/v1/prices
- PUT /api/v1/prices
GET /api/v1/products
— получить все продукты из каталога.
В ответ приходит json-объект
с данными:
{
"total": 1,
"items": [
{
"sku": "2074",
"name": "Кирпич",
"uri": "/product/brick-2074",
"description": "Кирпич",
"prices": [
{
"sale": 10.00,
"factory": 2.00,
"discount": 8.00
}
]
}
]
}
Поле uri содержит slug для продукта, состоящий из типа продукта и sku продукта, используется во фронтэнд-сервисе и
формируется по формуле /products/{тип продукта}-{sku}
.
Если массива цен нет, то в json должен возвращаться пустой массив.
GET /api/v1/search
— поиск продуктов по наименованию.
Параметры:
название | тип | обязательное |
---|---|---|
product_name | string |
да |
В ответ приходит json-объект
с данными:
{
"total": 1,
"items": [
{
"sku": "2074",
"name": "Кирпич",
"uri": "/product/brick-2074",
"description": "Кирпич",
"prices": [
{
"sale": 10.00,
"factory": 2.00,
"discount": 8.00
}
]
}
]
}
GET /api/v1/categories
— получить все продукты из каталога.
В ответ приходит json-объект
с данными:
{
"total": 2,
"items": [
{
"id": "2476",
"uri_name": "linoleum-2476",
"name": "Линолеум"
},
{
"id": "2480",
"uri_name": "laminat-2480",
"name": "Ламинат"
}
]
}
Поле uri содержит slug для категории, состоящий из названия категории и id категории, используется во фронтэнд-сервисе и
формируется по формуле {названия категории}-{id}
GET /api/v1/shops
— получить все продукты из каталога.
В ответ приходит json-объект
с данными:
{
"total": 2,
"items": [
{
"id": "1",
"name": "Магазин №1",
"address": " Ленина 1 стр 1",
"working_hours": "8:00-20:00",
"lon": "12.554764",
"lat": "12.554564",
},
{
"id": "2",
"name": "Магазин №2",
"address": " Ленина 2 стр 2",
"working_hours": "8:00-20:00",
"lon": "39.643151",
"lat": "-0.351560",
}
]
}
Выдает все активные продукты (у которых is_active == true).
GET /api/v1/categories/:category_id/products
— получить все продукты по категории
Параметры:
название | тип | обязательное |
---|---|---|
category_id | string |
да |
Ответ аналогичен ответу GET /api/v1/products
.
Выдает все активные продукты (у которых is_active == true)
GET /api/v1/shops/:shop_id/products
— получить все продукты по id магазина.
Параметры:
название | тип | обязательное |
---|---|---|
shop_id | string |
да |
Ответ аналогичен ответу GET /api/v1/products
Внимание! Категория и Магазин уже должны быть созданы
POST /api/v1/products
- добавляет продукт
{
"guid": "3ee995e3-0c96-4e30-ac1e-f7f04fd03e44",
"sku": "2075",
"name": "Кирпич 2",
"uri": "/product/brick-2075",
"description": "Кирпич 2",
"shop_id": "2",
"category_id": "2480"
}
В ответ приходит либо сообщение об ошибке, либо JSON-объект с данными:
{
"total": 1,
"items": [
{
"sku": "2075",
"name": "Кирпич 2",
"uri": "/product/brick-2075",
"description": "Кирпич 2"
}
]
}
{
"error": "что то пошло не так"
}
PUT /api/v1/products
- обновляет продукт
Обязательное поле sku
{
"sku": "2075",
"is_active": "false"
}
В ответ приходит либо сообщение об ошибке, либо JSON-объект с данными:
{
"total": 1,
"items": [
{
"sku": "2075",
"name": "Кирпич 2",
"uri": "/product/brick-2075",
"description": "Кирпич 2",
"is_active": "False"
}
]
}
{
"error": "что то пошло не так"
}
Аналогично делаем добавление и изменение магазинов, категорий и цен. Обратите внимание на то, что для продукта используется первичный ключ типа uuid.
- Необходимо предусмотреть возможность нашего сервиса обращаться в другие сервисы (например, сервис доступности или актуальных цен). Для этого необходимо использовать механизм gRPS (внешние сервисы необходимо замокать).
Для запуска приложения в корне проекта должны находиться следующие файлы:
Dockerfile
для сборки образа приложения;docker-compose.yaml
с сервисом приложения и сервисом postgres;README.md
с описанием проекта и вариантами его запуска.
Настройка параметров приложения должна производиться через переменные окружения. Это требование как для запуска в окружении хоста, так и при работе с docker.
Список переменных окружения должен быть описан в файле .env-example
. Этот файл не должен содержать значений. Пример файла:
HTTP_HOST=
HTTP_PORT=
POSTGRES_URL=
Что следует делать, чтобы все получилось:
- Попробовать найти ответ сначала самому в интернете. Именно этот скилл поиска ответов пригодится вам на первой работе. И только после этого спрашивать дипломного руководителя.
- В одном вопросе должна быть заложена одна проблема.
- По возможности прикрепляйте к вопросу скриншоты и стрелочкой показывать, где не получается. Программу для этого можно скачать здесь https://app.prntscr.com/ru/
- По возможности задавать вопросы в комментариях к коду.
- Начинайте работу над дипломом как можно раньше! Чтобы было больше времени на правки.
- Делать диплом по частям, а не все сразу. Иначе есть шанс, что нужно будет все переделывать :)
Что следует делать, чтобы ничего не получилось:
- Писать вопросы вида “Ничего не работает. Не запускается. Всё сломалось.”
- Откладывать диплом на потом.
- Ждать ответ на свой вопрос моментально. Дипломные руководители - работающие разработчики, которые занимаются, кроме преподавания, своими проектами. Их время ограничено, поэтому постарайтесь задавать правильные вопросы, чтобы получать быстрые ответы!