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

GET /api/agent/crm/leads/{leadId}/booking-intents — Список намерений лида

Агент (или руководитель агентства), ведущий лид, открывает экран «объекты клиента» в карточке лида и получает список объектов-намерений: что инвестор хочет купить/забронировать и что агент ему предложил. Каждая строка показывает состояние намерения — сторону-инициатора, подтверждено ли инвестором, есть ли сделка. Дом полей — lead.md.

Назначение

Отдать агенту/руководителю агентства список намерений лида с фильтром по статусу, стороне и признаку подтверждения. По умолчанию — активные намерения. Каждая строка несёт объект, застройщика, сторону инициатора, флаг ConfirmedByInvestor и ссылку на сделку (если заведена) — этого достаточно, чтобы агент понимал, по каким объектам можно двигать сделку.

Metadata

ПолеЗначение
Сервис/контекстcrm
API areaagent (JWT агента/руководителя агентства)
Feature groupbooking-intents
Статусdraft
Документdocs/06-services/crm/api/agent/list-booking-intents.md

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

ПроверкаЗначение
Actor typeUser (Агент или Руководитель агентства); Operator (Менеджер ПИН)
Auth policy / Permissionscrm.leads.view; инвестор этот метод не вызывает (у него свой список в карточке лида)
Scope (RBAC)организация (агентство) — actor.CompanyId = lead.TenantId
Record-levelАктор — участник лида (обычно Executor) либо руководитель компании-владельца (AgencyCompanyId = lead.TenantId) / Менеджер ПИН
Tenant isolationнамерения лида в tenant агентства (lead.TenantId = AgencyCompanyId); выборка ограничена LeadId в границах доступа к лиду
Auditread (собственные данные агентства; не sensitive)
Доступ

Список видит участник лида (обычно Executor) либо руководитель компании-владельца агентства (AgencyCompanyId = lead.TenantId), либо Менеджер ПИН (platform-scope, сквозной доступ). Сам инвестор этот метод не вызывает — у него отдельный список намерений в своей карточке лида.

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/agent/crm/leads/{leadId}/booking-intents
Success status200
Idempotency headerне применяется (безопасный read)
Correlationсквозной trace через заголовок traceparent

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
LeadIdrouteGuidДа!= Guid.Empty; существующий лид в границах доступа актора
StatusqueryBookingIntentStatus?Нетenum строкой; неизвестное значение → VALIDATION_FAILED; default — Active
SourcequeryBookingIntentSource?Нетenum строкой InvestorAdded/AgentProposed; фильтр по стороне
ConfirmedByInvestorquerybool?Нетфильтр по подтверждению инвестором
ActorUserIdidentity claimsGuidДаJWT; record-level по лиду
ActorAgencyCompanyIdidentity claimsGuidДа!= Guid.Empty; сверяется с lead.TenantIdTenant isolation

Список короткий (намерения одного лида), пагинация не требуется; сортировка — CreatedAt desc.

Пустой результат — не ошибка

Известное значение фильтра (Status/Source/ConfirmedByInvestor), под которое нет данных, возвращает пустой Items, а не ошибку. Ошибку даёт только неизвестное (не входящее в enum) значение Status/Source.

Модель ответа — список BookingIntentListItemModel

Контейнер: Items: IReadOnlyList<BookingIntentListItemModel> (сортировка CreatedAt desc).

BookingIntentListItemModel

ПолеТипОбязательностьИсточникMaskingОписание
IntentIdGuidДаLeadBookingIntentEntity.IdИдентификатор намерения.
PropertyObjectIdGuidДаPropertyObjectIdОбъект намерения; карточка/цена резолвятся фронтом из chessboard.
ProjectIdGuidДаProjectId (snapshot)Проект объекта.
DeveloperCompanyIdGuidДаDeveloperCompanyId (snapshot)Застройщик объекта.
Sourcestring (enum BookingIntentSource)ДаSourceInvestorAdded / AgentProposed.
ConfirmedByInvestorboolДаConfirmedByInvestorПодтверждено ли инвестором.
ConfirmedAtDateTimeOffset?НетConfirmedAtМомент подтверждения.
Statusstring (enum BookingIntentStatus)ДаStatusActive / Cancelled.
DealIdGuid?НетDealIdСделка по намерению (если заведена).
CreatedAtDateTimeOffsetДаCreatedAtМомент добавления (ключ сортировки).
RemovedAtDateTimeOffset?НетRemovedAtМомент снятия (для Cancelled).

Алгоритм

  1. Контекст и доступ. Операцию выполняет агент/руководитель агентства (permission crm.leads.view); якорь — ActorAgencyCompanyId.
  2. Проверка входа и предусловий.
    • формат: LeadId != Guid.Empty; Status/Source — известные значения enum, иначе VALIDATION_FAILED;
    • лид существует → иначе CRM_LEAD_NOT_FOUND;
    • лид принадлежит агентству актора и актор — участник лида / руководитель / Менеджер ПИН → иначе CRM_LEAD_FORBIDDEN.
  3. Что читаем. Намерения по LeadId с фильтрами Status (default Active), Source, ConfirmedByInvestor, если заданы; сортировка CreatedAt desc.
  4. Результат. Список Items (проекция по таблице выше) → HTTP 200. Несуществующие значения фильтров дают пустой список, не ошибку.

Диаграмма

Ошибки и failure modes

Ошибки

CRM_LEAD_NOT_FOUND (лид не существует) и CRM_LEAD_FORBIDDEN (лид другого агентства/агента) — разные коды (404/403), не маскируются под общий отказ.

КодHTTP statusУсловиеСообщениеRetry
VALIDATION_FAILED400LeadId == Guid.Empty, неизвестный Status/Source«Проверьте параметры запроса»no retry
UNAUTHORIZED401нет/невалидный JWT или нет crm.leads.view«Требуется авторизация»no retry
CRM_LEAD_NOT_FOUND404лид не найден«Лид не найден»no retry
CRM_LEAD_FORBIDDEN403лид другого агентства/агента«Нет доступа к лиду»no retry

Acceptance Criteria

  • Happy path. Given участник лида без фильтров; When GET; Then 200 — активные намерения лида, сортировка CreatedAt desc.
  • Фильтр по стороне. Given Source=AgentProposed; When GET; Then только предложенные агентом намерения.
  • Фильтр по подтверждению. Given ConfirmedByInvestor=false; When GET; Then только неподтверждённые (ждут инвестора).
  • Снятые. Given Status=Cancelled; When GET; Then только снятые намерения (с RemovedAt).
  • Чужой лид. Given лид другого агентства; When GET; Then 403 CRM_LEAD_FORBIDDEN.
  • Валидация. Given неизвестный Status; When GET; Then 400 VALIDATION_FAILED.

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

  • Новые optional фильтры/поля ответа — additive; сужение enum BookingIntentStatus/BookingIntentSource — breaking (migration клиента + rollout); неизвестный член enum на клиенте — по правилу unknown-enum.
  • Logs: booking-intents listed (LeadId, ActorUserId, count); metrics: crm_booking_intents_list_total, latency p95 (SLO списков); traces — сквозной trace через traceparent; dashboard pin-crm.

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

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

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