Перейти к основному содержимому

GET /api/v1/agent/calendar/slots — Список слотов доступности агента

Назначение

Отдаёт агенту (или консультанту ПИН) его собственные слоты доступности за диапазон дат — во всех статусах, включая занятые и истёкшие: агент видит, какая доступность опубликована, что уже забронировано и что пора архивировать. Документ — дом модели AgentSlotModel; выборка занятых слотов ведёт к записи через ActiveAppointmentId.

Metadata

ПолеЗначение
Сервис/контекстcalendar
API areaagent
Feature groupslots
Статусdraft
Документdocs/06-services/calendar/api/agent/list-slots.md

Актор и доступ

ПроверкаЗначение
Actor typeUser (агент агентства / консультант ПИН — владелец слотов)
Auth policy / Permissionscalendar.slots.manage
Scope (RBAC)организация — компания актора (агентство / ПИН)
Record-levelAgentUserId = ActorUserId из токена (sub), не из query — актор видит только собственные слоты (fail-closed); свободные слоты других агентов доступны через анонимную витрину ../public/list-available-slots.md
Tenant isolationTenantId из токена (tenant_id), ADR-0052
Auditread; Location может содержать адрес — в логи не пишется

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/agent/calendar/slots
Success status200
Idempotency headerнет (безопасное чтение)
Correlationсквозной trace через заголовок traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
ActorUserIdтокен (sub)GuidДаRequired; не принимается из queryrecord-level фильтр AgentUserId
TenantIdтокен (tenant_id)GuidДаRequiredTenant isolation
FromqueryDateTimeOffsetДаUTC; начало диапазона выборки
ToqueryDateTimeOffsetДаUTC; To > From; To − From ≤ 92 дня (квартальное окно)
StatusquerySlotStatus?Нетenum-строка Available/Booked/Expired/Archived (availability-slot.md)
KindqueryEventKind?Неттолько Showing / Consultation (подмножество EventKind)
BatchIdqueryGuid?Нетслоты одной публикации (publish-slots.md)
Page / PageSizequeryintНетPage ≥ 1; PageSize 1..500, default 200

Все фильтры комбинируются по «И». Без фильтра Status возвращаются слоты во всех статусах — скрытие Expired/Archived — забота клиента. Слот попадает в выборку, если его интервал пересекается с диапазоном: StartAt < To и EndAt > From.

Модель ответа — страница AgentSlotModel

Ответ — страница с полями Items, Page, PageSize, TotalCount. Сортировка — StartAt по возрастанию, затем Id (стабильный порядок). Поля — проекция availability-slot.md поле-в-поле плюс вычисляемый ActiveAppointmentId.

ПолеТипОбязательностьИсточникMaskingОписание
IdGuidДаentityИдентификатор слота.
KindEventKindДаentityВид встречи (Showing / Consultation).
StatusSlotStatusДаentityТекущий статус слота.
StartAtDateTimeOffsetДаentityНачало, UTC.
EndAtDateTimeOffsetДаentityКонец, UTC.
TimeZonestringДаentityIANA-таймзона батча.
BatchIdGuidДаentityПубликация, породившая слот; ключ массовой архивации (archive-slot.md).
AutoConfirmboolДаentityЗаписи на слот подтверждаются автоматически.
CancellationCutoffMinutesintДаentityCutoff отмены/переноса записи инвестором (INV-APT-3).
MinLeadTimeMinutesintДаentityМинимальный lead time бронирования (INV-SLT-5).
ProjectIdGuid?НетentityПроект застройщика (chessboard, логическая ссылка).
PropertyObjectIdGuid?НетentityОбъект недвижимости (chessboard, логическая ссылка).
Locationstring?Нетentityв логи не пишетсяМесто встречи (свободный текст).
ActiveAppointmentIdGuid?НетcomputedАктивная запись (Pending/Confirmed) на слоте; заполнен только у Booked-слота (INV-APT-1) — переход к карточке get-appointment.md.
CreatedAtDateTimeOffsetДаentityПубликация слота.
UpdatedAtDateTimeOffsetДаentityПоследнее изменение.
VersionintДаentityВерсия строки (оптимистическая блокировка).

Алгоритм

  1. Контекст и доступ. Актор — владелец слотов; требуется calendar.slots.manage (иначе CAL_SLOT_ACCESS_DENIED). AgentUserId и TenantId берутся из токена, не из запроса.
  2. Проверка входа. From/To заданы, To > From, диапазон ≤ 92 дней; enum-значения Status/Kind (если заданы) допустимы (Kind — только Showing/Consultation); paging в границах — иначе VALIDATION_FAILED.
  3. Что читаем. Страница слотов актора по пересечению интервала с диапазоном и фильтрам Status/Kind/BatchId (по «И»); сортировка StartAt возр., затем Id. Ведущий индекс — ix_availability_slots_agent_start (AgentUserId, StartAt). Для Booked-слотов страницы подтягивается идентификатор активной записи (ActiveAppointmentId).
  4. Результат. Страница AgentSlotModel → HTTP 200. Пустая выборка — 200 с Items = [], не 404. Данные — из source of truth calendar, актуальны на момент чтения.

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
VALIDATION_FAILED400From/To отсутствуют; To ≤ From; диапазон > 92 дней; enum Status/Kind вне значений; paging вне границ«Некорректные параметры выборки»no retry
UNAUTHORIZED401нет/просрочен JWT«Требуется авторизация»no retry
CAL_SLOT_ACCESS_DENIED403нет permission calendar.slots.manage«Недостаточно прав»no retry

Acceptance Criteria

  • AC-1 (happy path). Given у агента слоты во всех статусах в диапазоне месяца. When GET с From/To этого месяца. Then 200, страница AgentSlotModel, сортировка по StartAt возр.; слоты вне диапазона отсутствуют.
  • AC-2 (занятый слот). Given Booked-слот с активной записью. When выборка. Then у слота заполнен ActiveAppointmentId; у Available/Expired/Archivednull.
  • AC-3 (фильтр по батчу). Given две публикации с разными BatchId. When GET с BatchId первой. Then возвращаются только слоты первой публикации.
  • AC-4 (record-level). Given в tenant есть слоты другого агента. When выборка. Then они не попадают в результат; переданные в query идентификаторы владельца игнорируются (ключи — из токена).
  • AC-5 (диапазон обязателен). Given запрос без From или To. Then 400 VALIDATION_FAILED.
  • AC-6 (пустая выборка). Given в диапазоне слотов нет. Then 200, Items = [], TotalCount = 0.

Совместимость и наблюдаемость

  • Новые поля AgentSlotModel — additive nullable (без breaking change); удаление/переименование/смена типа — breaking. Неизвестное enum-значение в query → VALIDATION_FAILED; новые значения SlotStatus в ответе клиент обязан переживать (forward-compatible отображение «прочее»).
  • Logs: TenantId, AgentUserId, диапазон, применённые фильтры, TotalCount (без Location); metrics: calendar_api_request_duration_seconds{route}; traces — сквозной traceparent.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы