Skill (ru)

# Навык: Создать гостя (iiko)

## Что делает
Создаёт (или обновляет) гостя в iiko на основе пары `cardTrack` + `cardNumber`.

Если гость уже существует, функция возвращает его, а не создаёт нового.

## Входные данные
- `settings: IikoSettings` (настройки клиента, загружаются из переменных окружения)
- `organization_id: str` (необязательный явный iiko loyalty organization id)
- `all_organizations: bool` (если `True`, команда обрабатывает все найденные организации по очереди; иначе по умолчанию использует первую найденную организацию)
- `card_track: str` (track-номер гостя)
- `card_number: str` (номер карты)
- `name: str` (имя гостя; используется как запасной вариант)
- `transport: IikoTransport` (HTTP транспорт; можно подменить для тестов)
- `token_provider: Callable[[IikoSettings], Awaitable[str]]` (по умолчанию `shared.auth.get_access_token`)

В CLI: `--use-local-env` / `--no-use-local-env`; в MCP: аргумент `use_local_env` (см. `IIKO_DEFAULT_USE_LOCAL_ENV`).

## Выходные данные
`dict[str, str]` со структурой:
- Для существующего гостя:
  - `status: "existing"`
  - `guest_id: <id customer>`
  - `name: <существующее имя или предоставленное имя>`
- Для созданного гостя:
  - `status: "created"`
  - `guest_id: <id customer>`
  - `name: <указанное имя>`

## Как работает (реализация)
1. Получает iiko access token через `shared.auth.get_access_token` (или через внедрённый `token_provider`).
2. Разрешает организации:
   - использует `organization_id`, если он передан явно
   - иначе по умолчанию использует первую найденную организацию
   - если `all_organizations=True`, выполняет команду для всех найденных организаций по очереди
3. Делает поиск гостя по `cardTrack` через:
   - `shared.customers.get_customer_by_card_track`
   - POST `/loyalty/iiko/customer/info`
4. Обрабатывает случай “не найдено”:
   - если `IikoApiError.status_code == 404`, считаем это “гость не найден” и идём дальше
   - при любой другой ошибке пробрасываем исключение наверх
5. Создаёт/обновляет гостя через:
   - `shared.customers.create_customer_with_card_track`
   - POST `/loyalty/iiko/customer/create_or_update`
6. Возвращает небольшую структурированную пачку данных, удобную для CLI и для будущих MCP tool output.

## Используемые общие модули
- `src/iiko_api_mcp_server/config.py` (`IikoSettings`)
- `src/iiko_api_mcp_server/shared/auth.py` (`get_access_token`)
- `src/iiko_api_mcp_server/shared/http.py` (`IikoTransport`, маппинг `IikoApiError`)
- `src/iiko_api_mcp_server/shared/customers.py` (поиск и create/update хелперы)
- `src/iiko_api_mcp_server/commands/create_guest.py` (координационная логика)

## Тестирование
Юнит-тесты находятся в:
- `tests/commands/test_create_guest.py`

Тесты проверяют:
- путь для существующего гостя (возвращается `status="existing"` и делается только запрос info)
- путь для создания гостя (404 обрабатывается, затем выполняется create/update)
- по умолчанию при нескольких организациях используется первая найденная организация
- CLI корректно передаёт opt-in флаг `--all-organizations`

В тестах используется `RecordingTransport` и фейковый token provider, чтобы не обращаться к live iiko.

## Чеклист отладки
1. Запустить точечные тесты:
   - `python -m pytest tests/commands/test_create_guest.py -v`
2. Если форма запроса выглядит неверно, проверьте `RecordingTransport.calls`.
3. Если упало исключение, проверьте тип:
   - `IikoApiError` с `status_code == 404` (ожидаемый сценарий “не найдено”)
   - или другой статус (его нужно пробрасывать)