Files
family_budget/docs/backlog/format.md
2026-02-27 19:08:55 +03:00

83 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Формат импорта выписки (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"
}
]
}
```