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

UC-SEL-002. Шаринг подборки по ссылке (SharePopover + реферальная ссылка)

Назначение

Описывает сценарий, в котором владелец делится подборкой: подборка «привязана к текущему пользователю (владелец), но по ссылке (по ид) её может открыть кто угодно» (ТЗ.md:281). Прототип — SharePopover на странице /collection (prototype-mapping.md, строка /collection: «подборки из избранного + SharePopover с реф-ссылкой»): фронт комбинирует публичную ссылку подборки (PublicCode, контекст selections) с реферальной ссылкой владельца (контекст referral, existing-net) — получатель, перейдя по ссылке, попадает в реферальную воронку владельца (cookie referralUrl 30 дней, UC-1..3). Со стороны selections сценарий read-only: мутаций нет, ссылка существует с момента создания подборки (INV-SEL-005). Связан с контекстами selections и referral.

Metadata

ПолеЗначение
IDUC-SEL-002
Контекстselections (см. docs/06-services/selections/); интеграция — referral
Типосновной
Статусdraft

Актор

ПолеЗначение
РольИнвестор или Агент — владелец подборки (шаринг доступен любому владельцу; для агента это канал привлечения клиента — UC-SEL-005)
Permissions / scopeself-scope: список своих подборок — OwnerUserId = actor (INV-SEL-002); реф-ссылка — своя (referral, self-scope)
Tenantне tenanted (ADR-0052 п.2)
Record-levelGET /selections фильтруется по OwnerUserId = actor.UserId; чужую подборку «пошарить» нельзя — её PublicCode знает только тот, кому её уже открыли

Предусловие

  • У владельца есть хотя бы одна активная (не удалённая) подборка — UC-SEL-001 или создание вручную.
  • Для реф-части: у владельца есть (или создаётся на лету) дефолтная реферальная ссылка — операция getOrCreateDefaultReferralLink (referral, existing-net — ../../referral/README.md, будущий путь по конвенции).

Триггер

ПолеЗначение
ИсточникUI button
Триггерящий элементСтраница /collection → карточка подборки → кнопка «Поделиться» (SharePopover); заглушка прототипа «Поделиться подборкой» (prototype-mapping «Заглушки фронта»)

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

  1. Владелец открывает /collection; фронт отдаёт список GET /selections (query ListMySelectionsQuery, read-only: Filter(s => s.OwnerUserId == actor.UserId && s.DeletedAt == null, orderBy: CreatedAt desc); ответ каждой подборки содержит SelectionId, Title, PublicCode, ItemsCount, Source, CreatedAt).
  2. Владелец нажимает «Поделиться» у подборки — открывается SharePopover.
  3. Фронт строит ссылку локально, без запроса в selections (все данные уже есть):
    • базовая публичная ссылка: https://<host>/collection/{publicCode};
    • хук useShareReferralLink запрашивает у referral дефолтную реф-ссылку владельца (getOrCreateDefaultReferralLink — создаёт при первом обращении) и добавляет реф-параметр: итог https://<host>/collection/{publicCode}?ref={referralLinkId} (формат параметра — контракт referral, дом — docs/06-services/referral/ по конвенции).
  4. SharePopover предлагает: копировать ссылку / системный share / QR. Владелец копирует и отправляет получателю любым каналом (мессенджер, СМС — вне платформы).
  5. Получатель переходит по ссылке:
    • фронт по ?ref= ставит cookie referralUrl на 30 дней и валидирует ссылку (validateReferralLink, referral) — вход в реферальную воронку UC-1..3 (docs/02-architecture/scenarios/);
    • подборка открывается публично по publicCodeUC-SEL-003.
  6. Если получатель позже регистрируется/оставляет заявку — реферальная связь «кто привёл» создаётся по правилам привязки referral (Имя пустое / регистрация < 4 ч / владелец-агент — glossary «Реферальная связь»); для агента-владельца это ведёт к лиду в CRM.

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

A1. referral недоступен / реф-ссылку получить не удалось

  1. SharePopover деградирует до чистой публичной ссылки /collection/{publicCode} без ?ref= — шаринг подборки не блокируется реферальной системой; предупреждение владельцу не показывается (реф-атрибуция — бонус, не условие).
  2. Возврат к основному потоку, шаг 4.

