КурсыСтатьи

Как хранить деньги в базе данных

Владислав

17 нояб. 2025 г.

Лучшие практики работы с валютами

Предлагаемый подход: Целые числа в младших единицах

Мы используем подход Integer Minor Units (аналогично Stripe, Adyen, Klarna, MasterCard):

- Хранение: Суммы хранятся как целые числа в наименьшей единице валюты
  - RUB: хранится в копейках (1 RUB = 100 копеек)
  - USD: хранится в центах (1 USD = 100 центов)
  - JPY: хранится как есть (нет младшей единицы, 0 знаков после запятой)

YooKassa, например, использует формат String Base Units (например, "499.00") в своём API.

А внутреннее хранение всегда использует младшие единицы.

Почему этот подход?

Преимущества

1. Точность: Нет ошибок с плавающей точкой
2. Производительность: Целочисленная арифметика быстрее
3. Отраслевой стандарт: Используется крупными платежными процессорами
4. Типобезопасность: Четкое различие между базовыми и младшими единицами

Компромиссы

- Требует утилитарные функции конвертации
- Менее интуитивно, чем хранение "499.00" напрямую

Утилиты для валют

Все конвертации валют используют централизованные утилиты в `src/shared/lib/currency.ts`:

JavaScript
// Конвертировать базовые единицы в младшие
toMinorUnits(499.00, 'RUB') // Возвращает 49900


// Конвертировать младшие единицы в базовые
fromMinorUnits(49900, 'RUB') // Возвращает 499.00


// Форматировать для отображения
formatAmount(49900, 'RUB') // Возвращает "499.00 ₽"

Соответствие ISO 4217

Мы следуем стандарту ISO 4217 для кодов валют:

- База данных: Использует enum `Currency` для типобезопасности (RUB, USD, EUR, и т.д.)
- Типобезопасность: Только допустимые коды валют разрешены на уровне базы данных
- Метаданные младшей единицы: Хранятся в `CURRENCY_METADATA` в `src/shared/lib/currency.ts`
- Поддержка: доступны валюты с 0-18 знаками после запятой
- Текущие валюты: RUB, USD, EUR, KZT, BYN, UAH, CNY, JPY, GBP

Лучшие практики

1. Никогда не используйте арифметику с плавающей точкой для денег
2. Всегда храните код валюты вместе с суммой
3. Конвертируйте валюты как можно ближе к внешнему слою (в идеале через слой DTO)
4. Используйте централизованный модуль
5. Используйте типизирование везде, где это возможно

Реакции читателей

Магистры

Все права защищены © 2024

VKVKYouTube