This commit is contained in:
593
docs/NUTRITION_API.md
Normal file
593
docs/NUTRITION_API.md
Normal file
@@ -0,0 +1,593 @@
|
||||
# API Сервиса Питания (Nutrition Service)
|
||||
|
||||
Сервис питания предоставляет API для работы с данными о питании, включая поиск продуктов питания, добавление продуктов в дневник питания, отслеживание потребления воды и физической активности.
|
||||
|
||||
## Основные функции
|
||||
|
||||
- Поиск продуктов питания через FatSecret API
|
||||
- Отслеживание потребления пищи и питательных веществ
|
||||
- Учет потребления воды
|
||||
- Отслеживание физической активности
|
||||
- Установка и отслеживание целей по питанию и активности
|
||||
|
||||
## Базовый URL
|
||||
|
||||
```
|
||||
http://localhost:8006/api/v1/nutrition/
|
||||
```
|
||||
|
||||
## Swagger-документация
|
||||
|
||||
Интерактивная документация API доступна через Swagger UI по следующим URL:
|
||||
|
||||
```
|
||||
http://localhost:8006/docs
|
||||
```
|
||||
|
||||
или через ReDoc:
|
||||
|
||||
```
|
||||
http://localhost:8006/redoc
|
||||
```
|
||||
|
||||
> **Примечание**: Swagger-документация доступна только при запущенном сервисе питания. Если сервис не запущен, страница документации будет недоступна.
|
||||
|
||||
### Использование Swagger UI
|
||||
|
||||
1. Откройте URL `http://localhost:8006/docs` в браузере
|
||||
2. Авторизуйтесь с помощью кнопки "Authorize" в верхней части страницы:
|
||||
- Введите ваш JWT токен в формате: `Bearer <token>`
|
||||
- Нажмите "Authorize"
|
||||
3. Теперь вы можете тестировать все эндпоинты API непосредственно через Swagger UI:
|
||||
- Выберите нужный эндпоинт
|
||||
- Заполните параметры запроса
|
||||
- Нажмите "Execute" для отправки запроса
|
||||
|
||||

