POST /api/v1/my/commission-accruals/{accrualId}/adjustment-requests — Заявка агента на корректировку своей доли
Агент предлагает изменить размер собственной доли (Agent-строки) в пуле сделки, не правя
распределение напрямую: подаёт заявку CommissionAdjustmentRequestEntity в статусе Pending с
предлагаемой суммой ProposedAgentAmount и обязательным обоснованием. Само перераспределение пула
(Agency ↔ Agent) выполнит только руководитель агентства при одобрении заявки
(../agency/approve-distribution-adjustment.md, INV-12
domain/commission-accrual.md). Схема «агент запрашивает →
руководитель одобряет»: право распоряжаться пулом остаётся у руководителя, агент получает голос без
прямого доступа к строкам распределения.
Назначение
Дать агенту-исполнителю сделки инструмент инициировать пересмотр своей доли (индивидуальная
договорённость, вклад в сложную сделку, замеченная ошибка политики) через формальную заявку с
обоснованием — вместо внесистемных переговоров. Заявка не меняет деньги: она лишь фиксирует предложение,
которое руководитель одобряет или отклоняет. Feature group — my-commission.
Metadata
| Поле | Значение |
|---|---|
| Сервис/контекст | rewards |
| API area | agent |
| Feature group | my-commission |
| Статус | draft |
| Документ | docs/06-services/rewards/api/agent/request-distribution-adjustment.md |
Актор и доступ
| Проверка | Значение |
|---|---|
| Actor type | User (агент — исполнитель сделки) |
| Auth policy / Permissions | rewards.commission.adjust-request (право предложить корректировку своей доли — только заявка, не прямая правка) |
| Scope (RBAC) | организация: собственное агентство агента (Type ∈ {Agency, Broker, Pin}) |
| Record-level | RequestedByAgentUserId = ActorUserId из токена (sub); заявка допустима только по начислению, где AgentUserId = ActorUserId (агент правит только свою долю) |
| Tenant isolation | In-tenant: TenantId из claims; чужое начисление невидимо → 404 |
| Audit | insert: заявка CommissionAdjustmentRequestEntity (Pending, заявитель, ProposedAgentAmount, Reason); Version начисления не инкрементируется (распределение не меняется) |
HTTP-контракт
| Поле | Значение |
|---|---|
| Method | POST |
| Route | /api/v1/my/commission-accruals/{accrualId}/adjustment-requests |
| Success status | 201 |
| Idempotency header | не применяется; защита от повторной подачи — partial unique «одна Pending-заявка на начисление» (INV-12) |
| Correlation | сквозной trace через заголовок traceparent |
Входные данные / параметры запроса
| Поле | Источник | Тип | Обязательность | Валидация / Ограничения | Безопасность |
|---|---|---|---|---|---|
TenantId | identity claims (tenant_id) | Guid | Да | Required; не принимается из body | Tenant isolation |
ActorUserId | identity claims (sub) | Guid | Да | Required; не принимается из body | record-level RequestedByAgentUserId |
AccrualId | route {accrualId} | Guid | Да | Required, непустой | — |
ProposedAgentAmount | body | MoneyModel | Да | Value >= 0, scale 2; CurrencyId = валюте начисления (INV-6); Value <= пул агентства (CommissionAmount − PlatformFeeAmount) | Sensitive — не логируется |
Reason | body | string | Да | 1..1000, не пусто после trim — обязательное обоснование (INV-11/INV-12) | — |
Модель ответа CommissionAdjustmentRequestModel
Проекция созданной заявки — дом модели: README.md («Общие контрактные модели»). Возвращается
созданная заявка со Status = Pending, ProposedAgentAmount, Reason, RequestedByAgentUserId,
AccrualId, CreatedAt; поля разрешения (ResolvedByUserId/ResolvedAt/ResolutionComment/
AppliedAdjustmentId) — null.
Предусловия и постусловия
- Предусловия. Начисление существует в tenant-е агентства, принадлежит агенту (
AgentUserId = ActorUserId) и находится в статусеConfirmedилиMoneyReceived(распределение построено — три строки INV-4/9); собственнаяAgent-строка не включена в неотменённое платёжное поручение (PayoutOrderItemId is null); по начислению нет другой заявки в статусеPending. Актор имеетrewards.commission.adjust-request. - Постусловия (успех). Создана заявка
CommissionAdjustmentRequestEntity(Pending); распределение, суммы иVersionначисления не изменены. Опубликованоcommission-adjustment-request-status-changed(Pending) — руководителю уходит уведомление о новой заявке. - Постусловия (отказ). Заявка не создана; состояние начисления не изменено.
Алгоритм
- Контекст и доступ. Операцию выполняет агент; scope — организация (
TenantIdиз claims); требуется правоrewards.commission.adjust-request. Начисление ищется в tenant-е агентства. - Проверка входа.
AccrualIdнепустой;ProposedAgentAmount.Value >= 0, scale 2;Reasonнепустой после trim,<= 1000— иначеREWARDS_ACCRUAL_ADJUSTMENT_REASON_REQUIRED. Начисление существует и принадлежит агенту (AgentUserId = ActorUserId) — иначеREWARDS_ACCRUAL_NOT_FOUND(чужое/несуществующее не различаются, fail-closed).CurrencyIdсовпадает с валютой начисления (INV-6) — иначеREWARDS_CURRENCY_MISMATCH. - Guard заявки (INV-12). Статус начисления ∈ {
Confirmed,MoneyReceived} иAgent-строка свободна (PayoutOrderItemId is null) — иначеREWARDS_ADJUSTMENT_REQUEST_FORBIDDEN. По начислению нетPending-заявки — иначеREWARDS_ADJUSTMENT_REQUEST_ALREADY_PENDING(partial uniqueux_commission_adjustment_requests_one_pending).ProposedAgentAmount.Value <= пул агентства(CommissionAmount − PlatformFeeAmount, INV-10) — иначеREWARDS_ADJUSTMENT_REQUEST_AMOUNT_INVALID(строкаPlatformнеприкосновенна: агент не может предложить долю больше пула). - Создание. Заявка
CommissionAdjustmentRequestEntityсохраняется в статусеPending(RequestedByAgentUserId = ActorUserId,ProposedAgentAmount,Reason). В том же изменении публикуетсяcommission-adjustment-request-status-changed(Pending) для уведомления руководителя. - Результат. Проекция созданной заявки (
CommissionAdjustmentRequestModel,Status = Pending) →201.
Диаграмма
Побочные эффекты
- Событие статуса начисления не публикуется (распределение и
Versionне меняются). Деньги и балансыwalletне затрагиваются — заявка лишь предложение. commission-adjustment-request-status-changed(Pending) уходит вnotifications— руководитель агентства получает уведомление о заявке, требующей решения.
Ошибки и failure modes
Общие коды (ValidationError, FORBIDDEN, UNAUTHORIZED) — дом README.md «Общие ошибки».
Дельта операции:
| Код | HTTP status | Условие | Сообщение | Retry |
|---|---|---|---|---|
REWARDS_ACCRUAL_NOT_FOUND | 404 | Начисление не существует, принадлежит чужому tenant или чужому агенту | «Начисление не найдено» | no retry |
REWARDS_ACCRUAL_ADJUSTMENT_REASON_REQUIRED | 400 | Reason пустой/отсутствует (INV-12) | «Укажите обоснование заявки» | no retry |
REWARDS_ADJUSTMENT_REQUEST_FORBIDDEN | 409 | Статус вне {Confirmed, MoneyReceived} или Agent-строка уже в неотменённом поручении (INV-12) | «Заявка на корректировку недоступна в текущем состоянии начисления» | no retry |
REWARDS_ADJUSTMENT_REQUEST_ALREADY_PENDING | 409 | По начислению уже есть заявка в статусе Pending | «По начислению уже есть открытая заявка» | no retry (дождаться решения по текущей) |
REWARDS_ADJUSTMENT_REQUEST_AMOUNT_INVALID | 409 | ProposedAgentAmount отрицателен или превышает пул агентства (INV-10) | «Предлагаемая доля превышает пул агентства» | no retry (пересчитать по актуальному пулу) |
REWARDS_CURRENCY_MISMATCH | 400 | CurrencyId суммы не совпадает с валютой начисления (INV-6) | «Валюта доли не совпадает с валютой начисления» | no retry |
Acceptance criteria
- AC-1 (подача заявки). Given начисление
Confirmed, принадлежащее агенту, распределениеPlatform = 10 000,Agency = 27 000,Agent = 63 000(пул 90 000),Agent-строка свободна; When агент подаётProposedAgentAmount = 70 000,Reason; Then201: создана заявкаPending(ProposedAgentAmount = 70 000,RequestedByAgentUserId = агент); распределение иVersionначисления не изменены; опубликованоcommission-adjustment-request-status-changed(Pending). - AC-2 (только своя доля). Given начисление, где
AgentUserId ≠ ActorUserId; When подача; ThenREWARDS_ACCRUAL_NOT_FOUND(404) — агент не видит и не может править чужую долю. - AC-3 (одна открытая заявка). Given по начислению уже есть
Pending-заявка; When агент подаёт вторую; ThenREWARDS_ADJUSTMENT_REQUEST_ALREADY_PENDING(409). - AC-4 (предложение больше пула). Given пул 90 000; When
ProposedAgentAmount = 95 000; ThenREWARDS_ADJUSTMENT_REQUEST_AMOUNT_INVALID(409) — строкаPlatformи пул неприкосновенны. - AC-5 (граничная доля). Given
ProposedAgentAmount = 0(или = пулу); When подача; Then201— нулевая/полная доля пула допустима как предложение. - AC-6 (без обоснования). Given пустой
Reason; When подача; ThenREWARDS_ACCRUAL_ADJUSTMENT_REASON_REQUIRED(400), заявка не создана. - AC-7 (недопустимый статус). Given начисление в
PendingConfirmation(строк ещё нет) /Paid/Cancelled, либоAgent-строка уже в неотменённом поручении; When подача; ThenREWARDS_ADJUSTMENT_REQUEST_FORBIDDEN(409). - AC-8 (нет права). Given у агента нет
rewards.commission.adjust-request; When подача; Then403FORBIDDEN.
Совместимость и наблюдаемость
CommissionAdjustmentRequestModel— дом README.md; контракт additive-only.- Logs:
AccrualId,TenantId,RequestId,result(суммы не логируются — Sensitive); metrics:rewards_adjustment_request_created_total{result}; traces: OTel, correlation черезtraceparent; dashboardrewards-overview. - НФТ (ADR-0056): вставка одной дочерней записи; целевая латентность p95 < 300 мс; частота — единичные заявки агентов.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (1): Entity / Aggregate: CommissionAccrualEntity
- API (2): POST /api/v1/agency/commission-adjustment-requests/{requestId}/resolve — Решение по заявке агента на корректировку доли, Rewards API — реестр операций и общие контрактные модели
- Use Cases (1): UC-RWD-013. Агент предлагает корректировку своей доли, руководитель одобряет
- registries (1): Реестр API-методов PIN
Связанные документы
- Сущность и guard-ы: domain/commission-accrual.md
(
CommissionAdjustmentRequestEntity,CommissionAdjustmentRequestStatus, INV-11/INV-12). - Разрешение заявки: ../agency/approve-distribution-adjustment.md (одобрение исполняет корректировку логикой ../agency/adjust-accrual-distribution.md).
- Смежные agent-операции: list-my-accruals.md, get-my-commission-summary.md.
- Общие модели/ошибки: README.md; ADR-0066 (три строки распределения, пул), ADR-0067
(корректировки, гейт денег), ADR-0069 (co-broking — мультистрочный
Agentв v-next), ADR-0052 (tenancy).