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

GET /api/v1/developers/projects/{projectId}/buildings — Список зданий проекта

Назначение

Раздел «Здания» страницы проекта в кабинете застройщика: список литеров/корпусов проекта своей компании с пагинацией и фильтрами по статусу и статусу строительства — с этажностью, сроком сдачи, готовностью и счётчиками объектов недвижимости. Дом полей — сущность Здание.

Metadata

ПолеЗначение
Сервис/контекстchessboard
API areadevelopers
Feature groupbuildings
Статусdraft
Документdocs/06-services/chessboard/api/developers/search-buildings.md

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

ПроверкаЗначение
Actor typeUser (менеджер застройщика)
Auth policy / Permissionschessboard.buildings.manage
Scope (RBAC)организация / группа проектов / проект (projectId в scope)
Tenant isolationTenantId = CompanyId из JWT; чужой проект → 404

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/developers/projects/{projectId}/buildings
Success status200
Correlationсквозной trace через заголовок traceparent

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
TenantIdidentity claims (tenant_id)GuidДаRequiredTenant isolation
ProjectIdrouteGuidДасуществующий проект tenant-а404 при чужом
PagequeryintНет (default 1)>= 1
PageSizequeryintНет (default 50)1..200 (корпусов в проекте немного)
Statusesquery (csv)BuildingStatus[]?НетDraft/Published/Hidden
ConstructionStatusesquery (csv)ConstructionStatus[]?Нетenum reference-data.md
Searchquerystring?Нет<= 128; lower(name) like lower(@Search%)
IncludeDeletedqueryboolНет (default false)falseDeletedAt == null

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

ПолеТипОбязательностьИсточникMaskingОписание
ItemsDeveloperBuildingListItem[]Дапроекция BuildingEntityСтраница зданий.
Page / PageSizeintДаechoПагинация.
TotalCountlongДаподсчёт под фильтромВсего под фильтром.

Модель DeveloperBuildingListItem

ПолеТипОбязательностьИсточникMaskingОписание
IdGuidДаBuildingEntity.IdId здания.
ProjectIdGuidДаProjectIdПроект.
StatusBuildingStatusДаStatusDraft/Published/Hidden.
NamestringДаName«Литер 3», «Корпус Б».
Codestring?НетCodeТехнический код.
FloorsTotalshortДаFloorsTotalЭтажность.
SectionsCountshort?НетSectionsCountСекции.
DeliveryYearshort?НетDeliveryYearГод сдачи.
DeliveryQuartershort?НетDeliveryQuarterКвартал сдачи.
ConstructionStatusConstructionStatusДаConstructionStatusСтатус строительства.
ReadinessPercentdecimalДаReadinessPercentГотовность 0..100.
PropertyObjectsTotalCountintДаPropertyObjectsTotalCountВсего объектов недвижимости (денормализация).
PropertyObjectsFreeCountintДаPropertyObjectsFreeCountСвободных объектов недвижимости.
SyncSourceChessboardSyncSourceДаSyncSourcePin/TalentChessboard.
VersionlongДаVersionДля PUT.

Предусловия

  • Пользователь авторизован; tenant_id = его компания-застройщик.
  • У актора есть permission chessboard.buildings.manage в scope, покрывающем projectId.
  • Проект-родитель существует и принадлежит tenant-у актора (любой статус); иначе — 404.

Алгоритм

Операция read-only, доменных событий не публикует.

  1. Контекст и доступ. Операцию выполняет менеджер застройщика; tenant — его компания; требуется право chessboard.buildings.manage в scope, покрывающем projectId. Нет permission ни в одном scope → FORBIDDEN (403); просроченный/отозванный доступ → UNAUTHORIZED (401) / FORBIDDEN (403).
  2. Проверка входа. Диапазоны paging, csv-enum-ы (Statuses/ConstructionStatuses), длина Search — иначе ValidationError (400). Неизвестное значение enum → ValidationError. Проект-родитель существует в пределах tenant-а и его ProjectId входит в scope актора — иначе CHESSBOARD_PROJECT_NOT_FOUND (404; чужой/вне-scope проект неотличим от отсутствия, существование не раскрывается). Допустим любой статус проекта.
  3. Выборка. Страница зданий проекта собирается по фильтрам: ProjectId + tenant-фильтр, Statuses/ConstructionStatuses (совпадение по множеству), Search (префикс имени), DeletedAt == null при !IncludeDeleted; сортировка по имени (натуральный порядок литеров). Считается TotalCount под тем же фильтром. Пустой результат (нет зданий или ни одно не прошло фильтр) — валиден: 200 с Items = [], TotalCount = 0. Запрос страницы за пределами последней (Page > ceil(TotalCount/PageSize)) — тоже 200 с Items = [] и фактическим TotalCount.
  4. Результат. Возвращаются Items, Page, PageSize, TotalCount; HTTP 200. Freshness — read-committed снимок; счётчики объектов недвижимости (PropertyObjectsTotalCount/PropertyObjectsFreeCount) могут отставать до фонового пересчёта агрегатов (project-aggregates-recalc, окно ~40 с).

Acceptance Criteria

  • Happy path. Given проект tenant-а с несколькими зданиями; When GET .../projects/{projectId}/buildings; Then 200 с страницей зданий, отсортированной по имени, и корректным TotalCount.
  • Фильтр по статусу. Given Statuses=Published; When запрос; Then только Published-здания.
  • Пустой/за-предельный. Given фильтр без совпадений или Page за последней страницей; When запрос; Then 200, Items = [], TotalCount соответствует фильтру.
  • Чужой/вне-scope проект. Given projectId чужого tenant-а или вне scope; When запрос; Then 404 CHESSBOARD_PROJECT_NOT_FOUND.
  • Невалидный вход. Given PageSize вне 1..200 или неизвестный ConstructionStatus; When запрос; Then 400 ValidationError.
  • Нет права. Given нет chessboard.buildings.manage; When запрос; Then 403 FORBIDDEN.

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
ValidationError400Неверные paging/enumСписок ошибок полейno retry
CHESSBOARD_PROJECT_NOT_FOUND404Проект не найден / чужой tenant«Проект не найден»no retry
FORBIDDEN403Нет chessboard.buildings.manage«Недостаточно прав»no retry

Сквозные ошибки области (UNAUTHORIZED 401 — нет/просрочен JWT) — по реестру README.md, здесь не повторяются.

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

  • Новые optional фильтры/поля — additive; смена семантики default-сортировки — breaking (rollout); enum-строки (BuildingStatus/ConstructionStatus/ChessboardSyncSource) — клиентский fallback на unknown обязателен.
  • Logs: TenantId, ProjectId, применённые фильтры (без значения Search), TotalCount; metrics: chessboard_developers_buildings_search_total, latency p99 < 300 мс (SLO README); traces: OTel (traceparent). Dashboard chessboard-overview; read-only — runbook не требуется.

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

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

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