Как правильно округлить чек и пересчитать НДС в ККТ АТОЛ без БПО?

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

В розничной торговле часто возникает задача округления итоговой суммы чека до целого рубля или 50 копеек в пользу покупателя. Это позволяет ускорить расчеты наличными и повысить лояльность клиентов. Однако при реализации этой задачи в конфигурациях 1С, работающих напрямую с драйвером ККТ АТОЛ (без использования Библиотеки подключаемого оборудования — БПО), разработчики сталкиваются с серьезной проблемой: после применения скидки-округления на итог чека сумма НДС не пересчитывается должным образом, либо возникают расхождения в копейках.

В этой статье мы подробно разберем, почему встроенные механизмы фискального регистратора не справляются с этой задачей, проанализируем математические и налоговые аспекты проблемы, а также разработаем надежный алгоритм предобработки данных на стороне 1С, который позволит отправлять в ККТ абсолютно корректные данные.

Почему не работают встроенные функции драйвера ККТ?

На первый взгляд кажется, что проблема легко решается активацией флага "Пересчет суммы налогов после скидки на итог" в настройках драйвера АТОЛ или вызовом метода ОтменаНалога (или ResetTax). Однако на практике эти способы не дают результата по следующим причинам:

  1. Блокировка ручными настройками: Согласно документации АТОЛ, алгоритм автоматического пересчета налогов на стороне ККТ полностью отключается, если при регистрации товарных позиций налоги передаются из 1С вручную (например, через свойство TaxTypeNumber). Так как в большинстве учетных систем ставки НДС передаются жестко из карточки номенклатуры, драйвер игнорирует попытки автоматического перерасчета.
  2. Требования ФФД 1.05 и 1.2: Современные форматы фискальных документов требуют, чтобы все скидки и округления были распределены непосредственно по позициям чека. Понятие "скидка на чек" на уровне фискального накопителя фактически отсутствует. Каждая позиция должна быть зарегистрирована по своей конечной цене с учетом всех скидок. Любая попытка "списать" копейки на уровне итога чека произвольной командой блокируется фискальным накопителем из-за нарушения математического баланса.

Математический тупик обратного расчета НДС

Рассмотрим, почему возникает так называемая "проблема лишней копейки". Проанализируем пример, когда итоговая сумма чека после округления должна составить 360.00 рублей при ставке НДС 18% (расчет по формуле обратного акциза):

Сумма НДС = 360 * 18 / 118 = 54.9152 руб. (округляем до 54.92 руб.).

Казалось бы, все верно. Но давайте попробуем восстановить стоимость товара без НДС:

Стоимость без НДС = 360.00 - 54.92 = 305.08 руб.

Теперь проверим прямой расчет НДС от полученной стоимости без налога:

НДС = 305.08 * 18% = 54.9144 руб. (округляем до 54.91 руб.).

Складываем стоимость без НДС и полученный налог: 305.08 + 54.91 = 359.99 руб. Мы получили расхождение в 1 копейку! Если же мы попробуем увеличить стоимость без НДС до 305.09 рублей, то прямой НДС составит 54.92 рубля, а итоговая сумма чека станет 360.01 руб. Таким образом, получить ровную сумму 360.00 рублей математически невозможно без искусственной корректировки.

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

Пошаговый алгоритм решения задачи в 1С

Чтобы решить проблему округления и правильного расчета НДС, мы должны реализовать алгоритм, аналогичный поведению современной БПО 1С:

  1. Определить итоговую сумму чека до округления.
  2. Рассчитать сумму скидки-округления (разницу между исходным итогом и желаемым округленным значением).
  3. Пропорционально распределить полученную скидку по всем строкам чека.
  4. Рассчитать новые цены и суммы для каждой позиции с точностью до копейки.
  5. Выявить остаток распределения (ту самую "лишнюю копейку"), возникший из-за округления строк, и принудительно отнести его на одну из позиций чека (например, на товар с максимальной стоимостью).
  6. Рассчитать сумму НДС для каждой позиции исходя из ее финальной стоимости.
  7. Передать в драйвер ККТ готовые позиции без использования механизмов скидок на уровне кассы.

Рассмотрим практическую реализацию этого алгоритма на встроенном языке 1С.


