docs: adds rules and agents specs
This commit is contained in:
82
docs/backlog/format.md
Normal file
82
docs/backlog/format.md
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user