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

GET /api/v1/public/projects/{projectId}/buildings/{buildingId} — Карточка здания (литера/корпуса)

Назначение

Публичная карточка здания (литера/корпуса) внутри проекта: этажность, срок сдачи, готовность, статус строительства, счётчики объектов недвижимости. Используется для заголовка шахматки/ассортимента и для деталей «срок сдачи» в ограниченной карточке объекта. Ограниченная (аноним) и полная (авторизованный) проекции отличаются только счётчиком свободных объектов недвижимости — производной статусов объектов, скрываемой от неавторизованных. Зеркалируется в agents area (GET /api/v1/agents/projects/{projectId}/buildings/{buildingId}) той же операцией.

Metadata

ПолеЗначение
Сервис/контекстchessboard
API areapublic (зеркало: agents)
Feature groupbuildings
Статусdraft
OwnerPIN Platform Core
Документdocs/06-services/chessboard/api/public/buildings/get-building.md

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

ПроверкаЗначение
Actor typeAnonymous / User (инвестор, агент, менеджер застройщика)
Auth policy / Permissionsnone — public endpoint; masking по признаку авторизации
Scope (RBAC)не применяется
Record-levelне применяется
Tenant isolationBypass tenant-фильтра только для Building.Status = Published внутри Project.Status = Published при Developer.Status = Published
Auditnone (read)

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/public/projects/{projectId}/buildings/{buildingId}
Success status200
Idempotency headerне применяется (GET)
Correlationсквозной trace через заголовок traceparent

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
ProjectIdrouteGuidДаRequired, != Guid.Empty
BuildingIdrouteGuidДаRequired, != Guid.Empty; здание должно принадлежать проекту (шаг 2 алгоритма)
IsAuthenticatedidentity claimsboolДа (вычисляется)из контекста авторизацииопределяет masking

Модель ответа BuildingCardResponse

Проекция BuildingEntity; masking-колонка — правило для анонима.

ПолеТипОбязательностьИсточникMasking (аноним)Описание
IdGuidДаBuilding.IdИдентификатор здания.
ProjectIdGuidДаBuilding.ProjectIdПроект-родитель.
ProjectNamestringДаProject.NameДля хлебных крошек без второго запроса.
NamestringДаBuilding.Name«Литер 3», «Корпус Б».
FloorsTotalshortДаBuilding.FloorsTotalЭтажность (ось Y шахматки).
SectionsCountshort?НетBuilding.SectionsCountСекций/подъездов (ось X шахматки).
DeliveryYearshort?НетBuilding.DeliveryYearГод сдачи («срок сдачи»).
DeliveryQuartershort?НетBuilding.DeliveryQuarterКвартал сдачи («IV кв. 2027»).
DeliveredAtDateOnly?НетBuilding.DeliveredAtФактический ввод в эксплуатацию.
ConstructionStatusConstructionStatus (string)ДаBuilding.ConstructionStatusСтатус строительства здания (reference-data.md).
ReadinessPercentdecimalДаBuilding.ReadinessPercentГотовность 0–100.
CeilingHeightMetersdecimal?НетBuilding.CeilingHeightMetersТиповая высота потолков.
PropertyObjectsTotalCountintДаBuilding.PropertyObjectsTotalCountВсего объектов недвижимости здания.
PropertyObjectsFreeCountint?НетBuilding.PropertyObjectsFreeCountnull (производная статусов)Свободных объектов недвижимости.
IsLimitedboolДавычисляется: !IsAuthenticatedОтдана ограниченная проекция.
VersionlongДаBuilding.VersionВерсия агрегата.

Предусловия и постусловия

Предусловия:

  • Вызов анонимом (ограниченная проекция) или авторизованным пользователем (полная); признак авторизации определяет masking.
  • Здание видимо только по публичному срезу: Building.Status = Published внутри Project.Status = Published при Developer.Status = Published (INV-DEV-6). Иначе — неотличимо от отсутствия (404).

