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

Отчет/Export: Вознаграждения агентства по сотрудникам и сделкам (agency-rewards-by-employee-per-deal)

XLSX-выгрузка агентства: строка = одно комиссионное начисление (сделка агента) за период — с человекочитаемой карточкой объекта (тип/комнаты/площадь) и его конечной ценой, полной финансовой раскладкой (комиссия gross, удержание ПИН, пул агентства, доля агента, удержание агентства), статусными датами и номером платёжного поручения. Генерируется асинхронной задачей (../api/agency/create-rewards-export.md, ReportType = ByEmployeePerDeal) по конвейеру ADR-0041.

Назначение

Даёт владельцу/руководителю агентства детальную картину вознаграждений по каждому сотруднику и каждой сделке: сколько начислено застройщиком, сколько удержал ПИН, как пул поделён между агентом и агентством, что подтверждено/получено/выплачено и каким поручением. Decision value — сверка с бухгалтерией, контроль выплат агентам, разбор спорных сделок. Owning service — rewards.

Классификация

ПолеЗначение
Тип отчетаXLSX
Аудиториявладелец/руководитель агентства
ЧувствительностьFinancial/Sensitive — суммы вознаграждений и персональные доли агентов; PII инвесторов в отчёт не попадает
Freshness SLAсостояние rewards на момент генерации (строго согласованный снапшот OLTP; без окна eventual-consistency)
Retentionфайл — 7 дней в приватном объектном хранилище; данные-источник — бессрочно (финансовая история)

Доступ

ActorPermissionTenant/Brand scopeAudit
владелец/руководитель агентстваrewards.commission.view-allTenantId = CompanyId агентства из claims; fail-closedExportSensitive — постановка, выдача ссылки, исход генерации

Агент и застройщик доступа к выгрузке не имеют (агент видит только свои начисления в ../api/agent/list-my-accruals.md; застройщику распределение агентства не раскрывается).

Исходные Source Data

ИсточникВладелецТипFreshnessJoin key
rewards.commission_accrualsrewardssource of truth (в т.ч. FinalPriceAmount и снапшот атрибутов объекта AppliedRuleSnapshot../domain/commission-accrual.md)строго согласованоTenantId + DealCompletedAt (период)
rewards.commission_distributionsrewardssource of truth (три строки Platform/Agency/Agent../domain/commission-accrual.md)строго согласованоAccrualId
rewards.payout_order_items + rewards.payout_ordersrewardssource of truth (Number поручения — ../domain/payout-order.md)строго согласованоAgent-строка → PayoutOrderItemId → поручение
Пользователи identity (ФИО агентов)identityenrichment при генерации (не хранится в rewards)на момент генерацииAgentUserId
Компании identity (названия застройщиков)identityenrichment при генерациина момент генерацииDeveloperCompanyId

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

Фильтры AgencyRewardsByDealFilterModel

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

ПолеТипОбязательностьDefaultОграничения
TenantIdGuidДаidentity claimsRequired; не из UI
PeriodFromDateTimeOffsetДастроки: DealCompletedAt >= PeriodFrom
PeriodToDateTimeOffsetДа> PeriodFrom (исключительно); диапазон ≤ 1 года
AgentUserIdGuid?Нетвсе агентытолько сделки этого агента
Statusstring? (enum CommissionAccrualStatus)Нетвсе статусыPendingConfirmation/Confirmed/MoneyReceived/Paid/Cancelled

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

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

ПолеТипОбязательностьРасчетMasking
AgentFullNamestringДаenrichment identity по AgentUserId (ФИО на момент генерации)
DealIdGuidДаCommissionAccrualEntity.DealId
PropertyObjectIdGuidДаPropertyObjectId
PropertyTypestring (enum PropertyType)ДаAppliedRuleSnapshot.PropertyObjectPropertyType (снапшот на момент сделки)
Roomsint?Нет (null — студия/нежилой объект без комнатности)AppliedRuleSnapshot.PropertyObjectRooms
AreaTotalM2decimalДаAppliedRuleSnapshot.PropertyObjectAreaTotalM2 (снапшот, м²)
DeveloperNamestringДаenrichment identity по DeveloperCompanyId
DealCompletedAtDateTimeOffsetДаDealCompletedAt
Statusstring (enum CommissionAccrualStatus)ДаStatus
FinalPriceAmountdecimalДаFinalPriceAmount.Value (конечная цена объекта: базовая + ремонт, на момент сделки)Financial
CommissionGrossdecimalДаCommissionAmount.Value (после корректировок; исходная сумма — не выгружается, аудит корректировок — отдельная сущность)Financial
PlatformFeedecimalДаPlatformFeeAmount.Value (удержание ПИН, INV-10)Financial
AgencyPooldecimalДаCommissionGross − PlatformFeeFinancial
AgentSharedecimal?Нет (null до Confirmed — строк распределения ещё нет)Amount.Value строки AgentFinancial
AgencyRetentiondecimal?Нет (null до Confirmed)Amount.Value строки AgencyFinancial
ConfirmedAtDateTimeOffset?НетConfirmedAt
MoneyReceivedAtDateTimeOffset?НетMoneyReceivedAt (регистрация акта — гейт ADR-0067)
PaidAtDateTimeOffset?НетPaidAt
PayoutOrderNumberstring?Нет (null — доля не включена в поручение)Number поручения через Agent-строку → позицию (PO-{yyyy}-{seq})

