GET /api/v1/agency/payout-orders — Список платёжных поручений (история выплат)
Постраничная история выплат агентства: список всех платёжных поручений с номерами, периодами, суммами и статусами (ожидается / выплачено / отклонено) — экран «История выплат» ЛК руководителя агентства (матрица «Агенство» 5.5).
Назначение
Руководитель/бухгалтер агентства просматривает все платёжные поручения своего агентства — черновики в
работе, переданные в бухгалтерию (PendingPayment = «ожидается»), выплаченные (Paid = «выплачено») и
отклонённые (Rejected = «отклонено») — с фильтрами по статусу и периоду. Дом полей и статусная модель —
domain/payout-order.md; проекция PayoutOrderModel — README.md.
Feature group — payouts.
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | rewards |
| API area | agency |
| Feature group | payouts |
| Статус | draft |
| Документ | docs/06-services/rewards/api/agency/list-payout-orders.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (руководитель/бухгалтер/администратор агентства) |
| Auth policy / Permissions | rewards.payouts.manage (op22) |
| Scope (RBAC) | организация: компания Type ∈ {Agency, Broker, Pin} |
| Record-level | не применяется (все поручения агентства; агенту — отдельный path list-my-payouts) |
| Tenant isolation | TenantId = CompanyId агентства из claims; tenant-интерсептор (не из query) |
| Audit | read-sensitive (суммы выплат): в trace — actor + фильтры + TotalCount; суммы не логируются |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | GET |
| Route | /api/v1/agency/payout-orders |
| Success status | 200 |
| Idempotency header | не применяется (read) |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
TenantId | identity claims (tenant_id) | Guid | Да | Required; не принимается из query | Tenant isolation |
Status | query | PayoutOrderStatus? | Нет | enum Draft/PendingPayment/Paid/Rejected/Cancelled | — |
CreatedFrom | query | DateTimeOffset? | Нет | нижняя граница CreatedAt (включительно) | — |
CreatedTo | query | DateTimeOffset? | Нет | верхняя граница CreatedAt (исключительно); > CreatedFrom, если обе заданы | — |
PeriodTo | query | DateTimeOffset? | Нет | фильтр по концу расчётного периода: PayoutOrder.PeriodTo <= PeriodTo | — |
Page / PageSize | query | int | Нет | paging-конвенция — README.md (Page >= 1, PageSize 1..100) | — |
Модель ответа — постраничный список PayoutOrderModel
Постраничный ответ: Items (список PayoutOrderModel), Page, PageSize, TotalCount (paging-конвенция
— README.md). Проекция PayoutOrderModel — дом README.md «Общие
контрактные модели».
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|---|---|---|---|---|
Items | IReadOnlyList<PayoutOrderModel> | Да | projection PayoutOrderEntity | суммы видны только роли с rewards.payouts.manage | Страница поручений (newest-first). |
Page / PageSize / TotalCount | int / int / long | Да | paging | — | Параметры страницы. |
Дельта проекции для списка: PayoutOrderModel.Items (позиции PayoutOrderItemModel) в списке
отдаётся пустой коллекцией — дочерняя payout_order_items не джойнится ради производительности
истории; детализация состава загружается отдельным запросом одного поручения (GetById корня —
используется командами состава/утверждения: update-payout-order-items.md,
approve-payout-order.md). InvestorUserId в проекции отсутствует
(Masking-правила README.md).
Алгоритм
- Контекст и доступ. Операцию выполняет руководитель/бухгалтер/администратор агентства (тип компании
Agency/Broker/Pin); scope — организация (TenantIdиз claims, не из query); требуется правоrewards.payouts.manage. Иначе —FORBIDDEN. - Проверка входа.
Status— допустимое значение enumPayoutOrderStatus, если задан;CreatedTo > CreatedFrom, если обе заданы;Page/PageSize— по конвенции; иначе ошибка валидации. - Что читаем. Страница поручений агентства-tenant-а по фильтрам: опц.
Status, границыCreatedAt,PeriodTo; сортировка — поCreatedAtDESC (история — свежие сверху); пагинация — по конвенции. Опорный индекс —ix_payout_orders_tenant_statusпри заданномStatus, сортировка поддержанаix_payout_orders_created_at. Позиции поручений (payout_order_items) в список не включаются (детализация состава — отдельным запросом одного поручения). - Проекция. Каждое поручение разворачивается в
PayoutOrderModelполе-в-поле (дом README.md):Number,Title,PeriodFrom/To,Status(enum строкой),TotalAmount → MoneyModel,ItemsCount,ApprovedAt,PaidAt,RejectedAt,RejectReason,CancelledAt,CreatedAt,Version;Items = [](пустая коллекция, см. дельту). - Результат. Постраничный список (
Items,Page,PageSize,TotalCount) → HTTP200; суммы в логах маскируются, в теле доступны роли с permission.
Диаграмма
Ошибки и failure modes
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
ValidationError | 400 | Неверный Status (вне enum), CreatedTo <= CreatedFrom, PageSize вне 1..100 | «Проверьте параметры фильтра» | no retry |
FORBIDDEN | 403 | Нет rewards.payouts.manage / тип компании не агентство / чужой tenant | «Недостаточно прав» | no retry |
UNAUTHORIZED | 401 | Нет/просрочен JWT | «Требуется авторизация» | no retry |
Специфичных REWARDS_*-кодов у read-операции нет; коды выше — общие, дом
README.md «Общие ошибки».
Acceptance criteria
- AC-1 (история выплат). Given у агентства есть поручения в разных статусах; When руководитель
запрашивает список без фильтра; Then
200, поручения поCreatedAtDESC (свежие сверху), у каждого —Number,Status,PeriodFrom/To,TotalAmount,ItemsCount, даты переходов;Items = [](позиции в списке не джойнятся). - AC-2 (фильтр по статусу). Given те же данные; When
Status = Paid; Then в выдаче только выплаченные поручения; аналогичноPendingPayment= «ожидается»,Rejected= «отклонено»,Draft/Cancelled— рабочие/отменённые. - AC-3 (фильтр по периоду). Given поручения с разными
CreatedAt/PeriodTo; When заданыCreatedFrom/CreatedTo(илиPeriodTo); Then остаются только попавшие в границы;CreatedToисключителен,CreatedFromвключителен. - AC-4 (детализация состава — отдельным запросом). Given элемент списка с
ItemsCount = 5; When клиент открывает поручение; Then позиции по агентам грузятся отдельным запросом одного поручения (в спискеItems = []) — экономия джойна на истории. - AC-5 (пустой результат / за пределами страницы). Given нет поручений под фильтр или
Pageза последней; Then200,Items = [], корректныйTotalCount(не404). - AC-6 (валидация фильтра). Given
Statusвне enum,CreatedTo <= CreatedFromилиPageSizeвне1..100; ThenValidationError(400). - AC-7 (доступ и изоляция). Given актор без
rewards.payouts.manageили не роль агентства —FORBIDDEN(403); Given актор агентства A — в выдаче только поручения A (TenantIdиз claims, не из query), суммы видны лишь ролям сrewards.payouts.manage, в логи не пишутся. - AC-8 (свежесть). Given только что утверждено/выплачено поручение; When сразу запрошена история;
Then новый статус уже виден (строгая согласованность внутри
rewards— история читается из OLTP по поручениям, а не из событий).
Совместимость и наблюдаемость
PayoutOrderModel— общая проекция из README.md: новые optional поля additive; удаление/ переименование/смена типа — breaking (migration + rollout). Новые значенияPayoutOrderStatus— по unknown-enum-правилу cross-cutting.- Logs:
TenantId, фильтры (Status, границы дат),TotalCount(суммы поручений не логируются); metrics:rewards_api_request_duration_seconds{route}; traces: OTel, correlation черезtraceparent; dashboardrewards-overview; runbook — не применяется (read). - НФТ (ADR-0056): единицы поручений на агентство в месяц — история измеряется десятками-сотнями строк;
выборка идёт по
ix_payout_orders_tenant_status/ix_payout_orders_created_atбез джойна позиций; целевая латентность p95 < 250 мс; частота обращений низкая (back-office бухгалтерии/руководителя).
Обратные ссылки
Автоссылки: где используется этот документ.
- API (4): GET /api/v1/my/payouts — Мои выплаты (агент), GET /api/v1/platform/referral-payout-orders — Список реферальных платёжных поручений, POST /api/v1/agency/payout-orders/{orderId}/cancel — Отмена черновика поручения, Rewards API — реестр операций и общие контрактные модели
- Use Cases (2): UC-RWD-005. Агентство настраивает распределение и формирует платёжное поручение, US-реестр: Владелец агентства (US-OWN-AG)
- registries (1): Реестр API-методов PIN
Связанные документы
- Сущность и статусная модель: domain/payout-order.md (маппинг статусов на
матрицу 5.5:
PendingPayment=«ожидается»,Paid=«выплачено»,Rejected=«отклонено»). - Проекция и paging-конвенция: README.md («
PayoutOrderModel», «Paging»). - Создание и переходы поручения: create-payout-order.md, update-payout-order-items.md, approve-payout-order.md, mark-payout-order-paid.md, reject-payout-order.md, cancel-payout-order.md.