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

UC-REF-006. Ссылка от инвестора (не агента/застройщика) → связь без лида (модификатор R5)

Назначение

Привязка по ссылке, владелец которой не является агентом или застройщиком (например, инвестор пригласил друга): реферальная связь для будущих выплат создаётся по базовому правилу (R1 при регистрации, R2 при авторизации в окне lazy-регистрации), но лид в CRM НЕ создаётся — модификатор R5 NonAgentOwnerNoLead, инвариант INV-REF-002 attach-rules.md. Связан с контекстом referral.

Metadata

ПолеЗначение
IDUC-REF-006
Контекстreferral (см. docs/06-services/referral/)
Типальтернативный (модификатор базовых потоков UC-REF-003/004)
Статусdraft

Актор

ПолеЗначение
РольSystem (обработка события регистрации/входа, m2m ACL Kafka); реферер — Инвестор (или PartnerManager/PinEmployee — «не агент/застройщик» по таблице ролей attach-rules.md); приглашённый — Инвестор
Permissions / scopepermission не применяется (system actor)
TenantTenantId = link.TenantId: у реферера-инвестора null (ADR-0052) — связь и журнал вне tenant-а
Record-levelчтение связей — по ReferredUserId (getMyReferrer) и ReferrerUserId (список приглашённых владельца)

Предусловие

  • Владелец ссылки имеет ReferralUserReplica.Type ∈ {Investor, PartnerManager, PinEmployee} — «не агент/застройщик» (таблица «Термины и роли владельца ссылки» attach-rules.md); человек, работающий и как агент, имеет отдельную учётку Agent — для правил важен тип учётки-владельца конкретной ссылки.
  • Приглашённый открыл ссылку — cookie referralUrl жива (UC-REF-002).
  • Выполнены условия базового правила: регистрация с ReferrerUrl (R1, UC-REF-003) или авторизация в окне lazy-регистрации (R2, UC-REF-004).
  • Guard-ы G1–G5 attach-rules.md выполнены.

Триггер

ПолеЗначение
ИсточникKafka event
Триггерящий элементT1: событие регистрации UserUpsertedKafkaEvent (pin.identity.users.v1, first-seen c ReferrerUrl) — основной поток; T2: событие входа UserSignedInKafkaEvent (pin.identity.sign-ins.v1) — альтернатива A1

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

Поток повторяет UC-REF-003 (общий алгоритм привязки, attach-rules.md); ниже — дельта модификатора R5.

  1. Инвестор-реферер делится своей ссылкой (UC-REF-001); его друг открывает её (cookie) и регистрируется; identity публикует UserUpsertedKafkaEvent с ReferrerUrl = slug.
  2. Контекст и guard-ы. Идемпотентность first-seen (INV-REF-R1), guard-ы G1–G5; тип владельца ссылки читается как owner.Type = Investor.
  3. Базовое правило R1 — создание связи. Создаётся ReferralBondEntity: ReferredUserId = event.UserId, ReferrerUserId = link.OwnerUserId, ReferralLinkId = link.Id, TenantId = link.TenantId (null у инвестора), BoundAt = время события, AppliedRule = R1, Status = Active. Проверка INV-REF-002: owner.Type ∉ {Agent, DeveloperManager}лид не требуется (модификатор R5; в AppliedRule R5 не записывается — его след — поле LeadRequested = false журнала, enum ReferralAttachRule attach-rules.md). Фиксируется доменное событие ReferralBondCreatedEvent.
  4. Журнал Initial. Пишется запись c AppliedRule = R1, LeadRequested = false, денормализация LinkUrl/ReferrerUserId/TenantId = null.
  5. Интеграционные события. Публикуется только ReferralBondCreatedKafkaEvent (pin.referral.bonds.v1, key = ReferredUserId, ReferrerCompanyId = null); ReferralLeadAttachRequestedKafkaEvent НЕ публикуется (INV-REF-002).
  6. Согласованность. Связь + журнал + событие фиксируются в одном согласованном изменении; событие подтверждается (ack).
  7. Downstream. rewards фиксирует основание будущей выплаты рефереру-инвестору по BondId; notifications уведомляет реферера; messenger создаёт контакт «инвестор ↔ инвестор» (поток «Реферальная привязка» service-boundaries.md). crm события не получает — карточка лида не создаётся.

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

