b98d1f65d3
modified: main_dc/yalarba/api_yal/documentation/README.md date last commit that set base URL into easysite102.ru doc
1347 lines
28 KiB
Markdown
1347 lines
28 KiB
Markdown
# Документация API 1.0.2 last modifay 07/06/2026
|
|
|
|
## Базовый URL
|
|
```
|
|
https://easysite102.ru/api_yal/api/v1
|
|
```
|
|
|
|
## Аутентификация
|
|
|
|
Для доступа к защищенным эндпоинтам требуется JWT токен. Токен передается в заголовке:
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
Refresh token хранится в **HttpOnly cookie**.
|
|
|
|
---
|
|
|
|
## 1. Аутентификация (Auth)
|
|
|
|
### 1.1 Регистрация пользователя
|
|
**POST** `/auth/register`
|
|
|
|
Создает новый аккаунт пользователя.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов"
|
|
}
|
|
```
|
|
|
|
| Поле | Тип | Обязательное | Описание |
|
|
|------|-----|--------------|----------|
|
|
| email | string | ✅ | Email пользователя |
|
|
| password | string | ✅ | Пароль, минимум 6 символов |
|
|
| first_name | string | ✅ | Имя |
|
|
| last_name | string | ✅ | Фамилия |
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"token": "jwt_token_string",
|
|
"expires_at": "2024-01-01T00:00:00Z",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"full_name": "Иван Иванов",
|
|
"role": "user"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 1.2 Вход в систему
|
|
**POST** `/auth/login`
|
|
|
|
Аутентификация пользователя.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"token": "jwt_token_string",
|
|
"expires_at": "2024-01-01T00:00:00Z",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"full_name": "Иван Иванов",
|
|
"role": "user"
|
|
}
|
|
}
|
|
```
|
|
*Refresh token устанавливается в HttpOnly cookie.*
|
|
|
|
---
|
|
|
|
### 1.3 Обновление токена
|
|
**POST** `/auth/refresh`
|
|
|
|
Обновляет access token с использованием refresh token.
|
|
|
|
**Cookie Required:** `refresh_token`
|
|
|
|
**Request Body (опционально, для мобильных приложений):**
|
|
```json
|
|
{
|
|
"refresh_token": "refresh_token_string"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"token": "new_jwt_token_string",
|
|
"expires_at": "2024-01-01T00:00:00Z",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"full_name": "Иван Иванов",
|
|
"role": "user"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 1.4 Выход из системы
|
|
**POST** `/auth/logout`
|
|
|
|
Завершает сессию пользователя.
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Successfully logged out"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 1.5 Запрос сброса пароля
|
|
**POST** `/auth/password-reset/request`
|
|
|
|
Отправляет ссылку для сброса пароля (в тестовом режиме возвращает токен).
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Password reset link has been sent to your email",
|
|
"token": "reset_token" // только в тестовом режиме
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 1.6 Подтверждение сброса пароля
|
|
**POST** `/auth/password-reset/confirm`
|
|
|
|
Устанавливает новый пароль.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"token": "reset_token",
|
|
"new_password": "new_password123"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Password has been successfully reset"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 1.7 Вход для мобильных приложений
|
|
**POST** `/auth/mobile/login`
|
|
|
|
Альтернативный эндпоинт для мобильных клиентов.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"access_token": "jwt_token",
|
|
"refresh_token": "refresh_token_string",
|
|
"expires_at": "2024-01-01T00:00:00Z",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"full_name": "Иван Иванов",
|
|
"role": "user"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Аккаунт (Account)
|
|
|
|
### 2.1 Получение профиля пользователя
|
|
**GET** `/account/profile`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-01-01T00:00:00Z",
|
|
"email": "user@example.com",
|
|
"full_name": "Иван Иванов",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"phone": "+79991234567",
|
|
"city": "Москва",
|
|
"organization_form": "ООО",
|
|
"organization_name": "Организация",
|
|
"organization_short": "ООО Орг",
|
|
"inn": "1234567890",
|
|
"personal_inn": "",
|
|
"is_active": true,
|
|
"is_verified": false,
|
|
"role": "user",
|
|
"stats": {
|
|
"objects_count": 5,
|
|
"feedbacks_count": 12,
|
|
"comments_count": 34,
|
|
"ratings_count": 8,
|
|
"appeals_count": 3
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.2 Получение аккаунта по ID (свой профиль)
|
|
**GET** `/account`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-01-01T00:00:00Z",
|
|
"email": "user@example.com",
|
|
"full_name": "Иван Иванов",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"phone": "+79991234567",
|
|
"city": "Москва",
|
|
"is_active": true,
|
|
"is_verified": false,
|
|
"role": "user"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.3 Обновление аккаунта
|
|
**PUT** `/account`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"full_name": "Иван Петрович Иванов",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов",
|
|
"phone": "+79991234567",
|
|
"city": "Санкт-Петербург",
|
|
"organization_form": "ИП",
|
|
"organization_name": "ИП Иванов",
|
|
"organization_short": "ИП Иванов",
|
|
"inn": "123456789012",
|
|
"personal_inn": "123456789012"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** (тот же формат, что и `AccountResponse`)
|
|
|
|
---
|
|
|
|
### 2.4 Смена пароля
|
|
**POST** `/account/change-password`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"current_password": "old_password",
|
|
"new_password": "new_password123"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Password changed successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.5 Удаление аккаунта
|
|
**DELETE** `/account`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Account deleted successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.6 Список аккаунтов (админ/модератор)
|
|
**GET** `/admin/accounts`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 20, max: 100) |
|
|
| search | string | Поиск по email и имени |
|
|
| role | string | Фильтр по роли (user/admin/moderator) |
|
|
| is_active | bool | Фильтр по статусу активности |
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"items": [...],
|
|
"total": 100,
|
|
"page": 1,
|
|
"page_size": 20,
|
|
"total_pages": 5
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.7 Верификация аккаунта (админ)
|
|
**PUT** `/admin/accounts/verify`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| id | uint | ✅ ID аккаунта |
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"is_verified": true
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Account verified successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2.8 Обновление статуса аккаунта (админ)
|
|
**PUT** `/admin/accounts/status`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| id | uint | ✅ ID аккаунта |
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"is_active": true,
|
|
"role": "moderator"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Account status updated successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Объекты (Objects)
|
|
|
|
### 3.1 Создание объекта
|
|
**POST** `/objects`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"short_name": "Кафе Уют",
|
|
"long_name": "Кафе Уют на Невском",
|
|
"type": "cafe",
|
|
"phone": "+78121234567",
|
|
"email": "cafe@example.com",
|
|
"site": "https://cafe.example.com",
|
|
"short_description": "Уютное кафе в центре",
|
|
"description": "Подробное описание кафе",
|
|
"address": "г. Санкт-Петербург, Невский пр., 1",
|
|
"latitude": 59.9343,
|
|
"longitude": 30.3351,
|
|
"is_active": true,
|
|
"is_verified": false
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):** `ObjectResponse`
|
|
|
|
---
|
|
|
|
### 3.2 Получение объекта по ID
|
|
**GET** `/objects/{id}`
|
|
|
|
**Response (200 OK):** `ObjectResponse`
|
|
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"created_at": "2024-01-01T00:00:00Z",
|
|
"updated_at": "2024-01-01T00:00:00Z",
|
|
"deleted_at": null,
|
|
"owner_id": 1,
|
|
"owner": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"full_name": "Иван Иванов",
|
|
"first_name": "Иван",
|
|
"last_name": "Иванов"
|
|
},
|
|
"short_name": "Кафе Уют",
|
|
"long_name": "Кафе Уют на Невском",
|
|
"type": "cafe",
|
|
"phone": "+78121234567",
|
|
"email": "cafe@example.com",
|
|
"site": "https://cafe.example.com",
|
|
"short_description": "Уютное кафе в центре",
|
|
"description": "Подробное описание кафе",
|
|
"address": "г. Санкт-Петербург, Невский пр., 1",
|
|
"latitude": 59.9343,
|
|
"longitude": 30.3351,
|
|
"is_active": true,
|
|
"is_verified": false,
|
|
"feedback_count": 15,
|
|
"tourist_rating": {
|
|
"id": 1,
|
|
"created_at": "...",
|
|
"platform": "tourist",
|
|
"average_score": 4.5,
|
|
"total_votes": 10,
|
|
"vote_breakdown": {...}
|
|
},
|
|
"entrepreneur_rating": {...},
|
|
"feedbacks": [...]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3.3 Обновление объекта
|
|
**PUT** `/objects/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:** (все поля опциональны)
|
|
```json
|
|
{
|
|
"short_name": "Кафе Уютное",
|
|
"description": "Обновленное описание",
|
|
"is_active": false
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `ObjectResponse`
|
|
|
|
---
|
|
|
|
### 3.4 Удаление объекта
|
|
**DELETE** `/objects/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (204 No Content)**
|
|
|
|
---
|
|
|
|
### 3.5 Список объектов (с фильтрацией)
|
|
**GET** `/objects`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 10) |
|
|
| type | string | Фильтр по типу объекта |
|
|
| q | string | Поиск по названию |
|
|
| is_active | bool | Фильтр по активности |
|
|
|
|
**Response (200 OK):** `ObjectListResponse`
|
|
|
|
---
|
|
|
|
### 3.6 Объекты пользователя
|
|
**GET** `/objects/owner/{ownerId}`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 10) |
|
|
|
|
**Response (200 OK):** `ObjectListResponse`
|
|
|
|
---
|
|
|
|
### 3.7 Поиск объектов
|
|
**GET** `/objects/search`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Обязательное | Описание |
|
|
|----------|-----|--------------|----------|
|
|
| q | string | ✅ | Поисковый запрос |
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 10) |
|
|
|
|
**Response (200 OK):** `ObjectListResponse`
|
|
|
|
---
|
|
|
|
### 3.8 Ближайшие объекты
|
|
**GET** `/objects/nearby`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Обязательное | Описание |
|
|
|----------|-----|--------------|----------|
|
|
| lat | float | ✅ | Широта |
|
|
| lng | float | ✅ | Долгота |
|
|
| radius | float | Радиус в метрах (default: 1000) |
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 10) |
|
|
|
|
**Response (200 OK):** `ObjectListResponse`
|
|
|
|
---
|
|
|
|
### 3.9 Создание отзыва об объекте
|
|
**POST** `/objects/{id}/feedbacks`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"platform": "tourist",
|
|
"score": 5,
|
|
"text": "Отличное место!"
|
|
}
|
|
```
|
|
|
|
| Поле | Тип | Обязательное | Описание |
|
|
|------|-----|--------------|----------|
|
|
| platform | string | ✅ | `entrepreneur` или `tourist` |
|
|
| score | int | ✅ | Оценка от 1 до 5 |
|
|
| text | string | ✅ | Текст отзыва |
|
|
|
|
**Response (201 Created):** `FeedbackResponse`
|
|
|
|
---
|
|
|
|
### 3.10 Голосование за объект
|
|
**POST** `/objects/{id}/ratings`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"platform": "tourist",
|
|
"score": 5
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):** `RatingVoteResponse`
|
|
|
|
---
|
|
|
|
## 4. Отзывы (Feedbacks)
|
|
|
|
### 4.1 Создание отзыва
|
|
**POST** `/feedbacks`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"object_id": 1,
|
|
"rating": 5,
|
|
"text": "Отличное место!",
|
|
"platform": "tourist",
|
|
"media_urls": ["https://example.com/photo1.jpg"]
|
|
}
|
|
```
|
|
|
|
| Поле | Тип | Обязательное | Описание |
|
|
|------|-----|--------------|----------|
|
|
| object_id | uint | ✅ | ID объекта |
|
|
| rating | int | ✅ | Оценка от 1 до 5 |
|
|
| text | string | ✅ | Текст отзыва, мин 1, макс 2000 символов |
|
|
| platform | string | ✅ | `entrepreneur` или `tourist` |
|
|
| media_urls | []string | Список URL медиафайлов |
|
|
|
|
**Response (201 Created):** `FeedbackResponse`
|
|
|
|
---
|
|
|
|
### 4.2 Получение отзыва по ID
|
|
**GET** `/feedbacks/{id}`
|
|
|
|
**Response (200 OK):** `FeedbackResponse`
|
|
|
|
---
|
|
|
|
### 4.3 Обновление отзыва
|
|
**PUT** `/feedbacks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:** (все поля опциональны)
|
|
```json
|
|
{
|
|
"rating": 4,
|
|
"text": "Обновленный текст отзыва"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `FeedbackResponse`
|
|
|
|
---
|
|
|
|
### 4.4 Удаление отзыва
|
|
**DELETE** `/feedbacks/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (204 No Content)**
|
|
|
|
---
|
|
|
|
### 4.5 Список отзывов
|
|
**GET** `/feedbacks`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| offset | int | Смещение (default: 0) |
|
|
| limit | int | Лимит (default: 20, max: 100) |
|
|
|
|
**Response (200 OK):** `FeedbackListResponse`
|
|
|
|
---
|
|
|
|
### 4.6 Мои отзывы
|
|
**GET** `/feedbacks/my`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):** `FeedbackListResponse`
|
|
|
|
---
|
|
|
|
### 4.7 Отзывы по объекту
|
|
**GET** `/feedbacks/object/{objectID}`
|
|
|
|
**Response (200 OK):** `FeedbackListResponse`
|
|
|
|
---
|
|
|
|
### 4.8 Отзывы по платформе
|
|
**GET** `/feedbacks/platform/{platform}`
|
|
|
|
| Параметр | Описание |
|
|
|----------|----------|
|
|
| platform | `entrepreneur` или `tourist` |
|
|
|
|
**Response (200 OK):** `FeedbackListResponse`
|
|
|
|
---
|
|
|
|
### 4.9 Поиск отзывов
|
|
**GET** `/feedbacks/search`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Обязательное | Описание |
|
|
|----------|-----|--------------|----------|
|
|
| q | string | ✅ | Поисковый запрос |
|
|
|
|
**Response (200 OK):** `FeedbackListResponse`
|
|
|
|
---
|
|
|
|
### 4.10 Статистика отзывов
|
|
**GET** `/feedbacks/stats`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"total_feedbacks": 1000,
|
|
"average_rating": 4.2,
|
|
"rating_distribution": {
|
|
"1": 50,
|
|
"2": 100,
|
|
"3": 200,
|
|
"4": 300,
|
|
"5": 350
|
|
},
|
|
"platform_stats": {
|
|
"tourist": 600,
|
|
"entrepreneur": 400
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4.11 Комментарии к отзыву
|
|
**GET** `/feedbacks/{id}/comments`
|
|
|
|
**Response (200 OK):** `CommentListResponse`
|
|
|
|
---
|
|
|
|
### 4.12 Добавление комментария к отзыву
|
|
**POST** `/feedbacks/{id}/comments`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"text": "Отличный отзыв, согласен!"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):** `CommentResponse`
|
|
|
|
---
|
|
|
|
### 4.13 Обновление комментария
|
|
**PUT** `/feedbacks/{id}/comments/{commentID}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"text": "Обновленный текст комментария"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "comment updated successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4.14 Удаление комментария
|
|
**DELETE** `/feedbacks/{id}/comments/{commentID}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (204 No Content)**
|
|
|
|
---
|
|
|
|
## 5. Обращения (Appeals)
|
|
|
|
### 5.1 Создание обращения
|
|
**POST** `/appeals`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (опционально для анонимных)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"type": "complaint",
|
|
"title": "Проблема с заказом",
|
|
"message": "Подробное описание проблемы",
|
|
"priority": "high",
|
|
"object_id": 1,
|
|
"feedback_id": 1,
|
|
"comment_id": 1,
|
|
"contact_name": "Иван Иванов",
|
|
"contact_email": "ivan@example.com",
|
|
"contact_phone": "+79991234567",
|
|
"attachments": ["url1", "url2"],
|
|
"category": "technical",
|
|
"labels": ["bug", "urgent"],
|
|
"custom_data": {
|
|
"order_id": 12345
|
|
}
|
|
}
|
|
```
|
|
|
|
| Поле | Тип | Обязательное | Описание |
|
|
|------|-----|--------------|----------|
|
|
| type | string | ✅ | `complaint`, `suggestion`, `wish`, `question`, `other` |
|
|
| title | string | ✅ | Заголовок, 3-255 символов |
|
|
| message | string | ✅ | Сообщение, минимум 10 символов |
|
|
| priority | string | `low`, `medium`, `high`, `critical` |
|
|
| contact_email | string | Должен быть валидным email, если указан |
|
|
|
|
**Response (201 Created):** `AppealResponse`
|
|
|
|
---
|
|
|
|
### 5.2 Получение обращения по ID
|
|
**GET** `/appeals/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуется для просмотра чужих обращений)
|
|
|
|
**Response (200 OK):** `AppealResponse`
|
|
|
|
---
|
|
|
|
### 5.3 Обновление обращения
|
|
**PUT** `/appeals/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"title": "Обновленный заголовок",
|
|
"message": "Обновленное сообщение",
|
|
"priority": "critical",
|
|
"category": "billing"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `AppealResponse`
|
|
|
|
---
|
|
|
|
### 5.4 Удаление обращения
|
|
**DELETE** `/appeals/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (204 No Content)**
|
|
|
|
---
|
|
|
|
### 5.5 Список обращений (админ/модератор)
|
|
**GET** `/appeals`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin/moderator)
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| offset | int | Смещение (default: 0) |
|
|
| limit | int | Лимит (default: 20, max: 100) |
|
|
| status | string | `new`, `in_progress`, `resolved`, `rejected`, `closed` |
|
|
| type | string | `complaint`, `suggestion`, `wish`, `question`, `other` |
|
|
| priority | string | `low`, `medium`, `high`, `critical` |
|
|
| search | string | Поиск по заголовку/сообщению |
|
|
|
|
**Response (200 OK):** `ListAppealsResponse`
|
|
|
|
---
|
|
|
|
### 5.6 Мои обращения
|
|
**GET** `/appeals/me`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):** `ListAppealsResponse`
|
|
|
|
---
|
|
|
|
### 5.7 Обращения пользователя (админ)
|
|
**GET** `/appeals/user/{userID}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Response (200 OK):** `ListAppealsResponse`
|
|
|
|
---
|
|
|
|
### 5.8 Обновление статуса обращения
|
|
**PATCH** `/appeals/{id}/status`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin/moderator)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"status": "in_progress",
|
|
"comment": "Начата обработка обращения"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Status updated successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5.9 Назначение ответственного
|
|
**POST** `/appeals/{id}/assign`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin/moderator)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"assigned_to_id": 5
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Assigned successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5.10 Решение обращения
|
|
**POST** `/appeals/{id}/resolve`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin/moderator)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"resolution": "Проблема решена путем обновления настроек"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Appeal resolved successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5.11 История изменений обращения
|
|
**GET** `/appeals/{id}/history`
|
|
|
|
**Response (200 OK):** `ListHistoryResponse`
|
|
|
|
---
|
|
|
|
### 5.12 Статистика обращений (админ)
|
|
**GET** `/appeals/statistics`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"total": 1000,
|
|
"by_status": {
|
|
"new": 50,
|
|
"in_progress": 100,
|
|
"resolved": 800,
|
|
"rejected": 30,
|
|
"closed": 20
|
|
},
|
|
"by_type": {
|
|
"complaint": 400,
|
|
"suggestion": 200,
|
|
"wish": 150,
|
|
"question": 200,
|
|
"other": 50
|
|
},
|
|
"by_priority": {
|
|
"low": 200,
|
|
"medium": 500,
|
|
"high": 250,
|
|
"critical": 50
|
|
},
|
|
"by_category": {...},
|
|
"avg_resolve_time_hours": 24.5
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Комментарии (Comments)
|
|
|
|
### 6.1 Создание комментария
|
|
**POST** `/comments`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"feedback_id": 1,
|
|
"text": "Отличный отзыв!",
|
|
"parent_id": null
|
|
}
|
|
```
|
|
|
|
| Поле | Тип | Обязательное | Описание |
|
|
|------|-----|--------------|----------|
|
|
| feedback_id | uint | ✅ | ID отзыва |
|
|
| text | string | ✅ | Текст комментария, 1-5000 символов |
|
|
| parent_id | uint | ID родительского комментария |
|
|
|
|
**Response (201 Created):** `CommentResponse`
|
|
|
|
---
|
|
|
|
### 6.2 Получение комментария по ID
|
|
**GET** `/comments/{id}`
|
|
|
|
**Response (200 OK):** `CommentResponse`
|
|
|
|
---
|
|
|
|
### 6.3 Обновление комментария
|
|
**PUT** `/comments/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"text": "Обновленный текст"
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `CommentResponse`
|
|
|
|
---
|
|
|
|
### 6.4 Удаление комментария
|
|
**DELETE** `/comments/{id}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Comment deleted successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 6.5 Список комментариев (с фильтрацией)
|
|
**GET** `/comments`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 20, max: 100) |
|
|
| feedback_id | uint | Фильтр по отзыву |
|
|
| author_id | uint | Фильтр по автору |
|
|
| parent_id | uint | Фильтр по родительскому комментарию |
|
|
| verified | bool | Фильтр по верификации |
|
|
| sort_by | string | Поле сортировки (default: created_at) |
|
|
| sort_order | string | `asc` или `desc` (default: desc) |
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"data": [...],
|
|
"total": 100,
|
|
"page": 1,
|
|
"page_size": 20,
|
|
"total_pages": 5
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 6.6 Мои комментарии
|
|
**GET** `/comments/my`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):** (тот же формат, что и список)
|
|
|
|
---
|
|
|
|
### 6.7 Комментарии по отзыву
|
|
**GET** `/comments/feedback/{feedbackID}`
|
|
|
|
**Response (200 OK):** (тот же формат, что и список)
|
|
|
|
---
|
|
|
|
### 6.8 Ответы на комментарий
|
|
**GET** `/comments/replies/{parentID}`
|
|
|
|
**Response (200 OK):** (тот же формат, что и список)
|
|
|
|
---
|
|
|
|
### 6.9 Верификация комментария (админ)
|
|
**PUT** `/comments/{id}/verify`
|
|
|
|
**Headers:** `Authorization: Bearer <token>` (требуются права admin)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"verified": true
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"message": "Comment verified successfully"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 6.10 Статистика комментариев
|
|
**GET** `/comments/stats`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"total_comments": 5000,
|
|
"verified_comments": 3000,
|
|
"unverified_comments": 2000,
|
|
"avg_comments_per_feedback": 5.2,
|
|
"most_active_users": [...]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Рейтинги (Ratings)
|
|
|
|
### 7.1 Создание рейтинга
|
|
**POST** `/ratings`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"object_id": 1,
|
|
"platform": "tourist"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):** `RatingResponse`
|
|
|
|
---
|
|
|
|
### 7.2 Получение рейтинга по ID
|
|
**GET** `/ratings/{id}`
|
|
|
|
**Response (200 OK):** `RatingResponse`
|
|
|
|
---
|
|
|
|
### 7.3 Получение рейтинга объекта по платформе
|
|
**GET** `/ratings/object/{objectID}/platform/{platform}`
|
|
|
|
| Параметр | Описание |
|
|
|----------|----------|
|
|
| platform | `entrepreneur` или `tourist` |
|
|
|
|
**Response (200 OK):** `RatingResponse`
|
|
|
|
---
|
|
|
|
### 7.4 Список рейтингов
|
|
**GET** `/ratings`
|
|
|
|
**Query Parameters:**
|
|
| Параметр | Тип | Описание |
|
|
|----------|-----|----------|
|
|
| page | int | Номер страницы (default: 1) |
|
|
| page_size | int | Размер страницы (default: 20) |
|
|
| platform | string | `entrepreneur` или `tourist` |
|
|
| owner_id | uint | Фильтр по владельцу |
|
|
| object_id | uint | Фильтр по объекту |
|
|
|
|
**Response (200 OK):** `ListRatingsResponse`
|
|
|
|
---
|
|
|
|
### 7.5 Голосование
|
|
**POST** `/ratings/{targetID}/vote/{platform}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"score": 5
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `RatingResponse`
|
|
|
|
---
|
|
|
|
### 7.6 Мой голос
|
|
**GET** `/ratings/{targetID}/my-vote/{platform}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"has_voted": true,
|
|
"user_score": 5
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 7.7 Обновление моего голоса
|
|
**PUT** `/ratings/{targetID}/my-vote/{platform}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"score": 4
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):** `RatingResponse`
|
|
|
|
---
|
|
|
|
### 7.8 Удаление моего голоса
|
|
**DELETE** `/ratings/{targetID}/my-vote/{platform}`
|
|
|
|
**Headers:** `Authorization: Bearer <token>`
|
|
|
|
**Response (204 No Content)**
|
|
|
|
---
|
|
|
|
### 7.9 Статистика рейтингов
|
|
**GET** `/ratings/stats`
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"total_ratings": 500,
|
|
"total_votes": 5000,
|
|
"platform_distribution": {...},
|
|
"average_by_platform": {...}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Коды ошибок
|
|
|
|
| Код | Описание |
|
|
|-----|----------|
|
|
| 200 | Успешный запрос |
|
|
| 201 | Успешное создание ресурса |
|
|
| 204 | Успешное удаление (нет содержимого) |
|
|
| 400 | Ошибка валидации или неверный запрос |
|
|
| 401 | Не авторизован |
|
|
| 403 | Доступ запрещен |
|
|
| 404 | Ресурс не найден |
|
|
| 409 | Конфликт (например, пользователь уже существует) |
|
|
| 500 | Внутренняя ошибка сервера |
|
|
|
|
**Формат ошибки:**
|
|
```json
|
|
{
|
|
"error": "Описание ошибки"
|
|
}
|
|
```
|
|
|
|
Для валидационных ошибок:
|
|
```json
|
|
{
|
|
"error": "Validation failed",
|
|
"fields": [
|
|
"field email is invalid: required",
|
|
"field password is invalid: min"
|
|
]
|
|
}
|
|
``` |