Реализация REST API - сервиса Яндекс Лавки, предназначенного для взаимодействия с курьерами, работы с заказами и расчета статистики.
Разработка выполнена в рамках выполнения вступительного испытания в школу бекэнд разработки Академии Яндекса.
Сервис предоставляет функционал по регистрации курьеров и получения информации о них, добавлению новых заказов и расчету рейтинга и дохода курьера в зависимости от его типа за выбранный период.
Для защиты от DDOS атак в сервис введено ограничение на количество запросов (rate limiter) на каждый endpoint в количестве 10 RPS.
Микросервис построен с использованием принципов Clean architecture и предоставляет HTTP API, база данных построена на основе PostgresSQL.
Обработчик принимает на вход список в формате json с данными о курьерах и графиком их работы.
Курьеры работают только в заранее определенных районах, а также различаются по типу: пеший, велокурьер и курьер на автомобиле. От типа зависит объем заказов, которые перевозит курьер. Районы задаются целыми положительными числами. График работы задается списком строк формата HH:MM-HH:MM.
POST /couriers
{
"couriers": [
{
"courier_type": "FOOT",
"regions": [
1
],
"working_hours": [
"10:00-12:00"
]
}
]
}
200 OK
{
"couriers": [
{
"courier_id": 1,
"courier_type": "FOOT",
"regions": [
1
],
"working_hours": [
"10:00-12:00"
]
}
]
}
Возвращает информацию о курьере.
GET /couriers/{courier_id}
GET /couriers/1
200 OK
{
"courier_id": 1,
"courier_type": "FOOT",
"regions": [
1
],
"working_hours": [
"10:00-12:00"
]
}
Возвращает информацию о всех курьерах.
У метода есть параметры offset и limit, чтобы обеспечить постраничную выдачу.
Если:
offset или limit не передаются, по умолчанию offset = 0, limit = 1;
офферов по заданным offset и limit не найдено, возвращается пустой список couriers.
GET /couriers
GET /couriers?limit=10&offset=0
200 OK
{
"couriers": [
{
"courier_id": 1,
"courier_type": "FOOT",
"regions": [
1
],
"working_hours": [
"10:00-12:00"
]
}
],
"limit": 10,
"offset": 0
}
Принимает на вход список с данными о заказах в формате json.
У заказа отображаются характеристики — вес, район, время доставки и цена.
Время доставки - строка в формате HH:MM-HH:MM, где HH - часы (от 0 до 23) и MM - минуты (от 0 до 59). Примеры: “09:00-11:00”, “12:00-23:00”, “00:00-23:59”.
POST /orders
{
"orders": [
{
"weight": 10,
"regions": 1,
"delivery_hours": [
"10:00-12:00"
],
"cost": 100
}
]
}
200 OK
[
{
"order_id": 1,
"weight": 10,
"regions": 1,
"delivery_hours": [
"10:00-12:00"
],
"cost": 100,
"completed_time": "2023-05-11T11:13:34.330Z"
}
]
Возвращает информацию о заказе по его идентификатору, а также дополнительную информацию: вес заказа, район доставки, промежутки времени, в которые удобно принять заказ.
GET /orders/{order_id}
GET /orders/1
200 OK
{
"order_id": 1,
"weight": 10,
"regions": 1,
"delivery_hours": [
"10:00-12:00"
],
"cost": 100,
"completed_time": "2023-05-11T11:15:35.120Z"
}
Возвращает информацию о всех заказах, а также их дополнительную информацию: вес заказа, район доставки, промежутки времени, в которые удобно принять заказ.
У метода есть параметры offset и limit, чтобы обеспечить постраничную выдачу.
Если:
offset или limit не передаются, по умолчанию offset = 0, limit = 1;
офферов по заданным offset и limit не найдено, возвращается пустой список orders.
GET /orders
GET /orders?limit=10&offset=0
200 OK
{
"orders": [
{
"order_id": 1,
"weight": 10,
"regions": 1,
"delivery_hours": [
"10:00-12:00"
],
"cost": 100,
"completed_time": "2023-05-11T11:13:34.330Z"
}
],
"limit": 10,
"offset": 0
}
Принимает массив объектов, состоящий из трех полей: id курьера, id заказа и время выполнения заказа, после отмечает, что заказ выполнен.
POST /orders/complete
{
"complete_info": [
{
"courier_id": 1,
"order_id": 1,
"complete_time": "2023-05-11T11:19:43.120Z"
}
]
}
200 OK
[
{
"order_id": 1,
"weight": 10,
"regions": 1,
"delivery_hours": [
"10:00-12:00"
],
"cost": 100,
"completed_time": "2023-05-11T11:19:43.130Z"
}
]
Метод возвращает заработанные курьером деньги за заказы и его рейтинг.
Параметры метода:
start_date - дата начала отсчета рейтинга end_date - дата конца отсчета рейтинга.
Примером значения параметров может быть 2023-01-20. Все заказы и даты для расчетов имеют одну и ту же фиксированную временную зону - UTC.
Заработок рассчитывается по формуле:
Заработок рассчитывается как сумма оплаты за каждый завершенный развоз в период с start_date (включая) до end_date (исключая):
sum = ∑(cost * C)
C — коэффициент, зависящий от типа курьера:
пеший — 2
велокурьер — 3
авто — 4
Рейтинг рассчитывается по формуле:
Рейтинг рассчитывается следующим образом: ((число всех выполненных заказов с start_date по end_date) / (Количество часов между start_date и end_date)) * C C - коэффициент, зависящий от типа курьера:
пеший - 3
велокурьер - 2
авто - 1
GET /couriers/meta-info/{courier_id}
GET /couriers/meta-info/1?start_date=2023-05-01&end_date=2023-05-02
200 OK
{
"courier_id": 1,
"courier_type": "FOOT",
"regions": [
1
],
"working_hours": [
"10:00-12:00"
],
"rating": 2,
"earnings": 30
}
Развертывание микросервиса может быть осуществлено двумя способами:
- С использованием docker-compose
осуществляется командой:
make run.docker.compose
(внутри docker compose up) в директории с проектом.
При этом происходит развертывание базы данных PostgresSQL на основе образа postgres:15.2-alpine
- С использованием Dockerfile
В этом случае необходимо самостоятельно обеспечить работу базы данных PostgresSQL, запуск контейнера с сервисом осуществляется командой:
make run.docker
На основную логику работы микросервиса написаны тесты. Запуск осуществляется командой:
cd tests
go test -race