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

GET /api/developers/v1/ranking-rules — Список правил ранжирования застройщика

Назначение

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

Metadata

ПолеЗначение
Сервис/контекстcatalog
API areadevelopers
Feature groupranking
Статусdraft
Документdocs/06-services/catalog/api/developers/list-ranking-rules.md

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

ПроверкаЗначение
Actor typeUser (менеджер застройщика — JWT identity)
Auth policy / Permissionspermission catalog.ranking.view в scope организации или группы проектов/проекта (Scoped-RBAC — identity/domain/permission.md)
Scope (RBAC)организация (компания-застройщик) и ниже
Tenant isolationTenantId = CompanyId застройщика из identity claims (ADR-0052); выборка catalog.ranking_rules автоматически режется по TenantId

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/developers/v1/ranking-rules
Success status200
Idempotency headerне применяется (чтение)
Correlationсквозной trace через traceparent

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
TenantIdidentity claimsGuidДаRequired (= CompanyId застройщика)tenant isolation
TargetKindquerystring? (enum RankingTargetKind)Нет∈ {Project, PropertyObject}; null — оба вида
Statusquerystring? (enum RankingRuleStatus)Нет∈ {Active, Disabled}; null — все
TargetProjectIdqueryGuid?Нет!= Guid.Empty при заполнении; фильтр «правила одного проекта» (проектное правило + правила объектов недвижимости проекта)
PagequeryintНет (default 1)>= 1
PageSizequeryintНет (default 50)1..200

Модель ответа — пагинированный список RankingRuleListItem

Пагинированный контейнер (Items, TotalCount, Page, PageSize).

Модель RankingRuleListItem

ПолеТипОбязательностьИсточникMaskingОписание
IdGuidДаDeveloperRankingRule.IdПравило.
TargetKindstring (enum RankingTargetKind)ДаDeveloperRankingRule.TargetKindProject / PropertyObject.
TargetIdGuidДаDeveloperRankingRule.TargetIdЦель.
TargetNamestringДаCatalogProjectCard.Name / CatalogPropertyObjectCard.Title (батч-джойн шага 3)Отображаемое имя цели.
TargetProjectIdGuidДаTargetId (Project) / CatalogPropertyObjectCard.ProjectId (PropertyObject)Проект цели (для группировки в UI).
TargetCardStatusstring (enum PropertyObjectCardStatus/ProjectCardStatus)Дакарточка целиВидимость цели (правило по Delisted-цели показывается с пометкой).
PriorityintДаDeveloperRankingRule.Priority0..1000.
Statusstring (enum RankingRuleStatus)ДаDeveloperRankingRule.StatusActive / Disabled.
UpdatedAtDateTimeOffsetДаDeveloperRankingRule.UpdatedAtПоследняя правка.
UpdatedByUserIdGuid?НетUpdatedByUserId ?? CreatedByUserIdАвтор последней правки.
VersionlongДаDeveloperRankingRule.VersionДля optimistic-check мутаций.

Алгоритм

  1. Контекст и доступ. Актор — менеджер застройщика (JWT + permission catalog.ranking.view); TenantId из claims. Идемпотентность не применяется (чтение).
  2. Проверка входа. enum-значения TargetKind/Status, границы Page/PageSizeValidationError.
  3. Что читаем. Правила застройщика по фильтрам (TargetKind/Status/TargetProjectId) с пагинацией; к выборке автоматически добавляется TenantId = CompanyId; при TargetProjectId — проектное правило этого проекта + правила объектов недвижимости этого проекта. Фильтр TargetProjectId, указывающий на чужой/несуществующий проект, режется тем же TenantId и даёт пустую страницу (200, Items = []), а не 404/403 — чужие цели неотличимы от отсутствующих. Сортировка детерминирована и стабильна между страницами: TargetKind, Priority desc, UpdatedAt desc, финальный tie-break Id (иначе правила с равными Priority/UpdatedAt дрейфовали бы между страницами при keyset/offset-обходе). Затем батч-загрузка целей (карточки проектов и объектов недвижимости) — для TargetName/TargetProjectId/TargetCardStatus.
  4. Маппинг. Поля правила → одноимённые поля item-а; TargetName ← название проекта/объекта недвижимости; цель не найдена в карточках (делистинг + retention-очистка) → TargetName = "(объект удалён)", TargetCardStatus = Delisted (правило показывается — застройщик должен видеть «висящее» правило, чтобы удалить его).
  5. Результат. Пагинированный список RankingRuleListItem (200); нет ни одного правила (у застройщика нет настроек ранжирования либо фильтр сузил до нуля) → 200 с Items = [], TotalCount = 0 (не ошибка); страница за пределами TotalCount → пустой Items, TotalCount неизменен. Freshness — source of truth этого контекста (лага нет).

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
ValidationError400Невалидные enum/pagingОшибка валидации запросаno retry
UNAUTHORIZED401Нет/просрочен JWTТребуется авторизацияno retry
FORBIDDEN403Нет permission catalog.ranking.view в scopeДоступ запрещёнno retry
Пустой результат — не ошибка

200 с Items = [], TotalCount = 0 — у застройщика нет правил ранжирования либо фильтр сузил выборку до нуля; сюда же попадает TargetProjectId, указывающий на чужой/несуществующий проект (режется тем же TenantId — чужая цель неотличима от отсутствующей). Страница за пределами TotalCount — тот же пустой Items, TotalCount не меняется. 404/403 за отсутствие/чужеродность цели в этой операции не используются.

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

  • Новые optional поля item-а — additive; удаление/переименование — breaking (migration + rollout).
  • Logs: ranking-rules-listed (tenantId, фильтры, count); metrics: catalog_developers_operations_total{operation="list-ranking-rules"}, duration; traces: span приёма → span обработки → span обращения к хранилищу; correlation — сквозной trace через traceparent. Dashboard catalog-overview.

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

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

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