При оформлении продаж через онлайн-кассы (в частности, ККТ Атол под управлением драйверов 10.x в конфигурациях 1С:УПП 1.3, 1С:КА или 1С:ERP) пользователи часто сталкиваются со странным поведением оборудования. На печатной форме чека и в электронном документе одна товарная позиция неожиданно разделяется на две отдельные строки. При этом в одной строке цена может отличаться на одну копейку, а вся сумма НДС по позиции переносится исключительно на вторую строку, оставляя первую с нулевым налогом.
В этой статье мы подробно разберем причины возникновения данной проблемы, проанализируем внутренние алгоритмы работы кассового аппарата и рассмотрим практические способы ее устранения в кодовой базе 1С.
Согласно требованиям Федерального закона № 54-ФЗ и действующим форматам фискальных документов (ФФД 1.05 и ФФД 1.2), кассовый аппарат обязан соблюдать жесткое математическое равенство для каждой позиции чека:
Цена * Количество = Сумма
Все три параметра передаются в кассу в числовом формате с фиксированной точностью (округляются до копеек, то есть до двух знаков после запятой). Основной конфликт возникает при продаже дробного (весового) товара либо при распределении сложных скидок по позициям чека на стороне 1С.
Рассмотрим пример из XML-пакета, который 1С отправляет на кассу:
<FiscalString Name="Антисептик тонирующий" Quantity="7.7" PriceWithDiscount="90.99" SumWithDiscount="700.61" TaxSum="116.77"/>
Проведем несложный математический расчет:
7.7 кг * 90.99 руб. = 700.623 руб.
При округлении этого значения до двух знаков по правилам математики получается 700.62 руб. Однако учетная система 1С в силу внутренних алгоритмов распределения копеек или округлений передает в ККТ итоговую сумму по строке 700.61 руб. (разница составляет ровно 1 копейку).
Получив такой XML-пакет, драйвер ККТ запускает механизм форматно-логического контроля (ФЛК). Поскольку касса не может пробить чек с математической ошибкой (это приведет к отказу в регистрации чека фискальным накопителем), она принудительно разделяет позицию на две строки, подгоняя количество и цену под переданную сумму:
В сумме эти две строки дают ровно те 700.61 руб., которые запросила 1С. Касса успешно регистрирует чек, но его внешний вид становится некорректным.
Когда ККТ делит одну позицию на две, она сталкивается с необходимостью разделить общую сумму НДС (переданный тег TaxSum). Из-за ограничений прошивки кассового аппарата и особенностей округлений ККТ не может пропорционально разделить копейки налога между новыми строками. Чтобы общая сумма НДС по чеку сошлась с фискальными итогами, ККТ переносит всю сумму налога на одну из получившихся строк, оставляя вторую строку со ставкой НДС 20%, но с нулевой суммой налога (0.00 руб.). Это вызывает серьезные вопросы у бухгалтеров и налоговых инспекторов при проверке чеков.
Для исправления ситуации мы можем применить несколько подходов. Рассмотрим их подробнее.
Довольно часто причиной неверного расчета сумм налога и последующего расхождения округлений является устаревший код в нетиповых или давно не обновлявшихся конфигурациях 1С (например, 1С:УПП 1.3). Проанализируем запрос, формирующий данные для чека:
| ВЫБОР
| КОГДА ПрочиеРеализации.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18)
| ТОГДА 18
| КОГДА ПрочиеРеализации.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10)
| ТОГДА 10
| ИНАЧЕ 0
| КОНЕЦ КАК ПроцентНДС
В данном запросе жестко зашиты старые ставки налога. При работе со ставкой НДС 20% ветка ИНАЧЕ возвращает процент налога, равный 0. Это приводит к передаче неверных суммовых параметров в XML-пакет драйвера, из-за чего ККТ начинает пересчитывать налог и дробить строки.
Необходимо исправить запрос, добавив актуальную ставку НДС 20%:
| ВЫБОР
| КОГДА ПрочиеРеализации.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20)
| ТОГДА 20
| КОГДА ПрочиеРеализации.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18)
| ТОГДА 18
| КОГДА ПрочиеРеализации.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10)
| ТОГДА 10
| ИНАЧЕ 0
| КОНЕЦ КАК ПроцентНДС
После обновления запроса расчет НДС в коде интеграции с кассой станет корректным, что в большинстве случаев избавляет ККТ от необходимости разбивать строки чека.
Наиболее надежный способ избежать хаотичного деления строк кассовым аппаратом — контролировать округления на стороне 1С перед формированием XML-пакета для драйвера. Мы можем написать алгоритм, который будет проверять равенство цены, количества и суммы. Если выявляется расхождение на копейку, система должна самостоятельно распределить эту копейку, скорректировав цену или разбив позицию в 1С по контролируемым правилам.
Рассмотрим пример функции, которая корректирует параметры позиции:
Функция СкорректироватьПараметрыСтрокиЧека(Цена, Количество, Сумма) Экспорт
РасчетнаяСумма = Округлить(Цена * Количество, 2);
РазницаКопеек = Сумма - РасчетнаяСумма;
Если Абс(РазницаКопеек) > 0 Тогда
// Корректируем цену единицы товара, чтобы соблюсти равенство ФФД
НоваяЦена = Округлить(Сумма / Количество, 2);
Возврат НоваяЦена;
КонецЕсли;
Возврат Цена;
КонецФункции
Применение этой корректировки позволяет отправлять в ККТ параметры, которые полностью удовлетворяют правилу Цена * Количество = Сумма, исключая запуск алгоритма принудительного разбиения на стороне кассы.
В некоторых случаях можно скорректировать поведение драйвера через его тест. Для этого выполним следующие действия:
Важное предупреждение: Данный метод является вспомогательным. Под требованиями ФФД 1.05 и 1.2 прошивки кассовых аппаратов Атол часто игнорируют настройки драйвера, если переданные данные напрямую нарушают кассовое законодательство. Приоритетным решением всегда остается выравнивание математики на стороне 1С.