При работе в 1С:ERP Управление предприятием версии 2.5 (особенно в релизах ветки 2.5.7) пользователи часто сталкиваются с критической ошибкой при печати чеков на ККТ: "Сумма всех типов оплаты меньше итога чека". Ситуация выглядит парадоксально: клиент платит одну сумму, а в предпросмотре чека или в логах драйвера ККТ итоговая сумма позиций оказывается значительно выше. В этой статье мы подробно разберем, почему возникает этот программный сбой, как работает механизм распределения оплат и как устранить проблему с помощью программной доработки.
Рассмотрим типичный сценарий, который приводит к ошибке. Предположим, у нас есть клиент, который уже получил услуги, но еще не оплатил их. Мы выполняем следующие действия в системе:
Проанализируем, что происходит "под капотом" системы в проблемных релизах. Вместо того чтобы разделить 15 рублей на две части (10 и 5), алгоритм фискализации включает в чек:
В результате Итого по позициям получается 25 рублей (5 + 5 + 15), в то время как Оплата наличными составляет всего 15 рублей. Кассовый аппарат блокирует печать такого чека, так как нарушается математическая логика ФФД (формата фискальных данных).
Проблема кроется в работе общего модуля, отвечающего за формирование структуры данных для ККТ. В норме процедура ПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс должна корректировать сумму аванса, вычитая из нее те части, которые уже были распределены как оплата кредита. Однако в определенных версиях 1С:ERP этот механизм работает некорректно, и сумма документа оплаты попадает в чек целиком, игнорируя факт частичного закрытия задолженности.
Это происходит из-за того, что система пытается одновременно обработать и отгруженные ранее позиции (которые теперь оплачиваются), и остаток средств, который еще не привязан к конкретным товарам. В итоге сумма "задваивается".
Если вы столкнулись с этой проблемой, и обновление конфигурации на более свежий патч или релиз (например, 2.5.8) сейчас невозможно, необходимо внедрить исправление через механизм расширений. Мы перехватим процедуру обработки данных чека и принудительно скорректируем суммы.
Рассмотрим алгоритм решения: нам нужно найти в массиве позиций чека все строки с признаком ОплатаКредита и вычесть их общую сумму из строк с признаком Аванс. Посмотрим на пример кода, который реализует эту логику:
&После("ПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс")
Процедура упрПривестиДанныеКТребуемомуФорматуПозицийЧекаПоДокументамОплатыАванс(Знач ПараметрыФискальногоЧека, ПозицииЧека, СуммыАвансовПоСтавкамНДС)
Оплаты = Новый Массив;
Получатели = Новый Массив;
// Шаг 1: Распределяем позиции на "Оплаты" (авансы) и "Получатели" (погашение кредита)
ВсегоШагов = ПозицииЧека.Количество()-1;
Для ТекШаг = 0 По ВсегоШагов Цикл
ТекПозиция = ПозицииЧека[ТекШаг];
Если ТекПозиция.ПризнакПредметаРасчета <> Перечисления.ПризнакиПредметаРасчета.ПлатежВыплата Тогда
Продолжить;
КонецЕсли;
Если ТекПозиция.ПризнакСпособаРасчета = Перечисления.ПризнакиСпособаРасчета.ОплатаКредита Тогда
Получатели.Добавить(ТекПозиция);
ИначеЕсли ТекПозиция.ПризнакСпособаРасчета = Перечисления.ПризнакиСпособаРасчета.Аванс Тогда
Оплаты.Добавить(ТекПозиция);
КонецЕсли;
КонецЦикла;
// Шаг 2: Если есть и то, и другое — проводим корректировку
Если Оплаты.Количество() = 0 или Получатели.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для каждого ТекПолучатель Из Получатели Цикл
НетОплат = Истина;
Для каждого ТекОплата Из Оплаты Цикл
Если ТекОплата.Сумма = 0 Тогда
Продолжить;
КонецЕсли;
НетОплат = Ложь;
// Вычисляем сумму, которую нужно вычесть из аванса
СуммаКорректировки = Мин(ТекПолучатель.Сумма, ТекОплата.Сумма);
// Уменьшаем сумму аванса и пересчитываем цену
ТекОплата.Сумма = ТекОплата.Сумма - СуммаКорректировки;
ТекОплата.Цена = ТекОплата.Сумма / ТекОплата.Количество;
ТекОплата.ЦенаСоСкидками = ТекОплата.Сумма / ТекОплата.Количество;
// Не забываем про НДС, если он есть
Если ТекОплата.СуммаНДС <> Неопределено и ТекПолучатель.СуммаНДС <> Неопределено Тогда
СуммаНДС = Мин(ТекПолучатель.СуммаНДС, ТекОплата.СуммаНДС);
ТекОплата.СуммаНДС = ТекОплата.СуммаНДС - СуммаНДС;
КонецЕсли;
КонецЦикла;
Если НетОплат Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Проанализируем ситуацию после применения кода. Мы берем наши 15 рублей аванса и видим, что в чеке уже присутствуют позиции "Оплата кредита" на 10 рублей. Программа вычитает 10 из 15. В итоге в ПозицииЧека передаются следующие данные:
Итог чека: 15 рублей. Сумма позиций теперь в точности равна сумме оплаты. ККТ успешно принимает такой чек и печатает его без ошибок.
Если вы не хотите вносить изменения в программный код, рассмотрим другие варианты обхода проблемы:
1С:Обновление программ. Фирма "1С" выпускала исправления для модуля МенеджерОфлайнОборудования, которые устраняют данную ошибку в типовом коде.Важный нюанс: при использовании приведенного выше программного кода обязательно протестируйте его на копии базы. Особое внимание уделите случаям с разными ставками НДС, так как ручная корректировка СуммаНДС в коде должна строго соответствовать правилам округления вашего драйвера кассового аппарата.