Почему 1С:Управление торговлей 10.3 не передает сумму скидки в кассовый аппарат АТОЛ и как это исправить

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

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

В этой статье мы подробно разберем, почему возникает данная проблема, рассмотрим требования законодательства (ФФД) и логику Библиотеки подключаемого оборудования (БПО), а также дадим пошаговые инструкции, как исправить эту ситуацию в коде 1С и настройках ККТ.

---

Выясняем причину: логика БПО 1С и требования ФНС

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

  1. Требования ФФД (Формата фискальных документов) 1.05 и 1.2: Согласно актуальному законодательству, в фискальном документе обязательно должна быть указана конечная цена товара уже с учетом всех примененных скидок и наценок. Параметры PriceWithDiscount (цена со скидкой) и SumWithDiscount (сумма со скидкой) являются ключевыми для ОФД и налоговой службы. Сама же сумма скидки носит справочный характер для покупателя.
  2. Проблема копеечного округления: Это наиболее частая техническая проблема. Если 1С передает в ККТ цену без скидки, количество и сумму скидки (DiscountSum), то математический процессор кассы пытается самостоятельно рассчитать конечную стоимость позиции на своей стороне. При продаже дробного количества товара (например, весового товара) или при сложных процентах округления в 1С и алгоритмах кассы могут разойтись на 1 копейку. В результате кассовый аппарат возвращает аппаратную ошибку «Неверная цена (сумма)» или «Невозможно начислить скидку», блокируя пробитие чека.

Чтобы избежать постоянных сбоев на кассовых узлах, разработчики 1С в актуальных версиях БПО принудительно обнуляют или оставляют пустым параметр DiscountSum в XML-пакете чека. Касса просто регистрирует продажу по уже рассчитанной в 1С конечной цене товара.

---

Шаг 1. Проверка версии драйвера и шаблона чека в кассе

Прежде чем вносить изменения в программный код 1С, рассмотрим аппаратные настройки связки оборудования:

---

Шаг 2. Корректировка XML-пакета чека в коде 1С:УТ 10.3

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

В конфигурации «Управление торговлей 10.3» формирование XML-структуры чека происходит либо во встроенных общих модулях интеграции с торговым оборудованием, либо во внешней обработке обслуживания ККТ (например, ATOLkkt.epf). Нам необходимо найти функцию, которая собирает данные для фискализации — обычно она называется ПолучитьXMLПакетДляФискализацииЧека или СформироватьXMLПакетЧека.

Рассмотрим подробнее фрагмент кода, отвечающий за заполнение параметров товарной позиции (узла FiscalString):


// В типовом коде БПО атрибут DiscountSum часто передается пустым:
ЗаписьXML.ЗаписатьАтрибут("DiscountSum", "");

Чтобы касса увидела скидку, нам нужно рассчитать ее значение для каждой строки и передать в XML-структуру. Модифицируем этот участок кода следующим образом:


// Рассчитываем сумму скидки как разницу между исходной стоимостью и конечной суммой строки
ЦенаБезСкидки = ТекущаяСтрока.ЦенаБезСкидки; // Проверьте имя реквизита в вашей ТЧ
КоличествоТовара = ТекущаяСтрока.Количество;
КонечнаяСумма = ТекущаяСтрока.Сумма;

СуммаСкидки = (ЦенаБезСкидки * КоличествоТовара) - КонечнаяСумма;

Если СуммаСкидки > 0 Тогда
    // Форматируем число для передачи в XML без лишних пробелов и с 2 знаками после запятой
    ЗаписьXML.ЗаписатьАтрибут("DiscountSum", XMLСтрока(СуммаСкидки));
Иначе
    ЗаписьXML.ЗаписатьАтрибут("DiscountSum", "0.00");
КонецЕсли;

Важное предупреждение: При активации данного механизма будьте готовы к тому, что при продаже весового или акционного товара со сложными копейками кассовый аппарат начнет периодически выдавать ошибки округления ФН и аннулировать чеки.

---

Шаг 3. Безопасное решение — Вывод скидки текстовой строкой

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

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

Проанализируем пример реализации данного метода в цикле обхода строк чека:


// В цикле формирования позиций чека перед записью элемента FiscalString
СуммаСкидки = (ТекущаяСтрока.ЦенаБезСкидки * ТекущаяСтрока.Количество) - ТекущаяСтрока.Сумма;

Если СуммаСкидки > 0 Тогда
    // Добавляем нефискальную строку с описанием скидки для покупателя
    ЗаписьXML.ЗаписатьНачалоЭлемента("TextString");
    ТекстСкидки = " * Скидка по акции: " + Формат(СуммаСкидки, "ЧДЦ=2; ЧГ=0") + " руб.";
    ЗаписьXML.ЗаписатьАтрибут("Text", ТекстСкидки);
    ЗаписьXML.ЗаписатьКонецЭлемента(); // TextString
КонецЕсли;

// Далее идет стандартная запись фискальной строки по конечной цене
ЗаписьXML.ЗаписатьНачалоЭлемента("FiscalString");
ЗаписьXML.ЗаписатьАтрибут("Name", ТекущаяСтрока.Номенклатура.Наименование);
ЗаписьXML.ЗаписатьАтрибут("Quantity", XMLСтрока(ТекущаяСтрока.Количество));
ЗаписьXML.ЗаписатьАтрибут("PriceWithDiscount", XMLСтрока(ТекущаяСтрока.Цена));
ЗаписьXML.ЗаписатьАтрибут("SumWithDiscount", XMLСтрока(ТекущаяСтрока.Сумма));
ЗаписьXML.ЗаписатьАтрибут("DiscountSum", ""); // Оставляем пустым для избежания ошибок ККТ
// ... заполнение остальных атрибутов
ЗаписьXML.ЗаписатьКонецЭлемента(); // FiscalString

Этот способ является наиболее предпочтительным в современной розничной торговле, так как обеспечивает 100% стабильность работы кассовой смены и полностью закрывает потребность в информировании покупателей о выгоде покупки прямо на чековой ленте.

← На главную