GET /api/v1/lots/{id} — Карточка объекта недвижимости: ограниченная / полная
Назначение
Карточка объекта /lots/[id]/info: ограниченная для гостя (описание, цена, срок сдачи, общая и
жилая площадь, этаж, застройщик) и полная для авторизованного/реферального гостя (+ комнатность,
статус, метрики доходности, комиссия агенту). Один endpoint, два режима ответа — режим определяется
классом актора (правила маскирования MASK-ANALYTICS/MASK-STATUS — README.md). Дом
полей — catalog-property-object-card.
Детальная инвест-аналитика (график роста цены, калькулятор, серии, PDF-отчёт) — не этот метод:
полная карточка отдаёт денормализованные метрики и id для запросов в invest-analytics (страница
/lots/[id]/analytics).
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | catalog |
| API area | public |
| Feature group | cards |
| Статус | draft |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | Guest (ограниченная карточка, без гейта) / RefGuest, User (полная) |
| Auth policy / Permissions | чтение — без permission; agentCommission — catalog.commissions.view (MASK-COMMISSION) |
| Scope | платформа |
| Tenant isolation | не применяется (платформенная витрина) |
| Audit | none; просмотр пишет фронт событием в user-activity — каталог просмотры не сохраняет |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | GET |
| Route | /api/v1/lots/{id} |
| Success status | 200 |
| Idempotency | не применяется (safe GET) |
| Correlation | OpenTelemetry trace (traceparent) |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
Id | route | Guid | Да | валидный Guid; иначе 404 route-биндинга | — |
ActorClass | identity middleware | Guest/RefGuest/User | Да | определяет режим ограниченная/полная (README.md); невалидный токен → 401 | классы — README.md |
Модель ответа PropertyObjectCardModel
Колонка Masking: огр. → null — поле обнуляется в ограниченном режиме (Guest).
Источники effective-полей — дом ../domain/catalog-property-object-card.md.
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|---|---|---|---|---|
id | Guid | Да | CatalogPropertyObjectCard.Id | — | Объект недвижимости. |
projectId | Guid | Да | ProjectId | — | Проект (переход «О проекте»). |
building | BuildingRefModel | Да | BuildingId/BuildingName | — | Корпус (ref-модель — README.md). |
developer | DeveloperRefModel | Да | DeveloperId/DeveloperName | — | Застройщик (ref-модель — README.md; виден и гостю). |
number | string | Да | Number | — | Номер объекта недвижимости. |
title | string | Да | Title (effective) | — | Заголовок («описание» ограниченной карточки). |
typeName | string | Да | TypeName | — | Тип объекта. |
view | string? | Нет | View | — | Вид из окон. |
badge | string? | Нет | Badge (effective) | — | Бейдж. |
address | string | Да | Address | — | Адрес. |
distanceMinutes | int? | Нет | DistanceMinutes (effective) | — | Минуты до ключевой точки. |
stars | short? | Нет | Stars (effective) | — | Звёздность. |
deliveryDate | string (ISO 8601 date)? | Нет | DeliveryDate (effective) | — | Срок сдачи (виден гостю). |
readinessPercent | short? | Нет | ReadinessPercent (effective) | — | Готовность. |
price | decimal | Да | Price (effective) | — | Цена — видна и гостю (принятое расхождение MASK-PRICE, README.md: цена входит в ограниченную карточку). |
areaTotal | decimal | Да | AreaTotal | — | Общая площадь. |
areaLiving | decimal? | Нет | AreaLiving | — | Жилая площадь. |
pricePerMeter | decimal | Да | PricePerMeter | — | Цена за м². |
floor | short | Да | Floor | — | Этаж (виден гостю). |
floorsTotal | short | Да | FloorsTotal | — | Этажность корпуса. |
ceilingHeight | decimal? | Нет | CeilingHeight | — | Высота потолков, м. |
roomsCount | short | Да | RoomsCount | — | Комнатность. |
visualizationFileId | Guid? | Нет | VisualizationFileId | — | Планировка/визуализация (пресайн — storage/CDN). |
propertyObjectStatus | string (enum PropertyObjectAvailabilityStatus)? | Нет | PropertyObjectStatus | огр. → null (MASK-STATUS) | Free/Reserved/Booked/Sold; управляет кнопкой «Забронировать» (активна при Free; заявка — crm). |
payback | PaybackModel? | Нет | owned Payback (effective) | огр. → null (MASK-ANALYTICS) | Окупаемость. |
reliability | ReliabilityModel? | Нет | owned Reliability (effective) | огр. → null | Индекс надёжности. |
growthPercent | decimal? | Нет | GrowthPercent | огр. → null | Рост цены, %/год. |
rentalIncomePerYear | decimal? | Нет | RentalIncomePerYear | огр. → null | Арендный доход, ₽/год. |
rating | decimal? | Нет | Rating (effective) | огр. → null | Рейтинг. |
agentCommission | AgentCommissionModel? | Нет | owned AgentCommission | MASK-COMMISSION | Комиссия агенту на странице объекта. |
analyticsAvailable | bool | Да | computed | — | true в полном режиме при AnalyticsSyncedAt != null — фронт показывает вкладку /lots/[id]/analytics (данные — invest-analytics); в ограниченном режиме всегда false. |
isLimited | bool | Да | computed | — | true — ответ в ограниченном режиме (фронт показывает предложение войти). |
Алгоритм
- Контекст и доступ. Актор по токену (
User; невалидный → 401), затем по реф-cookiereferralUrl(RefGuest), иначеGuest— без отказа (ограниченный режим). ДляUser— праваcatalog.commissions.view. - Проверка входа.
Id != Guid.Empty— иначеValidationError(400). Карточка объекта должна существовать и быть опубликованной (Status = Published); если карточки нет либо она в статусеHidden/Delisted→CATALOG_PROPERTY_OBJECT_NOT_FOUND(404) — скрытые карточки неотличимы от несуществующих (не раскрываем факт скрытия). - Что читаем. Единственная карточка объекта по
id(все данные денормализованы; owned VO — часть той же строки). Запросов вchessboard/invest-analytics/rewardsнет. - Режим и маскирование.
isLimited = (ActorClass == Guest). Маппинг поле-в-поле — таблицаPropertyObjectCardModel; в ограниченном режиме поля с пометкой «огр. → null» обнуляются (MASK-STATUS + MASK-ANALYTICS),analyticsAvailable = false; в полном —analyticsAvailable = (AnalyticsSyncedAt != null).agentCommission— по MASK-COMMISSION независимо от режима. - Результат.
PropertyObjectCardModel→ 200 (оба режима). Консистентность — eventual (лаг консюмеров источников; критичную проверку статуса перед бронью выполняетcrmв источнике — ../README.md, «Известные ограничения»).
Диаграмма
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
| — (auth) | 401 | Передан невалидный/просроченный токен | без тела схемы (фронт очищает сессию) | re-login |
ValidationError | 400 | Id = Guid.Empty | Список ошибок полей | no retry |
CATALOG_PROPERTY_OBJECT_NOT_FOUND | 404 | Карточки нет либо Status ∈ {Hidden, Delisted} | «Объект не найден» | no retry |
Acceptance Criteria
- Полная карточка. Дано
User/RefGuestи опубликованный объект. Когда запрашивает/api/v1/lots/{id}. Тогда200сpropertyObjectStatus, метриками доходности (payback/reliability/growthPercent/rentalIncomePerYear/rating),analyticsAvailable = (AnalyticsSyncedAt != null),isLimited = false. - Ограниченная карточка (гость). Дано
Guest. Когда запрашивает. Тогда200, но поля с пометкой «огр. → null» обнулены (MASK-STATUS + MASK-ANALYTICS),analyticsAvailable = false,isLimited = true;price,floor,deliveryDateи застройщик остаются видны. - Комиссия по праву. Дано
Userбезcatalog.commissions.view. Когда возвращается карточка. ТогдаagentCommission = nullнезависимо от режима. - Скрытый/несуществующий объект. Дано карточка в
Hidden/Delistedлибо отсутствует. Когда запрашивают. ТогдаCATALOG_PROPERTY_OBJECT_NOT_FOUND(404) — скрытое неотличимо от несуществующего. - Кнопка брони. Дано
propertyObjectStatus = Freeв полном режиме. Когда фронт рендерит карточку. Тогда кнопка «Забронировать» активна; решающую проверку статуса перед заявкой выполняетcrm(витрина eventual, лаг консюмера). - Невалидный токен. Дано просроченный JWT. Когда приходит запрос. Тогда
401(фронт очищает сессию), в отличие от гостя без токена — тот получает ограниченный200.
Совместимость и наблюдаемость
- Расширение маскируемого набора — additive; раскрытие ранее маскированного поля гостю — breaking (пересмотр MASK-* в README.md).
- Logs: id, класс актора, режим (limited/full), результат; metrics —
catalog_property_object_card_requests_total{actor_class,result}, latency histogram, доля limited-ответов; traces/dashboard — общие правила area (README.md).
Обратные ссылки
Автоссылки: где используется этот документ.
- API (2): Catalog Public API — реестр методов и общие правила, GET /api/v1/lots — Лента объектов недвижимости
- Use Cases (1): UC-OWN-004. Карточка объекта портфеля с историей изменения цен
- registries (1): Реестр API-методов PIN
Связанные документы
- Общие правила area: README.md; дом полей: ../domain/catalog-property-object-card.md.
- Детальная аналитика объекта недвижимости:
../../invest-analytics/(страница/lots/[id]/analytics). - Бронирование/заявки с карточки:
../../crm/. - Трекинг просмотра:
../../user-activity/. - Лента: get-property-objects.md; карточка проекта: get-project.md.