Тестовое задание.
Описание задания
🔥 Необходимо разработать REST API сервиc для поиска ближайших машин к грузам.
◼Стек и требования:
- Python (Django Rest Framework / FastAPI) на выбор.
- DB - Стандартный PostgreSQL.
- Приложение должно запускаться в docker-compose без дополнительных доработок.
- Порт - 8000.
- БД по умолчанию должна быть заполнена 20 машинами.
- Груз обязательно должен содержать следующие характеристики:
- локация pick-up;
- локация delivery;
- вес (1-1000);
- описание.
- Машина обязательно должна в себя включать следующие характеристики:
- уникальный номер (цифра от 1000 до 9999 + случайная заглавная буква английского алфавита в конце, пример: "1234A", "2534B", "9999Z")
- текущая локация;
- грузоподъемность (1-1000).
- Локация должна содержать в себе следующие характеристики:
- город;
- штат;
- почтовый индекс (zip);
- широта;
- долгота.
Список уникальных локаций представлен в прикрепленном csv файле "uszips.csv". Необходимо осуществить выгрузку списка в базу данных Postgres при запуске приложения.
- При создании машин по умолчанию локация каждой машины заполняется случайным образом;
- Расчет и отображение расстояния осуществляется в милях;
- Расчет расстояния должен осуществляться с помощью библиотеки geopy. help(geopy.distance). Маршруты не учитывать, использовать расстояние от точки до точки.
Сервис должен поддерживать следующие базовые функции:
- Создание нового груза (характеристики локаций pick-up, delivery определяются по введенному zip-коду);
- Получение списка грузов (локации pick-up, delivery, количество ближайших машин до груза ( =< 450 миль));
- Получение информации о конкретном грузе по ID (локации pick-up, delivery, вес, описание, список номеров ВСЕХ машин с расстоянием до выбранного груза);
- Редактирование машины по ID (локация (определяется по введенному zip-коду));
- Редактирование груза по ID (вес, описание);
- Удаление груза по ID.
Все что в уровне 1 + дополнительные функции:
- Фильтр списка грузов (вес, мили ближайших машин до грузов);
- Автоматическое обновление локаций всех машин раз в 3 минуты (локация меняется на другую случайную).
-
Адекватность архитектуры приложения;
-
Оптимизация работы приложения.
Сервис реализован на FastAPI.
База данных - PostgreSQL
ORM - SQLAlchemy, миграции - Alembic
Проект разворачивается с помощью docker compose
При пулл реквесте или пуше в ветку main запускаются тесты.
Python версии 3.11.1
- alembic==1.11.1
- asyncpg==0.27.0
- SQLAlchemy==2.0.15
- uvicorn==0.22.0
- fastapi==0.95.2
- geopy==2.3.0
- python-dotenv==1.0.0
-
Клонировать репозиторий:
git clone ...
-
Перейти в папку с проектом:
cd nearest_trucks/
-
Создать и запустить контейнер:
docker-compose up -d
-
(Опционально) Запуск тестов.
Запуск отдельного контейнера с тестовой базой данных:
docker run --name postgres -e POSTGRES_PASSWORD=postgres -p 1111:5432 -d postgres:13.0-alpine
Запуск тестов
pytest
-
(Опционально) Панель управления pgadmin доступна по адресу http://localhost:5050/
Авторизация:
email=[email protected]
password=admin
Подключение к базе:
1.
2.
3.
- Ресурс доступен по адресу:
http://localhost:8000/
- Документация:
http://localhost:8000/docs
-
Добавление груза в базу данных.
POST http://localhost:8000/cargoes/add
-
Пример запроса:
{ "description": "Просто груз", "weight": 1000, "zip_pick_up": "18801", "zip_delivery": "44128" }
-
Пример ответа:
{ "description": "Просто груз", "weight": 1000, "id": 1, "pick_up_location_id": 5933, "delivery_location_id": 14526 }
-
Загрузка и конвертация файла.
GET http://localhost:8000/cargoes/1
-
Пример ответа:
{ "pick_up_location": { "city": "Cayey", "state": "PR", "postcode": "00736" }, "delivery_location": { "city": "Loiza", "state": "PR", "postcode": "00772" }, "trucks": [ { "VIN": "1002A", "distance": 1058.36 }, { "VIN": "1018A", "distance": 1302.2 }, { "VIN": "1017A", "distance": 1517.69 }, { "VIN": "1014A", "distance": 1571.64 }, { "VIN": "1007A", "distance": 1575.26 }, { "VIN": "1005A", "distance": 1580.43 }, { "VIN": "1019A", "distance": 1642.46 }, { "VIN": "1003A", "distance": 1687.65 }, { "VIN": "1010A", "distance": 1748.79 }, { "VIN": "1016A", "distance": 1778.3 }, { "VIN": "1011A", "distance": 1839.64 }, { "VIN": "1001A", "distance": 1911.3 }, { "VIN": "1004A", "distance": 1932.01 }, { "VIN": "1008A", "distance": 2153.88 }, { "VIN": "1000A", "distance": 2307.43 }, { "VIN": "1009A", "distance": 2764.41 }, { "VIN": "1015A", "distance": 2859.92 }, { "VIN": "1012A", "distance": 3109.1 }, { "VIN": "1013A", "distance": 3417.46 }, { "VIN": "1006A", "distance": 3577.55 } ] }
- Роман Дячук