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

GET /api/v1/catalog/filters — Справочники значений фильтров

Назначение

Отдаёт значения для панели «Дополнительные фильтры» лент проектов и объектов недвижимости: доступные типы объектов, классы, регионы, города, статусы строительства, варианты комнатности, глобальные границы цен и список сортировок. Возвращает только значения, реально присутствующие в опубликованных (Published) карточках, плюс статические enum-ы — чтобы в UI не было пустых фильтров. Вызывается один раз при открытии панели; доступен и гостю (границы цен для гостя округляются — MASK-PRICE, README.md). Источники значений — витринные проекции catalog-project-card и catalog-property-object-card.

Источник гео-значений

Своей реплики справочника handbook (регионы/города) у каталога нет: regions/cities строятся distinct-ом пар (RegionId, RegionName) / (CityId, CityName) по проекциям — id и display-имена приходят денормализованными в снапшотах событий chessboard.

Metadata

ПолеЗначение
Сервис/контекстcatalog
API areapublic
Feature groupfeed
Статусdraft

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

ПроверкаЗначение
Actor typeGuest / RefGuest / User (без гейта)
Auth policy / Permissionsnone
Scopeплатформа
Tenant isolationне применяется (платформенная витрина)
Auditnone

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/catalog/filters
Success status200
Idempotencyне применяется (safe GET)
CorrelationOpenTelemetry trace (traceparent)

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
KindqueryProjectKind?Нетenum ResidentialComplex/ApartHotel; сужает справочники до ленты /lots или /hotels; отсутствует — по всем Published
ActorClassidentity middlewareGuest/RefGuest/UserДаневалидный токен → 401определяет MASK-PRICE для priceBounds

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

ПолеТипОбязательностьИсточникMaskingОписание
kindsIReadOnlyList<FilterOptionModel>Даdistinct Kind опубликованных проектовТипы проектов (ЖК/отель).
propertyClassesIReadOnlyList<FilterOptionModel>Даdistinct PropertyClass проектовКлассы (фильтр «класс»).
constructionStatusesIReadOnlyList<FilterOptionModel>Даdistinct ConstructionStatus проектовСтатусы строительства.
regionsIReadOnlyList<RegionOptionModel>Даdistinct (RegionId,RegionName) опубликованных проектов, по имениРегионы (фильтр «регион»).
citiesIReadOnlyList<CityOptionModel>Даdistinct (CityId,CityName) опубликованных проектов, по имениГорода (фильтр «город»).
propertyObjectTypeNamesIReadOnlyList<FilterOptionModel>Даdistinct TypeName опубликованных объектовТипы объектов (фильтр «тип» ленты объектов недвижимости).
roomsCountsIReadOnlyList<short>Даdistinct RoomsCount объектов, по возрастаниюВарианты комнатности (0 = студия).
priceBoundsNullableRange<decimal>Даминимальная / максимальная Price опубликованных объектовMASK-PRICE (Guest: min↓/max↑ до 100 000 ₽)Границы слайдера цены (ref-модель — README.md); null/null — каталог пуст.
sortsIReadOnlyList<FilterOptionModel>Дастатический список enum FeedSort (README.md)Доступные сортировки для выпадающего списка.

FilterOptionModel

ПолеТипОбязательностьОписание
valuestringДаЗначение для query-параметра (enum-string / TypeName как есть).
labelstringДаОтображаемый текст (ru): enum → словарь локализации API; TypeName → само значение.

RegionOptionModel

ПолеТипОбязательностьОписание
regionIdlongДаRegionId — значение query-параметра regionId лент (ссылка на справочник handbook).
regionNamestringДаRegionName — отображаемый текст опции.

CityOptionModel

ПолеТипОбязательностьОписание
cityIdlongДаCityId — значение query-параметра cityId лент (ссылка на справочник handbook).
cityNamestringДаCityName — отображаемый текст опции.

Алгоритм

  1. Контекст и доступ. Актор без гейта — гость допустим; невалидный токен → 401. Idempotency неприменима (чтение).
  2. Проверка входа. Kind ∈ enum {ResidentialComplex, ApartHotel} — иначе ValidationError (400). Существование/состояние проверять нечего: пустой каталог — валидный ответ с пустыми списками.
  3. Сбор справочников. По опубликованным карточкам собрать уникальные значения: из проектов — типы, классы, статусы строительства, пары (RegionId, RegionName) и (CityId, CityName) (карточки с нерезолвленным гео — RegionId/CityId = null — в значения фильтров не попадают; у Published гео резолвлено — INV-PRJ-3 источника); из объектов недвижимости — типы объектов, варианты комнатности (по возрастанию), минимальную и максимальную цену. При заданном Kind выборка сужается до соответствующей ленты.
  4. Сборка ответа. Enum-значения превращаются в FilterOptionModel через словарь локализации API (Comfort → «Комфорт», InProgress → «Строится» и т.д.); TypeName — как есть; sorts — статический список FeedSort. Для гостя над priceBounds применяется MASK-PRICE.
  5. Результат. CatalogFiltersModel → 200. Консистентность — eventual; свежесть некритична (справочник панели фильтров), допустим HTTP-кэш Cache-Control: public, max-age=300 (значение — конфигурация).

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
— (auth)401Передан невалидный/просроченный токенбез тела схемыre-login
ValidationError400Kind вне enumСписок ошибок полейno retry
Пустой каталог — не ошибка

200 со всеми пустыми списками и priceBounds = null/null — валидный ответ (UI прячет фильтры).

Acceptance Criteria

  • Непустой каталог. Дано опубликованные проекты классов Comfort/Business и объекты недвижимости с комнатностью 0/1/2. Когда авторизованный пользователь открывает панель. Тогда propertyClasses содержит только Comfort и Business (реально присутствующие), roomsCounts = [0,1,2] по возрастанию, priceBounds — фактические min/max, sorts — полный статический список FeedSort.
  • Гео-опции из проекций. Дано опубликованные проекты одного региона в двух городах. Когда собираются справочники. Тогда regions содержит одну пару (regionId, regionName), cities — две; регионы и города, у которых нет опубликованных проектов, в списках не появляются (статического справочника регионов у каталога нет).
  • Сужение по Kind. Дано Kind = ApartHotel. Когда собираются справочники. Тогда значения берутся только из лент апарт-отелей; значения, присущие лишь ЖК, в списках не появляются.
  • Гость — маскирование границ. Дано актор Guest. Когда возвращается priceBounds. Тогда min округлён вниз, max — вверх до 100 000 ₽ (MASK-PRICE); остальные списки без изменений.
  • Пустой каталог. Дано нет опубликованных карточек. Когда приходит запрос. Тогда 200 со всеми пустыми списками и priceBounds = null/null — не ошибка (UI прячет фильтры).
  • Невалидный Kind. Дано Kind = Cottage. Когда приходит запрос. Тогда ValidationError (400), справочники не собираются.
  • Свежесть. Дано только что опубликованный проект (лаг проекции консюмера). Когда клиент запросил фильтры. Тогда в пределах окна eventual-consistency новые значения могут отсутствовать; ответ кэшируется Cache-Control: max-age=300, расхождение сходится по мере догона проекции.

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

  • Новые списки-справочники — additive; удаление списка или смена формата value — breaking. Локализация label — не контракт (фронт использует value).
  • Logs: Kind, размеры списков; metrics — catalog_filters_requests_total, latency histogram; traces/dashboard — общие правила area (README.md).

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

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

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