GET /api/v1/agency/agent-boost-campaigns — Список boost-кампаний агентов
Список временных мотивационных кампаний агентства (действующие, черновики, архив) — экран «Boost-кампании» ЛК руководителя агентства. Boost поднимает долю набора агентов на период поверх базовой комиссионной политики.
Назначение
Руководитель агентства видит действующие и подготовленные кампании и историю свёрнутых. Feature group —
agent-boost (операция op57 реестра README.md).
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | rewards |
| API area | agency |
| Feature group | agent-boost |
| Статус | draft |
| Документ | docs/06-services/rewards/api/agency/list-agent-boost-campaigns.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (руководитель/администратор агентства) |
| Auth policy / Permissions | rewards.commission-policy.view |
| Scope (RBAC) | организация: компания Type ∈ {Agency, Broker, Pin} |
| Record-level | не применяется |
| Tenant isolation | TenantId = CompanyId агентства из claims; tenant-интерсептор |
| Audit | none (read; ставки/наборы агентов — Internal-класс внутри агентства) |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | GET |
| Route | /api/v1/agency/agent-boost-campaigns |
| Success status | 200 |
| Idempotency header | не применяется (read) |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
TenantId | identity claims (tenant_id) | Guid | Да | Required | Tenant isolation |
Status | query | AgentBoostCampaignStatus? | Нет | enum Draft/Active/Archived | — |
AgentUserId | query | Guid? | Нет | опц. фильтр «кампании с этим агентом в наборе» | — |
Page / PageSize | query | int | Нет | paging-конвенция — README.md | — |
Модель ответа — постраничный список AgentBoostCampaignModel
Постраничный ответ (Items, Page, PageSize, TotalCount — paging-конвенция README.md).
Правило BoostRule и набор AgentUserIds отдаются только ролям с rewards.commission-policy.view/
rewards.commission-policy.manage (руководитель/администратор агентства); агент такой роли не имеет и на этот эндпоинт
не попадает — действующий к нему boost он видит лишь в проекции «моя комиссия»
(get-my-commission-summary.md, Masking-правила README.md).
AgentBoostCampaignModel (проекция AgentBoostCampaignEntity)
Дом формы — create-agent-boost-campaign.md; дом полей под-агрегата — domain/agency-commission-policy.md.
| Поле | Тип | Обязательность | Источник | Masking | Описание |
|---|---|---|---|---|---|
Id | Guid | Да | Id | — | Id кампании. |
Name | string | Да | Name | — | Название («Весенний boost 7%»). |
Description | string? | Нет | Description | — | Основание/условия. |
Status | string (enum AgentBoostCampaignStatus) | Да | Status | — | Draft/Active/Archived. |
BoostRule | AgencyRetentionRuleModel | Да | BoostRule | полное правило — только роли с rewards.commission-policy.view | Повышенная доля агента (Kind ∈ {AgentPercentOfPool, AgentPercentOfPrice}). |
AgentUserIds | IReadOnlyList<Guid> | Да | Targets.AgentUserIds | список агентов — только роли с rewards.commission-policy.view | Набор агентов кампании. |
EffectiveFrom | DateTimeOffset | Да | EffectiveFrom | — | Начало периода. |
EffectiveTo | DateTimeOffset? | Нет | EffectiveTo | — | Конец периода (исключительно); null — бессрочно. |
CreatedAt / UpdatedAt | DateTimeOffset | Да | audit-поля | — | Аудит. |
Version | long | Да | Version | — | Для ExpectedVersion мутаций. |
Вложенная AgencyRetentionRuleModel (Kind/Value/CurrencyId?) — дом list-agency-policies.md;
для boost Kind ограничен AgentPercentOfPool/AgentPercentOfPrice, CurrencyId = null.
Алгоритм
- Контекст и доступ. Операцию выполняет руководитель/администратор агентства; scope — организация
(
TenantIdиз claims); требуется правоrewards.commission-policy.view. - Проверка входа.
Status— допустимое значение enumAgentBoostCampaignStatus, если задан;AgentUserId— валидныйGuid, если задан;Page/PageSize— по конвенции; иначе ошибка валидации. - Что читаем. Страница кампаний агентства-tenant-а: опц. фильтры по
StatusиAgentUserId(кампании, содержащие этого агента в наборе); сортировка детерминированная:Activeвыше, затемDraft/ArchivedпоCreatedAtDESC (свежие черновики и последние архивы выше). Выборка поix_agent_boost_campaigns_tenant_status. У агентства, ещё не заводившего кампаний, страница пуста (Items = [],TotalCount = 0) — это не ошибка. - Проекция. Каждая кампания разворачивается в
AgentBoostCampaignModel; документыBoostRuleиTargetsразворачиваются вBoostRule+AgentUserIds(ContractVersionнаружу не отдаётся). - Результат. Постраничный список
AgentBoostCampaignModel(Items,Page,PageSize,TotalCount) → HTTP200. Данные строго согласованы внутриrewards: список отражает последний коммитcreate/activate/archiveнемедленно (агрегатное чтение OLTP) — задержки eventual-consistency нет.
Диаграмма
Ошибки и failure modes
Специфичных REWARDS_*-кодов у read-операции нет (нет мутаций и concurrency). Применяются общие коды —
дом README.md «Общие ошибки»:
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
ValidationError | 400 | Status вне enum AgentBoostCampaignStatus; PageSize вне 1..100 | «Проверьте параметры фильтра» | no retry |
UNAUTHORIZED | 401 | нет/просрочен JWT | «Требуется авторизация» | no retry |
FORBIDDEN | 403 | нет rewards.commission-policy.view / тип компании вне {Agency, Broker, Pin} / чужой tenant | «Недостаточно прав» | no retry |
Acceptance criteria
- AC-1 (список кампаний). Given у агентства есть действующие и архивные кампании; When руководитель
запрашивает список без фильтра; Then
200,Activeвыше, далееDraft/ArchivedпоCreatedAtDESC; для каждой отданыBoostRuleиAgentUserIds;ContractVersionв проекции отсутствует. - AC-2 (фильтр по статусу). Given те же данные; When запрос с
Status = Active; Then возвращаются только действующие кампании;Status = Archivedвозвращает историю поCreatedAtDESC. - AC-3 (фильтр по агенту). Given кампании с разными наборами; When запрос с
AgentUserId = X; Then только кампании, содержащиеXв наборе. - AC-4 (нет кампаний → пусто). Given агентство ещё не заводило кампаний; When запрос списка;
Then
200,Items = [],TotalCount = 0(не404). - AC-5 (недостаточно прав). Given актор без
rewards.commission-policy.viewили не роль агентства; When запрос; ThenFORBIDDEN(403), список не раскрывается. - AC-6 (изоляция tenant). Given актор агентства A; When запрос; Then в выдаче только кампании
A —
TenantIdберётся из claims, не из query; кампании агентства B недоступны. - AC-7 (свежесть). Given только что активирована новая кампания; When сразу запрошен список;
Then новая
Activeуже в выдаче (строгая согласованность внутриrewards, без окна eventual-consistency).
Совместимость и наблюдаемость
- Новые поля кампании — additive nullable; удаление/переименование/смена типа — breaking. Новые значения enum
AgentBoostCampaignStatusв query — по unknown-enum-правилу cross-cutting (ValidationError). - Logs:
TenantId, применённые фильтры,TotalCount(ставки/наборы не логируются — Internal-класс); metrics:rewards_api_request_duration_seconds{route}; traces: OTel, correlation черезtraceparent; dashboardrewards-overview. - НФТ (ADR-0056): единицы кампаний на агентство — выборка тривиальна; целевая латентность p95 < 200 мс; операция back-office (низкая частота).
Обратные ссылки
Автоссылки: где используется этот документ.
- API (4): POST /api/v1/agency/agent-boost-campaigns — Создание boost-кампании агентов (черновик), POST /api/v1/agency/agent-boost-campaigns/{campaignId}/activate — Активация boost-кампании, POST /api/v1/agency/agent-boost-campaigns/{campaignId}/archive — Архивирование boost-кампании, Rewards API — реестр операций и общие контрактные модели
- Use Cases (1): US-реестр: Владелец агентства (US-OWN-AG)
- registries (1): Реестр API-методов PIN
Связанные документы
- Под-агрегат: domain/agency-commission-policy.md («Под-агрегат
AgentBoostCampaignEntity»). - Мутации: create-agent-boost-campaign.md, activate-agent-boost-campaign.md, archive-agent-boost-campaign.md.
- Базовая политика: list-agency-policies.md.