feat(admin): an all-accounts ledger section with filters and totals
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 12s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m16s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m47s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 12s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m16s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m47s
There was no way to see the money as a whole: the ledger was only ever rendered inside one account's card, so "what came in last month" meant exporting the entire CSV and reading it elsewhere. /_gm/ledger lists every operation, newest first, filtered by date range (defaulting to the last 30 days), by wallet, by rail, by kind and by account. Wallet and rail are deliberately separate axes because they answer different questions — "what happened on VK" matches the funded segment or the benefit origin, while "what came through YooKassa" matches the settling provider, and a chip spend has no rail at all, so it drops out of that filter by construction. Above the table sit the totals for everything the filter matches, not merely the page on screen, which is the point of showing them. Money is listed per currency because the rails settle in roubles, Votes and Stars and one sum across them would mean nothing. Row amounts come from the operation snapshot, since the ledger's own columns count chips rather than money. Paging, the CSV export and a refund's way back are all built from the same encoded filter, so none of them can quietly show a different slice than the screen. The export moves here from the user card and gains the filter along with money columns; it is capped, because an append-only ledger grows forever and an unbounded export would eventually time out. The refund action moves onto the funded rows here — an operator can now find a payment by filter without knowing whose it is first — and returns to the same filtered view. The destination travels with the form but is only honoured when it is a console path, so a crafted form cannot turn it into an open redirect. The user card keeps the account's standing rather than its history: balances, benefits, the risk flag and a lifetime summary (money paid and refunded per currency, chips credited and spent), plus a link into the ledger scoped to that account. Operations are rendered in one place, with filters and paging, instead of two. Tests: the filter axes, paging that neither repeats nor drops a row, totals that describe the range rather than the page, money recovered from a snapshot and absent on a spend, and the console page, the export and the card hand-off. The existing finance-panel test now asserts the summary and that the card no longer re-renders the rows.
This commit is contained in:
+17
-3
@@ -418,9 +418,23 @@ origin** at grant time (compliance is on them: `origin=vk` point-wise/low-volume
|
||||
`origin=direct` = safe). A grant is a ledger transaction of type `admin_grant`, price 0
|
||||
chips (the by-product grant records the source `product_id` + snapshot) — full audit of rewards.
|
||||
|
||||
**Per-user financial report** in the admin console `/_gm` — segment balances, payments,
|
||||
spends, grants, refunds, full history — as an extension of the existing user card
|
||||
(`UserDetailView`, `handlers_admin_console.go`). Plus a ledger export.
|
||||
**The ledger section** `/_gm/ledger` is the all-accounts view of the money: every operation, newest
|
||||
first, filtered by date range (defaulting to the last 30 days), by **wallet** (`vk`/`telegram`/
|
||||
`direct` — matching the funded segment or the benefit origin), by **rail** (the settling provider, so
|
||||
chip spends drop out by construction), by kind and by account. Above the table sit the totals for
|
||||
**everything the filter matches**, not merely the page: money in and refunded per currency (the rails
|
||||
settle in roubles, Votes and Stars, so one sum across them would mean nothing) and chips credited and
|
||||
spent. The row amounts come from the ledger snapshot, since the ledger's own columns count chips.
|
||||
Paging, the CSV export and a refund's way back all carry the same filter query, so none of them can
|
||||
silently show a different slice than the screen.
|
||||
|
||||
The **refund action** lives on the funded rows here — the operator can find a payment by filter
|
||||
without knowing whose it is first — and returns to the same filtered view afterwards.
|
||||
|
||||
**The user card** carries the account's standing rather than its history: segment balances, benefits,
|
||||
the refund-risk flag, and a short lifetime summary (money paid and refunded per currency, chips
|
||||
credited and spent), with a link into the ledger section pre-filtered to that account. One place
|
||||
renders operations, with filters and paging, instead of two.
|
||||
|
||||
## 12. Taxes and compliance
|
||||
|
||||
|
||||
+18
-3
@@ -410,9 +410,24 @@ in-process кэш сегментов и бенефитов по ключу-ак
|
||||
типа `admin_grant`, цена 0 Фишек (грант по продукту пишет исходный `product_id` + снапшот) —
|
||||
полный аудит наград.
|
||||
|
||||
**Финансовый отчёт по пользователю** в админке `/_gm` — балансы сегментов, платежи, траты,
|
||||
гранты, возвраты, полная история — расширение существующей карточки (`UserDetailView`,
|
||||
`handlers_admin_console.go`). Плюс экспорт журнала.
|
||||
**Раздел журнала** `/_gm/ledger` — общий вид на деньги по всем аккаунтам: все операции, новые
|
||||
сверху, с фильтрами по диапазону дат (по умолчанию последние 30 дней), по **кошельку**
|
||||
(`vk`/`telegram`/`direct` — совпадение по пополненному сегменту или по origin бенефита), по
|
||||
**рельсу** (провайдер, который провёл платёж, поэтому траты Фишек в такой фильтр не попадают вовсе),
|
||||
по виду операции и по аккаунту. Над таблицей — итоги по **всему, что попало под фильтр**, а не по
|
||||
странице: пришло и возвращено денег по каждой валюте отдельно (рельсы считают в рублях, Голосах и
|
||||
Stars, общая сумма по ним не значила бы ничего) и начислено/списано Фишек. Суммы в строках берутся из
|
||||
снимка операции, потому что собственные колонки журнала считают Фишки, а не деньги. Пагинация,
|
||||
выгрузка в CSV и возврат оператора после refund несут одну и ту же строку фильтров, поэтому ни один
|
||||
из них не может незаметно показать срез, отличный от экрана.
|
||||
|
||||
**Кнопка возврата** живёт на строках пополнения здесь же — оператор может найти платёж фильтрами, не
|
||||
зная заранее, чей он, — и после возврата возвращает на тот же отфильтрованный вид.
|
||||
|
||||
**Карточка пользователя** показывает положение дел, а не историю: балансы сегментов, бенефиты, флаг
|
||||
риска и краткую сводку за всё время (сколько заплачено и возвращено по валютам, сколько Фишек
|
||||
начислено и потрачено), плюс ссылку в раздел журнала, уже отфильтрованный по этому аккаунту.
|
||||
Операции рисуются в одном месте, с фильтрами и страницами, а не в двух.
|
||||
|
||||
## 12. Налоги и комплаенс
|
||||
|
||||
|
||||
Reference in New Issue
Block a user