Как реализовать округление копеек в чеках ККТ АТОЛ при использовании XML в 1С

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

При работе с онлайн-кассами АТОЛ через XML-интерфейс (стандартная библиотека подключаемого оборудования 1С) программисты часто сталкиваются с проблемой: как округлить итоговую сумму чека до рубля при наличном расчете. Попытки передать общую сумму чека без копеек приводят к ошибке «Чек оплачен не полностью». Это происходит потому, что сумма всех позиций в чеке должна математически совпадать с итоговой суммой оплаты до копейки.

В этой статье мы разберем, почему встроенные методы драйвера могут не работать, как правильно распределять «скидку округления» по позициям и как сделать чек визуально понятным для покупателя, соблюдая требования законодательства (54-ФЗ).

Почему не работают стандартные методы округления

Проанализируем ситуацию с методом receiptTotal(), который упоминается в документации к драйверу АТОЛ 10. Данный метод действительно позволяет зарегистрировать итог меньше суммы чека в пределах копеек. Однако при работе через XML-пакеты 1С этот механизм часто оказывается недоступен по следующим причинам:

  1. Предварительная проверка в 1С: Компонента 1С (addin.atol_kkt_1c83_v10) перед отправкой данных в кассу сама проверяет корректность математики. Если сумма по тегам Amount (сумма строки) не совпадает с итогом оплаты, команда блокируется еще до того, как она попадет в драйвер кассы.
  2. Требования ФФД 1.05 и выше: Согласно формату фискальных данных, каждая позиция должна содержать конечную цену и сумму с учетом всех скидок. Понятие «скидка на весь чек» в электронном чеке, передаваемом в ОФД, отсутствует — любая скидка должна быть распределена по строкам.
  3. Игнорирование настроек ККТ: Настройки в таблицах самой кассы «Округлять итог до рубля» во многих современных прошивках игнорируются при работе в фискальном режиме, так как расчеты должно производить управляющее ПО.

Алгоритм программного округления в 1С

Единственный надежный путь — это самостоятельный пересчет цен и сумм в табличной части перед формированием XML-структуры CheckPackage. Рассмотрим, как это реализовать на практике.

Разберем ситуацию на примере: в чеке две позиции на общую сумму 15,57 руб. Нам нужно пробить чек на 15,00 руб. Сумма округления составляет 0,57 руб.

Нам необходимо распределить эти 0,57 руб. как скидку на товарные позиции. Наиболее стабильный метод — вычесть всю сумму округления из самой дорогой позиции или распределить ее пропорционально, а затем скорректировать последнюю строку, чтобы избежать ошибок округления.

Посмотрим на пример логики распределения суммы в коде:


// Допустим, СуммаЧека = 15.57, ЖелаемаяСумма = 15.00
СуммаСкидкиОкругления = СуммаЧека - Цел(СуммаЧека); // 0.57

// Проходим по строкам и уменьшаем итоговую сумму
// В XML нужно передавать уже рассчитанную сумму строки
Для Каждого СтрокаТЧ Из ТаблицаТоваров Цикл
    Если СуммаСкидкиОкругления > 0 Тогда
        ТекущаяСкидка = Мин(СтрокаТЧ.Сумма, СуммаСкидкиОкругления);
        СтрокаТЧ.Сумма = СтрокаТЧ.Сумма - ТекущаяСкидка;
        СуммаСкидкиОкругления = СуммаСкидкиОкругления - ТекущаяСкидка;
        
        // Пересчитываем цену, так как в XML важна связка Цена * Кол-во = Сумма
        СтрокаТЧ.Цена = СтрокаТЧ.Сумма / СтрокаТЧ.Количество;
    КонецЕсли;
КонецЦикла;

Важный нюанс: При изменении суммы позиции обязательно нужно пересчитывать сумму НДС (тег TaxSum в XML), иначе ККТ вернет ошибку о неверной сумме налога. Сумма НДС должна рассчитываться от новой итоговой суммы строки.

Как добиться отображения «Скидки» в чеке

Если вы просто уменьшите цены, покупатель увидит в чеке странные цифры (например, товар за 7,23 руб. превратится в 6,66 руб.). Чтобы чек выглядел как в крупных торговых сетях (например, «Магнит»), где указана полная цена и отдельная строка «Округление», выполним следующие шаги:

  1. В блоке Positions для каждой позиции передаем атрибут DiscountAmount. Это информационное поле, которое может быть напечатано в чеке.
  2. Для вывода красивой строки «Округление: 0,57» используем нефискальные текстовые строки. В XML-структуре АТОЛ это делается через добавление объектов в коллекцию перед или после позиций.

Проанализируем пример формирования структуры позиции в XML с учетом скидки:


<Position 
    Caption="Корнишоны" 
    MeasureOfQuantity="шт" 
    Quantity="1" 
    Price="15.57" 
    Amount="15.00" 
    DiscountAmount="0.57" 
    TaxCode="1" 
    TaxSum="2.50" />

Здесь Price — это исходная цена, а Amount — фактически оплаченная сумма. Разница между ними должна быть отражена в DiscountAmount. Однако помните, что для ККТ итогом является именно Amount. Если сумма всех Amount будет равна 15.00, а в блоке оплаты Payments вы также укажете Sum="15.00", чек будет пробит успешно.

Использование нефискальных строк

Чтобы итоговый документ выглядел профессионально, добавим текстовое пояснение об округлении. Рассмотрим, как добавить текст в XML-пакет:

В некоторых версиях драйвера и форматов XML 1С можно использовать блок TextString внутри тега Parameters или как отдельную позицию с нулевой суммой (если это поддерживает прошивка). Но самый надежный способ — это передача текста в параметрах закрытия чека, если ваша версия БПО это позволяет.

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

Рекомендации по реализации в самописных конфигурациях

При разработке собственного механизма взаимодействия с ККТ через XML, следуйте этим правилам:

Подводя итог, можно сказать, что хотя ККТ АТОЛ и обладает мощным функционалом скриптов и методов вроде receiptTotal, при работе через стандартный XML-слой 1С наиболее стабильным и предсказуемым решением остается предварительная подготовка данных в учетной системе. Это гарантирует отсутствие ошибок расхождения и полное соответствие чека требованиям ФЗ-54.

← На главную