---
title: Смена региона пользователя (Backend)
---

# Сценарий 1.3: Смена региона пользователя

## Бизнес-цель

Пользователь может переключать **регион** (филиал сети / географическая зона), чтобы видеть контент и услуги, релевантные выбранной территории. В API регион хранится в **`User::$regionId`** и участвует в выдаче данных на фронте.

## Точки входа

| Тип | Метод + URL | Класс |
| --- | --- | --- |
| HTTP | `PUT /user/change-region` | `App\Controller\UserController::changeRegion` |

Требуется аутентификация: `#[IsGranted('ROLE_USER')]` — клиент передаёт **JWT** в заголовке.

CLI и Messenger **не используются**.

## Пошаговый алгоритм (flow)

1. Клиент отправляет JSON с полем `regionId`.
2. Данные попадают в `App\Dto\RegionDto`; Symfony Validator проверяет ограничения DTO.
3. Вызывается `App\Service\User\UserProfileService::updateRegion($dto)`:
   - `JWTDecoderService::getUser()` — из текущего токена извлекается **username** и по нему загружается `User` из БД;
   - на найденного пользователя выставляется `setRegionId($dto->regionId)`;
   - `EntityManager::persist` + `flush`.
4. Контроллер сериализует **тот же** `User::toArray()` и возвращает `200` с `user` и `successful: true`.

## Mermaid

```mermaid
sequenceDiagram
    participant C as Клиент (JWT)
    participant UC as UserController
    participant V as Validator
    participant UPS as UserProfileService
    participant JWT as JWTDecoderService
    participant UR as UserRepository
    participant EM as EntityManager

    C->>UC: PUT /user/change-region {regionId}
    UC->>V: validate(RegionDto)
    UC->>UPS: updateRegion(dto)
    UPS->>JWT: getUser()
    JWT->>UR: find by token username
    UR-->>JWT: User
    UPS->>EM: setRegionId + flush
    UPS-->>UC: User
    UC-->>C: 200 { user, successful }
```

## Внешние зависимости

| Система | Участие |
| --- | --- |
| PostgreSQL | обновление строки в `users` |
| JWT | идентификация текущего пользователя |

## Обработка ошибок и edge cases

- **Невалидный `regionId`** — `400` с телом `errors` из Validator.
- **`getUser()` вернул null** — в текущей реализации сервиса нет явной проверки; при `ROLE_USER` обычно токен уже валиден, но при рассинхроне payload/БД возможна ошибка уровня type error или `flush` — сценарий стоит учитывать при доработках.
- **Справочник регионов**: этот эндпоинт **не проверяет**, существует ли `regionId` в таблице регионов — допустим любой int, прошедший валидацию DTO.

## Ссылки на классы

- `apps/backend/src/Controller/UserController.php` (`changeRegion`)
- `apps/backend/src/Service/User/UserProfileService.php`
- `apps/backend/src/Dto/RegionDto.php`
- `apps/backend/src/Service/DecoderJWT/JWTDecoderService.php`

См. [login-jwt.md](./login-jwt.md) и [backend-ddd.md](../backend-ddd.md).