A2. Подборка удалена между открытием списка и шарингом

  1. Ссылку построить можно (все данные локальны), но получатель получит 404 (SELECTIONS_NOT_FOUND — INV-SEL-009, UC-SEL-003 A1).
  2. Фронт владельца при обновлении списка перестаёт показывать удалённую подборку. Завершается.

A3. Получатель — уже авторизованный пользователь

  1. Cookie referralUrl ставится, но реферальная связь не возникнет (правила привязки referral отсеивают существующих пользователей вне окна); подборка открывается как обычно (UC-SEL-003 — любой актор). Завершается.

A4. Владелец делится «живой» подборкой и продолжает её править

  1. Ссылка не протухает (INV-SEL-005: PublicCode неизменяем); получатель всегда видит актуальное состояние подборки на момент открытия — подборка живая (заморозка состава существует только для постов, UC-SEL-004). Завершается.

A5. Реф-параметр ?ref= невалиден или чужой

  1. Получатель перешёл по ссылке, но validateReferralLink (referral) отклонил referralLinkId (устарел / отозван / не принадлежит никому): cookie referralUrl не ставится, реферальная воронка не активируется.
  2. Открытие самой подборки не зависит от валидности реф-части (это параллельный параметр selections) — подборка открывается по publicCode штатно (UC-SEL-003). Реф-атрибуция — бонус, не условие доступа. Завершается.

Постусловие

  • Состояние selections не изменилось (read-only сценарий; событий нет).
  • У получателя: подборка открыта (UC-SEL-003), cookie referralUrl на 30 дней (при наличии ?ref=).
  • Возможная будущая реферальная связь/лид — зона referral/crm (их UC).

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

КодHTTPУсловиеПоведение клиента
401401GET /selections без JWTAuth-модалка
5xx от referralРеф-ссылка недоступна (A1)Деградация: ссылка без ?ref=
SELECTIONS_NOT_FOUND404Получатель открыл удалённую подборку (A2)Страница «подборка не найдена»

Доменные События

Не поднимаются — read-only сценарий (изменений состояния в selections нет).

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

СобытиеTopicКогда публикуетсяConsumers
— (сценарий не публикует)

Факт «поделился подборкой» как ActionEvent не трекается на бэке selections (шаринг — клиентское действие копирования); просмотр получателем трекает user-activity при открытии (UC-SEL-003).

Acceptance Criteria

#КритерийПроверка
AC1GET /selections возвращает только активные подборки актора с PublicCode в каждойинтеграционный тест + тест изоляции (чужие не видны)
AC2SharePopover строит ?ref={referralLinkId} из дефолтной реф-ссылки владельца; при первом шаринге ссылка создаётся (getOrCreateDefaultReferralLink)e2e-тест фронта с mock referral
AC3При недоступном referral копируется ссылка без ?ref= (A1)e2e-тест деградации
AC4Переход получателя ставит cookie referralUrl на 30 дней и открывает подборку без авторизациисквозной тест UC-SEL-002 → UC-SEL-003
AC5PublicCode в разосланной ссылке остаётся рабочим после переименования/правки состава подборки (A4, INV-SEL-005)интеграционный тест
AC6Невалидный/чужой ?ref= не мешает открыть подборку по publicCode; cookie referralUrl не ставится (A5)e2e-тест деградации реф-части

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

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

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

  • Открытие получателем: UC-SEL-003 (публичный query).
  • Агентский сценарий поверх шаринга: UC-SEL-005.
  • Domain entity: ../domain/selection.md (PublicCode, INV-SEL-005).
  • API метод: ../api/public/list-my-selections.md (будущий путь по конвенции).
  • Реферальная система: docs/06-services/referral/README.md (будущий путь; getOrCreateDefaultReferralLink, validateReferralLink, правила привязки — existing-net, prototype-mapping «valio/referrals»); сквозные сценарии UC-1..3 — docs/02-architecture/scenarios/.
  • Правила: use-case-template, cross-cutting-document-requirements.