UC-WLT-005. Оператор ПИН смотрит журнал проводок счёта (сверка)
Назначение
Описывает сценарий финансового контроля: оператор ПИН открывает постраничный журнал проводок
произвольного счёта кошелька — холдерского (AgentCommission/ReferralCommission/AgencyCommission) или
системного (PlatformSettlement/PlatformRevenue) — чтобы разобрать инцидент рассинхрона, проверить счёт
перед ручной корректировкой и после неё, свериться «баланс = журнал» и аудировать движение средств. В
отличие от истории личного кошелька (UC-WLT-004), platform-журнал не ограничен холдером и раскрывает
служебные атрибуты: причину и актора ручной операции (Adjustment), причину компенсации (Correction),
направление, сумму и баланс-после каждой проводки. Чтение — read-only; журнал append-only. Связан с
контекстом wallet.
Metadata
| Поле | Значение |
|---|---|
| ID | UC-WLT-005 |
| Контекст | wallet (см. docs/06-services/wallet/) |
| Тип | основной |
| Статус | draft |
Актор
| Поле | Значение |
|---|---|
| Роль | Оператор/администратор ПИН |
| Permissions / scope | wallet.accounts.view-all, платформенный scope |
| Tenant | не применяется (платформенная операция над любым счётом, включая системные) |
| Record-level | нет — оператор видит журнал любого счёта |
Предусловие
- Оператор авторизован и имеет
wallet.accounts.view-all. - Целевой счёт существует (wallet-account.md); обычно выбирается из admin-реестра счетов (list-wallet-accounts.md).
- По счёту есть хотя бы одна проводка (иначе журнал пуст — не ошибка).
Триггер
| Поле | Значение |
|---|---|
| Источник | UI |
| Триггерящий элемент | admin-реестр счетов → счёт → «Журнал проводок»; либо разбор issue Reconciliation Center |
Основной Поток
- Оператор находит счёт в admin-реестре и открывает его журнал
(list-account-ledger.md,
GET /api/v1/platform/wallet/accounts/{accountId}/ledger), опционально задаёт фильтры: вид операции (WalletOperationKind), период (From/To), пагинация. - Система проверяет доступ и существование счёта (нет счёта →
WALLET_ACCOUNT_NOT_FOUND), корректность фильтров (вид вне enum /From >= To/ paging вне диапазона →ValidationError). - Система отдаёт страницу проводок этого счёта из журнала (ledger-transaction.md),
присоединяя атрибуты их транзакций. По каждой строке (
WalletLedgerEntryModel): вид операции;DebitилиCredit(разнесены по полям, бухгалтерский вид; заполнено ровно одно, суммы> 0);BalanceAfter(сальдо счёта сразу после проводки, зафиксировано при проведении);SourceId— непрозрачная ссылка-основание (расшифровка — вrewardsпо своим permissions); дляAdjustment/Correction—Comment(причина) иActorUserId(кто провёл ручную операцию), дляCorrection—CorrectedTransactionId;OccurredAt(момент бизнес-факта) иRecordedAt(момент проведения). Сортировка —RecordedAtпо убыванию, внутри момента — поEntryId(стабильные страницы). - Оператор сверяет: последняя (свежайшая)
BalanceAfterравна текущемуBalanceсчёта из реестра; при полном обходеBalance = Σ Credit − Σ Debitпроводок счёта. Сходимость подтверждает целостность; расхождение — сигнал инцидента (A2).
Альтернативные Потоки
A1. Системный счёт (PlatformSettlement/PlatformRevenue)
- Оператор открывает журнал транзитного
PlatformSettlement: баланс штатно<= 0(INV-WLT-3;|Balance|= объём средств, разнесённых по получателям и ещё не погашенных выплатами), в журнале — дебеты по кредитам получателям и кредиты по выплатам.PlatformRevenue— доход ПИН, кредитуетсяPlatform-строками. Проводки системных счетов событияtransaction-recordedне порождают, но в журнале видны полностью.
A2. Обнаружено расхождение баланса (сверка не сошлась)
- Пересчёт
Σ Credit − Σ Debitпо журналу не равен хранимомуBalanceсчёта → инцидент рассинхрона (ADR-0021, метрикаwallet_balance_drift_total). Журнал первичен: баланс восстанавливается пересчётом из журнала, журнал не правится. Из этого сценария оператор только диагностирует; исправление — пересчёт баланса и/или компенсирующая транзакция (UC-WLT-003), но не в рамках чтения журнала.
A3. Аудит ручных операций (фильтр Adjustment/Correction)
- Оператор фильтрует журнал по
OperationKind = Adjustment(илиCorrection), чтобы проверить все ручные вмешательства: по каждой строке видны причина (Comment), актор (ActorUserId) и, дляCorrection, исходная компенсируемая транзакция (CorrectedTransactionId). Журнал сам является audit trail.
A4. Основание проводки нужно расшифровать
SourceIdотдаётся как непрозрачная ссылка (id начисления / реферального начисления / позиции поручения / исходной транзакции / ключа корректировки — карта видов в ledger-transaction.md). Расшифровка «что за сделка/начисление» — вrewardsпо permissions оператора там;walletсоответствия «сумма ↔ клиент/сделка» в этой проекции не раскрывает.
A5. Счёт без проводок
- По счёту ещё не было ни одной проводки (например, только что созданный системный) → пустая страница; интерфейс показывает «Операций нет». Не ошибка.
Постусловие
- Состояние системы не изменено (read-only): мутаций, транзакций и событий нет.
- Показанные проводки согласованы с журналом; при полном обходе сумма направлений сходится с балансом счёта (или зафиксировано расхождение — A2).
- Факт обращения к журналу залогирован (актор,
AccountId, фильтры — без сумм; read-sensitive аудит).
Возможные Ошибки
| Код | HTTP | Условие | Поведение клиента |
|---|---|---|---|
WALLET_ACCOUNT_NOT_FOUND | 404 | Счёта с указанным AccountId не существует | Вернуться к реестру счетов |
ValidationError | 400 | OperationKind вне enum / From >= To / paging вне диапазона | Исправить фильтры |
FORBIDDEN | 403 | Нет wallet.accounts.view-all | «Недостаточно прав» |
UNAUTHORIZED | 401 | Нет/просрочен JWT | «Требуется авторизация» |
Acceptance Criteria
| # | Критерий | Проверка |
|---|---|---|
| AC1 | Given счёт с проводками, When оператор открывает журнал, Then каждая строка показывает вид, Debit/Credit (ровно одно), BalanceAfter, OccurredAt/RecordedAt; сортировка — свежие сверху | интеграционный тест |
| AC2 | Given полный обход журнала счёта, When суммируются направления, Then Σ Credit − Σ Debit = текущему Balance; последняя BalanceAfter = Balance | сверочный тест (ADR-0021) |
| AC3 | Given ручная операция, When она в журнале, Then видны Comment (причина) и ActorUserId; для Correction — CorrectedTransactionId (A3) | тест раскрытия служебных полей |
| AC4 | Given системный счёт PlatformSettlement, When оператор смотрит журнал, Then баланс <= 0 трактуется по INV-WLT-3, проводки видны полностью (A1) | тест системного счёта |
| AC5 | Given несуществующий AccountId, When запрос журнала, Then WALLET_ACCOUNT_NOT_FOUND (404) | негативный тест |
| AC6 | Given фильтр по виду операции/периоду, When применён, Then выборка ограничена корректно; неверный фильтр → ValidationError | тест фильтров |
| AC7 | Given чтение журнала, When операция завершена, Then состояние не изменено и факт обращения залогирован без сумм | read-only + аудит |
Обратные ссылки
Автоссылки: где используется этот документ.
- Use Cases (1): UC-WLT-006. Компенсирующее начисление отражается в балансе после MoneyReceived
- registries (1): Реестр use cases и user stories PIN
Связанные Документы
- API метод: list-account-ledger.md; реестр счетов — list-wallet-accounts.md; корректировка — create-wallet-adjustment.md.
- Domain entity: ledger-transaction.md (проводки, виды операций, карта оснований, INV-WLT-5..7), wallet-account.md (счета, сверка, INV-WLT-1..4).
- Holder-view истории: UC-WLT-004 (поток A2 — оператор ПИН); ручная корректировка: UC-WLT-003.
- ADR-0021 (разбор рассинхронов, сверка), ADR-0005 (двойная запись), ADR-0065 (счета и журнал).