Данный проект является FastAPI‑реализацией REST‑API для управления сервисом электронных кошельков в рамках выполнения тестового задания компании ITK-Academy.
Проект покрыт тестами (кроме error-handler'ов), проверяется линтерами и упакован в Docker‑контейнеры.
| № | Раздел |
|---|---|
| 1 | Анализ исходного ТЗ |
| 2 | Архитектура |
| 3 | Стек технологий |
| 4 | Как развернуть проект |
Требуется реализовать сервис, позволяющий:
- Изменение баланса кошелька
- Получение баланса кошелька
- Cоответствовать стандарту
PEP-8- Делать миграции для базы данных
- Работать корректно в конкурентной среде (корректно использовать асинхронный веб-фреймворк)
- Быть покрытым тестами и запускаться в Docker‑контейнерах.
Исходный вариант задания предлагал два эндпоинта:
POST /api/v1/wallets/<WALLET_UUID>/operationс полемoperation_type. Это не RESTful (один ресурс не должен решать две разные задачи).GET /api/v1/wallets/<WALLET_UUID>.
Опять же, для RESTful архитектуры приведён не полный список CRUD операций.
Из комментария к списку выше, было решено сохранить требуемый в задании эндпоинт, но к тому реализовать разделённые эндпоинты под здачи списания и зачисления средств, а также дополнить исходных спиоск до CRUD-полного.
Ниже приведена таблица итогового списка эндпоинтов текущей реализации:
| Операция | HTTP‑метод | Путь |
|---|---|---|
| Пополнение кошелька | POST |
/api/v1/wallets/{wallet_id}/deposit |
| Пополнение кошелька | POST |
/api/v1/wallets/{wallet_id}/operation?operation_type=DEPOSIT |
| Списание средств | POST |
/api/v1/wallets/{wallet_id}/withdraw |
| Списание средств | POST |
/api/v1/wallets/{wallet_id}/operation?operation_type=WITHDRAW |
| Узнать баланс | GET |
/api/v1/wallets/{wallet_id} |
| Создать кошелёк | POST |
/api/v1/wallets |
| Удалить кошелёк | DELETE |
/api/v1/wallets/{wallet_uuid} |
На операции изменения баланса кошелька наложены ограничения снизу (0.00) и сверху 1'000'000.00 для корректной обработки запросов.
| Требование | Реализация |
|---|---|
| Асинхронность | FastAPI + SQLAlchemy + asyncpg-драйвер для PostgreSQL |
| Конкурентность | Транзакции с уровнем изоляции SERIALIZABLE + SELECT … FOR UPDATE (row‑level pessimistic lock), asyncio |
| Миграции | alembic (автоматически генерируемые скрипты для миграций) |
| Docker | 2‑контейнерный docker‑compose‑стек: app (FastAPI) + db (PostgreSQL) |
| Тесты | pytest + pytest‑asyncio |
| Стиль кода | PEP‑8, ruff, pylint, flake8, mypy, black |
| Управление зависимостями | pip-tools (pip‑compile + pip‑sync). |
| Назначение | Инструмент |
|---|---|
| Web‑framework | FastAPI v0.135 |
| ORM / DB | SQLAlchemy v2.0 (async) + PostgreSQL v18 |
| Миграции | Alembic v1.18 |
| Тесты | pytest, pytest‑asyncio |
| Docker | Docker 20+, docker‑compose 2.20 |
| Linters / formatters | ruff v0.15, pylint v4, flake8 v7.3.0, black, isort v8 |
| Type checking | mypy v1.19 |
| Dependency management | pip‑tools (requirements*.txt) |
$ git clone https://github.com/archsaurus/ITK_Test-wallets-api.git
$ cd ITK_Test-wallets-api
$ docker compose up --build -dТребуются предустановленные Python 3.14+ и PostgreSQL.
$ git clone https://github.com/archsaurus/ITK_Test-wallets-api.git
$ cd ITK_Test-wallets-api
$ pip-sync requirements.txt # runtime-зависимости
$ pip-sync requirements-dev.txt # включает линтеры, mypy, pytest и т.д.
$ cp .env.example .env # копируем шаблон для задания переменных окружения .env (см. ниже)
$ alembic revision --autogenerate # создаём миграции (если изменяли структуру моделей)
$ alembic upgrade head # применяем миграции
uvicorn application.main:app --host 0.0.0.0 --port 8000 --reload # запускаем ASGI-сервер приложения| Переменная | Описание | Пример |
|---|---|---|
POSTGRES_USER |
Администратор базы данных | wallet_user |
POSTGRES_PASSWORD |
Пароль | qwerty |
POSTGRES_DB |
Имя базы данных | wallets_db |
POSTGRES_HOST |
Хост (Docker‑service) | db |
POSTGRES_PORT |
Порт | 5432 |
DATABASE_URL |
DSN для SQLAlchemy | postgresql+asyncpg://user:password@host:port/db_name |
MIGRATIONS |
Флаг аавтоматического совершения миграций (для контейнера) | true |
Файл example.env содержит подготовленный шаблон.