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

UC-WLT-001. Получение денег кредитует балансы получателей

Назначение

Описывает системный сценарий: оператор ПИН зарегистрировал акт поступления средств от застройщика (platform-receipt.md), начисления перешли в MoneyReceived — и кошелёк разносит полученную комиссию по счетам получателей: агенту, агентству и на счёт дохода ПИН, а связанное реферальное вознаграждение — партнёру. С этого момента холдеры видят суммы на своих балансах. Связан с контекстом wallet.

Metadata

ПолеЗначение
IDUC-WLT-001
Контекстwallet (см. docs/06-services/wallet/)
Типосновной
Статусdraft

Актор

ПолеЗначение
РольSystem (consumer событий rewards)
Permissions / scopeне применяется (m2m-обработка событий)
Tenantвне tenant-модели — счета user-centric / company / системные (wallet-account.md)

Предусловие

  • В rewards начисление комиссии подтверждено и вошло в зарегистрированный акт поступления средств — статус MoneyReceived, распределение построено тремя строками Platform/Agency/Agent (commission-accrual.md, INV-4/5/9).
  • Событие pin.rewards.commission-money-received.v1 опубликовано с построчной детализацией Distributions[] (id строки, RecipientType, RecipientUserId?, Amount).

Триггер

ПолеЗначение
ИсточникKafka event
Триггерящий элементpin.rewards.commission-money-received.v1 → consumer rewards-commission-money-received.md

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

  1. Кошелёк получает событие получения денег: начисление, агентство (TenantId), CommissionAmount и три строки распределения; проверяет вход (ровно три строки, Σ строк = CommissionAmount, единая допустимая валюта — negative-ветки в consumer-доке).
  2. Для каждой ненулевой строки Distributions[] кошелёк определяет счёт-получатель по RecipientType: Agent → счёт AgentCommission пользователя RecipientUserId; Agency → счёт AgencyCommission агентства; Platform → системный счёт PlatformRevenue. Нулевая строка проводку не порождает.
  3. Если счёта-получателя ещё нет — он создаётся lazy при первом кредите (wallet-account.md, INV-WLT-2).
  4. Проводится одна транзакция CommissionCredit (SourceId = id начисления): дебет PlatformSettlement на CommissionAmount, кредиты счетов-получателей на суммы строк; Σ дебетов = Σ кредитов (INV-WLT-5), валюта строк = валюте счетов (INV-WLT-4); балансы счетов и BalanceAfter проводок фиксируются атомарно (ledger-transaction.md).
  5. По каждой проводке холдерского счёта (AgentCommission, AgencyCommission) публикуется pin.wallet.transaction-recorded.v1 (wallet-transaction-recorded.md); проводка PlatformRevenue события не порождает.
  6. notifications доставляет холдерам «вам начислено {Amount}, баланс {BalanceAfter}».
  7. Агент и руководитель агентства видят пополненные балансы в ЛК (UC-WLT-004).

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

A1. Реферальное вознаграждение той же сделки

  1. Регистрация акта атомарно перевела связанное реферальное начисление Pending → Approved (referral-accrual.md, INV-RA-3); в топик pin.rewards.referral-accruals.v1 ушло событие смены статуса.
  2. Кошелёк (consumer rewards-referral-accrual-status-changed.md) проводит ReferralCredit (SourceId = id начисления): дебет PlatformSettlement, кредит ReferralCommission партнёра на Amount начисления.
  3. Далее — шаги 5–7 основного потока для счёта партнёра.

A2. Повторная доставка события

  1. Кошелёк получает то же событие повторно (at-least-once) либо второй инстанс обрабатывает его параллельно.
  2. Проведение упирается в unique (CommissionCredit, id начисления) — no-op (INV-WLT-7): балансы не меняются, событие transaction-recorded повторно не публикуется.

A3. Прерванная обработка

  1. Обработка прервалась до фиксации (сбой/рестарт): транзакция атомарна — частичных проводок не остаётся.
  2. Событие доставляется повторно и проводится целиком (либо no-op, если фиксация успела пройти). Итог эквивалентен однократной полной обработке.

A4. Отмена реферального начисления после Approved

  1. Оператор ПИН отменил рефералку из Approved (начисление свободно от поручения, referral-accrual.md, INV-RA-5).
  2. Кошелёк по событию Cancelled проводит компенсацию Correction (SourceId = id исходной ReferralCredit-транзакции): зеркальные проводки, баланс партнёра уменьшается; повторная компенсация исключена unique-ключом (INV-WLT-6).

Постусловие

  • По начислению существует ровно одна транзакция CommissionCredit: дебет PlatformSettlement на CommissionAmount + кредиты счетов-получателей по ненулевым строкам распределения.
  • Балансы AgentCommission агента, AgencyCommission агентства и PlatformRevenue увеличены на суммы своих строк; баланс PlatformSettlement уменьшен на CommissionAmount начисления.
  • Для каждого затронутого счёта: Balance = Σ кредитов − Σ дебетов его проводок.
  • События pin.wallet.transaction-recorded.v1 опубликованы по холдерским проводкам; уведомления доставлены.

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

СобытиеTopicКогда публикуетсяConsumers
WalletTransactionRecordedKafkaEventpin.wallet.transaction-recorded.v1Атомарно с проведением каждой транзакции — по проводке холдерского счётаnotifications

Acceptance Criteria

#КритерийПроверка
AC1Given событие с тремя ненулевыми строками распределения, When кошелёк обработал его, Then проведена одна CommissionCredit-транзакция (дебет PlatformSettlement + три кредита) и балансы агента/агентства/PlatformRevenue выросли ровно на суммы строкинтеграционный тест consumer-а
AC2Given холдер без счёта, When приходит первый кредит, Then счёт нужного вида создан lazy и кредитован; параллельный кредит тому же холдеру не создаёт второй счёттест гонки lazy-создания (INV-WLT-2)
AC3Given уже обработанное событие, When оно доставлено повторно, Then балансы не изменились и новые транзакции не появились (no-op по (OperationKind, SourceId))тест двойной доставки (INV-WLT-7)
AC4Given любой затронутый счёт, When сценарий завершён, Then хранимый Balance равен пересчёту из журнала (Σ кредитов − Σ дебетов)сверочный пересчёт (ADR-0021)
AC5Given связанная рефералка перешла в Approved, When кошелёк обработал событие статуса, Then счёт ReferralCommission партнёра кредитован на Amount — раздельно от его AgentCommission-балансаинтеграционный тест A1
AC6Given строка с нулевой суммой (срезанный пул / fallback 0 п.п.), When событие обработано, Then нулевая проводка не создана, счёт lazy не заведён, сверка сумм сходитсятест нулевых строк
AC7Given валюта события вне допустимых платформой, When проводится транзакция, Then проведение отклонено в DLQ WALLET_CURRENCY_MISMATCH и балансы не измененынегативный тест (INV-WLT-4)

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

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

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