// Процедура подготавливает табличную часть чека перед отправкой на печать
Процедура РаспределитьОкруглениеИРасчитатьНДС(ТаблицаТоваров, ИтогОкругленный)

    // Шаг 1: Считаем исходную сумму чека
    ИсходныйИтог = 0;
    Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
        ИсходныйИтог = ИсходныйИтог + (СтрокаТовара.Цена * СтрокаТовара.Количество);
    КонецЦикла;
    
    // Шаг 2: Определяем общую сумму округления (скидки)
    СуммаОкругления = ИсходныйИтог - ИтогОкругленный;
    
    Если СуммаОкругления <= 0 Тогда
        Возврат; // Округление не требуется или это наценка
    КонецЕсли;
    
    // Шаг 3: Пропорционально распределяем скидку по строкам
    ОстатокСкидки = СуммаОкругления;
    КоличествоСтрок = ТаблицаТоваров.Количество();
    
    Для Индекс = 0 По КоличествоСтрок - 1 Цикл
        СтрокаТовара = ТаблицаТоваров[Индекс];
        ДоляСтроки = (СтрокаТовара.Цена * СтрокаТовара.Количество) / ИсходныйИтог;
        СкидкаНаСтроку = Округлить(СуммаОкругления * ДоляСтроки, 2);
        
        // Накапливаем и распределяем остаток
        Если Индекс = КоличествоСтрок - 1 Тогда
            // В последнюю строку записываем весь оставшийся хвост
            СтрокаТовара.СуммаСкидки = ОстатокСкидки;
        Иначе
            СтрокаТовара.СуммаСкидки = СкидкаНаСтроку;
            ОстатокСкидки = ОстатокСкидки - СкидкаНаСтроку;
        КонецЕсли;
    КонецЦикла;
    
    // Шаг 4: Рассчитываем конечные суммы и НДС по каждой строке
    РаспределенныйИтог = 0;
    Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
        СтрокаТовара.Сумма = (СтрокаТовара.Цена * СтрокаТовара.Количество) - СтрокаТовара.СуммаСкидки;
        РаспределенныйИтог = РаспределенныйИтог + СтрокаТовара.Сумма;
    КонецЦикла;
    
    // Шаг 5: Проверка на соответствие целевому итогу (борьба с погрешностями округления)
    Погрешность = ИтогОкругленный - РаспределенныйИтог;
    Если Погрешность <> 0 Тогда
        // Корректируем строку с наибольшей суммой
        МаксСтрока = Неопределено;
        МаксСумма = 0;
        Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
            Если СтрокаТовара.Сумма > МаксСумма Тогда
                МаксСумма = СтрокаТовара.Сумма;
                МаксСтрока = СтрокаТовара;
            КонецЕсли;
        КонецЦикла;
        
        Если МаксСтрока <> Неопределено Тогда
            МаксСтрока.Сумма = МаксСтрока.Сумма + Погрешность;
        КонецЕсли;
    КонецЕсли;
    
    // Шаг 6: Финальный расчет НДС от скорректированной стоимости
    Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
        Если СтрокаТовара.СтавкаНДС = "18%" Тогда
            СтрокаТовара.СуммаНДС = Округлить(СтрокаТовара.Сумма * 18 / 118, 2);
        ИначеЕсли СтрокаТовара.СтавкаНДС = "20%" Тогда
            СтрокаТовара.СуммаНДС = Округлить(СтрокаТовара.Сумма * 20 / 120, 2);
        Иначе
            СтрокаТовара.СуммаНДС = 0;
        КонецЕсли;
        
        // Корректируем конечную цену для ККТ (чтобы Цена * Кол-во соответствовало Сумме)
        Если СтрокаТовара.Количество <> 0 Тогда
            СтрокаТовара.ЦенаККТ = Округлить(СтрокаТовара.Сумма / СтрокаТовара.Количество, 2);
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Передача подготовленных данных в драйвер АТОЛ

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


// Пример передачи подготовленных данных в драйвер АТОЛ v8/v10
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
    
    // Регистрация позиции с новой ценой, учитывающей округление
    Драйвер.Name = СтрокаТовара.Номенклатура;
    Драйвер.Price = СтрокаТовара.ЦенаККТ;
    Драйвер.Quantity = СтрокаТовара.Количество;
    
    // Указываем тип налога (например, 1 - НДС 18%, 2 - НДС 10% в зависимости от настроек ККТ)
    Драйвер.TaxTypeNumber = ПолучитьКодНалогаДляККТ(СтрокаТовара.СтавкаНДС);
    
    // В некоторых версиях драйвера можно явно передать рассчитанную сумму НДС
    // Драйвер.TaxSumm = СтрокаТовара.СуммаНДС; 
    
    Драйвер.Registration();
    
КонецЦикла;

// Регистрация оплаты и закрытие чека
Драйвер.Summ = ИтогОкругленный;
Драйвер.TypeClose = 0; // Наличные
Драйвер.Payment();

При таком подходе фискальный регистратор напечатает чек с красивой округленной суммой, а ФН рассчитает и отправит в ОФД абсолютно корректные данные по НДС, которые будут полностью совпадать с вашей Книгой продаж в 1С. Это исключит любые вопросы со стороны налоговых органов и избавит вас от необходимости исправлять расхождения вручную.

← На главную