Разработать микросервис для работы с балансом пользователей (баланс, зачисление/списание/перевод средств). Сервис должен предоставлять 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 // файлы конфигурации
- 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.
Запрос:
$ curl --location --request GET 'localhost:8000/balance' \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id":1
}'
Тело ответа:
{
"user_id": 1,
"balance": 1000
}
Запрос:
$ 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
}
Запрос:
$ 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"
}
]
Запрос:
$ 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"
}
]
Запрос:
$ 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"
}
]
Запрос:
$ 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
}
Запрос:
$ curl --location --request POST 'localhost:8000/debit' \
--header 'Content-Type: application/json' \
--data-raw '{
"user_id":1,
"amount":1000
}'
Тело ответа:
{
"user_id": 1,
"balance": 0
}
Запрос:
$ 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
}