Skip to content

cowabungal/avitoTech

Repository files navigation

Тестовое задание avitoTech

Содержание

  1. Описание задачи
  2. Реализация
  3. Endpoints
  4. Запуск
  5. Тестирование
  6. Примеры

Описание задачи

Разработать микросервис для работы с балансом пользователей (баланс, зачисление/списание/перевод средств). Сервис должен предоставлять HTTP API и принимать/отдавать запросы/ответы в формате JSON. Дополнительно реализовать методы конвертации баланса и получение списка транзакций. Полное описание в TASK.

Реализация

  • Следование дизайну REST API.
  • Подход "Чистой Архитектуры" и техника внедрения зависимости.
  • Работа с фреймворком gin-gonic/gin.
  • Работа с СУБД Postgres с использованием библиотеки sqlx и написанием SQL запросов.
  • Конфигурация приложения - библиотека viper.
  • Запуск из Docker.
  • Unit/Интеграционное - тестирование уровней обработчикоов, бизнес-логики и взаимодействия с БД с помощью моков - библиотеки testify, mock.

Структура проекта:

.
├── pkg
│   ├── handler     // обработчики запросов
│   ├── service     // бизнес-логика
│   └── repository  // взаимодействие с БД
├── cmd             // точка входа в приложение
├── schema          // SQL файлы с миграциями
├── configs         // файлы конфигурации

Endpoints

  • GET /balance/ - получение баланса пользователя
    • Тело запроса:
      • user_id - уникальный идентификатор пользователя.
    • Параметры запроса:
      • currency - валюта баланса.
  • GET /transaction/ - получение транзакций пользователя
    • Тело запроса:
      • user_id - уникальный идентификатор пользователя.
    • Параметры запроса:
      • sort - сортировка списка транзакций.
  • POST /top-up/ - пополнение баланса пользователя
    • Тело запроса:
      • user_id - идентификатор пользователя,
      • amount - сумма пополнения в RUB.
  • POST /debit/ - списание из баланса пользователя
    • Тело запроса:
      • user_id - идентификатор пользователя,
      • amount - сумма списания в RUB.
  • POST /transfer/ - перевод средств на баланс другого пользователя
    • Тело запроса:
      • user_id - идентификатор пользователя, с баланса которого списываются средства,
      • to_id - идентификатор пользователя, на баланс которого начисляются средства,
      • amount - сумма перевода в RUB.

Запуск

make build
make run

Если приложение запускается впервые, необходимо применить миграции к базе данных:

make migrate-up

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

Локальный запуск тестов:

make run-test

Примеры

Запросы сгенерированы из Postman для cURL.

1. GET /balance для user_id=1

Запрос:

$ curl --location --request GET 'localhost:8000/balance' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1
}'

Тело ответа:

{
    "user_id": 1,
    "balance": 1000
}

2. GET /balance для user_id=1 и currency=USD

Запрос:

$ curl --location --request GET 'localhost:8000/balance?currency=USD' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1
}'

Тело ответа:

{
    "user_id": 1,
    "balance": 13.542863492536123
}

3. GET /transaction для user_id=1

Запрос:

$ curl --location --request GET 'localhost:8000/transaction' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1
}'

Тело ответа:

[
    {
        "transaction_id": 3,
        "user_id": 1,
        "amount": 100,
        "operation": "Top-up by bank_card 100.000000RUB",
        "date": "2021-12-06T13:05:42Z"
    },
    {
        "transaction_id": 4,
        "user_id": 1,
        "amount": 10000,
        "operation": "Top-up by bank_card 10000.000000RUB",
        "date": "2021-12-06T13:05:53Z"
    },
    {
        "transaction_id": 5,
        "user_id": 1,
        "amount": 100,
        "operation": "Debit by transfer 100.000000RUB",
        "date": "2021-12-06T13:06:02Z"
    },
    {
        "transaction_id": 7,
        "user_id": 1,
        "amount": 9000,
        "operation": "Debit by purchase 9000.000000RUB",
        "date": "2021-12-06T15:50:15Z"
    }
]

4. GET /transaction для user_id=1, sort=date

Запрос:

$ curl --location --request GET 'localhost:8000/transaction?sort=date' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1
}'

Тело ответа:

[
    {
        "transaction_id": 7,
        "user_id": 1,
        "amount": 9000,
        "operation": "Debit by purchase 9000.000000RUB",
        "date": "2021-12-06T15:50:15Z"
    },
    {
        "transaction_id": 5,
        "user_id": 1,
        "amount": 100,
        "operation": "Debit by transfer 100.000000RUB",
        "date": "2021-12-06T13:06:02Z"
    },
    {
        "transaction_id": 4,
        "user_id": 1,
        "amount": 10000,
        "operation": "Top-up by bank_card 10000.000000RUB",
        "date": "2021-12-06T13:05:53Z"
    },
    {
        "transaction_id": 3,
        "user_id": 1,
        "amount": 100,
        "operation": "Top-up by bank_card 100.000000RUB",
        "date": "2021-12-06T13:05:42Z"
    }
]

5. GET /transaction для user_id=1, sort=amount

Запрос:

$ curl --location --request GET 'localhost:8000/transaction?sort=amount' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1
}'

Тело ответа:

[
    {
        "transaction_id": 4,
        "user_id": 1,
        "amount": 10000,
        "operation": "Top-up by bank_card 10000.000000RUB",
        "date": "2021-12-06T13:05:53Z"
    },
    {
        "transaction_id": 7,
        "user_id": 1,
        "amount": 9000,
        "operation": "Debit by purchase 9000.000000RUB",
        "date": "2021-12-06T15:50:15Z"
    },
    {
        "transaction_id": 3,
        "user_id": 1,
        "amount": 100,
        "operation": "Top-up by bank_card 100.000000RUB",
        "date": "2021-12-06T13:05:42Z"
    },
    {
        "transaction_id": 5,
        "user_id": 1,
        "amount": 100,
        "operation": "Debit by transfer 100.000000RUB",
        "date": "2021-12-06T13:06:02Z"
    }
]

6. POST /top-up для user_id=1, amount=1000

Запрос:

$ curl --location --request POST 'localhost:8000/top-up' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1,
    "amount":1000
}'

Тело ответа:

{
    "user_id": 1,
    "balance": 1000
}

7. POST /debit для user_id=1, amount=1000

Запрос:

$ curl --location --request POST 'localhost:8000/debit' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1,
    "amount":1000
}'

Тело ответа:

{
    "user_id": 1,
    "balance": 0
}

8. POST /transfer для user_id=1, to_id=2, amount=1000

Запрос:

$ curl --location --request POST 'localhost:8000/transfer' \
--header 'Content-Type: application/json' \
--data-raw '{
    "user_id":1,
    "to_id":2,
    "amount":1000
}'

Тело ответа:

{
    "user_id": 2,
    "balance": 1000
}

Releases

No releases published

Packages

No packages published

Languages