UC-CTL-006. Карточка проекта (полная: шахматка, список объектов, инвест-аналитика)
Назначение
Авторизованный пользователь открывает полную карточку проекта: шахматка этажей, список всех объектов с
ценами и статусами, детальная инвестиционная аналитика проекта, фильтры по списку объектов. Витрину и
ассортимент объектов проекта отдаёт каталог (CatalogPropertyObjectCard); шахматку — chessboard
(UC-CTL-009), аналитику — invest-analytics; факт просмотра — user-activity.
Metadata
| Поле | Значение |
|---|---|
| ID | UC-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 (список объектов) |
Основной Поток
- Пользователь открывает полную карточку проекта; интерфейс проверяет JWT — при отсутствии выполняется A1.
- Интерфейс запрашивает витринную часть карточки проекта по
id— без маскирования (для авторизованногоminPrice/maxPrice/propertyObjectsAvailableзаполнены,masked = false) и параллельно детали вкладок изchessboard(как UC-CTL-005). - Интерфейс открывает вкладку «Ассортимент» и запрашивает список объектов проекта с фильтрами: этаж
(
floor, диапазонNullableRange<short>), комнатность (rooms,short >= 0), цена (price,NullableRange<decimal>), корпус (buildingId,Guid), сортировка (sort,CatalogSort), курсор, размер страницы (1..30, по умолчанию 20). - Каталог формирует список объектов:
- Проверка входа. Границы
floor>= -5и well-formedFloor.Min <= Floor.Max,rooms >= 0,pricewell-formedPrice.Min <= Price.Max,limit1..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включается только при permissioncatalog.commissions.view(A3). - Результат. Список объектов,
nextCursor,hasMore,totalCount.
- Проверка входа. Границы
- Для шахматки интерфейс переходит в раздел «Шахматка» — UC-CTL-009 (интерактивная матрица
этажи × секции с цветовой индикацией статусов; дом —
chessboard). - Для детальной инвестиционной аналитики проекта интерфейс запрашивает
invest-analytics(динамика роста цены, серии доходности —docs/06-services/invest-analytics/). - Клик по объекту в списке или в шахматке открывает карточку объекта недвижимости — UC-CTL-008.
- Интерфейс записывает факт просмотра полной карточки в
user-activity:{ targetKind = Project, targetId = id, sessionId, userId }+ActionEvent { kind = FullProjectCardOpened }— события действий пробрасываются в карточку лида (crm), просмотры — в статистику застройщика (dev-stats, ADR-0057).
Альтернативные Потоки
A1. Пользователь не авторизован
- Шаг 1: JWT отсутствует/истёк → интерфейс показывает ограниченную версию (UC-CTL-005) с CTA входа либо перенаправляет в auth-модалку.
- После входа — возврат к шагу 2.
A2. Фильтры списка объектов дают пустой результат
- Шаг 4 возвращает
{ items: [], totalCount: 0 }; интерфейс показывает «Нет объектов с такими параметрами» + сброс фильтров. Возврат к шагу 3.
A3. Актор — агент (показ комиссий)
- JWT содержит permission
catalog.commissions.view: шаг 4 добавляет в каждый элемент спискаagentCommission { percentMin, percentMax, baseKind }(комиссия в списке объектов; дом — catalog-property-object-card.md, VOPropertyObjectAgentCommission). - Поток не меняется.
A4. invest-analytics недоступен
- Шаг 6 деградирует: блок детальной аналитики показывает skeleton/повтор; агрегатные метрики карточки (payback/rating) остаются — они денормализованы в витрине. Сценарий продолжается.
A5. chessboard недоступен (вкладки структуры / шахматка)
- Шаги 2 и 5 (детали вкладок и шахматка UC-CTL-009) падают по таймауту; витринная часть и список объектов (шаги 2, 4) уже отданы каталогом из витрины.
- Интерфейс показывает карточку со списком объектов и агрегатной аналитикой, но с skeleton/повтором на месте вкладок структуры и шахматки; просмотр всё равно записывается (шаг 8). Сценарий продолжается частично успешно.
A6. Устаревшая комиссия/статусы в момент открытия
AgentCommissionиPropertyObjectStatusв списке — денормализованы; комиссия обновляется консюмеромrewardsпо версии правила (INV-5 карточки), статус — консюмеромchessboard. В окне отставания консюмера агент может увидеть прежнюю комиссию, а статус объекта — прежнюю доступность.- Отображение помечается eventual-свежестью; итоговую комиссию сделки и актуальный статус для брони
подтверждают
rewards/crmв источнике, не витрина. Поток не меняется.
Постусловие
- Пользователь видит полную карточку: витрина, список объектов с ценами/статусами (с фильтрами), шахматка (UC-CTL-009), детальная аналитика.
- В
user-activityзаписаны просмотр полной карточки иActionEvent— доступны агенту в карточке лида и застройщику вdev-stats. - Состояние каталога не изменилось (read-only).
Возможные Ошибки
| Код | HTTP | Условие | Поведение клиента |
|---|---|---|---|
ValidationError | 400 | Невалидные фильтры (граница floor < -5, Price.Max < Price.Min, limit вне 1..30) | Подсветить фильтр |
Unauthorized | 401 | JWT отсутствует/истёк при запросе полных данных | A1: ограниченная версия / вход |
CATALOG_PROJECT_NOT_FOUND | 404 | Проект отсутствует или 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 |
Обратные ссылки
Автоссылки: где используется этот документ.
- registries (1): Реестр use cases и user stories PIN
Связанные Документы
- 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 (шахматка).