Event Contract: pin.rewards.commission-accrual-created
Версионируемый контракт интеграционного события «комиссия начислена». Consumer-документы ссылаются сюда, не
переописывая payload. Дом полей — entity: CommissionAccrualEntity.
Назначение
Фиксирует создание начисления комиссии по завершённой сделке: агент и его агентство узнают, что комиссия
начислена и ожидает подтверждения застройщиком, а crm отмечает факт начисления в таймлайне сделки.
Producer — rewards; событие публичное, потому что потребителям (notifications, crm) не нужен
синхронный запрос в rewards для реакции на факт начисления. Сводки ЛК агента/агентства («получим/получили
× подтверждено/ожидает») события не потребляют — они читаются SQL-агрегациями по PostgreSQL rewards
(решение №6 ../README.md, ADR-0056).
Metadata
| Поле | Значение |
|---|---|
| Event type | pin.rewards.commission-accrual-created |
| Topic | pin.rewards.commission-accrual-created.v1 |
| Partitions / key | 3 / key = Id начисления (объём — число завершённых сделок, ADR-0056) |
| ContractVersion | 1 |
| Producer | rewards: consumer crm-deal-completed.md (автоначисление), admin-API api/admin/create-manual-accrual.md (ручное начисление застройщиком, по конвенции) |
| Статус | draft |
Метаданные события: идентификатор сообщения (
MessageId, ключ дедупликации), время (CreatedAt),Version(=ContractVersion),AggregateId = Id,AggregateType = "CommissionAccrual". Событие публикуется атомарно с созданием начисления.
Payload CommissionAccrualCreatedKafkaEvent
Snapshot-поля ссылаются на дом commission-accrual.md —
перечисляется только то, что реально в событии. InvestorUserId, цены объекта недвижимости
(BasePriceAmount/FinalPriceAmount), CommissionPercent, AppliedRuleSnapshot и
AppliedPlatformTermsId в payload не входят (см. «Безопасность»).
| Поле | Тип | Обязательность | Источник (поле агрегата) | Compatibility | Описание |
|---|---|---|---|---|---|
Id | Guid | Да | CommissionAccrualEntity.Id | Immutable | Ключ агрегата (= Kafka key). |
TenantId | Guid | Да | CommissionAccrualEntity.TenantId | Immutable | Агентство-получатель комиссии (tenant boundary, решение №2 README). |
DealId | Guid | Да | CommissionAccrualEntity.DealId | Immutable | Сделка crm — ключ привязки таймлайна. |
DeveloperCompanyId | Guid | Да | CommissionAccrualEntity.DeveloperCompanyId | Immutable | Застройщик — подтверждающая сторона. |
AgentUserId | Guid | Да | CommissionAccrualEntity.AgentUserId | Immutable | Агент — адресат уведомления «комиссия начислена». |
PropertyObjectId | Guid | Да | CommissionAccrualEntity.PropertyObjectId | Immutable | Объект недвижимости (chessboard) — контекст уведомления. |
CommissionAmount | MoneyModel | Да | CommissionAccrualEntity.CommissionAmount | Additive only | Начисленная gross-сумма комиссии. |
PlatformFeeAmount | MoneyModel | Да | CommissionAccrualEntity.PlatformFeeAmount | Additive only | Удержание ПИН (INV-10, ADR-0066); 0 при fallback без условий. Пул агентства = CommissionAmount − PlatformFeeAmount. |
PlatformRetentionPercentagePoints | decimal | Да | CommissionAccrualEntity.PlatformRetentionPercentagePoints | Additive only | Удержание ПИН в процентных пунктах ставки застройщика (снапшот условий на DealCompletedAt; 0 — fallback). |
Status | string (enum CommissionAccrualStatus) | Да | CommissionAccrualEntity.Status | Additive only (новые значения) | Всегда PendingConfirmation в v1 (создание — единственная точка публикации); переходы — соседним событием commission-accrual-status-changed.md. |
DealCompletedAt | DateTimeOffset | Да | CommissionAccrualEntity.DealCompletedAt | Immutable | Момент завершения сделки (для текста уведомления/сортировки). |
Вложенная модель MoneyModel
Проекция VO Money (commission-accrual.md, раздел «Value objects»);
валюта всех сумм payload едина (INV-6).
| Поле | Тип | Обязательность | Ограничения | Описание |
|---|---|---|---|---|
Value | decimal | Да | >= 0, scale 2 | Сумма. |
CurrencyId | short | Да | ссылка на валюту справочника; RUB-only (ADR-0048) | Типизированная ссылка на валюту. |
CurrencySnapshot | CurrencySnapshot | Да | ../../handbook/domain/snapshots.md | Display-снапшот валюты на момент публикации. |
Когда публикуется
| Условие | Переход состояния | Согласованность |
|---|---|---|
| Consumer завершения сделки создал начисление (crm-deal-completed.md) | [*] → PendingConfirmation | начисление, отметка идемпотентности и событие — в одном согласованном изменении |
Менеджер застройщика создал ручное начисление (api/admin/create-manual-accrual.md, по конвенции; AppliedRuleId = null) | [*] → PendingConfirmation | начисление и событие — в одном согласованном изменении |
Skip-ветки consumer-а (нет агента, нет правила, дубль DealId) события не публикуют.
Потребители (consumers)
| Consumer-контекст | Эффект (side effects) | Идемпотентность | Задержка (SLA) |
|---|---|---|---|
notifications | Уведомление агенту (AgentUserId) и руководителю агентства (TenantId, роль с rewards.commission.view-all): «начислена комиссия по сделке, ожидает подтверждения застройщиком» | MessageId | < 5 мин |
crm | Запись в таймлайн сделки DealId (deal-timeline-event, тип «комиссия начислена») | MessageId + business key (DealId, Id) | < 5 мин |
rewards (self) | Наполнение user-centric проекции AgentPerformance (ADR-0061 п.5): DealsWonCount += 1, CommissionAccruedTotal += CommissionAmount | MessageId + факт Id | < 5 мин |
Гарантии доставки и порядка
- Доставка — at-least-once; каждый потребитель дедуплицирует по
MessageId(плюс бизнес-ключ, где указан), поэтому повторная доставка эффектов не удваивает. - Порядок. Событие создаётся один раз на начисление (точка публикации — только
[*] → PendingConfirmation), поэтому внутри топика для данногоIdоно единственное; между этим топиком иcommission-accrual-status-changed.v1сквозного порядка нет — переход статуса причинно следует за созданием, но технически может прийти раньше. Потребитель, читающий оба топика (self-проекцияAgentPerformance), обязан быть к этому устойчив: дельты идемпотентны поId, а счётчики защищены нижней границей (см. agent-performance.md, раздел о согласованности). - Атомарность. Публикация — в одном согласованном изменении с созданием начисления; skip-ветки consumer-а событие не публикуют, поэтому «пустых» уведомлений не бывает.
- Неизвестные поля у потребителя игнорируются (additive-политика ниже).
Версионирование и совместимость
- Версия — один
ContractVersion = 1; consumer при несовпадении версии логирует warning и продолжает (upcasting нет). - Additive-only для minor: новые optional-поля с безопасным default — без bump.
- Breaking (удаление/переименование/смена типа/смысла) —
ContractVersion = 2+ новый топикpin.rewards.commission-accrual-created.v2+ dual-publish на период миграции + deadline миграции consumers + sunset старого топика. - Unknown enum
Statusу потребителя — fallback: трактовать какPendingConfirmation+ warning. - Deprecation — по общему sunset-правилу событийного реестра.
Безопасность
| Поле | Класс данных | Правило |
|---|---|---|
Id, TenantId, DealId, DeveloperCompanyId, AgentUserId, PropertyObjectId, Status, DealCompletedAt | Internal | include |
CommissionAmount, PlatformFeeAmount, PlatformRetentionPercentagePoints | Sensitive (суммы комиссий и удержания ПИН, README «Безопасность») | include в payload (внутренний топик, m2m ACL Kafka); потребители не пишут суммы в логи; в уведомлении сумма видна только адресату |
InvestorUserId | Internal (маскируется в проекциях агентства) | exclude — в payload не входит |
Цены объекта недвижимости, CommissionPercent, AppliedRuleSnapshot, AppliedPlatformTermsId | Sensitive/Internal | exclude — условия правил застройщика и условий платформы не раскрываются потребителям |
Событие НЕ содержит secrets, tokens, raw credentials, PII (ФИО/телефоны), платёжные реквизиты, unbounded-вложения.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (1): Entity / Aggregate: CommissionAccrualEntity
- API (1): POST /api/v1/developer/commission-accruals — Ручное создание начисления застройщиком
- События (1): Event Contract: pin.rewards.commission-accrual-status-changed (CommissionAccrualStatusChangedKafkaEvent)
- Консюмеры (3): Consumer: Agent Performance Projection, Consumer: CRM Deal Completed, Consumer: Rewards Events → Notifications (notifications-rewards-events)
- Саги (1): Saga «Commission Settlement» (финансовый контур вознаграждений)
- registries (1): Реестр событий PIN
- index.md (1): Rewards Service
Связанные документы
- Сущность: commission-accrual.md (дом полей, stateDiagram).
- Источники: crm-deal-completed.md;
api/admin/create-manual-accrual.md(по конвенции). - Соседние контракты: commission-accrual-status-changed.md (переходы статусов), commission-money-received.md (гейт получения денег, распределение тремя строками).
- Snapshot-модели валюты: ../../handbook/domain/snapshots.md.
- Шаблон: event-contract-template.md.