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

4.4 KiB
Raw Permalink Blame History

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

{
  "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"
    }
  ]
}