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

Event Contract: pin.wallet.transaction-recorded (WalletTransactionRecordedKafkaEvent)

Версионируемый контракт интеграционного события «по счёту кошелька проведена операция». Consumer-документы ссылаются сюда, не переописывая payload. Дом полей — entity: LedgerTransactionEntity и entity: WalletAccountEntity.

Назначение

Фиксирует изменение баланса холдерского счёта кошелька: зачисление вознаграждения (кредит после гейта получения денег), списание по выплате, ручную корректировку или компенсацию. Producer — wallet; потребитель — notifications: уведомления холдеру («вам начислено», «вам выплачено», «баланс скорректирован») с актуальным балансом — без синхронного запроса в wallet. Проводки системных счетов (PlatformSettlement, PlatformRevenue) события не порождают — подписчиков у них нет, платформенные балансы читаются admin-API.

Metadata

ПолеЗначение
Event typepin.wallet.transaction-recorded
C# typeWalletTransactionRecordedKafkaEvent
Topicpin.wallet.transaction-recorded.v1
Partitions / key3 / key = AccountId — строгий порядок изменений per-account: BalanceAfter у потребителя монотонно согласован (объём — единицы событий на сделку, ADR-0056)
ContractVersion1
Producerwallet: проведение транзакции журнала (consumer-ы событий rewards, admin-корректировки)
Статусdraft

Публикуется атомарно с проведением транзакции — по одному событию на каждую проводку холдерского счёта: ReferralCredit/PayoutDebit касаются одного холдерского счёта и дают одно событие; CommissionCredit кредитует до двух холдерских счетов (агента и агентства) и даёт до двух событий. Повторная доставка события-основания в wallet — no-op (INV-WLT-7), повторной публикации нет.

Payload WalletTransactionRecordedKafkaEvent

Поля — проекция проводки и её счёта (ledger-transaction.md, wallet-account.md).

ПолеТипОбязательностьИсточник (поле агрегата)CompatibilityОписание
TransactionIdGuidДаLedgerTransactionEntity.IdImmutableТранзакция журнала.
EntryIdGuidДаLedgerEntryEntity.IdImmutableПроводка (уникальна в топике — дедупликация потребителя).
AccountIdGuidДаLedgerEntryEntity.AccountIdImmutableСчёт проводки (= Kafka key).
AccountKindstring (enum WalletAccountKind)ДаWalletAccountEntity.AccountKindAdditive only (новые значения)AgentCommission / ReferralCommission / AgencyCommission — вид баланса в тексте уведомления.
HolderUserIdGuid?Да для счетов пользователей, иначе nullWalletAccountEntity.HolderUserIdImmutableПользователь-холдер — адресат уведомления.
HolderCompanyIdGuid?Да для AgencyCommission, иначе nullWalletAccountEntity.HolderCompanyIdImmutableКомпания-холдер — уведомление руководителю агентства.
OperationKindstring (enum WalletOperationKind)ДаLedgerTransactionEntity.OperationKindAdditive onlyВид операции — выбор шаблона уведомления.
Directionstring (enum LedgerEntryDirection)ДаLedgerEntryEntity.DirectionAdditive onlyCredit (баланс вырос) / Debit (баланс уменьшился) — знак операции для Adjustment/Correction.
AmountdecimalДаLedgerEntryEntity.Amount.ValueAdditive onlyСумма операции (> 0, знак — в Direction).
BalanceAfterdecimalДаLedgerEntryEntity.BalanceAfter.ValueAdditive onlyБаланс счёта после операции.
CurrencyIdshortДаLedgerEntryEntity.Amount.CurrencyIdImmutableВалюта суммы и баланса (едина, INV-WLT-4).
CurrencySnapshotCurrencySnapshotДарезолв на публикацииAdditive onlyDisplay-снапшот валюты — snapshots.md (поля не переописываются).
SourceIdGuidДаLedgerTransactionEntity.SourceIdImmutableОснование операции (строка распределения / рефералка / позиция поручения / исходная транзакция — карта в ledger-transaction.md).
OccurredAtDateTimeOffsetДаLedgerTransactionEntity.OccurredAtImmutableМомент бизнес-факта.
AccountVersionlongДа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)дебет холдерского счёта получателя позицииатомарно
Ручная корректировка ПИН-админа (Adjustmentcreate-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, CurrencySnapshotInternalinclude
Amount, BalanceAfterSensitive (суммы и балансы)include (внутренний топик, m2m ACL Kafka); в логи не пишутся; в уведомлении холдер видит только свой счёт
HolderUserId, HolderCompanyIdInternalinclude (адресация уведомлений)

Событие НЕ содержит причин корректировок (Comment — только admin-журнал), банковских реквизитов (в платформе не хранятся), PII, secrets, unbounded-вложений.

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

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

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