Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Валюты и курсы в приложении

Валюты и курсы: пересчёт сумм и хранение курса

Работа с валютами: код валюты, разрядность, хранение курса на дату, пересчёт сумм и проверка согласованности расчёта.

Прямой ответ

Сумма хранится вместе с кодом валюты, а пересчёт выполняется по курсу на дату операции, поэтому значение однозначно относится к валюте и моменту.

Параметр Что определяет
Код валюты Валюту, к которой относится сумма
Разрядность Число разменных единиц в основной единице
Курс на дату Значение для пересчёта в момент операции
Валюта учёта Валюту, в которой ведётся отчётность
from decimal import Decimal

amount = Decimal("100.00")
rate = Decimal("92.5")          # курс на дату операции
converted = (amount * rate).quantize(Decimal("0.01"))

Пересчёт выполняется по курсу на дату операции, поэтому сумма в валюте учёта соответствует моменту совершения операции. О хранении сумм — в статье про деньги в приложении.

Код валюты и разрядность

Код валюты определяет валюту суммы, а разрядность — число разменных единиц, поэтому хранение требует обоих параметров.

Код валюты. Сумма сопровождается кодом, поэтому значение однозначно относится к одной валюте и не смешивается с другими.

Разрядность валюты. Число разменных единиц в основной единице различается между валютами, поэтому разрядность хранится либо определяется по коду.

Проверка при операции. Операция над суммами проверяет совпадение кодов, поэтому сложение сумм в разных валютах отклоняется.

Практическое следствие: сумма без кода валюты складывается с суммой в другой валюте, поэтому результат не имеет смысла, а ошибка не обнаруживается.

Отдельный аспект — разрядность при хранении в минимальных единицах. Сумма в минимальных единицах хранится целым числом, поэтому разрядность определяет, сколько разрядов соответствует основной единице. Разрядность, не сохранённая вместе с суммой, делает значение неоднозначным.

Курс на дату и пересчёт сумм

Курс на дату операции определяет значение для пересчёта, поэтому сумма в валюте учёта соответствует моменту совершения операции.

Курс на дату. Значение курса фиксируется на дату операции, поэтому пересчёт не зависит от изменения курса после операции.

Хранение курса. Курс сохраняется вместе с операцией, поэтому пересчёт воспроизводим и не требует обращения к истории курса.

Валюта учёта. Сумма пересчитывается в валюту отчётности, поэтому отчёт формируется в одной валюте.

Практическое следствие: пересчёт по текущему курсу вместо курса на дату операции меняет сумму задним числом, поэтому отчётность за прошлый период не воспроизводится.

Валюта учёта и согласованность расчёта

Валюта учёта определяет валюту отчётности, поэтому пересчёт выполняется до формирования отчёта, а не при чтении.

Пересчёт до отчёта. Сумма пересчитывается в валюту учёта при формировании отчёта, поэтому значение фиксируется в документе.

Согласованность курса. Все операции периода пересчитываются по курсу на дату операции, поэтому итог соответствует моменту каждой операции.

Проверка итога. Сумма в валюте учёта сравнивается с суммой в исходной валюте по курсу, поэтому расхождение указывает на неверный курс.

Практическое следствие: пересчёт при чтении отчёта по текущему курсу даёт значение, отличающееся от зафиксированного в документе, поэтому отчёт не воспроизводится.

О правиле округления при пересчёте — в статье про округление денежных значений; о сверке сумм — в статье про сверку платежей.

Практика: работа с валютами и курсами

1. Храните код валюты вместе с суммой. Значение однозначно относится к валюте, поэтому смешение сумм исключается.

2. Фиксируйте разрядность валюты. Число разменных единиц определяет представление суммы в минимальных единицах.

3. Сохраняйте курс на дату операции. Пересчёт воспроизводим и не зависит от изменения курса после операции.

4. Пересчитывайте по курсу на дату, а не по текущему. Сумма за прошлый период не меняется задним числом.

5. Определяйте валюту учёта для отчётности. Отчёт формируется в одной валюте, поэтому пересчёт выполняется до формирования.

6. Округляйте после пересчёта. Промежуточное значение сохраняет точность, поэтому итог не накапливает погрешность.

7. Проверяйте итог в валюте учёта против исходной суммы. Расхождение указывает на неверный курс либо на ошибку пересчёта.

Рекомендации:

  1. Не пересчитывайте по текущему курсу для прошлых периодов. Сумма меняется задним числом, поэтому отчётность не воспроизводится.
  2. Учитывайте разрядность при хранении в минимальных единицах. Разрядность, не сохранённая с суммой, делает значение неоднозначным.
  3. Сопоставляйте курс с датой операции. Курс на дату фиксируется вместе с операцией, поэтому пересчёт воспроизводим.
  4. Фиксируйте валюту учёта в настройках отчётности. Отчёт формируется в одной валюте, поэтому пересчёт выполняется единообразно.
  5. Пересматриваем набор валют при добавлении новой. Новая валюта может требовать иной разрядности и источника курса.

Практический сценарий: отчёт за прошлый месяц менялся при повторном формировании

Контекст: отчёт за прошлый месяц формировался повторно и показывал иные суммы, при этом операции не изменялись.

  1. Диагностика. Проверка показала, что пересчёт сумм выполнялся по текущему курсу валюты. Курс изменился после совершения операций, поэтому пересчёт давал иное значение при каждом формировании отчёта.
  2. Причина. Курс на дату операции не сохранялся, поэтому пересчёт использовал текущее значение вместо значения на момент операции.
  3. Действия. (а) Добавили сохранение курса на дату операции вместе с суммой, чтобы пересчёт использовал зафиксированное значение; (б) пересчитали отчёт за прошлый месяц и убедились, что значение не меняется при повторном формировании; (в) зафиксировали валюту учёта в настройках отчётности, чтобы пересчёт выполнялся единообразно; (г) перенесли округление в конец пересчёта, чтобы промежуточные значения сохраняли точность; (д) добавили проверку итога в валюте учёта против суммы в исходной валюте, чтобы расхождение обнаруживалось.
  4. Результат. Отчёт за прошлый период воспроизводится, поскольку пересчёт выполняется по курсу на дату операции.

Вывод: пересчёт по текущему курсу меняет суммы прошлых периодов задним числом, поэтому отчёт не воспроизводится при повторном формировании. Сохранение курса на дату операции и пересчёт по зафиксированному значению делают отчётность стабильной.

FAQ

Зачем хранить код валюты вместе с суммой? Сумма без кода валюты складывается с суммой в другой валюте, поэтому результат не имеет смысла, а ошибка не обнаруживается.

Какой курс использовать для пересчёта? Курс на дату операции. Пересчёт по текущему курсу меняет суммы прошлых периодов задним числом.

Что такое валюта учёта? Валюта, в которой ведётся отчётность. Суммы пересчитываются в валюту учёта при формировании отчёта.

Почему важна разрядность валюты? Число разменных единиц в основной единице различается между валютами, поэтому разрядность определяет представление суммы.

Источники: PostgreSQL money type, PostgreSQL numeric types, Python decimal — ссылки в шапке.