Почему в 1С:ERP сумма позиций в чеке превышает сумму оплаты и как это исправить?

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

При работе в 1С:ERP Управление предприятием версии 2.5 (особенно в релизах ветки 2.5.7) пользователи часто сталкиваются с критической ошибкой при печати чеков на ККТ: "Сумма всех типов оплаты меньше итога чека". Ситуация выглядит парадоксально: клиент платит одну сумму, а в предпросмотре чека или в логах драйвера ККТ итоговая сумма позиций оказывается значительно выше. В этой статье мы подробно разберем, почему возникает этот программный сбой, как работает механизм распределения оплат и как устранить проблему с помощью программной доработки.

Разбор ситуации: откуда берется "лишняя" сумма

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

  1. Оформляем Акт выполненных работ на общую сумму 10 рублей (две услуги по 5 рублей). На этом этапе в системе фиксируется задолженность клиента (кредит).
  2. Клиент приходит в кассу и вносит 15 рублей наличными. Мы создаем Приходный кассовый ордер (ПКО).
  3. Программа должна понимать: 10 рублей из этой суммы идут на погашение старого долга (Оплата кредита), а оставшиеся 5 рублей остаются как предоплата на будущее (Аванс).

Проанализируем, что происходит "под капотом" системы в проблемных релизах. Вместо того чтобы разделить 15 рублей на две части (10 и 5), алгоритм фискализации включает в чек:

В результате Итого по позициям получается 25 рублей (5 + 5 + 15), в то время как Оплата наличными составляет всего 15 рублей. Кассовый аппарат блокирует печать такого чека, так как нарушается математическая логика ФФД (формата фискальных данных).

Выясняем причину программного сбоя

Проблема кроется в работе общего модуля, отвечающего за формирование структуры данных для ККТ. В норме процедура ПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс должна корректировать сумму аванса, вычитая из нее те части, которые уже были распределены как оплата кредита. Однако в определенных версиях 1С:ERP этот механизм работает некорректно, и сумма документа оплаты попадает в чек целиком, игнорируя факт частичного закрытия задолженности.

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

Программное решение: используем расширение

Если вы столкнулись с этой проблемой, и обновление конфигурации на более свежий патч или релиз (например, 2.5.8) сейчас невозможно, необходимо внедрить исправление через механизм расширений. Мы перехватим процедуру обработки данных чека и принудительно скорректируем суммы.

Рассмотрим алгоритм решения: нам нужно найти в массиве позиций чека все строки с признаком ОплатаКредита и вычесть их общую сумму из строк с признаком Аванс. Посмотрим на пример кода, который реализует эту логику:


&После("ПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс")
Процедура упрПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс(Знач ПараметрыФискальногоЧека, ПозицииЧека, СуммыАвансовПоСтавкамНДС)
    
    Оплаты = Новый Массив;  
    Получатели = Новый Массив;
    
    // Шаг 1: Распределяем позиции на "Оплаты" (авансы) и "Получатели" (погашение кредита)
    ВсегоШагов = ПозицииЧека.Количество()-1;
    Для ТекШаг = 0 По ВсегоШагов Цикл
    
        ТекПозиция = ПозицииЧека[ТекШаг];
        
        Если ТекПозиция.ПризнакПредметаРасчета <> Перечисления.ПризнакиПредметаРасчета.ПлатежВыплата Тогда
            Продолжить;
        КонецЕсли;  
        
        Если ТекПозиция.ПризнакСпособаРасчета = Перечисления.ПризнакиСпособаРасчета.ОплатаКредита Тогда
            Получатели.Добавить(ТекПозиция);    
        ИначеЕсли ТекПозиция.ПризнакСпособаРасчета = Перечисления.ПризнакиСпособаРасчета.Аванс Тогда    
            Оплаты.Добавить(ТекПозиция);    
        КонецЕсли;
        
    КонецЦикла;
   
    // Шаг 2: Если есть и то, и другое — проводим корректировку
    Если Оплаты.Количество() = 0 или Получатели.Количество() = 0 Тогда
        Возврат;    
    КонецЕсли;

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

Как работает это решение?

Проанализируем ситуацию после применения кода. Мы берем наши 15 рублей аванса и видим, что в чеке уже присутствуют позиции "Оплата кредита" на 10 рублей. Программа вычитает 10 из 15. В итоге в ПозицииЧека передаются следующие данные:

  1. Услуга 1 (Кредит) — 5 руб.
  2. Услуга 2 (Кредит) — 5 руб.
  3. Аванс — 5 руб. (вместо исходных 15).

Итог чека: 15 рублей. Сумма позиций теперь в точности равна сумме оплаты. ККТ успешно принимает такой чек и печатает его без ошибок.

Альтернативные способы решения

Если вы не хотите вносить изменения в программный код, рассмотрим другие варианты обхода проблемы:

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

← На главную