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

GET /api/v1/developer/commission-accruals — Начисления комиссий для застройщика

Постраничный список начислений комиссий, где текущая компания-застройщик — плательщик (DeveloperCompanyId), с фильтрами по статусу и датам — очередь подтверждения обязательств по комиссиям.

Назначение

Менеджер застройщика видит, какие комиссии начислены по его сделкам, что ожидает подтверждения и что уже подтверждено/выплачено. Это cross-tenant чтение: начисления живут в tenant-е агентства (ADR-0052, решение №2 ../README.md), застройщик читает их по своему явному полю DeveloperCompanyId. Feature group — developer-accruals.

Metadata

ПолеЗначение
Сервис/контекстrewards
API areadeveloper-admin
Feature groupdeveloper-accruals
Статусdraft
Документdocs/06-services/rewards/api/admin/list-developer-accruals.md

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

ПроверкаЗначение
Actor typeUser (менеджер компании-застройщика)
Auth policy / Permissionsrewards.accruals.confirm
Scope (RBAC)организация: компания Type = Developer
Record-levelфильтр DeveloperCompanyId = CompanyId актора (жёстко на сервере, не из query)
Tenant isolationCross-tenant чтение: выборка не ограничивается tenant-ом агентства; изоляция — permission + обязательный серверный фильтр DeveloperCompanyId
Auditread-sensitive (суммы комиссий): в trace фиксируется actor + фильтры, суммы не логируются

HTTP-контракт

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

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
DeveloperCompanyIdidentity claims (tenant_id актора)GuidДаRequired; не принимается из queryrecord-level фильтр
StatusqueryCommissionAccrualStatus?Нетenum PendingConfirmation/Confirmed/Paid/Cancelled
DealCompletedFromqueryDateTimeOffset?Нет
DealCompletedToqueryDateTimeOffset?Нет> DealCompletedFrom, если обе заданы
AgencyCompanyIdqueryGuid?Нетфильтр по агентству-получателю
Page / PageSizequeryintНетpaging-конвенция — README.md

Модель ответа ListDeveloperAccrualsQueryResult

Страница DeveloperAccrualListItemModel. Дельта от CommissionAccrualModel (README.md): без Distributions (распределение — внутреннее дело агентства, Masking-правила реестра) и без AppliedPolicyId.

ПолеТипОбязательностьИсточникMaskingОписание
ItemsIReadOnlyList<DeveloperAccrualListItemModel>ДаprojectionDistributions/AppliedPolicyId/InvestorUserId исключеныСтраница начислений.
Page / PageSize / TotalCountint / int / longДаpagingПараметры страницы.

DeveloperAccrualListItemModel = CommissionAccrualModel минус Distributions, AppliedPolicyId.

Алгоритм

  1. Контекст и доступ. Операцию выполняет менеджер компании-застройщика (тип компании Developer, иначе FORBIDDEN); scope — организация застройщика; требуется право rewards.accruals.confirm. DeveloperCompanyId берётся только из claims актора, не из query.
  2. Проверка входа. Enum Status, согласованность дат (DealCompletedTo > DealCompletedFrom), параметры paging — иначе ValidationError.
  3. Выборка. Постранично отбираются начисления с обязательным фильтром DeveloperCompanyId = компания актора (cross-tenant чтение, без ограничения по tenant-у агентства) и опциональными Status, диапазоном DealCompletedAt, AgencyCompanyId. Сортировка — DealCompletedAt DESC, Id DESC: вторичный ключ Id обеспечивает стабильный порядок страниц (без пропусков/дублей при равных DealCompletedAt).
  4. Проекция и маскирование. Каждая строка отдаётся как DeveloperAccrualListItemModel; AgencyCompanyId — из TenantId начисления, AppliedRule.RuleName — из snapshot-а. Distributions и AppliedPolicyId застройщику не отдаются (внутреннее дело агентства); InvestorUserId не отдаётся никогда.
  5. Результат. Страница начислений (Items, Page, PageSize, TotalCount) → 200.

Диаграмма

Ошибки и failure modes

Общие коды (ValidationError, FORBIDDEN, UNAUTHORIZED) — README.md. Специфичных нет.

Acceptance-критерии

  • Happy path. Дано: по сделкам застройщика есть начисления в разных статусах, актор с rewards.accruals.confirm. Когда: GET /api/v1/developer/commission-accruals. Тогда: 200, страница начислений, где DeveloperCompanyId = компания актора; сортировка по DealCompletedAt DESC, Id DESC; в каждой строке нет Distributions, AppliedPolicyId, InvestorUserId.
  • Стабильная пагинация при равных датах. Дано: несколько начислений с одинаковым DealCompletedAt, выборка разбита на страницы. Когда: последовательный GET страниц. Тогда: каждая строка попадает ровно на одну страницу (вторичный ключ Id DESC исключает пропуски и дубли на границах страниц).
  • Очередь на подтверждение. Дано: ?status=PendingConfirmation. Когда: GET. Тогда: только начисления, ожидающие подтверждения этим застройщиком.
  • Cross-tenant изоляция. Дано: начисления живут в tenant-ах разных агентств. Когда: GET. Тогда: застройщик видит начисления всех агентств по своему DeveloperCompanyId, но не начисления с чужим DeveloperCompanyId.
  • Фильтр по агентству. Дано: ?agencyCompanyId=A. Когда: GET. Тогда: только начисления, где агентство-получатель = A.
  • Некорректный диапазон дат. Дано: ?dealCompletedFrom > ?dealCompletedTo. Когда: GET. Тогда: 400 ValidationError.
  • Пустой результат. Дано: под фильтр не подходит ни одно начисление. Когда: GET. Тогда: 200, Items = [], TotalCount = 0.
  • Нет права. Дано: у актора нет rewards.accruals.confirm. Когда: GET. Тогда: 403 FORBIDDEN.

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

  • Модель — проекция общего CommissionAccrualModel: изменения additive.
  • Logs: DeveloperCompanyId, фильтры, TotalCount (суммы не логируются); metrics: rewards_api_request_duration_seconds{route}, rewards_developer_accruals_pending_gauge (для алёрта «зависшие подтверждения»); traces: OTel; dashboard rewards-overview.

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

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

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