InvestorUserId, ставки правил застройщика и снапшот условий платформы в выгрузку не попадают — только итоговые суммы. Строка Platform раскрывается единственным числом PlatformFee. Карточка объекта (PropertyType/Rooms/AreaTotalM2) берётся из снапшота начисления AppliedRuleSnapshot — это значения на момент сделки (последующие правки объекта в chessboard отчёт не меняют); адрес объекта в снапшот не входит и в выгрузку не попадает.

Модель Totals AgencyRewardsByDealTotalsModel

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

ПолеТипОбязательностьРасчетPrecision
RowsCountintДаcount строк выборки (все статусы, включая Cancelled)целое
CancelledCountintДаcount строк со статусом Cancelled в выборке (справочно)целое
TotalGrossdecimalДаΣ CommissionGross по строкам со статусом ≠ Cancelledscale 2, banker's; CurrencyId выборки
TotalPlatformFeedecimalДаΣ PlatformFee (строки ≠ Cancelled)scale 2
TotalAgencyPooldecimalДаΣ AgencyPool (строки ≠ Cancelled)scale 2
TotalAgentSharedecimalДаΣ AgentShare (строки ≠ Cancelled; строки без распределения дают 0)scale 2
TotalAgencyRetentiondecimalДаΣ AgencyRetention (строки ≠ Cancelled; строки без распределения дают 0)scale 2

Денежные totals исключают Cancelled — как в парном сводном отчёте (agency-rewards-period-summary.md): отменённое начисление в суммы не входит, но остаётся строкой таблицы и учитывается счётчиками RowsCount/CancelledCount (детальный аудит показывает и отменённые сделки). FinalPriceAmount — атрибут строки и в totals не суммируется (цены объектов не складываются).

Контроль сходимости: TotalPlatformFee + TotalAgentShare + TotalAgencyRetention = TotalGross — сходится по строкам со статусом Confirmed и выше (INV-5 ../domain/commission-accrual.md); строки PendingConfirmation дают TotalGross, но ещё не имеют распределения, поэтому точное равенство достигается только когда в выборке нет PendingConfirmation (либо при фильтре Status ≥ Confirmed).

Формат Export-а

Лист XLSX by-deal; заголовки русские; суммы — числовой формат scale 2; шапка листа — период, агентство, применённые фильтры, время генерации (UTC).

ColumnЗаголовокТипФорматNullableИсточник
AgentFullNameАгентstringтекстНетAgencyRewardsByDealRowModel.AgentFullName
DealIdСделкаGuidтекстНет.DealId
PropertyObjectIdОбъект (id)GuidтекстНет.PropertyObjectId
PropertyTypeТип объектаstringтекст (рус. подпись типа)Нет.PropertyType
RoomsКомнатint# ##0Да.Rooms
AreaTotalM2Площадь, м²decimal# ##0.00Нет.AreaTotalM2
DeveloperNameЗастройщикstringтекстНет.DeveloperName
DealCompletedAtДата завершенияDateTimeOffsetdd.MM.yyyyНет.DealCompletedAt
StatusСтатус начисленияstringтекст (рус. подпись статуса)Нет.Status
FinalPriceAmountКонечная цена объектаdecimal# ##0.00Нет.FinalPriceAmount
CommissionGrossКомиссия (gross)decimal# ##0.00Нет.CommissionGross
PlatformFeeУдержание ПИНdecimal# ##0.00Нет.PlatformFee
AgencyPoolПул агентстваdecimal# ##0.00Нет.AgencyPool
AgentShareДоля агентаdecimal# ##0.00Да.AgentShare
AgencyRetentionУдержание агентстваdecimal# ##0.00Да.AgencyRetention
ConfirmedAtПодтвержденоDateTimeOffsetdd.MM.yyyyДа.ConfirmedAt
MoneyReceivedAtПолученоDateTimeOffsetdd.MM.yyyyДа.MoneyReceivedAt
PaidAtВыплаченоDateTimeOffsetdd.MM.yyyyДа.PaidAt
PayoutOrderNumber№ порученияstringтекстДа.PayoutOrderNumber

Сортировка строк: AgentFullName ASC, затем DealCompletedAt DESC.

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

  1. Постановка задачи, проверка permission rewards.commission.view-all, tenant scope, лимитов и audit — ../api/agency/create-rewards-export.md.
  2. Фоновый исполнитель читает начисления tenant-а за период (+ фильтры AgentUserId/Status) со строками распределения и привязкой к поручениям — согласованный снапшот на момент чтения.
  3. Обогащение: ФИО агентов и названия застройщиков из identity (batch по уникальным id).
  4. Проверка лимита строк (≤ 100 000, иначе задача → Failed c REWARDS_EXPORT_ROW_LIMIT_EXCEEDED).
  5. Формирование AgencyRewardsByDealRowModel[] (потоково) и AgencyRewardsByDealTotalsModel (денежные суммы — без Cancelled); контроль сходимости totals по подмножеству Confirmed+ (расхождение — дефект целостности, задача → Failed, алерт).
  6. Сериализация XLSX → приватное объектное хранилище (retention 7 дней); задача → Completed; финальная audit-запись (число строк, исход). Ссылка на скачивание — короткоживущий signed URL (../api/agency/get-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=by_employee_per_deal,result}
Logsпостановка / генерация / выдача ссылки / истечение / отказ — с актором и фильтрами; суммы не логируются (Financial)
Tracestraceparent, TenantId, JobId
AuditExportSensitive на постановку, выдачу ссылки и исход генерации

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

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

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