A1. Привязка при авторизации (базовое правило R2)

  1. Триггер T2 (UserSignedInKafkaEvent c ReferrerUrl), условие окна lazy-регистрации выполнено (UC-REF-004) → связь создаётся с AppliedRule = R2, LeadRequested = false; lead-событие не публикуется. Далее — шаги 6–7 основного потока.

A2. Владелец-инвестор, авторизация вне окна (R3 + R5)

  1. IsNameFilled = true И регистрация ≥ 4 ч → базовое правило R3 связь не создаёт (UC-REF-005), а R5 отменяет лид → полный no-op (structured log). Событие подтверждается. Завершение.

A3. Ссылка менеджера застройщика (DeveloperManager)

  1. Контрпример границы правила: DeveloperManager — «агент/застройщик» по таблице ролей, R5 НЕ применяется, лид создаётся — сценарий идёт по UC-REF-003/UC-REF-004 без модификатора. Человек «застройщик и одновременно агент» действует той учёткой, которой принадлежит ссылка.

Постусловие

  • Создана ReferralBondEntity (Status = Active, TenantId = null при реферере-инвесторе) — основание будущей выплаты рефереру; getMyReferrer приглашённого возвращает реферера-инвестора.
  • Журнальная запись Initial с LeadRequested = false — след применения R5 для метрик.
  • Карточка лида в CRM НЕ создана; топик pin.referral.lead-attachments.v1 события не получил.

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

КодHTTPУсловиеПоведение
— (no-op, warning)— (Kafka consumer, HTTP нет)Guard G1–G4 не пройденМетрика no-op guard-ов
— (идемпотентный no-op)G5/INV-REF-001: активная связь уже есть (лид в этом кейсе тоже не создаётся — R5)Событие подтверждается
retry consumer-аРеплика владельца/пользователя отсутствуетRetry
DLQ после исчерпания retryИнфраструктурный сбойRunbook referral-consumer-lag (README.md)

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

СобытиеКогда поднимаетсяSubscribers
ReferralBondCreatedEventСоздание связи (шаг 3)in-proc аудит
ReferralRegistrationRecordedEventЗапись журнала Initial (шаг 4)in-proc

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

СобытиеTopicКогда публикуетсяConsumers
ReferralBondCreatedKafkaEventpin.referral.bonds.v1Связь создана (шаг 5)rewards (основание выплат), notifications (уведомление рефереру), messenger (контакт «инвестор ↔ инвестор»)
ReferralLeadAttachRequestedKafkaEventpin.referral.lead-attachments.v1Не публикуется в этом сценарии (R5/INV-REF-002)

Acceptance Criteria

#КритерийПроверка
AC1Регистрация по ссылке инвестора → связь Active создана, lead-событие отсутствуетинтеграционный тест: топик lead-attachments пуст
AC2Журнальная запись имеет LeadRequested = false при AppliedRule = R1проверка колонок журнала
AC3ReferralBondCreatedKafkaEvent опубликован с ReferrerCompanyId = null (реферер-инвестор)контракт-тест события
AC4Ссылка PartnerManager/PinEmployee даёт тот же исход, что и инвесторская (таблица ролей)параметризованный тест по типам владельца
AC5Ссылка DeveloperManager → лид СОЗДАЁТСЯ (граница R5)контрпример-тест A3
AC6Авторизация вне окна по ссылке инвестора → полный no-op (R3 + R5): ни связи, ни лида, ни журналатест A2
AC7rewards получает BondId и может строить начисление рефереру-инвесторуe2e с rewards-стабом
AC8Повторная доставка события регистрации/входа не создаёт дублей связи/журнала (INV-REF-R1 + MessageId/G5)двойная доставка

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

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

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