spec: plan grouping of all-account rows by instrument (WealthLedger/main#47)
Conventional commits / commits (pull_request) Successful in 9s
Specs security / security (pull_request) Successful in 6s
Specs verify / verify (pull_request) Successful in 8s

This commit is contained in:
2026-10-30 07:12:37 +03:00
parent 322ddf6a7f
commit 9aa390b8e9
13 changed files with 1233 additions and 0 deletions
@@ -0,0 +1,69 @@
# Test Cases — grouping
## TC-GRP-001 — Интерливинг трёх записей одной группы в серверном порядке
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger groups same-day entries of one instrument` (new combination: порядок внутри группы из 3+ записей с интерливингом чужих записей)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета»; брокерский счёт и ИИС доступны; период подтверждённо полный.
**Test Data:** Серверный порядок записей одного дня: A1 (купон X, Брокерский, +200 RUB), B (перевод, без Instrument), A2 (купон X, ИИС, +100 RUB), C (купон Y, Брокерский, +50 RUB), A3 (купон X, Брокерский, +150 RUB).
**Steps:**
1. Открыть полный журнал в режиме «Все счета» за этот день.
2. Зафиксировать порядок групп и записей.
**Expected Results:** Группа X (A1+A2+A3) стоит на месте A1 — до B; внутри группы порядок A1, A2, A3; затем B, затем C. Относительный порядок B и C сохранён. Итог группы +450 RUB.
**Automation Candidate:** yes (E2E)
## TC-GRP-002 — Две разные группы, записи которых чередуются
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger groups same-day entries of one instrument` / `All-accounts ledger grouping preserves order and limits` (new combination)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** Порядок: X1 (купон X), Y1 (дивиденд Y), X2, Y2, X3. X — облигация, Y — акция; купоны X по 100 RUB (Брокерский, ИИС, Брокерский), дивиденды Y по 50 RUB (ИИС, Брокерский).
**Steps:**
1. Открыть журнал «Все счета» за день.
**Expected Results:** Две группы: группа X на месте X1 с итогом +300 RUB, группа Y на месте Y1 с итогом +100 RUB; порядок групп X → Y; внутри каждой — серверный порядок записей.
**Automation Candidate:** yes (E2E)
## TC-GRP-003 — Одна и та же бумага: figi-only identity против instrumentUid — не смешивать разные идентичности
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger groups same-day entries of one instrument` (new combination: строгость identity-ключа)
**Risk / Priority:** Средний / High
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** В один день: купон облигации Z на счёте 1 (+100 RUB, identity по figi), купон облигации Z на счёте 2 (+100 RUB, identity по instrumentUid без figi); и купон облигации W на двух счетах (+100 RUB и +50 RUB), где обе записи имеют одинаковый identity.
**Steps:**
1. Открыть журнал «Все счета» за день.
**Expected Results:** Облигация W образует группу с итогом +150 RUB. Две записи облигации Z показаны отдельно: равенство identity не доказано, ключ строится по первому непустому идентификатору (design D2), а группировка без доказанного равенства не выполняется.
**Automation Candidate:** yes (E2E со stubbed API, отложено до появления QA repo)
## TC-GRP-004 — Граница дня около полуночи местного времени
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger groups same-day entries of one instrument` (new combination: экранный день в местном времени)
**Risk / Priority:** Средний / Medium
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** Купон X +100 RUB с execution time 23:59:30 Europe/Moscow и купон X +100 RUB с execution time 00:00:30 следующего календарного дня Europe/Moscow.
**Steps:**
1. Открыть журнал «Все счета», охватывающий оба момента.
**Expected Results:** Экранный день определяется так же, как дата, которую строка показывает на этом экране (spec: «как на экране», design D2 — локальная timezone браузера). При timezone браузера Europe/Moscow записи показаны в разных днях и группу не образуют. Oracle — дата, показанная в строке, а не UTC-дата `occurredAt`.
**Automation Candidate:** yes (E2E с фиксированной timezone браузера, отложено до появления QA repo)
## TC-GRP-005 — Прогноз: неизвестная сумма + известные суммы в двух валютах в одной группе
**Verifies:** `brokerage-account-upcoming-events` — `All-accounts upcoming event group shows each event and a forecast total` (new combination)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета», страница «Будущие события».
**Test Data:** Дивиденд D: событие на Брокерском 10 USD (известно), событие на ИИС 200 RUB (известно), событие на третьем счёте без суммы; все — одна дата реестра, один точный тип.
**Steps:**
1. Открыть «Будущие события» в режиме «Все счета».
**Expected Results:** Одна группа из трёх событий; строка без суммы показывает «неизвестно»; итог группы скрыт, потому что у одного события сумма неизвестна (прогноз полный, но не полностью известен по суммам); известные 10 USD и 200 RUB показаны отдельными строками, без конвертации и без общего итога. Дата в заголовке обозначена как дата реестра.
**Automation Candidate:** yes (E2E)
## TC-GRP-006 — «Выплаты» в `all`: отрицательная корректировка и дубли operation IDs внутри одной группы, аналитические итоги не меняются
**Verifies:** `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries` / Scenario: Отрицательная корректировка и повторяющиеся IDs сохраняются (new combination: то же внутри группы `all`)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета», раздел «Выплаты», период подтверждённо полный.
**Test Data:** За один день по облигации X: купон +200 RUB (Брокерский, opId=77), купон +100 RUB (ИИС, opId=77 — дубликат), корректировка −50 RUB (Брокерский, тот же тип). Аналитические итоги страницы зафиксированы до.
**Steps:**
1. Открыть «Выплаты» в режиме «Все счета» за период.
2. Сравнить аналитические итоги с зафиксированными.
**Expected Results:** Одна группа из трёх карточек; обе записи opId=77 — отдельные карточки; корректировка со знаком «−»; итог группы +250 RUB; валютные заголовки групп и receipt count отсутствуют; аналитические итоги страницы не пересчитаны и не изменились.
**Automation Candidate:** yes (E2E)
@@ -0,0 +1,38 @@
# Test Cases — pagination
## TC-PAG-001 — Группа, разрезанная границей страницы журнала: конкретное содержимое страниц и переходы
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger grouping preserves order and limits` / Scenario: Группа на границе страницы (new combination: конкретное содержимое страниц, next/prev)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета»; полный период; тестовые данные строятся вокруг фактического размера страницы N, который возвращает сервер (фиксируется в момент прогона).
**Test Data:** Серверный порядок: p1..p5 (прочие записи), X1 (купон X, +100 RUB), X2 (купон X, +150 RUB), X3 (купон X, +50 RUB), p9..p12. Размер страницы N — как у сервера; данные готовятся так, чтобы X1 был последней записью страницы 1, а X2, X3 — началом страницы 2.
**Steps:**
1. Открыть страницу 1 журнала; зафиксировать состав.
2. Перейти на страницу 2.
3. Вернуться на страницу 1.
**Expected Results:** Страница 1 заканчивается записью X1 как обычной строкой: группы нет (для группы нужно ≥2 показанных записей), итог не показывается. Страница 2 начинается группой X2+X3 (итог +200 RUB, разбивка X2/X3), затем p9…. Возврат на страницу 1 воспроизводит тот же состав. Серверный относительный порядок нигде не нарушен; записи одной группы не «стягиваются» через границу страницы.
**Automation Candidate:** yes (E2E)
## TC-PAG-002 — Обзор «Все счета»: пять записей, шестая подходящая существует, но не показана
**Verifies:** `brokerage-account-ledger` — `Account overview includes recent ledger events` / Scenario: Отображение последних событий (new combination: группа на границе лимита 5)
**Risk / Priority:** Высокий / High
**Preconditions:** Обзор «Все счета».
**Test Data:** Последние 6 записей в серверном порядке (свежая → старая): X1 (купон X, ИИС, +100 RUB), p2, p3, p4, p5, X0 (купон X, Брокерский, +200 RUB — шестая, за пределами выборки). X1 и X0 приходятся на один и тот же экранный день и один точный тип — по ключу они образовали бы группу, но X0 не входит в выборку обзора.
**Steps:**
1. Открыть обзор «Все счета».
2. Перейти в полный журнал.
**Expected Results:** В обзоре ровно 5 записей; X1 не образует группу (второй записи с тем же ключом в выборке нет) и показан отдельной строкой; X0 в обзоре отсутствует. Полный журнал показывает группу X0+X1 с итогом +300 RUB на месте своей первой записи.
**Automation Candidate:** yes (E2E)
## TC-PAG-003 — Обзор «Все счета»: лимит 5 считается по записям, группа занимает одну визуальную позицию
**Verifies:** `brokerage-account-ledger` — `Account overview includes recent ledger events` / Scenario: Группировка в последних записях обзора (new combination: счётчик лимита)
**Risk / Priority:** Средний / Medium
**Preconditions:** Обзор «Все счета».
**Test Data:** Последние записи (свежая → старая): p1, X1 (купон X, +100 RUB), X0 (купон X, +200 RUB, тот же экранный день и точный тип), p4, p5, p6.
**Steps:**
1. Открыть обзор «Все счета».
2. Посчитать визуальные позиции и проверить отсутствие p6.
**Expected Results:** Лимит 5 считается по записям: показаны записи p1, X1, X0, p4, p5 — это 4 визуальные позиции: p1, группа X (на месте X1, итог +300 RUB, разбивка X1/X0), p4, p5. Запись p6 не показана: она шестая по счётчику записей, свободной позиции от лимита нет.
**Automation Candidate:** yes (E2E)
@@ -0,0 +1,58 @@
# Test Cases — totals
## TC-TOT-001 — Мультивалютная группа со смешанными знаками и большой разрядностью: точный десятичный оракул
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger group shows each entry and an exact total` (new combination: calculated oracle)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** Один день, облигация X, точный тип «купон»: +0.1 RUB (Брокерский), +0.2 RUB (ИИС), −1500000.45 RUB (Брокерский, корректировка того же типа), +200 RUB (ИИС); плюс в той же группе день выплат USD: +0.01 USD и −0.02 USD.
**Steps:**
1. Открыть журнал «Все счета» за день.
2. Прочитать итог группы по каждой валюте.
**Expected Results:** Итог RUB = −1499800.15 (точная десятичная сумма: 0.1+0.2−1500000.45+200), без плавающей точки артефактов (не −1499800.1499999); итог USD = −0.01; два отдельных итога, без конвертации и без общего итога; каждая строка показывает свою сумму со знаком.
**Automation Candidate:** yes (E2E)
## TC-TOT-002 — Разное число знаков после запятой у записей группы
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger group shows each entry and an exact total` (new combination)
**Risk / Priority:** Средний / High
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** Группа купонов X: +100.5 RUB, +49.50 RUB, +0.005 RUB (если сервер отдаёт такую точность).
**Steps:**
1. Открыть журнал, прочитать итог.
**Expected Results:** Итог = 150.005 RUB ровно, без округления до 2 знаков и без потери младшего разряда; строки показывают суммы как отданы сервером.
**Automation Candidate:** yes (E2E)
## TC-TOT-003 — Нулевой итог и запись без денежного изменения в одной группе
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger group shows each entry and an exact total` / Scenario: Нулевой итог; Scenario: Группа с записью без денежного изменения (new combination: обе записи в одной группе)
**Risk / Priority:** Средний / Medium
**Preconditions:** Режим «Все счета», полный период.
**Test Data:** Группа X: +150.10 RUB, −150.10 RUB, запись без денежного изменения (например, только количество бумаг).
**Steps:**
1. Открыть журнал, прочитать группу.
**Expected Results:** Итог группы скрыт; запись без изменения обозначена как «без движения», а не как 0 RUB; строки остаются видимыми.
**Automation Candidate:** yes (E2E)
## TC-TOT-004 — `partial` → подтверждённая полнота: итог появляется
**Verifies:** `brokerage-account-ledger` — `All-accounts ledger group shows each entry and an exact total` / Scenario: Итог скрыт при неполном периоде (new combination: смена состояния)
**Risk / Priority:** Высокий / High
**Preconditions:** Режим «Все счета»; заглушка API (MSW/Playwright route) с управляемым `meta`.
**Test Data:** Группа X: +200 RUB и +100 RUB. Первый ответ — `meta` с `partial` для одного из счетов; второй ответ — подтверждённая полнота.
**Steps:**
1. Открыть журнал с partial-ответом; зафиксировать группу.
2. Подтвердить полноту (повторный запрос/фоновая догрузка с полной `meta`).
**Expected Results:** При `partial`: строки видны, итог скрыт. После полноты: появляется точный итог +300 RUB; состав и порядок строк не изменились.
**Automation Candidate:** yes (E2E)
## TC-TOT-005 — Прогнозный итог при частично неизвестных суммах скрыт, при полной известности — показан по валютам
**Verifies:** `brokerage-account-upcoming-events` — `All-accounts upcoming event group shows each event and a forecast total` (new combination)
**Risk / Priority:** Средний / High
**Preconditions:** Режим «Все счета», «Будущие события».
**Test Data:** Два соседних дня: день 1 — купоны X на двух счетах по 100 RUB (обе суммы известны); день 2 — купоны X на двух счетах, у одной суммы нет.
**Steps:**
1. Открыть «Будущие события».
**Expected Results:** Группа дня 1: итог +200 RUB. Группа дня 2: итог скрыт, строка без суммы обозначена как неизвестная. Итоги списком не сводятся.
**Automation Candidate:** yes (E2E)