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

UC-CTL-006. Карточка проекта (полная: шахматка, список объектов, инвест-аналитика)

Назначение

Авторизованный пользователь открывает полную карточку проекта: шахматка этажей, список всех объектов с ценами и статусами, детальная инвестиционная аналитика проекта, фильтры по списку объектов. Витрину и ассортимент объектов проекта отдаёт каталог (CatalogPropertyObjectCard); шахматку — chessboard (UC-CTL-009), аналитику — invest-analytics; факт просмотра — user-activity.

Metadata

ПолеЗначение
IDUC-CTL-006
Контекстcatalog (см. docs/06-services/catalog/) + чтение chessboard, invest-analytics
Типосновной
Статусdraft

Актор

ПолеЗначение
РольИнвестор / Агент / Девелопер / МенеджерПИН (авторизованные)
Permissions / scopeвалидный JWT; permissions на чтение не требуются; агент дополнительно получает блок комиссий по catalog.commissions.view (A3)
Tenantне применяется — платформенная витрина (ADR-0052 п.3)
Record-levelне применяется

Предусловие

  • Пользователь авторизован (JWT валиден); иначе — A1 (ограниченная версия / вход).
  • CatalogProjectCard.Status = Published; у проекта есть объекты недвижимости в витрине property_object_cards.

Триггер

ПолеЗначение
ИсточникUI navigation
Триггерящий элементОткрытие /hotels/[id]/info авторизованным пользователем; вкладка assortment (список объектов)

Основной Поток

  1. Пользователь открывает полную карточку проекта; интерфейс проверяет JWT — при отсутствии выполняется A1.
  2. Интерфейс запрашивает витринную часть карточки проекта по id — без маскирования (для авторизованного minPrice/maxPrice/propertyObjectsAvailable заполнены, masked = false) и параллельно детали вкладок из chessboard (как UC-CTL-005).
  3. Интерфейс открывает вкладку «Ассортимент» и запрашивает список объектов проекта с фильтрами: этаж (floor, диапазон NullableRange<short>), комнатность (rooms, short >= 0), цена (price, NullableRange<decimal>), корпус (buildingId, Guid), сортировка (sort, CatalogSort), курсор, размер страницы (1..30, по умолчанию 20).
  4. Каталог формирует список объектов:
    • Проверка входа. Границы floor >= -5 и well-formed Floor.Min <= Floor.Max, rooms >= 0, price well-formed Price.Min <= Price.Max, limit 1..30. Карточка проекта существует и Status = Published; иначе — CATALOG_PROJECT_NOT_FOUND (404).
    • Выборка. Объекты витрины ProjectId = id ∧ Status = Published с наложением фильтров этаж/комнатность/цена/корпус, порядок — сортировка UC-CTL-004.
    • Состав элемента списка ApartmentListItem (дом полей — catalog-property-object-card.md): id, number, title, typeName, buildingId/buildingName, badge, deliveryDate, stars, distanceMinutes, address, developer, payback {value, period}, reliability {value, max}, price (эффективная), areaTotal, pricePerMeter, growthPercent, rating, readinessPercent, rentalIncomePerYear, propertyObjectStatus (цены и статусы видны — пользователь авторизован). Инвестиционные показатели уровня проекта (Payback, GrowthPercent, Rating) — агрегаты карточки проекта, рассчитанные консюмером invest-analytics; детальная аналитика — по запросу в invest-analytics (шаг 6). AgentCommission включается только при permission catalog.commissions.view (A3).
    • Результат. Список объектов, nextCursor, hasMore, totalCount.
  5. Для шахматки интерфейс переходит в раздел «Шахматка» — UC-CTL-009 (интерактивная матрица этажи × секции с цветовой индикацией статусов; дом — chessboard).
  6. Для детальной инвестиционной аналитики проекта интерфейс запрашивает invest-analytics (динамика роста цены, серии доходности — docs/06-services/invest-analytics/).
  7. Клик по объекту в списке или в шахматке открывает карточку объекта недвижимости — UC-CTL-008.
  8. Интерфейс записывает факт просмотра полной карточки в user-activity: { targetKind = Project, targetId = id, sessionId, userId } + ActionEvent { kind = FullProjectCardOpened } — события действий пробрасываются в карточку лида (crm), просмотры — в статистику застройщика (dev-stats, ADR-0057).

Альтернативные Потоки

A1. Пользователь не авторизован

  1. Шаг 1: JWT отсутствует/истёк → интерфейс показывает ограниченную версию (UC-CTL-005) с CTA входа либо перенаправляет в auth-модалку.
  2. После входа — возврат к шагу 2.

