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

Отчет/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 актора.

ActorPermissionОбласть выборкиAudit
реферальный партнёрrewards.referral.view-ownrecord-level: только PartnerUserId = ActorUserId (из claims, не из фильтров)ExportSensitive — постановка, выдача ссылки, исход генерации
Менеджер ПИНrewards.commission.view-allплатформенный scope: все партнёры; опциональный фильтр PartnerUserIdExportSensitive — постановка, выдача ссылки, исход генерации

Агентству и застройщику реферальные начисления не раскрываются.

Исходные Source Data

ИсточникВладелецТипFreshnessJoin key
rewards.referral_accrualsrewardssource of truth (суммы/статусы/снапшот ставки — ../domain/referral-accrual.md)строго согласованоDealCompletedAt (период) [+ PartnerUserId]
rewards.payout_order_items + rewards.payout_orders (Kind = ReferralReward)rewardssource of truth (Number поручения — ../domain/payout-order.md)строго согласованоPayoutOrderItemId → поручение
Пользователи identity (ФИО партнёров)identityenrichment при генерации (не хранится в rewards)на момент генерацииPartnerUserId
Компании identity (названия застройщиков)identityenrichment при генерациина момент генерацииDeveloperCompanyId

ФИО партнёра и название застройщика подставляются в момент генерации (актуальные значения identity); при недоступности identity задача ретраится, частичный файл не публикуется. Если пользователь/компания не найдены (устаревшая ссылка) — в ячейку пишется id (fail-open отображения, warn-лог). Область применённой ставки (проект, группа планировок) отдаётся идентификаторами из снапшота начисления — без enrichment имён каталога.

Фильтры ReferralRewardsByPartnerFilterModel

Снимаются с задачи выгрузки (../api/partner/create-referral-rewards-export.md).

ПолеТипОбязательностьDefaultОграничения
ActorUserIdGuidДаidentity claimsRequired; не из UI
Scopestring (own/all)Дапо permission актораown для rewards.referral.view-own; all для rewards.commission.view-all
PeriodFromDateTimeOffsetДастроки: DealCompletedAt >= PeriodFrom
PeriodToDateTimeOffsetДа> PeriodFrom (исключительно); диапазон ≤ 1 года
PartnerUserIdGuid?Нетвсе партнёры (только Scope = all)при Scope = own игнорируется и жёстко замещается ActorUserId (warn-лог, если задан иной)
Statusstring? (enum ReferralAccrualStatus)Нетвсе статусыPending/Approved/Paid/Cancelled

Строка Отчета ReferralRewardsByPartnerRowModel

Одна строка = одно начисление (ReferralAccrualEntity) выборки. Все суммы — в валюте начисления (CurrencyId, RUB-only по ADR-0048); валюта выборки едина, иначе генерация падает REWARDS_CURRENCY_MISMATCH (защита целостности, задача → Failed).

ПолеТипОбязательностьРасчетMasking
PartnerFullNamestringДаenrichment identity по PartnerUserId (ФИО на момент генерации)
DealIdGuidДаReferralAccrualEntity.DealId
DeveloperNamestringДаenrichment identity по DeveloperCompanyId (застройщик сделки)
DealCompletedAtDateTimeOffsetДаDealCompletedAt
AppliedPercentdecimalДаAppliedRateSnapshot.Percent (применённая ставка)
AppliedRateScopestring (enum ReferralRateScope)ДаAppliedRateSnapshot.Scope (область: PartnerDeveloperProjectLayoutGroupGlobal)
AppliedScopeProjectIdGuid?Нет (null — область без проекта)AppliedRateSnapshot.ProjectId (проект области ставки)
AppliedScopeLayoutGroupIdGuid?Нет (null — область без группы планировок)AppliedRateSnapshot.LayoutGroupId
BaseAmountdecimalДаBaseAmount.Value (конечная цена сделки — база расчёта)Financial
AmountdecimalДаAmount.Value (BaseAmount × Percent / 100, INV-RA-2)Financial
Statusstring (enum ReferralAccrualStatus)ДаStatus
ApprovedAtDateTimeOffset?НетApprovedAt (авто-апрув при MoneyReceived родителя — гейт ADR-0067)
PaidAtDateTimeOffset?НетPaidAt
CancelledAtDateTimeOffset?НетCancelledAt
CancelReasonstring? (enum ReferralCancelReason)Нет (обязателен при Cancelled)CancelReason
PayoutOrderNumberstring?Нет (null — не включено в поручение)Number реферального поручения через PayoutOrderItemId → позицию (PO-{yyyy}-{seq})

