При работе со старыми конфигурациями 1С, такими как «Управление торговлей 10.2» (и даже ранние релизы 10.3), разработчики часто сталкиваются с серьезной проблемой: штатные механизмы торгового оборудования давно не обновлялись и физически не поддерживают требования актуального законодательства (54-ФЗ, ФФД 1.05 и 1.2), а также новые модели оборудования. Попытки перенести подсистему торгового оборудования из современных конфигураций часто заканчиваются путаницей в коде и зря потраченным временем.
В этой статье мы подробно разберем, как подключить современный фискальный регистратор (на примере ККТ АТОЛ) к старой конфигурации напрямую через внешнюю компоненту, минуя сложные типовые механизмы. Мы пройдем весь путь: от инициализации компоненты в коде до решения проблем со скидками и округлениями, из-за которых ККТ часто аннулирует чеки.
В старых версиях конфигураций для работы с торговым оборудованием использовался метод ЗагрузитьВнешнююКомпоненту(). Этот метод часто дает сбои на современных операционных системах и требует обязательной регистрации библиотек в реестре Windows через утилиту regsvr32. Чтобы избежать этих проблем, мы рекомендуем использовать более надежный и современный метод платформы — ПодключитьВнешнююКомпоненту().
Для интеграции касс АТОЛ можно использовать два пути в зависимости от установленной версии драйверов торгового оборудования (ДТО):
AddIn.FprnM45 (или библиотеку FprnM1C82_54FZ.dll для совместимости с 54-ФЗ).AddIn.Fptr10.Рассмотрим пример инициализации драйвера в коде. Мы можем разместить этот код непосредственно в модуле формы документа «Чек ККМ» или в глобальном модуле для повторного использования:
// Попытка подключения компоненты ДТО 10
ПрогИД = "AddIn.Fptr10";
Подключено = ПодключитьВнешнююКомпоненту(ПрогИД);
Если Не Подключено Тогда
// Если десятая версия не установлена, пробуем подключить восьмую версию для совместимости
ПрогИД = "AddIn.FprnM45";
Подключено = ПодключитьВнешнююКомпоненту(ПрогИД);
КонецЕсли;
Если Подключено Тогда
Драйвер = Новый (ПрогИД);
Сообщить("Внешняя компонента ККМ успешно подключена!");
Иначе
ВызватьИсключение "Не удалось загрузить внешнюю компоненту ККМ. Проверьте установку драйверов!";
КонецЕсли;
Если при выполнении приведенного выше кода вы получаете ошибку «Не удалось загрузить внешнюю компоненту», выясним причину этой неполадки. В 90% случаев это связано с несовпадением разрядности технологической платформы 1С и установленного драйвера АТОЛ.
Старые конфигурации на обычных формах (УТ 10.2) запускаются под управлением 32-битного клиента 1С:Предприятие. Даже если у вас установлена 64-разрядная операционная система Windows, для работы с кассой вам необходимо скачать и установить именно 32-битный дистрибутив Драйвера ККТ АТОЛ (installer с суффиксом x86 или windows32). При установке драйвера все необходимые COM-объекты автоматически зарегистрируются в операционной системе, и ручной вызов утилиты regsvr32 не понадобится.
В сообщении форума автор столкнулся со сложностями при попытке настроить параметры подключения (номер COM-порта и скорость обмена) напрямую из кода. Рассмотрим, как это сделать правильно.
Если вы используете современный ДТО 10, параметры связи передаются объекту драйвера перед открытием соединения с помощью специальных методов. Это избавляет от необходимости предварительно настраивать кассу через утилиту «Тест драйвера ККТ»:
// Установка типа подключения (COM-порт)
Драйвер.setSingleSetting(Драйвер.LIBFPTR_SETTING_PORT, Строка(Драйвер.LIBFPTR_PORT_COM));
// Задаем номер порта и скорость обмена данными
Драйвер.setSingleSetting(Драйвер.LIBFPTR_SETTING_COM_PORT, "COM3"); // Укажите ваш порт, к которому подключена ККТ
Драйвер.setSingleSetting(Драйвер.LIBFPTR_SETTING_BAUDRATE, Строка(Драйвер.LIBFPTR_PORT_SPEED_115200));
// Применяем настройки и открываем сессию связи с устройством
Драйвер.applySingleSettings();
Драйвер.open();
Если Не Драйвер.isOpened() Тогда
Сообщить("Ошибка связи с ККТ: " + Драйвер.errorDescription());
КонецЕсли;
Если ККТ подключена по интерфейсу USB, современные драйверы поддерживают автоматический поиск устройства. Для этого достаточно указать тип порта USB:
Драйвер.setSingleSetting(Драйвер.LIBFPTR_SETTING_PORT, Строка(Драйвер.LIBFPTR_PORT_USB));
Драйвер.applySingleSettings();
Драйвер.open();
Очень распространенная ситуация при самостоятельной интеграции ККТ в старые конфигурации: касса начинает печатать чек, но в самом конце аннулирует его и выдает ошибку. Выясним причину этого поведения.
Современные кассовые аппараты, работающие по стандартам 54-ФЗ, производят жесткий арифметический контроль по каждой позиции чека. Должно соблюдаться строгое равенство до копейки:
(Цена * Количество) - Скидка = Сумма строки
В старых версиях «1С:Управление торговлей 10.2» расчет скидок в документе часто происходит по сложному алгоритму распределения накладных расходов или суммовых скидок на весь документ. В результате деления конечной суммы на количество товара могут получаться бесконечные периодические дроби (например, при продаже 3 штук товара на общую сумму 100 рублей цена одной штуки составит 33.3333... рублей). 1С округляет цену в чеке до двух знаков (33.33), перемножает на количество (3) и получает 99.99 рублей. Из-за расхождения в 1 копейку ККТ мгновенно бракует и аннулирует чек.
Проанализируем два надежных способа решения этой проблемы:
Самый простой и эффективный способ для старых конфигураций — передавать в ККТ позиции номенклатуры уже с учетом всех примененных скидок. То есть мы передаем в драйвер скорректированную конечную цену товара, а параметр «Скидка» всегда оставляем равным нулю.
Если при расчете цены со скидкой получается дробное значение копеек, мы можем программно разбить одну строку товара на несколько строк в чеке так, чтобы математические правила сошлись идеально.
Пример: Вместо передачи одной строки «Товар Х — 3 шт. по цене 33.3333 руб. на сумму 100 руб.», мы передаем в ККТ две строки:
Сумма чека сойдется идеально (66.66 + 33.34 = 100.00), и ККТ успешно напечатает фискальный документ.
По закону 54-ФЗ касса обязана содержать реквизиты кассира (ФИО и ИНН), а также иметь возможность отправки электронного чека покупателю (на email или телефон). Ниже приведен пример того, как передать эти данные в драйвер перед открытием документа.
// Передача ФИО и ИНН кассира (Обязательные теги 1021 и 1203)
Драйвер.setParam(Драйвер.LIBFPTR_PARAM_CASHIER_NAME, "Иванов Иван Иванович");
Драйвер.setParam(Драйвер.LIBFPTR_PARAM_CASHIER_INN, "771234567890");
Драйвер.operatorLogin();
// Передача контактов покупателя для отправки SMS или Email (Тег 1008)
// Значением может быть телефон в формате +79991112233 или адрес почты
КонтактПокупателя = "client@example.com";
Если Не ПустаяСтрока(КонтактПокупателя) Тогда
Драйвер.setParam(Драйвер.LIBFPTR_PARAM_CLIENT_CONTACT, КонтактПокупателя);
КонецЕсли;
Сведем все полученные знания в единую готовую процедуру, которую вы сможете вставить в модуль документа «Чек ККМ» вашей конфигурации «Управление торговлей 10.2».
Процедура ПробитьЧекНаККТ() Экспорт
// 1. Инициализация компоненты ДТО 10
Если Не ПодключитьВнешнююКомпоненту("AddIn.Fptr10") Тогда
Предупреждение("Компонента АТОЛ ДТО 10 не найдена на компьютере!");
Возврат;
КонецЕсли;
Касса = Новый COMОбъект("AddIn.Fptr10");
// 2. Настройка соединения
Касса.setSingleSetting(Касса.LIBFPTR_SETTING_PORT, Строка(Касса.LIBFPTR_PORT_USB));
Касса.applySingleSettings();
Касса.open();
Если Не Касса.isOpened() Тогда
Предупреждение("Не удалось открыть порт ККТ: " + Касса.errorDescription());
Возврат;
КонецЕсли;
Попытка
// 3. Регистрация кассира
Касса.setParam(Касса.LIBFPTR_PARAM_CASHIER_NAME, "Администратор");
Касса.operatorLogin();
// 4. Открытие чека (Тип чека: 1 - Приход, 2 - Возврат прихода)
Касса.setParam(Касса.LIBFPTR_PARAM_RECEIPT_TYPE, Касса.LIBFPTR_RT_SELL);
Касса.openReceipt();
// 5. Цикл по табличной части документа 1С
Для Каждого СтрокаТовара Из Товары Цикл
// Расчет чистой цены без копеечных погрешностей
КонечнаяЦена = Окр(СтрокаТовара.Сумма / СтрокаТовара.Количество, 2);
СуммаСтроки = КонечнаяЦена * СтрокаТовара.Количество;
// Регистрация позиции номенклатуры
Касса.setParam(Касса.LIBFPTR_PARAM_COMMODITY_NAME, СтрокаТовара.Номенклатура.Наименование);
Касса.setParam(Касса.LIBFPTR_PARAM_PRICE, КонечнаяЦена);
Касса.setParam(Касса.LIBFPTR_PARAM_QUANTITY, СтрокаТовара.Количество);
Касса.setParam(Касса.LIBFPTR_PARAM_POSITION_SUM, СуммаСтроки);
// Настройка ставки НДС (например, Без НДС - LIBFPTR_TAX_NO)
Касса.setParam(Касса.LIBFPTR_PARAM_TAX_TYPE, Касса.LIBFPTR_TAX_NO);
// Регистрация продажи позиции
Касса.registration();
КонецЦикла;
// 6. Регистрация оплаты (Тип оплаты: 1 - Электронные/Карта, 0 - Наличные)
// В примере регистрируем оплату наличными на общую сумму документа
Касса.setParam(Касса.LIBFPTR_PARAM_PAYMENT_TYPE, Касса.LIBFPTR_PT_CASH);
Касса.setParam(Касса.LIBFPTR_PARAM_PAYMENT_SUM, Итог("Сумма"));
Касса.payment();
// 7. Закрытие чека
Касса.closeReceipt();
Сообщить("Чек успешно пробит на ККТ!");
Исключение
// В случае ошибки отменяем документ на кассе, чтобы не заблокировать ФН
Касса.cancelReceipt();
Сообщить("Произошла ошибка при печати чека: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
// Закрываем соединение с устройством
Касса.close();
КонецПроцедуры
Используя данный подход, вы сможете гарантировать стабильное пробитие чеков на любой современной кассе АТОЛ напрямую из «1С:Управление торговлей 10.2», полностью контролируя процесс передачи данных и исключая влияние устаревших системных библиотек конфигурации.