A2. Фильтры списка объектов дают пустой результат

  1. Шаг 4 возвращает { items: [], totalCount: 0 }; интерфейс показывает «Нет объектов с такими параметрами» + сброс фильтров. Возврат к шагу 3.

A3. Актор — агент (показ комиссий)

  1. JWT содержит permission catalog.commissions.view: шаг 4 добавляет в каждый элемент списка agentCommission { percentMin, percentMax, baseKind } (комиссия в списке объектов; дом — catalog-property-object-card.md, VO PropertyObjectAgentCommission).
  2. Поток не меняется.

A4. invest-analytics недоступен

  1. Шаг 6 деградирует: блок детальной аналитики показывает skeleton/повтор; агрегатные метрики карточки (payback/rating) остаются — они денормализованы в витрине. Сценарий продолжается.

A5. chessboard недоступен (вкладки структуры / шахматка)

  1. Шаги 2 и 5 (детали вкладок и шахматка UC-CTL-009) падают по таймауту; витринная часть и список объектов (шаги 2, 4) уже отданы каталогом из витрины.
  2. Интерфейс показывает карточку со списком объектов и агрегатной аналитикой, но с skeleton/повтором на месте вкладок структуры и шахматки; просмотр всё равно записывается (шаг 8). Сценарий продолжается частично успешно.

A6. Устаревшая комиссия/статусы в момент открытия

  1. AgentCommission и PropertyObjectStatus в списке — денормализованы; комиссия обновляется консюмером rewards по версии правила (INV-5 карточки), статус — консюмером chessboard. В окне отставания консюмера агент может увидеть прежнюю комиссию, а статус объекта — прежнюю доступность.
  2. Отображение помечается eventual-свежестью; итоговую комиссию сделки и актуальный статус для брони подтверждают rewards/crm в источнике, не витрина. Поток не меняется.

Постусловие

  • Пользователь видит полную карточку: витрина, список объектов с ценами/статусами (с фильтрами), шахматка (UC-CTL-009), детальная аналитика.
  • В user-activity записаны просмотр полной карточки и ActionEvent — доступны агенту в карточке лида и застройщику в dev-stats.
  • Состояние каталога не изменилось (read-only).

Возможные Ошибки

КодHTTPУсловиеПоведение клиента
ValidationError400Невалидные фильтры (граница floor < -5, Price.Max < Price.Min, limit вне 1..30)Подсветить фильтр
Unauthorized401JWT отсутствует/истёк при запросе полных данныхA1: ограниченная версия / вход
CATALOG_PROJECT_NOT_FOUND404Проект отсутствует или Status != PublishedСтраница «Проект недоступен»

Kafka Интеграционные События

СобытиеTopicКогда публикуетсяConsumers
ActionEventRecorded (производит user-activity)pin.user-activity.actions.v1приём FullProjectCardOpened (шаг 8)crm (карточка лида)
PropertyObjectViewEnded (производит user-activity)pin.user-activity.property-object-view-ended.v1закрытие просмотра polling-ом (ADR-0056 п.3)catalog (популярность), dev-stats (статистика застройщика)

Acceptance Criteria

#КритерийПроверка
AC1Авторизованный видит точные цены и статусы всех Published-объектов недвижимости проектасравнение с гостевым ответом (masked)
AC2Фильтры списка объектов работают: этаж, комнатность, ценатри изолированных + комбинированный тест
AC3Список объектов возвращает контракт ApartmentListItem (все поля списка)контракт-тест полей ответа
AC4Объекты недвижимости со статусом карточки Hidden/Delisted в список не попадаютскрыть объект недвижимости оверрайдом → исчез
AC5Агент с catalog.commissions.view видит agentCommission; инвестор — нетдва актора, один запрос
AC6Просмотр полной карточки создаёт запись view + ActionEvent (FullProjectCardOpened) в user-activityпроверка записей
AC7Неавторизованный не получает полный список объектов недвижимости (401 → A1)запрос без JWT
AC8Недоступность chessboard (вкладки/шахматка) не рушит карточку: список объектов и аналитика отдаются, вкладки деградируют skeleton-ом, просмотр записантест с выключенным chessboard API

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

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

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

  • API метод: get-project.md, get-project-property-objects.md.
  • Domain entity: ../domain/catalog-project-card.md, ../domain/catalog-property-object-card.md (ApartmentListItem, PropertyObjectAgentCommission).
  • Шахматка: UC-CTL-009 + ../../chessboard/ (дом матрицы).
  • Аналитика: ../../invest-analytics/ (детальные серии/график роста).
  • Просмотры/действия: ../../user-activity/ (ADR-0054), ../../dev-stats/ (ADR-0057).
  • Связанные UC: UC-CTL-005 (ограниченная версия), UC-CTL-008 (карточка объекта недвижимости), UC-CTL-009 (шахматка).