UC-RWD-017. Уволенный агент: судьба заработанных комиссий
Назначение
Описывает поведение вознаграждений при увольнении/исключении агента (ADR-0072): что происходит с его
начислениями в rewards и с его доступом к финансовым разделам. Ключевые гарантии: начисления в статусах
PendingConfirmation/Confirmed продолжают жизненный цикл (застройщик подтверждает, оператор ПИН
регистрирует акт, руководитель агентства выплачивает) и по-прежнему адресованы бывшему агенту —
AgentUserId и OriginAgentUserId иммутабельны; заработанное и выплаченное (MoneyReceived/Paid)
сохраняется; интерактивный доступ к финансам агентства у уволенного revoke (снятие назначения роли в
scope этого агентства), а его личный кабинет вознаграждений становится read-only — право получить уже
заработанное не отчуждается. Связан с контекстом rewards.
Metadata
| Поле | Значение |
|---|---|
| ID | UC-RWD-017 |
| Контекст | rewards (см. docs/06-services/rewards/) |
| Тип | исключительный (реакция на увольнение; смешанный: system-каскад + read-only self-view) |
| Статус | draft |
Актор
| Поле | Значение |
|---|---|
| Роль | System (consumer события членства agent-membership-changed в rewards) — основной поток; Уволенный агент (read-only self-view) — потоки чтения |
| Permissions / scope | System — m2m-обработка события; агент после увольнения — rewards.commission.view-own (record-level, read-only) сохраняется, интерактивные rewards.commission.adjust-request в scope этого агентства revoke (снятие назначения роли в identity, ADR-0072) |
| Tenant | Начисления — в tenant агентства (TenantId = AgencyCompanyId); user-centric проекция AgentPerformance и счета кошелька агента — вне tenant (переживают увольнение, ADR-0061 п.5) |
| Record-level | Агент видит только свои начисления (AgentUserId из claims) и свою проекцию карьеры |
Предусловие
identityперевёл членство пары(AgentUserId, CompanyId)Active → Left(terminate-agent-membership.md — исключение руководителем,Reason = ExcludedByAgency; либо self-leave,Reason = SelfLeave) и опубликовалpin.identity.agent-membership-changed.v1сReason/EffectiveAt(ADR-0072).- Перед снятием членства guard «единственный активный
Executor» уже отработал: активные лиды/сделки/ фиксации агента переназначены на преемника (ADR-0071/0072) — новые начисления по ним пойдут преемнику; уже созданные начисления агента остаются за ним. - Историческая привязка сделок/фиксаций (
OriginAgencyCompanyId/OriginAgentUserId) иммутабельна, back-fill запрещён (ADR-0061 п.4).
Триггер
| Поле | Значение |
|---|---|
| Источник | Kafka event (основной каскад) / UI (чтение агентом) |
| Триггерящий элемент | Consumer rewards топика pin.identity.agent-membership-changed.v1 (Status = Left); ЛК агента → «Мои комиссии» |
Основной Поток
identityпубликуетagent-membership-changed (Left, Reason, EffectiveAt, key = AgentUserId).- Consumer
rewardsприменяет событие (идемпотентно, monotonic-guard по версии членства строки):- Проекция карьеры. Строка
AgentPerformanceEntity (AgentUserId, CompanyId)этого агентства переводится вMembershipStatus = Left; накопленные метрики строки не обнуляются (user-centric, UC-RWD-006 A1). Прочие строки (другие агентства) не тронуты. - Начисления не пересчитываются. Существующие начисления агента в этом tenant остаются в своих
статусах;
AgentUserId/OriginAgentUserId/распределения/суммы иммутабельны. Никаких массовых переходов статусов увольнение не запускает — деньги следуют цепочке подтверждений, а не членству. - Revoke интерактивного доступа. Снятие назначения роли
agentв scope этого агентства (выполняетidentity, ADR-0072) убирает у уволенного возможность действий над финансами агентства: подавать заявки на корректировку своей доли, участвовать в согласованиях. Право чтения своих начислений (rewards.commission.view-own, record-levelAgentUserId) сохраняется — ЛК становится read-only.
- Проекция карьеры. Строка
- Уволенный агент открывает «Мои комиссии»: видит свои начисления и их статусы (в т.ч.
Confirmed«подтверждено, ждём деньги»,MoneyReceived,Paid) в режиме только чтение; интерактивные действия (заявка на корректировку доли) недоступны — при попытке403 FORBIDDEN(право revoke). - Цепочка вознаграждений по начислениям уволенного продолжается независимо от него:
PendingConfirmation→ застройщик подтверждает (UC-RWD-004/UC-RWD-016): строится распределение, строкаAgentссылается наAgentUserIdуволенного — он остаётся получателем;Confirmed→ оператор ПИН регистрирует акт поступления средств (UC-RWD-010): начисление→ MoneyReceived, кошелёк кредитует user-centric счётAgentCommissionуволенного (счёт переживает утрату агентства, ADR-0061 п.5, UC-WLT-001);MoneyReceived→ руководитель агентства/оператор ПИН формирует платёжное поручение; приPaidAgent-строки выплачены, начисление→ Paid.
notificationsдоставляет уволенному агенту уведомления о переходах его начислений («комиссия подтверждена», «деньги получены», «выплачено») — право на заработанное реализуется до конца.
Альтернативные Потоки
A1. Начисление подтверждается уже после увольнения
- Застройщик подтверждает
PendingConfirmation-начисление уволенного (UC-RWD-004/016): строится распределение, строкаAgent→AgentUserIdуволенного. Увольнение не влияет на получателя. Далее — штатная цепочка. Завершается.
A2. Деньги получены после увольнения (кредит user-centric счёта)
- Оператор ПИН регистрирует акт по
Confirmed-начислению уволенного →MoneyReceived; событиеcommission-money-receivedкредитует счётAgentCommissionбывшего агента (счёт user-centric, создаётся/живёт независимо от членства). Баланс уволенного растёт; он видит его read-only (UC-WLT-004, AC4). Не ошибка.
A3. Заработанное/выплаченное до увольнения
- Начисления в
MoneyReceived/Paidна момент увольнения не меняются: суммы, распределения и Origin- снапшоты иммутабельны; уволенный видит их и историю выплат read-only. Отмена таких начислений запрещена (INV-8) — только компенсирующие операции (ADR-0067), увольнение их не инициирует.
A4. Попытка интерактивного действия после увольнения
- Уволенный пытается подать заявку на корректировку своей доли → отказ: право
rewards.commission.adjust-requestв scope агентства снято (revoke),403 FORBIDDEN. СуществующиеPending-заявки, поданные до увольнения, разрешает руководитель агентства штатно (UC-RWD-011) — их исход также адресованAgentUserIdуволенного.
A5. Мульти-членство: уволен из одного агентства, активен в другом
- Увольнение затрагивает только пару
(AgentUserId, CompanyId)этого агентства (ADR-0070): строкаAgentPerformanceэтого агентства →Left, интерактивный доступ к финансам этого агентства revoke; членство, доступ и начисления в других агентствах сохранены. Агрегированная карьера (UC-RWD-006) по- прежнему суммирует все строки. Завершается.
A6. Расторжение сделки уволенного агента
- По не-получившему деньги начислению уволенного приходит
deal-cancelled— consumer отменяет начисление (CancelReason = DealCancelled, INV-8: изPendingConfirmation/Confirmed, если строки свободны и нет не-отменённого акта). Это системная реакция на расторжение сделки, не на увольнение. Завершается.
A7. Повторная/переставленная доставка события членства
- Повтор
agent-membership-changed— идемпотентный skip; переставленный старый переход отбрасывается monotonic-guard по версии членства строки (UC-RWD-006 AC3). Начисления в любом случае не затрагиваются.
Постусловие
AgentUserId/OriginAgentUserId, суммы и распределения начислений уволенного — неизменны; earned (MoneyReceived) и paid (Paid) сохранены;Pending/Confirmedпродолжают цикл и остаются адресованы бывшему агенту.- Строка
AgentPerformanceэтого агентства —Left(метрики сохранены); интерактивный доступ к финансам агентства у уволенного revoke; ЛК вознаграждений — read-only; право получить заработанное реализуется штатной цепочкой и кредитуется на user-centric счёт кошелька. - Историческая привязка сделок/фиксаций не пересчитана (снапшоты иммутабельны).
Согласованность и межсервисное взаимодействие
- Ожидает на входе. Долговечное
pin.identity.agent-membership-changed.v1(Left,Reason,EffectiveAt); reassign активных процессов уже выполнен guard-ом до увольнения — новые начисления по ним адресуются преемнику, а не уволенному. - Предоставляет на выходе. Ничего нового
rewardsпо факту увольнения не публикует (обновляет лишь проекцию карьеры). Дальнейшие переходы начислений публикуют штатныеcommission-accrual-status-changed/commission-money-receivedнезависимо от членства. - Окно eventual-consistency. Между увольнением в
identityи применением события в проекции/доступе — лаг (< 5 мин SLO): короткое время уволенный может ещё видеть интерактивные элементы (действие всё равно отклонит серверная проверка права). Не ошибка. - Инвариант права. Финансовое право следует иммутабельному
AgentUserIdи user-centric счёту, а не активному членству: увольнение снимает доступ к процессам агентства, но не отчуждает заработанное (ADR-0072 п.4, ADR-0061 п.5).
Возможные Ошибки
| Код | HTTP | Условие | Поведение клиента |
|---|---|---|---|
403 FORBIDDEN | 403 | Интерактивное действие над финансами агентства после revoke (A4) | Скрыть кнопки действий, оставить read-only |
| — (идемпотентный skip) | — | Повтор события членства (A7) | Consumer: skip |
Чтение своих начислений уволенным — не ошибка (200, read-only).
Kafka Интеграционные События
| Событие | Topic | Когда | Consumers |
|---|---|---|---|
| — (потребление) | pin.identity.agent-membership-changed.v1 (Left) | Наполнение проекции + отражение revoke | consumer rewards (проекция карьеры) |
CommissionAccrualStatusChangedKafkaEvent.v1 | pin.rewards.commission-accrual-status-changed.v1 | Продолжение цикла начислений уволенного (Confirm/MoneyReceived/Paid/Cancelled) | notifications |
CommissionMoneyReceivedKafkaEvent.v1 | pin.rewards.commission-money-received.v1 | Confirmed → MoneyReceived начисления уволенного | wallet (кредит user-centric счёта), notifications |
Acceptance Criteria
| # | Критерий | Проверка |
|---|---|---|
| AC1 | Увольнение не меняет статусы/суммы/получателя существующих начислений (AgentUserId/Origin иммутабельны) | тест: terminate → перечитать начисления, всё неизменно |
| AC2 | PendingConfirmation-начисление уволенного подтверждается и адресовано ему же (A1) | тест Confirm после увольнения → строка Agent на AgentUserId уволенного |
| AC3 | Confirmed → MoneyReceived уволенного кредитует его user-centric счёт кошелька (A2) | интеграционный тест commission-money-received → баланс уволенного |
| AC4 | earned/paid до увольнения сохранены и видны read-only (A3) | тест: MoneyReceived/Paid неизменны, отмена запрещена |
| AC5 | Интерактивное финансовое действие уволенного отклонено (403), ЛК read-only (A4) | негативный тест заявки на корректировку после revoke |
| AC6 | Мульти-членство: revoke и Left только для покинутого агентства; другие сохранены (A5) | тест terminate из одного из двух агентств |
| AC7 | Строка AgentPerformance покинутого агентства → Left, метрики не обнулены | тест проекции после увольнения |
| AC8 | Повтор/переставленное событие членства не искажает начисления и проекцию (A7) | тест идемпотентности/monotonic-guard |
Наблюдаемость и НФТ
- Логи (без секретов/PII).
agent-membership-left-applied(agentUserId,companyId,reason,effectiveAt,perfRowStatus = Left); попытки интерактивных действий после revoke логируются какforbidden(без содержимого). Суммы — класс Sensitive, в логи не пишутся. - Метрики.
rewards_membership_left_applied_total{reason};rewards_terminated_agent_forbidden_total(интерактивные попытки после revoke); лаг применения membership-события (alert > 5 мин). - Доступ/безопасность.
rewards.commission.view-own(read-only) сохраняется; интерактивные права в scope покинутого агентства — revoke; получатель финансового права — иммутабельныйAgentUserId, не членство.
Обратные ссылки
Автоссылки: где используется этот документ.
- Use Cases (2): UC-RWD-016. Застройщик подтверждает начисление после смены исполнителя, UC-WLT-006. Компенсирующее начисление отражается в балансе после MoneyReceived
- registries (1): Реестр use cases и user stories PIN
Связанные Документы
- Увольнение/исключение и каскад: terminate-agent-membership.md, ADR-0072.
- Карьера агента (user-centric, сохранение метрик): UC-RWD-006, ../domain/agent-performance.md.
- Цепочка вознаграждений: UC-RWD-004, UC-RWD-016, UC-RWD-010, UC-RWD-011.
- Начисление (иммутабельность получателя/атрибуции, статусы): ../domain/commission-accrual.md.
- Кошелёк (user-centric счета, кредит по
MoneyReceived): ../../wallet/use-cases/UC-WLT-001-commission-money-received-credits-balances.md, ../../wallet/domain/wallet-account.md. - ADR: 0061 (п.4 запрет back-fill, п.5 user-centric), 0070 (мульти-членство), 0067 (гейт денег, компенсации).