docs: adds rules and agents specs

This commit is contained in:
Anton
2026-02-27 19:08:55 +03:00
commit 9551b93a09
12 changed files with 1151 additions and 0 deletions

82
docs/backlog/format.md Normal file
View File

@@ -0,0 +1,82 @@
# Формат импорта выписки (JSON 1.0)
## Общие принципы
- На вход SPA принимает файл в формате JSON фиксированной схемы версии `1.0`.
- Один JSON-файл = выписка по одному счёту одного банка за произвольный период.
- Все суммы хранятся в минорных единицах (копейки) как целые числа.
- Дата и время операции передаются в формате ISO 8601 с таймзоной (например, `2026-02-26T14:06:57+03:00`).
## Структура JSON 1.0
Корневые поля:
- `schemaVersion: "1.0"` — версия схемы обменного формата.
- `bank: string` — идентификатор банка (например, `"VTB"`).
- `statement: object` — заголовок выписки.
- `transactions: array` — массив операций.
### Объект `statement`
Обязательные поля:
- `accountNumber: string` — номер счёта в банке (как в выписке). Допускается полный номер.
- `currency: string` — код валюты счёта (например, `"RUB"`).
- `openingBalance: integer` — баланс на начало периода в копейках.
- `closingBalance: integer` — баланс на конец периода в копейках.
- `exportedAt: string` — дата и время формирования выписки в формате ISO 8601 с таймзоной.
Особенности:
- Период выписки (даты "с" и "по") в JSON не передаётся, так как каждая транзакция содержит свой `operationAt`.
- Балансы `openingBalance` и `closingBalance` используются для первичной и периодической сверки остатков, а также при первичной загрузке выписки в пустую БД.
### Массив `transactions`
Каждый элемент массива описывает одну транзакцию и имеет следующую структуру:
Обязательные поля:
- `operationAt: string` — дата и время операции в формате ISO 8601 с таймзоной.
- `amountSigned: integer` — сумма операции в копейках:
- `> 0` — приход;
- `< 0` — расход.
- `commission: integer` — комиссия по операции в копейках (всегда передаётся, даже если `0`).
- `description: string` — текстовое описание операции из выписки банка (как есть).
Особенности:
- Никакие ID транзакций банка не используются, так как они отсутствуют в выписке.
- Поле `accountNumber` внутри транзакции не дублируется — связь идёт через `statement.accountNumber`.
- Поле `fingerprint` в JSON не передаётся — оно будет вычисляться на стороне backend при импорте и храниться только в БД.
## Идемпотентность импорта
- Для каждой транзакции backend вычисляет `fingerprint` (например, SHA-256 от конкатенации:
`accountNumber + operationAt + amountSigned + commission + normalizedDescription`).
- В БД вводится уникальное ограничение по паре `(account_id, fingerprint)`,
что позволяет безопасно загружать один и тот же файл (или пересекающиеся по периоду файлы) без появления дублей.
## Пример JSON 1.0
```json
{
"schemaVersion": "1.0",
"bank": "VTB",
"statement": {
"accountNumber": "40817810825104025611",
"currency": "RUB",
"openingBalance": 4256167,
"closingBalance": 8845938,
"exportedAt": "2026-02-27T13:23:00+03:00"
},
"transactions": [
{
"operationAt": "2026-02-26T14:06:57+03:00",
"amountSigned": -50000,
"commission": 0,
"description": "Оплата товаров и услуг. PAVELETSKAYA. по карте *8214"
}
]
}
```