Отчет/Export: Реферальные вознаграждения по партнёрам (referral-rewards-by-partner)
XLSX-выгрузка реферальных вознаграждений: строка = одно реферальное начисление по завершённой сделке
приведённого инвестора — с партнёром-получателем, сделкой, застройщиком, применённой ставкой и её областью,
базой расчёта и суммой, статусом и статусными датами, номером реферального поручения. Генерируется
асинхронной задачей (../api/partner/create-referral-rewards-export.md,
ReportType = ByPartner) по конвейеру
ADR-0041.
Назначение
Даёт детальную картину реферальных вознаграждений по каждому партнёру и каждой сделке: по какой ставке
и в какой области (партнёр / застройщик / проект / группа планировок) начислено, что подтверждено получением
денег от застройщика (Approved), что выплачено (Paid) и каким реферальным поручением. Аудитория двойная:
партнёр выгружает свои начисления (сверка личных вознаграждений), Менеджер ПИН — все (сверка с
бухгалтерией, контроль реферальных выплат, разбор спорных начислений). Личные данные приведённых инвесторов
(InvestorUserId) в отчёт не попадают. Owning service — rewards.
Классификация
| Поле | Значение |
|---|---|
| Тип отчета | XLSX |
| Аудитория | реферальный партнёр (свои начисления) / Менеджер ПИН (все начисления) |
| Чувствительность | Financial/Sensitive — суммы вознаграждений и персональные итоги партнёров; PII приведённых инвесторов в отчёт не попадает |
| Freshness SLA | состояние rewards на момент генерации (строго согласованный снапшот OLTP; без окна eventual-consistency) |
| Retention | файл — 7 дней в приватном объектном хранилище; данные-источник — бессрочно (финансовая история) |
Доступ
Реферальные начисления вне tenant-модели (../domain/referral-accrual.md): scope разрешается по permission актора.
| Actor | Permission | Область выборки | Audit |
|---|---|---|---|
| реферальный партнёр | rewards.referral.view-own | record-level: только PartnerUserId = ActorUserId (из claims, не из фильтров) | ExportSensitive — постановка, выдача ссылки, исход генерации |
| Менеджер ПИН | rewards.commission.view-all | платформенный scope: все партнёры; опциональный фильтр PartnerUserId | ExportSensitive — постановка, выдача ссылки, исход генерации |
Агентству и застройщику реферальные начисления не раскрываются.
Исходные Source Data
| Источник | Владелец | Тип | Freshness | Join key |
|---|---|---|---|---|
rewards.referral_accruals | rewards | source of truth (суммы/статусы/снапшот ставки — ../domain/referral-accrual.md) | строго согласовано | DealCompletedAt (период) [+ PartnerUserId] |
rewards.payout_order_items + rewards.payout_orders (Kind = ReferralReward) | rewards | source of truth (Number поручения — ../domain/payout-order.md) | строго согласовано | PayoutOrderItemId → поручение |
Пользователи identity (ФИО партнёров) | identity | enrichment при генерации (не хранится в rewards) | на момент генерации | PartnerUserId |
Компании identity (названия застройщиков) | identity | enrichment при генерации | на момент генерации | DeveloperCompanyId |
ФИО партнёра и название застройщика подставляются в момент генерации (актуальные значения identity);
при недоступности identity задача ретраится, частичный файл не публикуется. Если пользователь/компания не
найдены (устаревшая ссылка) — в ячейку пишется id (fail-open отображения, warn-лог). Область применённой
ставки (проект, группа планировок) отдаётся идентификаторами из снапшота начисления — без enrichment имён
каталога.
Фильтры ReferralRewardsByPartnerFilterModel
Снимаются с задачи выгрузки (../api/partner/create-referral-rewards-export.md).
| Поле | Тип | Обязательность | Default | Ограничения |
|---|---|---|---|---|
ActorUserId | Guid | Да | identity claims | Required; не из UI |
Scope | string (own/all) | Да | по permission актора | own для rewards.referral.view-own; all для rewards.commission.view-all |
PeriodFrom | DateTimeOffset | Да | — | строки: DealCompletedAt >= PeriodFrom |
PeriodTo | DateTimeOffset | Да | — | > PeriodFrom (исключительно); диапазон ≤ 1 года |
PartnerUserId | Guid? | Нет | все партнёры (только Scope = all) | при Scope = own игнорируется и жёстко замещается ActorUserId (warn-лог, если задан иной) |
Status | string? (enum ReferralAccrualStatus) | Нет | все статусы | Pending/Approved/Paid/Cancelled |
Строка Отчета ReferralRewardsByPartnerRowModel
Одна строка = одно начисление (ReferralAccrualEntity) выборки. Все суммы — в валюте начисления
(CurrencyId, RUB-only по ADR-0048); валюта выборки едина, иначе генерация падает
REWARDS_CURRENCY_MISMATCH (защита целостности, задача → Failed).
| Поле | Тип | Обязательность | Расчет | Masking |
|---|---|---|---|---|
PartnerFullName | string | Да | enrichment identity по PartnerUserId (ФИО на момент генерации) | — |
DealId | Guid | Да | ReferralAccrualEntity.DealId | — |
DeveloperName | string | Да | enrichment identity по DeveloperCompanyId (застройщик сделки) | — |
DealCompletedAt | DateTimeOffset | Да | DealCompletedAt | — |
AppliedPercent | decimal | Да | AppliedRateSnapshot.Percent (применённая ставка) | — |
AppliedRateScope | string (enum ReferralRateScope) | Да | AppliedRateSnapshot.Scope (область: PartnerDeveloperProjectLayoutGroup…Global) | — |
AppliedScopeProjectId | Guid? | Нет (null — область без проекта) | AppliedRateSnapshot.ProjectId (проект области ставки) | — |
AppliedScopeLayoutGroupId | Guid? | Нет (null — область без группы планировок) | AppliedRateSnapshot.LayoutGroupId | — |
BaseAmount | decimal | Да | BaseAmount.Value (конечная цена сделки — база расчёта) | Financial |
Amount | decimal | Да | Amount.Value (BaseAmount × Percent / 100, INV-RA-2) | Financial |
Status | string (enum ReferralAccrualStatus) | Да | Status | — |
ApprovedAt | DateTimeOffset? | Нет | ApprovedAt (авто-апрув при MoneyReceived родителя — гейт ADR-0067) | — |
PaidAt | DateTimeOffset? | Нет | PaidAt | — |
CancelledAt | DateTimeOffset? | Нет | CancelledAt | — |
CancelReason | string? (enum ReferralCancelReason) | Нет (обязателен при Cancelled) | CancelReason | — |
PayoutOrderNumber | string? | Нет (null — не включено в поручение) | Number реферального поручения через PayoutOrderItemId → позицию (PO-{yyyy}-{seq}) | — |
InvestorUserId, BondId и родительское комиссионное начисление (CommissionAccrualId) в выгрузку не
попадают — только основание расчёта и итоговые суммы.
Модель Totals ReferralRewardsByPartnerTotalsModel
Итоги по всей выборке фильтра (строка «Итого» под таблицей).
| Поле | Тип | Обязательность | Расчет | Precision |
|---|---|---|---|---|
RowsCount | int | Да | count строк выборки | целое |
TotalBaseAmount | decimal | Да | Σ BaseAmount | scale 2, banker's; CurrencyId выборки |
TotalAmount | decimal | Да | Σ Amount (все строки выборки) | scale 2 |
TotalPendingAmount | decimal | Да | Σ Amount строк в Pending | scale 2 |
TotalApprovedAmount | decimal | Да | Σ Amount строк в Approved | scale 2 |
TotalPaidAmount | decimal | Да | Σ Amount строк в Paid | scale 2 |
TotalCancelledAmount | decimal | Да | Σ Amount строк в Cancelled (справочно) | scale 2 |
Контроль сходимости: TotalPendingAmount + TotalApprovedAmount + TotalPaidAmount + TotalCancelledAmount = TotalAmount (каждое начисление ровно в одном статусе).
Формат Export-а
Лист XLSX by-partner; заголовки русские; суммы — числовой формат scale 2; шапка листа — период, область
выборки (свои / все партнёры), применённые фильтры, время генерации (UTC).
| Column | Заголовок | Тип | Формат | Nullable | Источник |
|---|---|---|---|---|---|
PartnerFullName | Партнёр | string | текст | Нет | ReferralRewardsByPartnerRowModel.PartnerFullName |
DealId | Сделка | Guid | текст | Нет | .DealId |
DeveloperName | Застройщик | string | текст | Нет | .DeveloperName |
DealCompletedAt | Дата завершения | DateTimeOffset | dd.MM.yyyy | Нет | .DealCompletedAt |
AppliedPercent | Ставка, % | decimal | # ##0.00 | Нет | .AppliedPercent |
AppliedRateScope | Область ставки | string | текст (рус. подпись области) | Нет | .AppliedRateScope |
AppliedScopeProjectId | Проект области | Guid | текст | Да | .AppliedScopeProjectId |
AppliedScopeLayoutGroupId | Группа планировок области | Guid | текст | Да | .AppliedScopeLayoutGroupId |
BaseAmount | База (цена сделки) | decimal | # ##0.00 | Нет | .BaseAmount |
Amount | Вознаграждение | decimal | # ##0.00 | Нет | .Amount |
Status | Статус | string | текст (рус. подпись статуса) | Нет | .Status |
ApprovedAt | Одобрено | DateTimeOffset | dd.MM.yyyy | Да | .ApprovedAt |
PaidAt | Выплачено | DateTimeOffset | dd.MM.yyyy | Да | .PaidAt |
CancelledAt | Отменено | DateTimeOffset | dd.MM.yyyy | Да | .CancelledAt |
CancelReason | Причина отмены | string | текст (рус. подпись причины) | Да | .CancelReason |
PayoutOrderNumber | № поручения | string | текст | Да | .PayoutOrderNumber |
Сортировка строк: PartnerFullName ASC, затем DealCompletedAt DESC. Для партнёра (Scope = own) все
строки — по одному партнёру.
Процесс Генерации
- Постановка задачи, разрешение scope по permission (
rewards.referral.view-own→ own /rewards.commission.view-all→ all), проверка лимитов и audit — ../api/partner/create-referral-rewards-export.md. - Фоновый исполнитель читает реферальные начисления за период (record-level
PartnerUserIdприown; опциональныйPartnerUserId/Statusприall) с привязкой к реферальным поручениям — согласованный снапшот на момент чтения. - Обогащение: ФИО партнёров и названия застройщиков из
identity(batch по уникальным id). - Проверка лимита строк (≤ 100 000, иначе задача →
FailedcREWARDS_EXPORT_ROW_LIMIT_EXCEEDED). - Формирование
ReferralRewardsByPartnerRowModel[](потоково) иReferralRewardsByPartnerTotalsModel; контроль сходимости totals (расхождение — дефект целостности, задача →Failed, алерт). - Сериализация XLSX → приватное объектное хранилище (retention 7 дней); задача →
Completed; финальная audit-запись (число строк, исход). Ссылка на скачивание — короткоживущий signed URL (../api/partner/get-referral-rewards-export-job.md).
Лимиты
| Лимит | Значение | Ошибка |
|---|---|---|
| Max rows | 100 000 строк | REWARDS_EXPORT_ROW_LIMIT_EXCEEDED (задача Failed) |
| Max date range | 1 год | REWARDS_EXPORT_PERIOD_TOO_WIDE (400 на постановке) |
| Concurrent exports | 2 активные задачи на актора | REWARDS_EXPORT_CONCURRENCY_LIMIT (429 на постановке) |
| Форматы | XLSX | — |
Наблюдаемость
| Тип | Правило |
|---|---|
| Metrics | rewards_export_duration_seconds, rewards_export_rows, rewards_export_file_bytes, rewards_export_jobs_total{report_type=referral_by_partner,result} |
| Logs | постановка / генерация / выдача ссылки / истечение / отказ — с актором, scope и фильтрами; суммы не логируются (Financial) |
| Traces | traceparent, ActorUserId, JobId |
| Audit | ExportSensitive на постановку, выдачу ссылки и исход генерации |
Обратные ссылки
Автоссылки: где используется этот документ.
- API (3): GET /api/v1/my/referral-accruals — Мои реферальные начисления (партнёр), GET /api/v1/referral-rewards-exports/{jobId} — Статус выгрузки и ссылка на скачивание, POST /api/v1/referral-rewards-exports — Постановка Excel-выгрузки реферальных вознаграждений
- Use Cases (1): US-реестр: Реферальный партнёр (US-PRT)
- Отчёты (1): Отчет/Export: Сводка реферальных вознаграждений за период (referral-rewards-period-summary)
- index.md (1): Rewards Service
Связанные документы
- Операции конвейера: ../api/partner/create-referral-rewards-export.md, ../api/partner/get-referral-rewards-export-job.md.
- Сводный отчёт за период: referral-rewards-period-summary.md.
- Дома полей: ../domain/referral-accrual.md (снапшот ставки, статусы,
INV-RA-2), ../domain/referral-rate-rule.md (область/специфичность
ставки), ../domain/payout-order.md (
ReferralReward,Number). - Онлайн-аналог для партнёра: ../api/partner/list-my-referral-accruals.md.
- ADR-0041 (async pipeline,
signed URL), ADR-0066 (реферальные начисления — отдельная сущность), ADR-0067 (гейт
MoneyReceived→Approved), ADR-0048 (RUB-only), ADR-0052 (tenancy — платформенная сущность).