Skip to content

Реализация сервиса Яндекс.Лавка, выполненная в качестве вступительного задания в ШБР Академии Яндекса

Notifications You must be signed in to change notification settings

BruteMors/yandex-lavka-service

Repository files navigation

Yandex-lavka-service

Реализация REST API - сервиса Яндекс Лавки, предназначенного для взаимодействия с курьерами, работы с заказами и расчета статистики.
Разработка выполнена в рамках выполнения вступительного испытания в школу бекэнд разработки Академии Яндекса.

Общее описание

Сервис предоставляет функционал по регистрации курьеров и получения информации о них, добавлению новых заказов и расчету рейтинга и дохода курьера в зависимости от его типа за выбранный период.

Для защиты от DDOS атак в сервис введено ограничение на количество запросов (rate limiter) на каждый endpoint в количестве 10 RPS.

Архитектура

Микросервис построен с использованием принципов Clean architecture и предоставляет HTTP API, база данных построена на основе PostgresSQL.

DB architecture

Описание методов API

Загрузка списка курьеров в систему

Обработчик принимает на вход список в формате 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
}

Развертывание

Развертывание микросервиса может быть осуществлено двумя способами:

  1. С использованием docker-compose

осуществляется командой:

make run.docker.compose

(внутри docker compose up) в директории с проектом.

При этом происходит развертывание базы данных PostgresSQL на основе образа postgres:15.2-alpine

  1. С использованием Dockerfile

В этом случае необходимо самостоятельно обеспечить работу базы данных PostgresSQL, запуск контейнера с сервисом осуществляется командой:

make run.docker

Тестирование

На основную логику работы микросервиса написаны тесты. Запуск осуществляется командой:

cd tests
go test -race

About

Реализация сервиса Яндекс.Лавка, выполненная в качестве вступительного задания в ШБР Академии Яндекса

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published