Постусловия (read — состояние не меняется):

  • Возвращена карточка здания; для анонима PropertyObjectsFreeCount = null, IsLimited = true; для авторизованного значения отдаются как есть, IsLimited = false.
Freshness

Счётчики PropertyObjectsTotalCount/PropertyObjectsFreeCount — денормализация, отстаёт до debounce-джоба project-aggregates-recalc; остальные поля — прямое чтение source of truth.

Алгоритм

Чтение карточки здания по публичному срезу с проверкой публичности родителей и masking свободного счётчика для анонима.

  1. Контекст и доступ. Вызывает аноним или авторизованный пользователь; признак авторизации определяет masking. Чтение — только по публичному срезу (Published-иерархия).
  2. Проверка входа. ProjectId и BuildingId заданы (не пустые); иначе — VALIDATION_ERROR. Существование, публичность и принадлежность здания проекту проверяются при чтении (шаг 3, единый 404).
  3. Что читаем (родители до дочернего — для проверок публичности):
    • Проект по id со статусом Published и не удалённый; не найден → CHESSBOARD_PROJECT_NOT_FOUND.
    • Застройщик проекта; если его статус не Published — проект публично невидим (INV-DEV-6) → CHESSBOARD_PROJECT_NOT_FOUND.
    • Здание по id в этом проекте со статусом Published и не удалённое; не найдено → CHESSBOARD_BUILDING_NOT_FOUND. Условие принадлежности проекту проверяется вместе с существованием (несовпадение неотличимо от отсутствия — без утечки структуры чужих проектов).
  4. Сборка ответа и masking. Поля ответа — по таблице модели: плоские значения здания, ProjectName из проекта. При анониме PropertyObjectsFreeCount = null, IsLimited = true; для авторизованного значения отдаются как есть, IsLimited = false.
  5. Результат. Карточка здания, статус 200; не найдено/непублично → 404; нарушение проверки входа → 400.

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
VALIDATION_ERROR400Пустые ProjectId/BuildingId«Некорректные параметры запроса»no retry
CHESSBOARD_PROJECT_NOT_FOUND404Проект не существует / не публичен / застройщик скрыт«Проект не найден»no retry
CHESSBOARD_BUILDING_NOT_FOUND404Здание не существует / не Published / не принадлежит проекту / удалено«Здание не найдено»no retry
INTERNAL_ERROR500Инфраструктурный сбойgenericretry (backoff)

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

Breaking changes

Optional-поля — additive; изменение masking в сторону раскрытия — breaking (новая версия route).

  • Enum-строки: unknown-fallback на клиенте обязателен.
  • Logs: projectId, buildingId, actor type; metrics: chessboard_public_building_requests_total, latency histogram (SLO p99 < 300 мс); traces: OTel span chessboard.get-public-building.
  • Dashboard/runbook — chessboard-overview (README).

Acceptance Criteria

  • AC1 (полная проекция). Дано: авторизованный пользователь, published-здание published-проекта published-застройщика. Когда: GET. Тогда: 200, PropertyObjectsFreeCount заполнен, IsLimited = false.
  • AC2 (masking для анонима). Дано: тот же ресурс, вызывает аноним. Когда: GET. Тогда: 200, PropertyObjectsFreeCount = null, IsLimited = true.
  • AC3 (непубличный родитель). Дано: проект не Published или застройщик скрыт (INV-DEV-6). Когда: GET. Тогда: CHESSBOARD_PROJECT_NOT_FOUND (404) — причина не раскрывается.
  • AC4 (здание вне проекта/не published). Дано: BuildingId не принадлежит проекту, не Published или удалён. Когда: GET. Тогда: CHESSBOARD_BUILDING_NOT_FOUND (404), неотличимо от отсутствия.
  • AC5 (пустые идентификаторы). Дано: ProjectId/BuildingId = Guid.Empty. Когда: GET. Тогда: VALIDATION_ERROR (400).

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

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

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