Почему 1С округляет суммы в запросе и как это исправить?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

При разработке отчетов, связанных с денежными средствами, особенно когда речь идет о кассовых операциях, точность вычислений до копейки имеет критическое значение. Часто программисты сталкиваются с ситуацией, когда в базе данных значение суммы содержит дробную часть (например, 549.50), а в результате запроса или в печатной форме отчета отображается округленное целое число (550). Это создает расхождения в учете и вызывает вопросы у контролирующих органов.

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

Анализируем причину: неявное определение типа в конструкции «ВЫБОР»

Проанализируем ситуацию на примере типичного запроса, где используется выбор знака суммы в зависимости от вида операции (Продажа или Возврат). В исходном коде автора мы видим следующую конструкцию:


ТекстЗапроса = "ВЫБРАТЬ
               |    ВЫБОР
               |        КОГДА ЧекККМОплата.Ссылка.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОперацийЧекККМ.Продажа)
               |            ТОГДА ЧекККМОплата.Сумма
               |        ИНАЧЕ -ЧекККМОплата.Сумма
               |    КОНЕЦ КАК Сумма,
               ...

Выясним причину округления. Когда платформа 1С выполняет запрос, содержащий оператор ВЫБОР (аналог CASE в SQL), она должна заранее определить тип возвращаемого значения для всей колонки. Если в одном из условий возвращается число, а в другом — результат арифметической операции (например, унарный минус -ЧекККМОплата.Сумма), система может столкнуться с неопределенностью разрядности.

В некоторых случаях (зависящих от версии платформы и используемой СУБД) система может привести результат к типу Число с нулевой точностью по умолчанию. Это означает, что на уровне выполнения SQL-запроса дробная часть просто отсекается или округляется, и в результат попадает уже целое число. Это особенно актуально при использовании унарного минуса над полями, точность которых не была жестко зафиксирована в метаданных вычисляемого поля запроса.

Решение №1: Использование функции ВЫРАЗИТЬ

Самым надежным способом решения проблемы в языке запросов 1С является явное приведение типа. Мы должны принудительно указать системе, какую точность (количество знаков после запятой) мы ожидаем получить. Для этого используется функция ВЫРАЗИТЬ.

Разберем, как изменить исходный код, чтобы избежать округления до целых. Нам необходимо обернуть конструкцию ВЫБОР в функцию приведения типа:


ТекстЗапроса = "ВЫБРАТЬ
               |    ВЫРАЗИТЬ(ВЫБОР
               |        КОГДА ЧекККМОплата.Ссылка.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОперацийЧекККМ.Продажа)
               |            ТОГДА ЧекККМОплата.Сумма
               |        ИНАЧЕ -ЧекККМОплата.Сумма
               |    КОНЕЦ КАК Число(15, 2)) КАК Сумма,
               ...

В данном примере Число(15, 2) означает, что число может содержать до 15 знаков в целой части и ровно 2 знака после запятой. Это стандарт для денежных полей в большинстве типовых конфигураций. Такое явное описание типа предотвращает автоматическое округление на уровне СУБД.

Решение №2: Проверка настроек Системы Компоновки Данных (СКД)

Если после исправления запроса сумма в отчете по-прежнему выглядит округленной, нам стоит обратить внимание на механизм вывода данных. В 1С:Предприятии 8 отчеты чаще всего строятся на базе СКД. Округление может происходить не в базе данных, а на этапе визуализации.

Проанализируем настройки оформления полей в СКД:

  1. Откройте схему компоновки данных.
  2. Перейдите на закладку «Наборы данных» или «Настройки».
  3. Найдите поле Сумма.
  4. Проверьте свойство «Оформление». Там может быть задан параметр «Формат». Если в строке формата указано ЧДЦ=0 (Число Дробных Цифр равно 0), то число 549.50 будет отображаться как 550, хотя в памяти компьютера оно хранится корректно.
  5. Установите значение ЧДЦ=2 для корректного отображения копеек.

Также важно проверить роли полей. Если поле помечено как Остатки или имеет специфические настройки агрегации в ресурсах, СКД может применять внутренние алгоритмы обработки, которые требуют явного указания точности в ресурсах отчета.

Влияние СУБД и математика округления

Посмотрим на ситуацию с точки зрения серверной части. При трансляции запроса в SQL Server или PostgreSQL, СУБД четко следует типам данных. Однако при выполнении деления или сложных математических операций результат может быть приведен к типу с меньшей точностью для оптимизации производительности. Использование ВЫРАЗИТЬ в 1С транслируется в SQL-команду CAST или CONVERT, что гарантирует сохранение дробной части на уровне сервера.

Важно помнить о разнице между арифметическим и банковским округлением:

В рассматриваемом случае с кассой, накопление ошибки даже в полкопейки при суммировании итогов может привести к серьезному дефициту или излишку. Если исходное поле в основной части запроса потеряло точность, то секция ИТОГИ СУММА(Сумма) будет рассчитываться на основе уже округленных данных, что многократно увеличит итоговую погрешность.

Заключение и рекомендации

Подведем итог нашего исследования. Для обеспечения стопроцентной точности в финансовых отчетах 1С рекомендуется придерживаться следующих правил:

  1. Всегда используйте ВЫРАЗИТЬ для вычисляемых полей в запросах, если они участвуют в дальнейших расчетах или итогах.
  2. При использовании конструкции ВЫБОР приводите весь результат блока к нужному числовому типу.
  3. Проверяйте форматную строку в настройках оформления СКД и в свойствах ячеек табличного документа.
  4. Помните, что округление в запросе и округление при выводе в отчет — это два разных процесса, и каждый из них нужно контролировать отдельно.

Применяя эти методы, мы обеспечим корректность работы кассовых отчетов и исключим ситуации, когда «пропадают» или «появляются» лишние рубли из-за особенностей механизмов платформы.

← На главную