Проблема расхождения НДС на несколько копеек — это классическая ситуация, с которой сталкивается практически каждый технический специалист и бухгалтер при работе в 1С:Предприятие. Ситуация обычно выглядит так: бухгалтер берет итоговую сумму реализации, умножает её на 18/118 (или 20/120) на калькуляторе и получает результат, который отличается от итоговой суммы в документе 1С на 1, 2 или более копеек. При этом Excel часто подтверждает правоту калькулятора, а 1С упорно показывает «неверную» сумму. Разберем детально, почему это происходит, кто прав в этой ситуации и как объяснить это пользователям.
Разберем фундаментальное различие в подходах. Проанализируем, как считает калькулятор: он берет одну большую цифру (общий итог) и применяет к ней формулу. Однако, согласно налоговому законодательству РФ и правилам заполнения счетов-фактур (Постановление Правительства №1137), НДС должен рассчитываться по каждой товарной позиции отдельно. Сумма налога в документе — это не налог от итоговой суммы, а сумма округленных значений налога по каждой строке.
Рассмотрим пример. Допустим, в документе 100 строк. В каждой строке расчетный НДС составил 10,004 рубля.
Как мы видим, разница составила целых 40 копеек «из ниоткуда». В данном случае 1С действует абсолютно корректно с точки зрения методологии бухгалтерского учета.
Часто программисты слышат аргумент: «Я скопировала данные в Excel, и там всё сходится!». Выясним причину этого феномена. Excel по умолчанию работает с точностью до 15 знаков после запятой. Когда вы видите в ячейке 366308,24, внутри неё может храниться значение 366308,24444.... При сложении таких ячеек Excel суммирует именно «хвосты», а в итоговой ячейке просто скрывает их за форматом отображения. 1С же является базой данных, где в реквизит СуммаНДС с типом Число(15, 2) записывается уже округленное до двух знаков значение. «Хвосты» отбрасываются в момент записи строки документа, и суммировать их физически невозможно.
Посмотрим на пример кода, который часто пытаются использовать для «исправления» ситуации. Проанализируем функцию Окр(). Многие пытаются играть с разрядностью, но математический принцип остается неизменным. Рассмотрим типичный фрагмент расчета в конфигурации:
// Типичный расчет НДС в документе
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
// Расчет НДС для каждой строки отдельно
СтрокаТЧ.СуммаНДС = Окр(СтрокаТЧ.Сумма * 18 / 118, 2, РежимОкругления.Окр15как20);
КонецЦикла;
// Итог документа — это просто сумма по колонке
Объект.ВсегоНДС = Объект.Товары.Итог("СуммаНДС");
Здесь важно понимать, что РежимОкругления.Окр15как20 или другие параметры функции Окр не изменят того факта, что сумма округлений не обязана быть равна округлению суммы. Это свойство математики, которое невозможно «починить» программным кодом, не нарушив целостность данных в строках.
Проанализируем ситуацию с точки зрения настроек документа. Расхождения чаще всего возникают, когда выбран режим «НДС в сумме». В этом случае цена включает налог, и программа вынуждена выполнять деление (на 1.18 или 1.20). Деление крайне часто порождает бесконечные дроби, которые приходится округлять в каждой строке.
Если контрагент требует идеального совпадения «итого * процент», предложите бухгалтерии использовать режим «НДС сверху». В этом случае цена устанавливается за чистый товар, а налог вычисляется умножением на 0.18 или 0.20. Точность таких расчетов математически выше, и «плавающих» копеек становится значительно меньше.
Если бухгалтерия или контрагенты настаивают на изменениях, приведите следующие доводы:
Попытки «побороть» математику округлений через программный код обычно приводят к еще большим проблемам: цена за единицу товара перестает соответствовать сумме, или возникают сложности при частичном возврате товара, когда «подогнанная» копейка зависает на остатках.
Рекомендация для программиста: Не пытайтесь переписывать типовой механизм расчета 1С. Вместо этого проверьте, не используются ли в табличной части неокругленные значения, которые могли попасть туда из внешних обработок или обменов. Для этого можно использовать простую проверку:
Для Каждого Строка Из Товары Цикл
Если Строка.СуммаНДС <> Окр(Строка.СуммаНДС, 2) Тогда
Сообщить("В строке " + Строка.НомерСтроки + " обнаружена 'грязная' точность!");
Строка.СуммаНДС = Окр(Строка.СуммаНДС, 2);
КонецЕсли;
КонецЦикла;
Если все суммы в строках уже округлены до 2 знаков, а итоговая сумма все равно не нравится бухгалтеру — это методологическая особенность, которую нужно просто принять.