docs: add comprehensive Russian README
This commit is contained in:
@@ -1,350 +1,138 @@
|
|||||||
# Nashel Backend
|
# 🔮 Nashel — Backend API
|
||||||
|
|
||||||
Бэкенд для маркетплейса услуг "Nashel" — платформа для поиска мастеров и исполнителей.
|
> **ASP.NET Core · Modular Monolith · PostgreSQL · Docker**
|
||||||
|
|
||||||
## 🏗️ Архитектура
|
Серверная часть платформы **Nashel** — маркетплейса для поиска и найма профессиональных исполнителей (мастеров, специалистов и компаний). Бэкенд построен по принципу **Модульного Монолита** с чёткой доменной изоляцией.
|
||||||
|
|
||||||
Проект построен на архитектуре **Clean Architecture** с модульным подходом:
|
---
|
||||||
|
|
||||||
|
## 🎯 Какую проблему решает Nashel
|
||||||
|
|
||||||
|
В России огромное количество мастеров и специалистов, которые работают «по сарафанному радио» — без нормальных инструментов для привлечения клиентов. А клиенты, в свою очередь, тратят время на поиск через знакомых или ненадёжные сайты объявлений.
|
||||||
|
|
||||||
|
**Nashel** — это:
|
||||||
|
- Удобный и быстрый поиск исполнителей **рядом с тобой** на карте
|
||||||
|
- Прозрачная система услуг с ценами, фото и описанием
|
||||||
|
- Система репутации и отзывов
|
||||||
|
- Безопасное взаимодействие клиента и исполнителя
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 👤 Роли пользователей
|
||||||
|
|
||||||
|
| Роль | Описание |
|
||||||
|
|------|----------|
|
||||||
|
| **Клиент** | Ищет услуги на карте, просматривает профили исполнителей, оставляет заявки |
|
||||||
|
| **Кандидат в мастера** | Зарегистрировался как исполнитель, проходит верификацию |
|
||||||
|
| **Мастер** | Верифицированный исполнитель — частный специалист, самозанятый |
|
||||||
|
| **Компания** | Юридическое лицо, предоставляющее услуги через платформу |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 Архитектура
|
||||||
|
|
||||||
|
Проект реализован как **Modular Monolith** — единое приложение, разделённое на изолированные модули с чёткими границами. Каждый модуль содержит:
|
||||||
|
|
||||||
```
|
```
|
||||||
nashel-backend/
|
Modules/<Module>/
|
||||||
├── src/
|
├── Application/ # Команды, запросы, DTO (MediatR)
|
||||||
│ ├── BuildingBlocks/ # Общие блоки для всех модулей
|
├── Domain/ # Сущности, бизнес-логика, интерфейсы репозиториев
|
||||||
│ │ ├── Application/ # Общие абстракции и поведения
|
├── Infrastructure/ # Реализация репозиториев, EF Core DbContext
|
||||||
│ │ ├── Domain/ # Базовые доменные сущности
|
└── Presentation/ # HTTP Endpoints (Minimal API)
|
||||||
│ │ └── Infrastructure/ # Общая инфраструктура
|
|
||||||
│ ├── Modules/ # Модули бизнес-логики
|
|
||||||
│ │ ├── Identity/ # Модуль авторизации и профилей
|
|
||||||
│ │ └── Order/ # Модуль заказов
|
|
||||||
│ └── Host/ # Точка входа приложения
|
|
||||||
└── tests/ # Тесты
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Модульность
|
### Модули
|
||||||
|
|
||||||
Каждый модуль (Identity, Order) является автономным и содержит:
|
| Модуль | Назначение |
|
||||||
- **Domain** — бизнес-логика, сущности, репозитории
|
|--------|------------|
|
||||||
- **Application** — Use Cases, команды, запросы, валидация
|
| **Identity** | Регистрация, авторизация (JWT), профиль, роли, аватар, геолокация, расписание |
|
||||||
- **Infrastructure** — реализация репозиториев, EF Core
|
| **Catalog** | Управление услугами (CRUD), изображения, статусы, атрибуты |
|
||||||
- **Presentation** — API endpoints
|
| **Geo** | Геозоны, расчёт расстояний (PostGIS / NetTopologySuite) |
|
||||||
|
| **Search** | Полнотекстовый поиск по услугам и компетенциям с учётом геопозиции |
|
||||||
|
| **Reputation** | Отзывы и рейтинги (в разработке) |
|
||||||
|
| **Collaboration** | Заявки и взаимодействие клиент ↔ исполнитель (в разработке) |
|
||||||
|
| **Order** | Заказы и их жизненный цикл (в разработке) |
|
||||||
|
|
||||||
## 🚀 Технологический стек
|
### Host
|
||||||
|
|
||||||
- **.NET 10** — фреймворк
|
`Host/` — точка входа приложения. Здесь настраиваются DI, middleware, маршрутизация и сборка всех модулей.
|
||||||
- **ASP.NET Core** — веб-фреймворк
|
|
||||||
- **Entity Framework Core** — ORM
|
|
||||||
- **PostgreSQL** — база данных
|
|
||||||
- **MediatR** — паттерн CQRS/Mediator
|
|
||||||
- **FluentValidation** — валидация
|
|
||||||
- **JWT** — аутентификация
|
|
||||||
- **Docker** — контейнеризация
|
|
||||||
- **Swagger/OpenAPI** — документация API
|
|
||||||
|
|
||||||
## 📦 Установка и запуск
|
---
|
||||||
|
|
||||||
### Требования
|
## ✅ Что реализовано
|
||||||
|
|
||||||
- .NET 10 SDK
|
### Аутентификация и профиль
|
||||||
- Docker и Docker Compose
|
- Регистрация и вход по логину/паролю (JWT токены)
|
||||||
- PostgreSQL
|
- Смена пароля, обновление профиля
|
||||||
|
- Загрузка аватара (хранится как base64 в БД)
|
||||||
|
- Переход в роль исполнителя: описание, компетенции, геолокация
|
||||||
|
|
||||||
### Запуск через Docker Compose
|
### Геолокация
|
||||||
|
- Привязка основного адреса и текущего местоположения
|
||||||
|
- Расчёт расстояния до исполнителей с помощью **PostGIS + NetTopologySuite**
|
||||||
|
- Геозоны для фильтрации исполнителей в радиусе
|
||||||
|
|
||||||
```bash
|
### Услуги (Catalog)
|
||||||
# Клонирование репозитория
|
- Создание, редактирование, удаление (soft delete) услуг
|
||||||
git clone <repository-url>
|
- Приостановка услуги (пауза)
|
||||||
cd nashel-backend
|
- Загрузка до 10 изображений (≤5 МБ каждое), хранение в БД
|
||||||
|
- Атрибуты услуги (произвольные ключ-значение пары)
|
||||||
|
- Первое изображение является обложкой
|
||||||
|
|
||||||
# Запуск всех сервисов
|
### Поиск
|
||||||
docker-compose up -d
|
- Полнотекстовый поиск по: названию услуги, описанию, компетенциям
|
||||||
|
- Результаты сортируются с учётом расстояния и релевантности
|
||||||
|
- Исполнитель показывается в поиске только если у него нет найденных услуг (приоритет услуги над специалистом)
|
||||||
|
- Приостановленные и удалённые услуги не отображаются
|
||||||
|
- Возврат URL первого изображения услуги для превью в поиске
|
||||||
|
|
||||||
# Просмотр логов
|
### Расписание и статус доступности
|
||||||
docker-compose logs -f app
|
- Настройка рабочих дней и «всегда готов»
|
||||||
|
- Умная логика статуса: ручное включение статуса «Готов к заказу» переопределяет расписание до конца текущего дня
|
||||||
|
|
||||||
# Остановка сервисов
|
---
|
||||||
docker-compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
### Локальный запуск
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Восстановление зависимостей
|
|
||||||
dotnet restore
|
|
||||||
|
|
||||||
# Настройка переменных окружения
|
|
||||||
cp src/Host/appsettings.json src/Host/appsettings.Development.json
|
|
||||||
# Отредактируйте ConnectionStrings__DefaultConnection
|
|
||||||
|
|
||||||
# Применение миграций
|
|
||||||
dotnet ef database update --project src/Host --startup-project src/Host
|
|
||||||
|
|
||||||
# Запуск
|
|
||||||
dotnet run --project src/Host
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔧 Переменные окружения
|
|
||||||
|
|
||||||
| Переменная | Описание | Пример |
|
|
||||||
|------------|----------|--------|
|
|
||||||
| `ASPNETCORE_ENVIRONMENT` | Окружение | `Development`, `Production` |
|
|
||||||
| `ConnectionStrings__DefaultConnection` | Строка подключения к БД | `Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres` |
|
|
||||||
| `JWT__Secret` | Секретный ключ JWT | `your-super-secret-key` |
|
|
||||||
| `JWT__Issuer` | Издатель токена | `nashel-api` |
|
|
||||||
| `JWT__Audience` | Аудитория токена | `nashel-client` |
|
|
||||||
| `JWT__ExpirationMinutes` | Время жизни токена (мин) | `60` |
|
|
||||||
|
|
||||||
## 📚 API Документация
|
|
||||||
|
|
||||||
Swagger доступен по адресу: `http://localhost:5000/swagger`
|
|
||||||
|
|
||||||
### Основные эндпоинты
|
|
||||||
|
|
||||||
#### Аутентификация
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/auth/register
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"phone": "+79001234567",
|
|
||||||
"firstName": "Иван",
|
|
||||||
"lastName": "Иванов",
|
|
||||||
"password": "password123",
|
|
||||||
"confirmPassword": "password123",
|
|
||||||
"isCompany": false,
|
|
||||||
"companyName": "ООО 'Ромашка'",
|
|
||||||
"inn": "1234567890"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST /api/auth/login
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"phone": "+79001234567",
|
|
||||||
"password": "password123"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Профиль пользователя
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /api/profile
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
|
|
||||||
PUT /api/profile
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"firstName": "Иван",
|
|
||||||
"lastName": "Иванов",
|
|
||||||
"patronymic": "Иванович",
|
|
||||||
"companyName": "ООО 'Ромашка'",
|
|
||||||
"inn": "1234567890"
|
|
||||||
}
|
|
||||||
|
|
||||||
POST /api/profile/change-phone
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"newPhone": "+79009876543"
|
|
||||||
}
|
|
||||||
|
|
||||||
POST /api/profile/become-performer
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
|
|
||||||
POST /api/profile/avatar
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
Content-Type: multipart/form-data
|
|
||||||
|
|
||||||
avatar: <file>
|
|
||||||
|
|
||||||
PUT /api/profile/competencies
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"Competencies": ["сантехника", "электрика"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Компетенции
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET /api/competencies/search?q=сантех
|
|
||||||
Authorization: Bearer {access_token}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎯 Реализованный функционал
|
|
||||||
|
|
||||||
### Модуль Identity
|
|
||||||
|
|
||||||
#### Аутентификация и авторизация
|
|
||||||
- ✅ Регистрация пользователей (частные лица и компании)
|
|
||||||
- ✅ Вход в систему (JWT токены)
|
|
||||||
- ✅ Обновление токенов
|
|
||||||
- ✅ Выход из системы
|
|
||||||
- ✅ Ролевая модель (Client, Master, Candidate, Company, Admin)
|
|
||||||
|
|
||||||
#### Профиль пользователя
|
|
||||||
- ✅ Получение профиля
|
|
||||||
- ✅ Редактирование профиля
|
|
||||||
- ✅ Изменение номера телефона
|
|
||||||
- ✅ Загрузка аватара с кропом
|
|
||||||
- ✅ Управление компетенциями
|
|
||||||
- ✅ Стать исполнителем
|
|
||||||
|
|
||||||
#### Компетенции
|
|
||||||
- ✅ Поиск компетенций по подстроке
|
|
||||||
- ✅ Общий пул компетенций для всех исполнителей
|
|
||||||
- ✅ Автоматическое создание новых компетенций
|
|
||||||
|
|
||||||
#### Компании
|
|
||||||
- ✅ Регистрация компаний с ИНН
|
|
||||||
- ✅ Управление данными компании
|
|
||||||
- ✅ Отдельная логика для компаний
|
|
||||||
|
|
||||||
### Модуль Order (в разработке)
|
|
||||||
- ⏳ Создание заказов
|
|
||||||
- ⏳ Поиск заказов на карте
|
|
||||||
- ⏳ SLA таймер для отклика на заказы
|
|
||||||
|
|
||||||
## 🗄️ База данных
|
## 🗄️ База данных
|
||||||
|
|
||||||
### Схема
|
- **PostgreSQL** с расширением **PostGIS** (геопространственные запросы)
|
||||||
|
- **Entity Framework Core** (Code First, миграции)
|
||||||
|
- Структура: таблица `Accounts`, `Performers`, `Offers`, `Competencies` и др.
|
||||||
|
|
||||||
```
|
---
|
||||||
accounts (аккаунты пользователей)
|
|
||||||
├── id (PK)
|
|
||||||
├── phone (уникальный)
|
|
||||||
├── password_hash
|
|
||||||
├── roles (массив ролей)
|
|
||||||
└── profile_id (FK)
|
|
||||||
|
|
||||||
user_profiles (профили пользователей)
|
## 🐳 Запуск через Docker
|
||||||
├── id (PK)
|
|
||||||
├── account_id (FK)
|
|
||||||
├── first_name
|
|
||||||
├── last_name
|
|
||||||
├── patronymic
|
|
||||||
├── company_name
|
|
||||||
├── inn (для компаний)
|
|
||||||
├── avatar_url
|
|
||||||
└── competency_profiles (связь с компетенциями)
|
|
||||||
|
|
||||||
competencies (компетенции/навыки)
|
|
||||||
├── id (PK)
|
|
||||||
├── name (уникальное, в нижнем регистре)
|
|
||||||
|
|
||||||
competency_profiles (связь профилей и компетенций)
|
|
||||||
├── id (PK)
|
|
||||||
├── profile_id (FK)
|
|
||||||
├── competency_id (FK)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Миграции
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Создание новой миграции
|
# Запуск базы данных и бэкенда
|
||||||
dotnet ef migrations add AddNewFeature --project src/Infrastructure --startup-project src/Host
|
docker-compose up -d --build
|
||||||
|
|
||||||
# Применение миграций
|
|
||||||
dotnet ef database update --project src/Infrastructure --startup-project src/Host
|
|
||||||
|
|
||||||
# Откат последней миграции
|
|
||||||
dotnet ef database update --project src/Infrastructure --startup-project src/Host
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔐 Безопасность
|
Настройки в `docker-compose.yml` (строка подключения, порты, переменные окружения).
|
||||||
|
|
||||||
- Хеширование паролей (BCrypt)
|
---
|
||||||
- JWT токены с refresh token
|
|
||||||
- Валидация входных данных (FluentValidation)
|
|
||||||
- CORS политика
|
|
||||||
- Rate limiting (в планах)
|
|
||||||
|
|
||||||
## 🧪 Тестирование
|
## ⚙️ Локальный запуск
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Запуск всех тестов
|
cd nashel-backend
|
||||||
dotnet test
|
|
||||||
|
|
||||||
# Запуск тестов с покрытием
|
# Применить миграции
|
||||||
dotnet test --collect:"XPlat Code Coverage"
|
dotnet ef database update -p src/Host -s src/Host
|
||||||
|
|
||||||
# Запуск конкретного теста
|
# Запустить
|
||||||
dotnet test --filter "FullyQualifiedName~TestName"
|
dotnet run --project src/Host
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📝 Конвенции кода
|
Swagger UI доступен по адресу: `http://localhost:5000/swagger`
|
||||||
|
|
||||||
### CQRS Pattern
|
---
|
||||||
|
|
||||||
Используем MediatR для реализации CQRS:
|
## 🔮 Планы развития
|
||||||
|
|
||||||
```csharp
|
|
||||||
// Команда (Command)
|
|
||||||
public record UpdateProfileCommand(...) : IRequest;
|
|
||||||
|
|
||||||
// Обработчик команды (Handler)
|
|
||||||
public class UpdateProfileCommandHandler : IRequestHandler<UpdateProfileCommand>
|
|
||||||
{
|
|
||||||
public async Task Handle(UpdateProfileCommand request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// Логика
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Валидация
|
|
||||||
|
|
||||||
Используем FluentValidation:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class UpdateProfileCommandValidator : AbstractValidator<UpdateProfileCommand>
|
|
||||||
{
|
|
||||||
public UpdateProfileCommandValidator()
|
|
||||||
{
|
|
||||||
RuleFor(x => x.FirstName).NotEmpty().MinimumLength(2);
|
|
||||||
RuleFor(x => x.LastName).NotEmpty().MinimumLength(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚨 Обработка ошибок
|
|
||||||
|
|
||||||
- Глобальный exception handler
|
|
||||||
- Стандартные HTTP статусы (400, 401, 403, 404, 500)
|
|
||||||
- Подробные сообщения об ошибках в Development режиме
|
|
||||||
- Обобщенные сообщения в Production режиме
|
|
||||||
|
|
||||||
## 📦 Статические файлы
|
|
||||||
|
|
||||||
Загруженные аватары хранятся в `wwwroot/uploads/` и доступны по URL:
|
|
||||||
```
|
|
||||||
http://localhost:5000/uploads/{filename}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔄 CI/CD
|
|
||||||
|
|
||||||
- GitHub Actions для автоматического тестирования
|
|
||||||
- Docker Hub для хранения образов
|
|
||||||
- Автоматический деплой (в планах)
|
|
||||||
|
|
||||||
## 📞 Контакты
|
|
||||||
|
|
||||||
- **Проект:** Nashel
|
|
||||||
- **Версия:** 1.0.0
|
|
||||||
- **Лицензия:** MIT
|
|
||||||
|
|
||||||
## 🤝 Вклад в проект
|
|
||||||
|
|
||||||
1. Fork репозитория
|
|
||||||
2. Создайте ветку для фичи (`git checkout -b feature/AmazingFeature`)
|
|
||||||
3. Закоммитьте изменения (`git commit -m 'Add some AmazingFeature'`)
|
|
||||||
4. Запушьте в ветку (`git push origin feature/AmazingFeature`)
|
|
||||||
5. Откройте Pull Request
|
|
||||||
|
|
||||||
|
- [ ] Полный модуль **Collaboration**: чат между клиентом и исполнителем
|
||||||
|
- [ ] Модуль **Order**: жизненный цикл заказа, статусы, оплата
|
||||||
|
- [ ] Модуль **Reputation**: система отзывов и рейтингов (реальные данные вместо заглушек)
|
||||||
|
- [ ] Верификация документов исполнителя
|
||||||
|
- [ ] Push-уведомления
|
||||||
|
- [ ] Поддержка OAuth (VK, Google)
|
||||||
|
- [ ] Аналитика для исполнителей (просмотры, конверсии)
|
||||||
|
|||||||
Reference in New Issue
Block a user