docs(specs): archive improved ledger event rows
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
schema: wealth-ledger-sdd
|
||||
created: 2026-08-26
|
||||
goal: Сделать записи журнала операций и последние записи на обзоре счёта визуально понятнее.
|
||||
affected_areas:
|
||||
- frontend
|
||||
- backend
|
||||
- specs
|
||||
- docs
|
||||
@@ -0,0 +1,151 @@
|
||||
## Context
|
||||
|
||||
Account Ledger already preserves the signed upstream payment and the operation
|
||||
identifiers, but the operations response has no instrument brand metadata. The
|
||||
portfolio resolves the same metadata from the existing server-side T-Bank
|
||||
boundary and uses the brand file name to render an image with an initial-based
|
||||
fallback. The account overview and the full ledger currently render separate,
|
||||
text-heavy operation layouts; the full ledger also keeps page data and JSX in
|
||||
one component instead of the finance view-model boundary.
|
||||
|
||||
The public OpenAPI contract is the frontend authority. T-Bank rate limiting,
|
||||
authentication and upstream failure handling remain owned by the backend.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Supply nullable instrument brand metadata with each Ledger Entry without
|
||||
altering its monetary or business meaning.
|
||||
- Reuse one accessible, responsive presentation of a Ledger Entry in the
|
||||
account overview and full ledger.
|
||||
- Present the already-signed payment with a textual directional cue, a sign and
|
||||
semantic positive/negative/neutral styling.
|
||||
- Preserve local error, loading, empty, filter and cursor states.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No new ledger categories, financial calculations, historical balance or
|
||||
currency conversion.
|
||||
- No changes to the T-Bank integration boundary, access rules, pagination or
|
||||
query semantics.
|
||||
- No logo enrichment for Future Cash Events or Portfolio Positions outside the
|
||||
existing supplied metadata.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Enrich Ledger Entries through a shared instrument-metadata resolver
|
||||
|
||||
The backend will extract the existing Portfolio instrument lookup and its
|
||||
short-lived metadata caching into a reusable resolver. After obtaining a ledger
|
||||
page, the service will resolve unique operation instrument identities through
|
||||
that resolver and attach nullable `logoName` metadata to its entries. Lookup by
|
||||
UID remains preferred; FIGI is the fallback. An unavailable or unresolvable
|
||||
instrument remains a successful Ledger Entry with `logoName: null`; enrichment
|
||||
must not hide a ledger page or change its money, category or identifiers.
|
||||
|
||||
This preserves the existing server-side T-Bank boundary and its rate limiting,
|
||||
deduplicates repeated instruments in one page and avoids a separate visual-data
|
||||
API. The shared resolver replaces Portfolio's private copy so the two consumers
|
||||
have identical lookup and failure semantics.
|
||||
|
||||
### Make the additive contract explicit and nullable
|
||||
|
||||
`BrokerageOperationDto` gains the nullable logo file name as presentation
|
||||
metadata. The generated backend OpenAPI and committed frontend snapshot remain
|
||||
the only contract path. Existing consumers can ignore the additive field;
|
||||
updated consumers must treat absence as normal and use the text fallback.
|
||||
|
||||
### Use a shared Ledger Entry presentation component
|
||||
|
||||
The frontend will expose a focused entity-level presentation component for a
|
||||
Ledger Entry and use it both in the account overview and the full journal. It
|
||||
will show the logo image when available, otherwise a deterministic initial
|
||||
fallback; the visible operation and instrument text remains the primary label.
|
||||
The existing image URL formatter is reused. Logo loading failure falls back in
|
||||
place without moving the row.
|
||||
|
||||
The full ledger page is brought to the existing `container → ViewModel → view`
|
||||
boundary while retaining its current query and interaction state. The ViewModel
|
||||
prepares collection-level presentation data; the shared row owns only one
|
||||
entry's display. This prevents duplication while keeping data fetching outside
|
||||
presentation views.
|
||||
|
||||
### Convey money direction independently of colour
|
||||
|
||||
The row derives direction only from the sign already present in `payment.value`:
|
||||
positive is a labelled `+` «Поступление», negative is a labelled `−` «Списание»,
|
||||
and missing payment is the existing neutral «Без движения денег» state. Semantic
|
||||
Mantine theme tokens supply positive, negative and neutral tones; the sign and
|
||||
visible Russian label make the state understandable without colour. Amounts
|
||||
remain formatted from their decimal string and are not converted to JavaScript
|
||||
numbers for the direction decision.
|
||||
|
||||
The row uses a three-part hierarchy: instrument identity on the left, operation
|
||||
and date/category as secondary metadata, and a right-aligned amount/direction
|
||||
group. At narrow widths the metadata may wrap below the primary line while the
|
||||
amount stays associated with its entry; the list never requires horizontal
|
||||
scrolling.
|
||||
|
||||
## Delivery Map
|
||||
|
||||
| Area | Status | Architectural outcome or N/A reason |
|
||||
| --- | --- | --- |
|
||||
| frontend | `affected` | Generated contract update, reusable accessible Ledger Entry row, and aligned overview/full-ledger layouts through the finance VM/view boundary. |
|
||||
| backend | `affected` | Shared server-side instrument metadata resolver and nullable logo metadata on each operations response. |
|
||||
| specs | `affected` | Approved delta requirements become the versioned behavioural contract. |
|
||||
| docs | `affected` | Account Ledger as-built documentation describes the delivered metadata and directional row semantics. |
|
||||
|
||||
### Contract Gate Decision
|
||||
|
||||
| Gate | Status | Reason |
|
||||
| --- | --- | --- |
|
||||
| runtime-openapi | `required` | Backend adds public response metadata and frontend consumes the generated contract. |
|
||||
|
||||
## Solution Assessment
|
||||
|
||||
The change extends an existing external T-Bank metadata lookup and introduces a
|
||||
shared cache consumer, so it evaluates the available approaches.
|
||||
|
||||
| Option | Fit and maturity | Security and operating cost | Decision |
|
||||
| --- | --- | --- | --- |
|
||||
| Resolve every operation independently | Uses existing client but repeats calls for the same instrument and exposes journal latency to upstream volume. | Rate limiter prevents excess but adds queueing and avoidable upstream load. | Rejected. |
|
||||
| Reuse Portfolio's private cache by duplicating it in the ledger | Works locally but creates divergent TTL, failure and fallback behaviour. | Low initial cost, growing maintenance and inconsistent cache pressure. | Rejected. |
|
||||
| Extract a bounded, short-lived shared resolver around the existing client | Reuses mature authenticated boundary and gives both consumers one lookup policy. | No new credential or storage; cached public brand metadata is returned only after account access. Bounded memory and non-fatal failures limit operating risk. | Chosen. |
|
||||
|
||||
No third-party package or new external integration is justified: the T-Bank
|
||||
client already supplies the required brand metadata and resilience controls.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- A page with many distinct instruments can still need several metadata lookups
|
||||
on a cold cache. Deduplication, bounded cache lifetime and the existing
|
||||
limiter trade initial completeness latency for upstream protection.
|
||||
- Some past operations do not identify an instrument or have no brand asset.
|
||||
The mandatory text fallback keeps these rows legible without inventing data.
|
||||
- An additive nullable OpenAPI field requires atomic runtime-contract and
|
||||
frontend-snapshot alignment. Until the compatible frontend is delivered,
|
||||
old consumers safely ignore the field.
|
||||
- Green/red alone can exclude users; sign and text are required alongside
|
||||
semantic colours, and images remain supplementary to visible text.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Introduce the shared resolver and the nullable response metadata while
|
||||
preserving the operations payload and failure behaviour.
|
||||
2. Publish and sync the generated OpenAPI contract, then consume it in the
|
||||
frontend presentation boundary.
|
||||
3. Replace the duplicated overview and journal row rendering with the shared
|
||||
responsive component and update the as-built feature documentation after
|
||||
verification.
|
||||
|
||||
### Rollback Contract
|
||||
|
||||
| Field | Decision |
|
||||
| --- | --- |
|
||||
| Status | `required` |
|
||||
| Reason | The change adds a public API response field consumed by the frontend. |
|
||||
| Trigger | Runtime OpenAPI mismatch, unacceptable additional ledger latency, or a regression that hides ledger entries. |
|
||||
| Actions | Revert the frontend to the prior row presentation and revert the backend response enrichment; retain the pre-change response shape when rollback is complete. |
|
||||
| Data safety | No persistent data, migration or credential changes occur. In-memory metadata and page caches can expire or be discarded safely. |
|
||||
| Verification | Re-run affected canonical gates, the runtime OpenAPI contract gate, and the ledger scenarios for signed, unsigned and missing-logo entries. |
|
||||
@@ -0,0 +1,46 @@
|
||||
## Why
|
||||
|
||||
Сейчас последние записи на обзоре счёта и строки полного журнала воспринимаются
|
||||
как плотный текст: инструмент не имеет наглядного визуального якоря, а денежное
|
||||
движение трудно быстро отличить как поступление или списание. Это замедляет
|
||||
просмотр недавней активности и разрывает визуальную согласованность с уже
|
||||
оформленными позициями акций и облигаций.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Сделать каждую Ledger Entry в «Последних событиях» и в «Журнале операций»
|
||||
компактной структурированной строкой с визуальной идентичностью инструмента,
|
||||
понятным fallback при её отсутствии и читаемой группировкой основных и
|
||||
второстепенных сведений.
|
||||
- Явно обозначать направление денежного движения: поступления и списания
|
||||
должны различаться знаком, текстовой семантикой и цветом; запись без движения
|
||||
денег должна оставаться нейтральной и ясно подписанной.
|
||||
- Сохранить одинаковые смысл, порядок данных и визуальную иерархию для полной
|
||||
истории и пяти последних записей на обзоре счёта, с адаптацией плотности к
|
||||
узкому экрану.
|
||||
- Не изменять состав исполненных операций, их порядок, фильтрацию, пагинацию,
|
||||
расчёт денежных значений, категории, навигацию или правила доступа к счёту.
|
||||
- Не добавлять в журнал расчёт доходности, баланса после операции, валютную
|
||||
конвертацию или трактовку категории операции как финансового результата.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
Нет.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `brokerage-account-ledger`: записи журнала и блок последних записей получают
|
||||
доступную presentation metadata инструмента и явно отображают направление
|
||||
денежного движения без изменения факта или суммы операции.
|
||||
|
||||
## Impact
|
||||
|
||||
- Пользователь быстрее распознаёт инструмент и видит, была ли конкретная
|
||||
операция поступлением, списанием или движением без денег.
|
||||
- Затрагиваются отображение последних записей, полный журнал и данные,
|
||||
необходимые для их визуальной идентичности.
|
||||
- Документация Account Ledger после поставки будет уточнена как фактическое
|
||||
состояние; публичное поведение журнала требует согласованного изменения
|
||||
frontend и backend.
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Ledger entries preserve broker operation meaning
|
||||
Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, доступную presentation metadata инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.
|
||||
|
||||
#### Scenario: Отображение купонной выплаты
|
||||
- **WHEN** T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
|
||||
- **THEN** запись журнала определяет её как income и передаёт исходную сумму выплаты, валюту и данные инструмента
|
||||
|
||||
#### Scenario: Отображение комиссии сделки без синтетической записи
|
||||
- **WHEN** T-Bank возвращает исполненную сделку, содержащую выплату и комиссию
|
||||
- **THEN** журнал содержит одну запись сделки с комиссией в качестве её детали
|
||||
|
||||
#### Scenario: Отображение движения бумаг без денег
|
||||
- **WHEN** T-Bank возвращает исполненную операцию, изменяющую состав инструментов, но без денежной выплаты
|
||||
- **THEN** запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением
|
||||
|
||||
#### Scenario: Доступна визуальная идентичность инструмента
|
||||
- **WHEN** для инструмента исполненной операции доступна presentation metadata бренда
|
||||
- **THEN** запись журнала передаёт её вместе с доступными идентификаторами инструмента, не меняя остальные сведения операции
|
||||
|
||||
### Requirement: Account overview includes recent ledger events
|
||||
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Каждая показанная запись MUST иметь ту же визуальную идентичность инструмента и семантику денежного движения, что и запись полного журнала. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||
|
||||
#### Scenario: Отображение последних событий
|
||||
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
||||
- **THEN** обзор показывает не более пяти последних записей и ссылку на полный журнал
|
||||
|
||||
#### Scenario: Последние записи недоступны
|
||||
- **WHEN** обзор счёта успешно загружается, но запрос последних записей завершается ошибкой
|
||||
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
||||
|
||||
#### Scenario: Последняя запись не содержит visual metadata инструмента
|
||||
- **WHEN** одна из последних записей не имеет доступной presentation metadata инструмента
|
||||
- **THEN** обзор показывает для неё понятный текстовый fallback и сохраняет дату, тип, инструмент и денежное изменение записи доступными для чтения
|
||||
|
||||
### Requirement: Full ledger presents compact rows
|
||||
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте в компактной структурированной строке. При доступной presentation metadata инструмента строка MUST показывать его визуальную идентичность; при её отсутствии MUST использовать понятный текстовый fallback. Для положительной денежной выплаты строка MUST явно обозначать поступление знаком, текстовой семантикой и положительным цветом; для отрицательной — списание знаком, текстовой семантикой и отрицательным цветом. Страница MUST обозначать записи без движения денег нейтрально и MUST NOT показывать цену или количество.
|
||||
|
||||
#### Scenario: Отображение записи только с инструментом
|
||||
- **WHEN** полный журнал отображает запись без денежной выплаты
|
||||
- **THEN** страница определяет её как запись без движения денег
|
||||
|
||||
#### Scenario: Отображение поступления
|
||||
- **WHEN** полный журнал отображает запись с положительной денежной выплатой
|
||||
- **THEN** строка явно показывает поступление и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отображение списания
|
||||
- **WHEN** полный журнал отображает запись с отрицательной денежной выплатой
|
||||
- **THEN** строка явно показывает списание и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отсутствует visual metadata инструмента
|
||||
- **WHEN** полный журнал отображает запись без доступной presentation metadata инструмента
|
||||
- **THEN** строка показывает понятный текстовый fallback без подмены или сокрытия доступных данных инструмента
|
||||
@@ -0,0 +1,43 @@
|
||||
## 1. Backend contract and metadata delivery
|
||||
|
||||
- [x] 1.1 [backend] Извлечь из Portfolio общий bounded resolver metadata инструмента, применить его к уникальным идентификаторам страницы журнала и добавить nullable `logoName` в Ledger Entry без изменения исходных сумм, категорий или ошибок журнала.
|
||||
- **Covers:** `brokerage-account-ledger` — `Ledger entries preserve broker operation meaning`
|
||||
- **Verification:** Добавить risk-based Jest-проверки UID/FIGI lookup, дедупликации, nullable fallback и сохранения содержимого Ledger Entry; выполнить `npm run verify` в `backend`.
|
||||
|
||||
- [x] 1.2 [backend] Опубликовать additive nullable metadata в runtime OpenAPI и проверить совместимость существующего ответа операций.
|
||||
- **Covers:** `N/A` — реализация Contract Gate Decision из утверждённого Design; самостоятельного дополнительного observable requirement не создаёт.
|
||||
- **Verification:** Выполнить backend runtime preflight и подтвердить наличие nullable `logoName` в `BrokerageOperationDto` опубликованного OpenAPI до frontend sync.
|
||||
|
||||
## 2. Frontend ledger presentation
|
||||
|
||||
- [x] 2.1 [frontend] Синхронизировать committed OpenAPI snapshot после опубликованного backend contract и обновить типизированное потребление Ledger Entry.
|
||||
- **Covers:** `N/A` — обязательное связывание frontend с изменённым публичным contract из Design, без нового отдельного behavior.
|
||||
- **Verification:** Выполнить `npm run openapi:sync` в `frontend`, проверить generated diff на nullable `logoName` и выполнить `npm run openapi:check`.
|
||||
|
||||
- [x] 2.2 [frontend] Создать единое presentation отображение Ledger Entry с логотипом или текстовым fallback, русскими подписями «Поступление»/«Списание», знаком и семантическими тонами; применить его к пяти последним записям обзора и полному журналу.
|
||||
- **Covers:** `brokerage-account-ledger` — `Account overview includes recent ledger events`; `brokerage-account-ledger` — `Full ledger presents compact rows`
|
||||
- **Verification:** Добавить риск-ориентированные Vitest-проверки положительной, отрицательной, безденежной и безлоготипной записи в обоих потребителях; вручную проверить узкую ширину, клавиатурный фокус и читаемость без цветового восприятия.
|
||||
|
||||
- [x] 2.3 [frontend] Перевести полный журнал на finance boundary `container → ViewModel → view`, сохранив фильтрацию, cursor-пагинацию и все loading/error/empty состояния.
|
||||
- **Covers:** `N/A` — техническая структура нужна для повторного использования строки и соблюдения утверждённого UI Pattern, не расширяя Delta Specs.
|
||||
- **Verification:** Выполнить `npm run verify` в `frontend`.
|
||||
|
||||
## 3. Documentation and SDD delivery
|
||||
|
||||
- [x] 3.1 [docs] Обновить as-built Account Ledger documentation после поставки: отразить nullable visual metadata и русскую семантику поступления, списания и отсутствия движения денег без дублирования change artifacts.
|
||||
- **Covers:** `N/A` — docs фиксирует только проверенное поставленное состояние, определённое Delivery Map.
|
||||
- **Verification:** Выполнить `npm run verify` в `docs` и проверить локальные ссылки изменённого feature document.
|
||||
|
||||
- [x] 3.2 [specs] Выполнить strict validation change и Delta Specs в canonical store после завершения planning artifacts.
|
||||
- **Covers:** `N/A` — specs владеет versioned SDD contract и его structural validation, а application behavior реализуют frontend и backend.
|
||||
- **Verification:** Выполнить `openspec validate improve-ledger-event-rows --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs` и `git diff --check` в `specs`.
|
||||
|
||||
## 4. Cross-area contract and completion
|
||||
|
||||
- [x] 4.1 [workspace] Выполнить required runtime OpenAPI gate после backend publication и frontend snapshot sync.
|
||||
- **Covers:** `N/A` — workspace координирует Contract Gate Decision между двумя владельцами, не реализуя отдельное behavior.
|
||||
- **Verification:** Выполнить `bash specs/scripts/verify-runtime-openapi.sh` из workspace root.
|
||||
|
||||
- [x] 4.2 [workspace] Сверить поставленное поведение с Proposal, Delta Specs и Design, затем запустить canonical dispatcher и независимый read-only review перед archive.
|
||||
- **Covers:** `N/A` — workspace владеет только межрепозиторной semantic verification и review, а не реализацией требований.
|
||||
- **Verification:** Выполнить `bash specs/scripts/verify-workspace-change.sh improve-ledger-event-rows` из workspace root и подтвердить отсутствие Critical/Important findings в independent review.
|
||||
@@ -29,7 +29,7 @@
|
||||
- **THEN** система возвращает следующую страницу без повторения записей предыдущей страницы
|
||||
|
||||
### Requirement: Ledger entries preserve broker operation meaning
|
||||
Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.
|
||||
Система MUST представлять одну upstream-операцию одной записью журнала и MUST передавать её timestamp, тип операции, категорию, описание, доступные идентификаторы инструмента, доступную presentation metadata инструмента, денежную выплату, количество, цену, НКД и комиссию. Денежные поля MUST сохранять исходную валюту и точное десятичное значение.
|
||||
|
||||
#### Scenario: Отображение купонной выплаты
|
||||
- **WHEN** T-Bank возвращает исполненную купонную операцию с выплатой и данными инструмента
|
||||
@@ -43,8 +43,12 @@
|
||||
- **WHEN** T-Bank возвращает исполненную операцию, изменяющую состав инструментов, но без денежной выплаты
|
||||
- **THEN** запись журнала передаёт доступное количество и не содержит искусственной денежной выплаты с нулевым значением
|
||||
|
||||
#### Scenario: Доступна визуальная идентичность инструмента
|
||||
- **WHEN** для инструмента исполненной операции доступна presentation metadata бренда
|
||||
- **THEN** запись журнала передаёт её вместе с доступными идентификаторами инструмента, не меняя остальные сведения операции
|
||||
|
||||
### Requirement: Account overview includes recent ledger events
|
||||
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||
Обзор счёта MUST показывать пять последних исполненных записей журнала этого счёта и действие перехода к его полному журналу. Каждая показанная запись MUST иметь ту же визуальную идентичность инструмента и семантику денежного движения, что и запись полного журнала. Неуспешный или пустой запрос последних записей MUST оставаться локальным состоянием блока последних событий и MUST NOT заменять успешно отображённый обзор Portfolio.
|
||||
|
||||
#### Scenario: Отображение последних событий
|
||||
- **WHEN** загружается обзор счёта и его журнал содержит исполненные операции
|
||||
@@ -54,13 +58,29 @@
|
||||
- **WHEN** обзор счёта успешно загружается, но запрос последних записей завершается ошибкой
|
||||
- **THEN** обзор Portfolio остаётся доступным, а блок последних событий отображает собственное состояние восстановления
|
||||
|
||||
#### Scenario: Последняя запись не содержит visual metadata инструмента
|
||||
- **WHEN** одна из последних записей не имеет доступной presentation metadata инструмента
|
||||
- **THEN** обзор показывает для неё понятный текстовый fallback и сохраняет дату, тип, инструмент и денежное изменение записи доступными для чтения
|
||||
|
||||
### Requirement: Full ledger presents compact rows
|
||||
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте. Она MUST обозначать записи без движения денег и MUST NOT показывать цену или количество.
|
||||
Страница полного журнала MUST показывать для каждой записи дату, тип операции, инструмент и денежное изменение в исходной валюте в компактной структурированной строке. При доступной presentation metadata инструмента строка MUST показывать его визуальную идентичность; при её отсутствии MUST использовать понятный текстовый fallback. Для положительной денежной выплаты строка MUST явно обозначать поступление знаком, текстовой семантикой и положительным цветом; для отрицательной — списание знаком, текстовой семантикой и отрицательным цветом. Страница MUST обозначать записи без движения денег нейтрально и MUST NOT показывать цену или количество.
|
||||
|
||||
#### Scenario: Отображение записи только с инструментом
|
||||
- **WHEN** полный журнал отображает запись без денежной выплаты
|
||||
- **THEN** страница определяет её как запись без движения денег
|
||||
|
||||
#### Scenario: Отображение поступления
|
||||
- **WHEN** полный журнал отображает запись с положительной денежной выплатой
|
||||
- **THEN** строка явно показывает поступление и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отображение списания
|
||||
- **WHEN** полный журнал отображает запись с отрицательной денежной выплатой
|
||||
- **THEN** строка явно показывает списание и его денежное изменение в исходной валюте, не полагаясь только на цвет
|
||||
|
||||
#### Scenario: Отсутствует visual metadata инструмента
|
||||
- **WHEN** полный журнал отображает запись без доступной presentation metadata инструмента
|
||||
- **THEN** строка показывает понятный текстовый fallback без подмены или сокрытия доступных данных инструмента
|
||||
|
||||
### Requirement: Кэш страниц журнала ограничивает локальные ресурсы
|
||||
Система SHALL кэшировать не более 100 недавно использованных страниц Account Ledger в каждом backend process не более чем на 30 секунд. Cache key MUST включать User, Brokerage Account, нормализованные период и categories, opaque cursor и limit; порядок или дублирование categories MUST NOT создавать отдельную cache identity, а отсутствующий конец периода MUST использовать текущий 30-секундный bucket. Просроченная страница MUST NOT возвращаться, а при переполнении cache MUST удалять наименее недавно использованную страницу.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user