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

GET /api/v1/my/referral-accruals — Мои реферальные начисления (партнёр)

Постраничный список реферальных начислений текущего пользователя-партнёра (../../domain/referral-accrual.md): сколько и по каким сделкам приведённых им инвесторов начислено, что уже одобрено к выплате (деньги от застройщика получены) и что выплачено.

Назначение

Реферальный партнёр в личном кабинете видит свои вознаграждения и их статусы: «начислено» (Pending), «одобрено» (Approved — гейт получения денег пройден, ADR-0067), «выплачено» (Paid), «отменено» (Cancelled). Личные данные приведённых инвесторов партнёру не раскрываются. Feature group — my-referral.

Metadata

ПолеЗначение
Сервис/контекстrewards
API areapartner
Feature groupmy-referral
Статусdraft
Документdocs/06-services/rewards/api/partner/list-my-referral-accruals.md

Актор и доступ

ПроверкаЗначение
Actor typeUser (реферальный партнёр — любой авторизованный пользователь с реферальными начислениями; компания не требуется)
Auth policy / Permissionsrewards.referral.view-own
Scope (RBAC)платформа (реферальные начисления — вне tenant-модели, ../../domain/referral-accrual.md)
Record-levelPartnerUserId = ActorUserId — выборка жёстко ограничена начислениями самого актора (фильтр из claims, не из query)
Auditnone (read собственных данных; суммы — Sensitive, не логируются)

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/my/referral-accruals
Success status200
Idempotency headerне применяется (read)
Correlationсквозной trace через заголовок traceparent

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
ActorUserIdidentity claims (sub)GuidДаRequired; используется как PartnerUserId выборкиrecord-level
Statusquerystring? (enum ReferralAccrualStatus)НетPending/Approved/Paid/Cancelled; пусто = все
PeriodFromqueryDateTimeOffset?Нетфильтр по DealCompletedAt >= PeriodFrom
PeriodToqueryDateTimeOffset?НетPeriodTo > PeriodFrom, если оба заданы; DealCompletedAt < PeriodTo
Page / PageSizequeryintНетpaging-конвенция — README.md

Модель ответа — постраничный список ReferralAccrualModel

Постраничный ответ (Items, Page, PageSize, TotalCount — paging-конвенция README.md); дом модели ReferralAccrualModelREADME.md («Общие контрактные модели»). Masking для партнёра: InvestorUserId не отдаётся (PII приведённого инвестора — ../../domain/referral-accrual.md, «Permissions / PII»); партнёр видит основание (BondId), сделку (DealId — без деталей), застройщика, применённый процент из снапшота ставки, сумму и статусные даты.

Алгоритм

Тривиальное постраничное чтение: проверить Status/PeriodFrom/PeriodTo/Page/PageSize (иначе ValidationError); выбрать начисления с PartnerUserId = ActorUserId (record-level из claims), применить опциональные фильтры по статусу и периоду DealCompletedAt; сортировка — DealCompletedAt DESC (свежие сделки выше); спроецировать в ReferralAccrualModel (применённый процент — из AppliedRateSnapshot; InvestorUserId не проецируется). Пустая страница у пользователя без начислений — валидный ответ (Items = [], TotalCount = 0), не ошибка. Данные строго согласованы внутри rewards: статусы отражают последнюю регистрацию акта/выплату немедленно (агрегатное чтение OLTP, без eventual-consistency).

Ошибки и failure modes

Специфичных REWARDS_*-кодов у read-операции нет. Применяются общие коды — дом README.md «Общие ошибки»:

КодHTTP statusУсловиеСообщениеRetry
ValidationError400Status вне enum; PeriodTo <= PeriodFrom; PageSize вне 1..100«Проверьте параметры фильтра»no retry
UNAUTHORIZED401нет/просрочен JWT«Требуется авторизация»no retry
FORBIDDEN403нет rewards.referral.view-own«Недостаточно прав»no retry

Acceptance criteria

  • AC-1 (мои начисления). Given у партнёра есть начисления в разных статусах; When GET без фильтров; Then 200, только начисления с PartnerUserId = актор, отсортированы по DealCompletedAt DESC; в каждой строке — Amount, применённый Percent, статус и даты (ApprovedAt/PaidAt/CancelledAt); InvestorUserId отсутствует в payload.
  • AC-2 (фильтр по статусу). Given те же данные; When GET с Status = Approved; Then только начисления, одобренные к выплате (деньги от застройщика получены).
  • AC-3 (фильтр по периоду, границы). Given начисления с DealCompletedAt == PeriodFrom и == PeriodTo; When GET с периодом; Then первое в выдаче (нижняя граница включительна), второе — нет (верхняя исключительна).
  • AC-4 (record-level). Given в системе есть начисления других партнёров; When GET; Then чужие начисления не возвращаются ни при каких параметрах query — PartnerUserId берётся из claims.
  • AC-5 (пусто). Given у пользователя нет начислений; When GET; Then 200, Items = [], TotalCount = 0 (не 404).
  • AC-6 (свежесть). Given только что зарегистрирован акт поступления средств по родительскому начислению; When сразу GET; Then начисление уже Approved c ApprovedAt (строгая согласованность внутри rewards).

Совместимость и наблюдаемость

  • Новые optional поля ReferralAccrualModel — additive; новые значения ReferralAccrualStatus в фильтре — по unknown-enum-правилу (ValidationError); удаление/переименование полей — breaking.
  • Logs: ActorUserId, применённые фильтры, TotalCount (суммы не логируются — Sensitive); metrics: rewards_api_request_duration_seconds{route}; traces: OTel, correlation через traceparent.
  • НФТ (ADR-0056): выборка по ix_referral_accruals_partner (partner_user_id, status); единицы–десятки строк на партнёра; целевая латентность p95 < 200 мс.

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

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

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