|
||||
|
||||
## Эндпоинты
|
||||
|
||||
### Поиск продуктов
|
||||
|
||||
#### Поиск по названию
|
||||
|
||||
```http
|
||||
POST /api/v1/nutrition/search
|
||||
```
|
||||
|
||||
Параметры запроса:
|
||||
```json
|
||||
{
|
||||
"query": "яблоко",
|
||||
"page_number": 0,
|
||||
"max_results": 10
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"fatsecret_id": "35718",
|
||||
"name": "Apple",
|
||||
"brand": null,
|
||||
"description": "A common fruit",
|
||||
"food_type": "Generic",
|
||||
"serving_size": "100g",
|
||||
"serving_weight_grams": 100.0,
|
||||
"calories": 52.0,
|
||||
"protein_grams": 0.26,
|
||||
"fat_grams": 0.17,
|
||||
"carbs_grams": 13.81,
|
||||
"fiber_grams": 2.4,
|
||||
"sugar_grams": 10.39,
|
||||
"sodium_mg": 1.0,
|
||||
"cholesterol_mg": 0.0,
|
||||
"ingredients": null,
|
||||
"is_verified": true,
|
||||
"created_at": "2025-10-16T23:10:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Получение информации о продукте
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/food/{food_id}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"fatsecret_id": "35718",
|
||||
"name": "Apple",
|
||||
"brand": null,
|
||||
"description": "A common fruit",
|
||||
"food_type": "Generic",
|
||||
"serving_size": "100g",
|
||||
"serving_weight_grams": 100.0,
|
||||
"calories": 52.0,
|
||||
"protein_grams": 0.26,
|
||||
"fat_grams": 0.17,
|
||||
"carbs_grams": 13.81,
|
||||
"fiber_grams": 2.4,
|
||||
"sugar_grams": 10.39,
|
||||
"sodium_mg": 1.0,
|
||||
"cholesterol_mg": 0.0,
|
||||
"ingredients": null,
|
||||
"is_verified": true,
|
||||
"created_at": "2025-10-16T23:10:00"
|
||||
}
|
||||
```
|
||||
|
||||
### Дневник питания
|
||||
|
||||
#### Добавление записи в дневник питания
|
||||
|
||||
```http
|
||||
POST /api/v1/nutrition/diary
|
||||
```
|
||||
|
||||
Параметры запроса:
|
||||
```json
|
||||
{
|
||||
"food_item_id": 1,
|
||||
"entry_date": "2025-10-16",
|
||||
"meal_type": "breakfast",
|
||||
"quantity": 1.5,
|
||||
"unit": "piece",
|
||||
"notes": "Morning apple"
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"meal_type": "breakfast",
|
||||
"food_item_id": 1,
|
||||
"custom_food_name": null,
|
||||
"quantity": 1.5,
|
||||
"unit": "piece",
|
||||
"calories": 78.0,
|
||||
"protein_grams": 0.39,
|
||||
"fat_grams": 0.255,
|
||||
"carbs_grams": 20.715,
|
||||
"notes": "Morning apple",
|
||||
"created_at": "2025-10-16T23:15:00"
|
||||
}
|
||||
```
|
||||
|
||||
#### Получение записей дневника за день
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/diary?date=2025-10-16
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"meal_type": "breakfast",
|
||||
"food_item_id": 1,
|
||||
"custom_food_name": null,
|
||||
"quantity": 1.5,
|
||||
"unit": "piece",
|
||||
"calories": 78.0,
|
||||
"protein_grams": 0.39,
|
||||
"fat_grams": 0.255,
|
||||
"carbs_grams": 20.715,
|
||||
"notes": "Morning apple",
|
||||
"created_at": "2025-10-16T23:15:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Получение сводки за день
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/summary?date=2025-10-16
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"date": "2025-10-16",
|
||||
"total_calories": 2150.5,
|
||||
"total_protein": 85.2,
|
||||
"total_fat": 65.4,
|
||||
"total_carbs": 275.3,
|
||||
"water_consumed_ml": 1500,
|
||||
"activity_minutes": 45,
|
||||
"calories_burned": 350,
|
||||
"entries_by_meal": {
|
||||
"breakfast": [
|
||||
{
|
||||
"id": 1,
|
||||
"food_name": "Apple",
|
||||
"quantity": 1.5,
|
||||
"unit": "piece",
|
||||
"calories": 78.0
|
||||
}
|
||||
],
|
||||
"lunch": [...],
|
||||
"dinner": [...],
|
||||
"snack": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Потребление воды
|
||||
|
||||
#### Добавление записи о потреблении воды
|
||||
|
||||
```http
|
||||
POST /api/v1/nutrition/water
|
||||
```
|
||||
|
||||
Параметры запроса:
|
||||
```json
|
||||
{
|
||||
"amount_ml": 250,
|
||||
"entry_date": "2025-10-16",
|
||||
"notes": "Morning glass"
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"amount_ml": 250,
|
||||
"entry_time": "2025-10-16T08:30:00",
|
||||
"notes": "Morning glass"
|
||||
}
|
||||
```
|
||||
|
||||
#### Получение записей о потреблении воды за день
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/water?date=2025-10-16
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"amount_ml": 250,
|
||||
"entry_time": "2025-10-16T08:30:00",
|
||||
"notes": "Morning glass"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"uuid": "223e4567-e89b-12d3-a456-426614174001",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"amount_ml": 500,
|
||||
"entry_time": "2025-10-16T12:15:00",
|
||||
"notes": "Lunch"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Физическая активность
|
||||
|
||||
#### Добавление записи о физической активности
|
||||
|
||||
```http
|
||||
POST /api/v1/nutrition/activity
|
||||
```
|
||||
|
||||
Параметры запроса:
|
||||
```json
|
||||
{
|
||||
"entry_date": "2025-10-16",
|
||||
"activity_type": "running",
|
||||
"duration_minutes": 30,
|
||||
"distance_km": 5.2,
|
||||
"intensity": "medium",
|
||||
"notes": "Morning run"
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"activity_type": "running",
|
||||
"duration_minutes": 30,
|
||||
"calories_burned": 300.5,
|
||||
"distance_km": 5.2,
|
||||
"steps": null,
|
||||
"intensity": "medium",
|
||||
"notes": "Morning run",
|
||||
"created_at": "2025-10-16T09:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
#### Получение записей об активности за день
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/activity?date=2025-10-16
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"user_id": 42,
|
||||
"entry_date": "2025-10-16",
|
||||
"activity_type": "running",
|
||||
"duration_minutes": 30,
|
||||
"calories_burned": 300.5,
|
||||
"distance_km": 5.2,
|
||||
"steps": null,
|
||||
"intensity": "medium",
|
||||
"notes": "Morning run",
|
||||
"created_at": "2025-10-16T09:00:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Цели по питанию и активности
|
||||
|
||||
#### Установка целей
|
||||
|
||||
```http
|
||||
POST /api/v1/nutrition/goals
|
||||
```
|
||||
|
||||
Параметры запроса:
|
||||
```json
|
||||
{
|
||||
"daily_calorie_goal": 2000,
|
||||
"protein_goal_grams": 100,
|
||||
"fat_goal_grams": 65,
|
||||
"carbs_goal_grams": 250,
|
||||
"water_goal_ml": 2500,
|
||||
"activity_goal_minutes": 45,
|
||||
"weight_goal_kg": 75.5,
|
||||
"goal_type": "lose_weight"
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 42,
|
||||
"daily_calorie_goal": 2000,
|
||||
"protein_goal_grams": 100,
|
||||
"fat_goal_grams": 65,
|
||||
"carbs_goal_grams": 250,
|
||||
"water_goal_ml": 2500,
|
||||
"activity_goal_minutes": 45,
|
||||
"weight_goal_kg": 75.5,
|
||||
"goal_type": "lose_weight",
|
||||
"created_at": "2025-10-16T10:00:00",
|
||||
"updated_at": "2025-10-16T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
#### Получение текущих целей
|
||||
|
||||
```http
|
||||
GET /api/v1/nutrition/goals
|
||||
```
|
||||
|
||||
Ответ:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 42,
|
||||
"daily_calorie_goal": 2000,
|
||||
"protein_goal_grams": 100,
|
||||
"fat_goal_grams": 65,
|
||||
"carbs_goal_grams": 250,
|
||||
"water_goal_ml": 2500,
|
||||
"activity_goal_minutes": 45,
|
||||
"weight_goal_kg": 75.5,
|
||||
"goal_type": "lose_weight",
|
||||
"created_at": "2025-10-16T10:00:00",
|
||||
"updated_at": "2025-10-16T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
## Коды ошибок
|
||||
|
||||
| Код | Описание |
|
||||
|-----|----------|
|
||||
| 400 | Некорректный запрос |
|
||||
| 401 | Не авторизован |
|
||||
| 403 | Доступ запрещен |
|
||||
| 404 | Ресурс не найден |
|
||||
| 500 | Внутренняя ошибка сервера |
|
||||
|
||||
## Аутентификация
|
||||
|
||||
Все запросы к API требуют JWT-токен в заголовке Authorization:
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
Токен можно получить через сервис авторизации (User Service) по эндпоинту `/api/v1/auth/login`.
|
||||
|
||||
## Интеграции
|
||||
|
||||
Сервис питания интегрирован с API FatSecret для получения данных о продуктах питания и их пищевой ценности. Работа с API FatSecret осуществляется через OAuth 1.0 аутентификацию с использованием ключей, указанных в конфигурации приложения.
|
||||
|
||||
## Тестирование API
|
||||
|
||||
### Тестирование через Swagger UI
|
||||
|
||||
Самый простой способ протестировать API - использовать встроенный интерфейс Swagger UI:
|
||||
|
||||
1. Убедитесь, что сервис питания запущен:
|
||||
```bash
|
||||
# Запуск всех сервисов
|
||||
./start_services.sh
|
||||
```
|
||||
|
||||
2. Откройте в браузере URL: `http://localhost:8006/docs`
|
||||
|
||||
3. Авторизуйтесь:
|
||||
- Нажмите на кнопку "Authorize" в правом верхнем углу
|
||||
- Введите ваш JWT токен в формате `Bearer <token>`
|
||||
- Нажмите "Authorize"
|
||||
|
||||
4. Теперь вы можете интерактивно тестировать все эндпоинты:
|
||||
- Выберите нужный эндпоинт
|
||||
- Заполните параметры запроса
|
||||
- Нажмите "Execute"
|
||||
- Просмотрите результат запроса и код ответа
|
||||
|
||||
### Настройка и запуск через CLI
|
||||
|
||||
1. Убедитесь, что все необходимые сервисы запущены:
|
||||
```bash
|
||||
# Запуск всех сервисов
|
||||
./start_services.sh
|
||||
```
|
||||
|
||||
2. Получите токен аутентификации:
|
||||
```bash
|
||||
# Регистрация нового пользователя
|
||||
curl -X POST http://localhost:8001/api/v1/auth/register -H "Content-Type: application/json" -d '{
|
||||
"email": "test_user@example.com",
|
||||
"username": "test_user",
|
||||
"password": "Test123!",
|
||||
"first_name": "Test",
|
||||
"last_name": "User",
|
||||
"phone": "+79991234567"
|
||||
}' | jq
|
||||
|
||||
# Вход и получение токена
|
||||
curl -X POST http://localhost:8001/api/v1/auth/login -H "Content-Type: application/json" -d '{
|
||||
"username": "test_user",
|
||||
"password": "Test123!"
|
||||
}' | jq
|
||||
```
|
||||
|
||||
3. Сохраните полученный токен в переменную для дальнейшего использования:
|
||||
```bash
|
||||
export TOKEN="ваш_полученный_jwt_токен"
|
||||
```
|
||||
|
||||
### Примеры запросов
|
||||
|
||||
#### Поиск продуктов
|
||||
|
||||
```bash
|
||||
# Поиск продуктов по названию
|
||||
curl -X POST http://localhost:8006/api/v1/nutrition/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{
|
||||
"query": "apple",
|
||||
"max_results": 5
|
||||
}' | jq
|
||||
```
|
||||
|
||||
#### Работа с дневником питания
|
||||
|
||||
```bash
|
||||
# Добавление записи в дневник питания
|
||||
curl -X POST http://localhost:8006/api/v1/nutrition/diary \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{
|
||||
"food_item_id": 1,
|
||||
"entry_date": "2025-10-16",
|
||||
"meal_type": "breakfast",
|
||||
"quantity": 1.5,
|
||||
"unit": "piece",
|
||||
"notes": "Morning apple"
|
||||
}' | jq
|
||||
|
||||
# Получение дневника за день
|
||||
curl -X GET http://localhost:8006/api/v1/nutrition/diary?date=2025-10-16 \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
#### Работа с водой
|
||||
|
||||
```bash
|
||||
# Добавление записи о потреблении воды
|
||||
curl -X POST http://localhost:8006/api/v1/nutrition/water \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{
|
||||
"amount_ml": 250,
|
||||
"entry_date": "2025-10-16",
|
||||
"notes": "Morning glass"
|
||||
}' | jq
|
||||
|
||||
# Получение записей о потреблении воды за день
|
||||
curl -X GET http://localhost:8006/api/v1/nutrition/water?date=2025-10-16 \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
#### Работа с активностью
|
||||
|
||||
```bash
|
||||
# Добавление записи о физической активности
|
||||
curl -X POST http://localhost:8006/api/v1/nutrition/activity \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{
|
||||
"entry_date": "2025-10-16",
|
||||
"activity_type": "running",
|
||||
"duration_minutes": 30,
|
||||
"distance_km": 5.2,
|
||||
"intensity": "medium",
|
||||
"notes": "Morning run"
|
||||
}' | jq
|
||||
|
||||
# Получение записей об активности за день
|
||||
curl -X GET http://localhost:8006/api/v1/nutrition/activity?date=2025-10-16 \
|
||||
-H "Authorization: Bearer $TOKEN" | jq
|
||||
```
|
||||
|
||||
### Автоматизированное тестирование
|
||||
|
||||
В папке `tests` есть скрипты для автоматизированного тестирования API:
|
||||
|
||||
```bash
|
||||
# Запуск всех тестов для nutrition service
|
||||
cd tests
|
||||
./test_nutrition_service.sh
|
||||
|
||||
# Запуск тестов через Python
|
||||
python test_nutrition_api.py
|
||||
```
|
||||
|
||||
Для непосредственного тестирования FatSecret API можно использовать скрипт в корне проекта:
|
||||
|
||||
```bash
|
||||
# Тестирование FatSecret API
|
||||
python test_fatsecret_api_oauth1.py
|
||||
```
|
||||
Reference in New Issue
Block a user