Event Contract: pin.wallet.transaction-recorded (WalletTransactionRecordedKafkaEvent)
Версионируемый контракт интеграционного события «по счёту кошелька проведена операция».
Consumer-документы ссылаются сюда, не переописывая payload. Дом полей —
entity: LedgerTransactionEntity и
entity: WalletAccountEntity.
Назначение
Фиксирует изменение баланса холдерского счёта кошелька: зачисление вознаграждения (кредит после гейта
получения денег), списание по выплате, ручную корректировку или компенсацию. Producer — wallet;
потребитель — notifications: уведомления холдеру («вам начислено», «вам выплачено», «баланс
скорректирован») с актуальным балансом — без синхронного запроса в wallet. Проводки системных счетов
(PlatformSettlement, PlatformRevenue) события не порождают — подписчиков у них нет, платформенные
балансы читаются admin-API.
Metadata
| Поле | Значение |
|---|---|
| Event type | pin.wallet.transaction-recorded |
| C# type | WalletTransactionRecordedKafkaEvent |
| Topic | pin.wallet.transaction-recorded.v1 |
| Partitions / key | 3 / key = AccountId — строгий порядок изменений per-account: BalanceAfter у потребителя монотонно согласован (объём — единицы событий на сделку, ADR-0056) |
| ContractVersion | 1 |
| Producer | wallet: проведение транзакции журнала (consumer-ы событий rewards, admin-корректировки) |
| Статус | draft |
Публикуется атомарно с проведением транзакции — по одному событию на каждую проводку холдерского
счёта: ReferralCredit/PayoutDebit касаются одного холдерского счёта и дают одно событие;
CommissionCredit кредитует до двух холдерских счетов (агента и агентства) и даёт до двух событий.
Повторная доставка события-основания в wallet — no-op (INV-WLT-7), повторной публикации нет.
Payload WalletTransactionRecordedKafkaEvent
Поля — проекция проводки и её счёта (ledger-transaction.md, wallet-account.md).
| Поле | Тип | Обязательность | Источник (поле агрегата) | Compatibility | Описание |
|---|---|---|---|---|---|
TransactionId | Guid | Да | LedgerTransactionEntity.Id | Immutable | Транзакция журнала. |
EntryId | Guid | Да | LedgerEntryEntity.Id | Immutable | Проводка (уникальна в топике — дедупликация потребителя). |
AccountId | Guid | Да | LedgerEntryEntity.AccountId | Immutable | Счёт проводки (= Kafka key). |
AccountKind | string (enum WalletAccountKind) | Да | WalletAccountEntity.AccountKind | Additive only (новые значения) | AgentCommission / ReferralCommission / AgencyCommission — вид баланса в тексте уведомления. |
HolderUserId | Guid? | Да для счетов пользователей, иначе null | WalletAccountEntity.HolderUserId | Immutable | Пользователь-холдер — адресат уведомления. |
HolderCompanyId | Guid? | Да для AgencyCommission, иначе null | WalletAccountEntity.HolderCompanyId | Immutable | Компания-холдер — уведомление руководителю агентства. |
OperationKind | string (enum WalletOperationKind) | Да | LedgerTransactionEntity.OperationKind | Additive only | Вид операции — выбор шаблона уведомления. |
Direction | string (enum LedgerEntryDirection) | Да | LedgerEntryEntity.Direction | Additive only | Credit (баланс вырос) / Debit (баланс уменьшился) — знак операции для Adjustment/Correction. |
Amount | decimal | Да | LedgerEntryEntity.Amount.Value | Additive only | Сумма операции (> 0, знак — в Direction). |
BalanceAfter | decimal | Да | LedgerEntryEntity.BalanceAfter.Value | Additive only | Баланс счёта после операции. |
CurrencyId | short | Да | LedgerEntryEntity.Amount.CurrencyId | Immutable | Валюта суммы и баланса (едина, INV-WLT-4). |
CurrencySnapshot | CurrencySnapshot | Да | резолв на публикации | Additive only | Display-снапшот валюты — snapshots.md (поля не переописываются). |
SourceId | Guid | Да | LedgerTransactionEntity.SourceId | Immutable | Основание операции (строка распределения / рефералка / позиция поручения / исходная транзакция — карта в ledger-transaction.md). |
OccurredAt | DateTimeOffset | Да | LedgerTransactionEntity.OccurredAt | Immutable | Момент бизнес-факта. |
AccountVersion | long | Да | WalletAccountEntity.Version после проведения | Immutable semantics | Монотонный guard потребителя per-account. |
Когда публикуется
| Условие | Операция | Публикация |
|---|---|---|
Получение денег от застройщика разнесено по счетам (CommissionCredit по строкам Distributions[] — rewards-commission-money-received.md) | кредит AgentCommission / AgencyCommission (проводка PlatformRevenue события не порождает) | атомарно с проведением транзакции |
Реферальное начисление перешло в Approved (ReferralCredit), отмена после Approved (Correction) — rewards-referral-accrual-status-changed.md | кредит ReferralCommission партнёра / зеркальная компенсация | атомарно |
Поручение перешло в Paid (PayoutDebit по позициям Items[] — rewards-payout-order-status-changed.md) | дебет холдерского счёта получателя позиции | атомарно |
Ручная корректировка ПИН-админа (Adjustment — create-wallet-adjustment.md) | проводка целевого счёта в направлении знака суммы | атомарно |
Потребители (consumers)
| Потребитель | Эффект (событие → действие) | Идемпотентность | Задержка (SLA) |
|---|---|---|---|
notifications | По OperationKind/Direction: CommissionCredit/ReferralCredit — холдеру «вам начислено {Amount}, баланс {BalanceAfter}»; PayoutDebit — «вам выплачено {Amount}»; Adjustment/Correction — «баланс скорректирован ({Direction})». Адресат — HolderUserId; для AgencyCommission — руководитель агентства HolderCompanyId (роль с rewards.payouts.manage) | MessageId + EntryId; порядок — key = AccountId, монотонность — AccountVersion | < 5 мин |
Гарантии доставки и порядка
- Доставка — at-least-once; потребитель дедуплицирует по
MessageId/EntryId— повторная доставка не рассылает уведомление дважды. - Порядок — строгий per-account (key =
AccountId): изменения одного счёта приходят в порядке проведения,BalanceAfterмонотонно согласован; guard —AccountVersion. - События разных счетов (например, кредиты агента и агентства по одной сделке) взаимного порядка не имеют.
Версионирование и совместимость
ContractVersion = 1; несовпадение версии контракта в сообщении — warn-and-proceed.- Additive-only без bump: новые optional-поля, новые значения enum
WalletAccountKind/WalletOperationKind/LedgerEntryDirection. - Breaking —
ContractVersion = 2+ топикpin.wallet.transaction-recorded.v2+ dual-publish + deadline миграции consumers + sunset старой версии. - Unknown enum у потребителя — уведомление не отправляется, warning + метрика (fail-safe).
Безопасность
| Поле | Класс данных | Правило |
|---|---|---|
TransactionId, EntryId, AccountId, AccountKind, OperationKind, Direction, SourceId, OccurredAt, AccountVersion, CurrencyId, CurrencySnapshot | Internal | include |
Amount, BalanceAfter | Sensitive (суммы и балансы) | include (внутренний топик, m2m ACL Kafka); в логи не пишутся; в уведомлении холдер видит только свой счёт |
HolderUserId, HolderCompanyId | Internal | include (адресация уведомлений) |
Событие НЕ содержит причин корректировок (Comment — только admin-журнал), банковских реквизитов
(в платформе не хранятся), PII, secrets, unbounded-вложений.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (3): Entity / Aggregate: LedgerTransactionEntity (+ LedgerEntryEntity), Entity / Aggregate: NotificationEntity, Entity / Aggregate: WalletAccountEntity
- API (1): POST /api/v1/platform/wallet/adjustments — Ручная корректировка счёта
- Use Cases (4): UC-WLT-001. Получение денег кредитует балансы получателей, UC-WLT-002. Выплата поручения дебетует баланс получателя, UC-WLT-003. ПИН-админ вручную корректирует баланс, US-реестр: Реферальный партнёр (US-PRT)
- Консюмеры (5): Consumer: Rewards Commission Distribution Adjusted, Consumer: Rewards Commission Money Received, Consumer: Rewards Payout Order Status Changed, Consumer: Rewards Referral Accrual Status Changed, Consumer: Wallet Events → Notifications (notifications-wallet-events)
- registries (1): Реестр событий PIN
- index.md (1): Wallet Service
Связанные документы
- Сущности: ledger-transaction.md (карта проводок, INV-WLT-5..7), wallet-account.md (счета, INV-WLT-1..4).
- События-основания: commission-accrual.md
(
commission-money-received), referral-accrual.md (топикpin.rewards.referral-accruals.v1), payout-order-status-changed.md. - Snapshot-модели: snapshots.md.
- ADR-0065.