InvestorUserId, BondId и родительское комиссионное начисление (CommissionAccrualId) в выгрузку не попадают — только основание расчёта и итоговые суммы.

Модель Totals ReferralRewardsByPartnerTotalsModel

Итоги по всей выборке фильтра (строка «Итого» под таблицей).

ПолеТипОбязательностьРасчетPrecision
RowsCountintДаcount строк выборкицелое
TotalBaseAmountdecimalДаΣ BaseAmountscale 2, banker's; CurrencyId выборки
TotalAmountdecimalДаΣ Amount (все строки выборки)scale 2
TotalPendingAmountdecimalДаΣ Amount строк в Pendingscale 2
TotalApprovedAmountdecimalДаΣ Amount строк в Approvedscale 2
TotalPaidAmountdecimalДаΣ Amount строк в Paidscale 2
TotalCancelledAmountdecimalДаΣ 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Дата завершенияDateTimeOffsetdd.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ОдобреноDateTimeOffsetdd.MM.yyyyДа.ApprovedAt
PaidAtВыплаченоDateTimeOffsetdd.MM.yyyyДа.PaidAt
CancelledAtОтмененоDateTimeOffsetdd.MM.yyyyДа.CancelledAt
CancelReasonПричина отменыstringтекст (рус. подпись причины)Да.CancelReason
PayoutOrderNumber№ порученияstringтекстДа.PayoutOrderNumber

Сортировка строк: PartnerFullName ASC, затем DealCompletedAt DESC. Для партнёра (Scope = own) все строки — по одному партнёру.

Процесс Генерации

  1. Постановка задачи, разрешение scope по permission (rewards.referral.view-own → own / rewards.commission.view-all → all), проверка лимитов и audit — ../api/partner/create-referral-rewards-export.md.
  2. Фоновый исполнитель читает реферальные начисления за период (record-level PartnerUserId при own; опциональный PartnerUserId/Status при all) с привязкой к реферальным поручениям — согласованный снапшот на момент чтения.
  3. Обогащение: ФИО партнёров и названия застройщиков из identity (batch по уникальным id).
  4. Проверка лимита строк (≤ 100 000, иначе задача → Failed c REWARDS_EXPORT_ROW_LIMIT_EXCEEDED).
  5. Формирование ReferralRewardsByPartnerRowModel[] (потоково) и ReferralRewardsByPartnerTotalsModel; контроль сходимости totals (расхождение — дефект целостности, задача → Failed, алерт).
  6. Сериализация XLSX → приватное объектное хранилище (retention 7 дней); задача → Completed; финальная audit-запись (число строк, исход). Ссылка на скачивание — короткоживущий signed URL (../api/partner/get-referral-rewards-export-job.md).

Лимиты

ЛимитЗначениеОшибка
Max rows100 000 строкREWARDS_EXPORT_ROW_LIMIT_EXCEEDED (задача Failed)
Max date range1 годREWARDS_EXPORT_PERIOD_TOO_WIDE (400 на постановке)
Concurrent exports2 активные задачи на актораREWARDS_EXPORT_CONCURRENCY_LIMIT (429 на постановке)
ФорматыXLSX

Наблюдаемость

ТипПравило
Metricsrewards_export_duration_seconds, rewards_export_rows, rewards_export_file_bytes, rewards_export_jobs_total{report_type=referral_by_partner,result}
Logsпостановка / генерация / выдача ссылки / истечение / отказ — с актором, scope и фильтрами; суммы не логируются (Financial)
Tracestraceparent, ActorUserId, JobId
AuditExportSensitive на постановку, выдачу ссылки и исход генерации

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

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

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