GET /api/v1/developers/projects/{projectId}/buildings — Список зданий проекта
Назначение
Раздел «Здания» страницы проекта в кабинете застройщика: список литеров/корпусов проекта своей компании с
пагинацией и фильтрами по статусу и статусу строительства — с этажностью, сроком сдачи, готовностью и
счётчиками объектов недвижимости. Дом полей — сущность Здание.
| Поле | Значение |
|---|
| Сервис/контекст | chessboard |
| API area | developers |
| Feature group | buildings |
| Статус | draft |
| Документ | docs/06-services/chessboard/api/developers/search-buildings.md |
Актор и доступ
| Проверка | Значение |
|---|
| Actor type | User (менеджер застройщика) |
| Auth policy / Permissions | chessboard.buildings.manage |
| Scope (RBAC) | организация / группа проектов / проект (projectId в scope) |
| Tenant isolation | TenantId = CompanyId из JWT; чужой проект → 404 |
HTTP-контракт
| Поле | Значение |
|---|
| Method | GET |
| Route | /api/v1/developers/projects/{projectId}/buildings |
| Success status | 200 |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|
TenantId | identity claims (tenant_id) | Guid | Да | Required | Tenant isolation |
ProjectId | route | Guid | Да | существующий проект tenant-а | 404 при чужом |
Page | query | int | Нет (default 1) | >= 1 | — |
PageSize | query | int | Нет (default 50) | 1..200 (корпусов в проекте немного) | — |
Statuses | query (csv) | BuildingStatus[]? | Нет | Draft/Published/Hidden | — |
ConstructionStatuses | query (csv) | ConstructionStatus[]? | Нет | enum reference-data.md | — |
Search | query | string? | Нет | <= 128; lower(name) like lower(@Search%) | — |
IncludeDeleted | query | bool | Нет (default false) | false → DeletedAt == null | — |
Модель ответа SearchDeveloperBuildingsResult
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|
Items | DeveloperBuildingListItem[] | Да | проекция BuildingEntity | — | Страница зданий. |
Page / PageSize | int | Да | echo | — | Пагинация. |
TotalCount | long | Да | подсчёт под фильтром | — | Всего под фильтром. |
Модель DeveloperBuildingListItem
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|
Id | Guid | Да | BuildingEntity.Id | — | Id здания. |
ProjectId | Guid | Да | ProjectId | — | Проект. |
Status | BuildingStatus | Да | Status | — | Draft/Published/Hidden. |
Name | string | Да | Name | — | «Литер 3», «Корпус Б». |
Code | string? | Нет | Code | — | Технический код. |
FloorsTotal | short | Да | FloorsTotal | — | Этажность. |
SectionsCount | short? | Нет | SectionsCount | — | Секции. |
DeliveryYear | short? | Нет | DeliveryYear | — | Год сдачи. |
DeliveryQuarter | short? | Нет | DeliveryQuarter | — | Квартал сдачи. |
ConstructionStatus | ConstructionStatus | Да | ConstructionStatus | — | Статус строительства. |
ReadinessPercent | decimal | Да | ReadinessPercent | — | Готовность 0..100. |
PropertyObjectsTotalCount | int | Да | PropertyObjectsTotalCount | — | Всего объектов недвижимости (денормализация). |
PropertyObjectsFreeCount | int | Да | PropertyObjectsFreeCount | — | Свободных объектов недвижимости. |
SyncSource | ChessboardSyncSource | Да | SyncSource | — | Pin/TalentChessboard. |
Version | long | Да | Version | — | Для PUT. |
Предусловия
- Пользователь авторизован;
tenant_id = его компания-застройщик.
- У актора есть permission
chessboard.buildings.manage в scope, покрывающем projectId.
- Проект-родитель существует и принадлежит tenant-у актора (любой статус); иначе — 404.
Алгоритм
Операция read-only, доменных событий не публикует.
- Контекст и доступ. Операцию выполняет менеджер застройщика; tenant — его компания; требуется право
chessboard.buildings.manage в scope, покрывающем projectId. Нет permission ни в одном scope →
FORBIDDEN (403); просроченный/отозванный доступ → UNAUTHORIZED (401) / FORBIDDEN (403).
- Проверка входа. Диапазоны paging, csv-enum-ы (
Statuses/ConstructionStatuses), длина Search —
иначе ValidationError (400). Неизвестное значение enum → ValidationError. Проект-родитель существует в
пределах tenant-а и его ProjectId входит в scope актора — иначе CHESSBOARD_PROJECT_NOT_FOUND (404;
чужой/вне-scope проект неотличим от отсутствия, существование не раскрывается). Допустим любой статус
проекта.
- Выборка. Страница зданий проекта собирается по фильтрам:
ProjectId + tenant-фильтр,
Statuses/ConstructionStatuses (совпадение по множеству), Search (префикс имени),
DeletedAt == null при !IncludeDeleted; сортировка по имени (натуральный порядок литеров). Считается
TotalCount под тем же фильтром. Пустой результат (нет зданий или ни одно не прошло фильтр) — валиден:
200 с Items = [], TotalCount = 0. Запрос страницы за пределами последней (Page > ceil(TotalCount/PageSize))
— тоже 200 с Items = [] и фактическим TotalCount.
- Результат. Возвращаются
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 |
|---|
ValidationError | 400 | Неверные paging/enum | Список ошибок полей | no retry |
CHESSBOARD_PROJECT_NOT_FOUND | 404 | Проект не найден / чужой tenant | «Проект не найден» | no retry |
FORBIDDEN | 403 | Нет 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 не требуется.
Обратные ссылки
Автоссылки: где используется этот документ.
Связанные документы