# Формат импорта выписки (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" } ] } ```