GET /api/v1/agent/calendar/appointments/{appointmentId} — Карточка записи
Назначение
Отдаёт агенту (или консультанту ПИН) полную карточку записи инвестора: статус и дедлайн решения, снапшот
времени, комментарий инвестора, display-данные инвестора из реплики identity, параметры слота-источника
(auto-confirm, cutoff) и след переноса. С карточки агент принимает решение — подтвердить, отклонить,
отменить или зафиксировать исход.
| Поле | Значение |
|---|
| Сервис/контекст | calendar |
| API area | agent |
| Feature group | appointments |
| Статус | draft |
| Документ | docs/06-services/calendar/api/agent/get-appointment.md |
Актор и доступ
| Проверка | Значение |
|---|
| Actor type | User (агент агентства / консультант ПИН) |
| Auth policy / Permissions | calendar.appointments.view |
| Scope (RBAC) | организация — компания актора (агентство / ПИН) |
| Record-level | только собственные записи (AgentUserId = actor); чужая запись не раскрывается — APPOINTMENT_NOT_FOUND (fail-closed) |
| Tenant isolation | TenantId из токена (ADR-0052) |
| Audit | read-sensitive: карточка содержит Comment (Internal) и display-данные инвестора — в логи не пишутся |
HTTP-контракт
| Поле | Значение |
|---|
| Method | GET |
| Route | /api/v1/agent/calendar/appointments/{appointmentId} |
| Success status | 200 |
| Idempotency header | нет (безопасное чтение) |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|
ActorUserId | токен (sub) | Guid | Да | Required | record-level фильтр AgentUserId |
TenantId | токен (tenant_id) | Guid | Да | Required | Tenant isolation |
AppointmentId | route | Guid | Да | Required; валидный Guid | — |
Модель ответа AgentAppointmentDetailsModel
Все поля AgentAppointmentModel (дом — list-appointments.md) плюс параметры
слота-источника:
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|
(поля AgentAppointmentModel) | — | — | list-appointments.md | — | Проекция записи + контекст слота + InvestorDisplayName. |
AutoConfirm | bool | Да | слот | — | Запись была создана на слоте с автоподтверждением (Pending не проходилась). |
CancellationCutoffMinutes | int | Да | слот | — | Cutoff отмены/переноса инвестором (INV-APT-3) — агент видит, до какого момента инвестор ещё может отменить. |
MinLeadTimeMinutes | int | Да | слот | — | Lead time слота — определяет, вернётся ли слот на витрину при отмене (правило освобождения, appointment.md). |
Алгоритм
Тривиальное чтение: проверить permission calendar.appointments.view (иначе APPOINTMENT_ACCESS_DENIED);
найти запись по AppointmentId среди записей актора в его tenant — не найдена или принадлежит другому
агенту → APPOINTMENT_NOT_FOUND (fail-closed, существование чужой записи не раскрывается). К записи
подтягиваются параметры слота-источника и InvestorDisplayName из display-реплики identity
(../../consumers/identity-user-upserted.md); отставание реплики — не ошибка, поле null. Ответ —
AgentAppointmentDetailsModel, HTTP 200; данные записи — из source of truth calendar, актуальны на
момент чтения.
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|
VALIDATION_FAILED | 400 | AppointmentId — не валидный Guid | «Некорректный идентификатор» | no retry |
UNAUTHORIZED | 401 | нет/просрочен JWT | «Требуется авторизация» | no retry |
APPOINTMENT_ACCESS_DENIED | 403 | нет permission calendar.appointments.view | «Недостаточно прав» | no retry |
APPOINTMENT_NOT_FOUND | 404 | запись не существует или принадлежит другому агенту/tenant (fail-closed) | «Запись не найдена» | no retry |
Acceptance Criteria
- AC-1 (happy path). Given
Pending-запись к актору с комментарием инвестора. When GET карточки.
Then 200: статус, PendingExpiresAt, Comment, InvestorDisplayName, параметры слота (AutoConfirm,
CancellationCutoffMinutes, MinLeadTimeMinutes).
- AC-2 (терминальная запись). Given запись
Cancelled с CancelledBy = Investor. When GET. Then
200: заполнены CancelReason, CancelledBy; при переносе — RescheduledToAppointmentId.
- AC-3 (чужая запись). Given запись к другому агенту того же tenant. When
GET по её идентификатору.
Then 404 APPOINTMENT_NOT_FOUND.
- AC-4 (лаг реплики). Given display-реплика инвестора отсутствует. When
GET. Then 200,
InvestorDisplayName = null, остальные поля полны.
Совместимость и наблюдаемость
- Новые поля — additive nullable; удаление/переименование/смена типа — breaking. Новые значения
AppointmentStatus/AppointmentCancelledBy клиент обязан переживать.
- Logs:
TenantId, AgentUserId, AppointmentId, Status (без Comment/display-данных); metrics:
calendar_api_request_duration_seconds{route}; traces — сквозной traceparent.
Обратные ссылки
Автоссылки: где используется этот документ.
Связанные документы