Как подключить кассы АТОЛ напрямую к 1С 7.7 без XML: решаем проблему с номерами чеков, скидками и авансами

Программист 1С v7.7 Налоговый учет Торговля и дистрибуция
← На главную

При переходе на новые форматы фискальных данных (ФФД 1.05 и выше) многие разработчики 1С 7.7 сталкиваются с тем, что стандартные двухслойные обработки от 1С (использующие XML-прокладки) начинают некорректно отображать налоговые ставки или избыточно усложняют схему взаимодействия с ККТ. В такой ситуации логичным решением становится прямой обход «прослоек» и работа с оборудованием напрямую через драйвер АТОЛ (в частности, ДТО 8, использующий OLE-объект FprnM45 или FptrM8).

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

Часть 1. Как получить реальный «Номер чека за смену» и «Номер ФД»

В старых версиях прошивок ККТ и ДТО свойство драйвера CheckNumber возвращало привычный порядковый номер чека внутри текущей смены. Однако с переходом на онлайн-кассы и ФФД 1.05 логика работы изменилась: это свойство зачастую начинает возвращать сквозной номер фискального документа (ФД) с момента активации фискального накопителя, либо возвращает некорректные данные.

Для того чтобы получить точные фискальные показатели чека непосредственно после его закрытия с помощью метода CloseCheck(), мы должны обратиться к внутренним регистрам ККТ. Проанализируем, как это сделать программно в среде 1С 7.7.

Выясним причину путаницы. В новых прошивках сквозной номер документа хранится в 51-м регистре, а данные о текущей смене и количестве пробитых документов — в 53-м регистре. Давайте разберем по шагам, как вытащить эти параметры:


// Создаем объект драйвера ККТ (если он еще не создан)
Если ФС.СуществуетФайл(КаталогИБ() + "FprnM45.dll") = 1 Тогда
    ЗагрузитьВнешнююКомпоненту(КаталогИБ() + "FprnM45.dll");
КонецЕсли;
ОбъектECR = СоздатьОбъект("AddIn.FprnM45");

// ... код открытия чека и добавления позиций ...
// ... успешное выполнение метода CloseCheck() ...

// Шаг 1. Получаем номер Фискального Документа (ФД) и Фискальный Признак (ФП) из регистра 51
ОбъектECR.RegisterNumber = 51;
ОбъектECR.GetRegister();

НомерФД = ОбъектECR.НомерДокумента; // Сквозной номер документа в ФН
ФискальныйПризнак = ОбъектECR.ФискальныйПризнак; // ФПД документа

// Шаг 2. Получаем реальный порядковый номер чека за смену из регистра 53
ОбъектECR.RegisterNumber = 53;
ОбъектECR.GetRegister();

// Свойство Count в 53-м регистре хранит количество документов за текущую смену
НомерЧекаЗаСмену = ОбъектECR.Count; 
НомерСмены = ОбъектECR.Session; // Дополнительно можем зафиксировать номер смены

Сообщить("Чек успешно пробит!");
Сообщить("Номер смены: " + НомерСмены);
Сообщить("Порядковый номер чека за смену: " + НомерЧекаЗаСмену);
Сообщить("Фискальный документ №: " + НомерФД);
Сообщить("ФП: " + ФискальныйПризнак);

Важное примечание для бухгалтерии: В соответствии с требованиями ФНС для экономии кассовой ленты новые шаблоны чеков на ККТ АТОЛ могут по умолчанию не выводить на печать номер чека за смену, даже если касса его фиксирует. В ОФД эти данные отправляются в обязательном порядке. Если вашим бухгалтерам или клиентам критически важно видеть номер чека на бумажном носителе, вам потребуется изменить шаблон оформления в самой кассе с помощью утилиты «Редактор шаблонов АТОЛ».

Часть 2. Решение ошибки «Чек оплачен не полностью» (ResultCode = -3897) при авансах

Рассмотрим ситуацию: предприятие принимает аванс или предоплату от покупателя. При попытке пробить чек на сумму аванса (которая меньше полной стоимости товара/услуги) касса возвращает ошибку ResultCode = -3897 с описанием «Чек оплачен не полностью». Выясним, почему это происходит.

Логика работы современных онлайн-касс требует жесткого математического соответствия: итоговая сумма всех зарегистрированных позиций в чеке должна до копейки совпадать с суммой переданных оплат. Если вы регистрируете товар стоимостью 10 000 рублей, а метод Payment() вызываете только на сумму аванса 4 000 рублей, касса заблокирует закрытие чека из-за возникшего расхождения в 6 000 рублей.

Для правильного оформления чеков с частичной оплатой, авансами или кредитами в ФФД 1.05 мы должны использовать комбинацию признаков способа расчета PaymentMode и типов закрытия чека TypeClose.

Разберем доступные значения свойства PaymentMode (признак способа расчета для позиции чека):

  1. 1 — Полная предварительная оплата (до момента передачи товара).
  2. 2 — Частичная предварительная оплата (до момента передачи товара).
  3. 3 — Аванс.
  4. 4 — Полный расчет (производится в момент передачи товара с учетом ранее внесенного аванса).
  5. 5 — Частичный расчет и кредит (передача товара с частичной оплатой и отсрочкой).
  6. 6 — Передача в кредит (отгрузка без оплаты в момент передачи).
  7. 7 — Оплата кредита (погашение ранее взятого долга).

Разберем доступные значения свойства TypeClose (варианты оплаты при закрытии чека):

Посмотрим на практический пример решения задачи. Допустим, мы отгружаем товар стоимостью 5 000 рублей. Покупатель закрывает 1 000 рублей ранее внесенным авансом (предоплатой), а оставшиеся 4 000 рублей доплачивает наличными в момент получения товара.

В этом случае признак способа расчета для товара должен быть равен 4 (Полный расчет), а сумма чека в 5 000 рублей должна быть закрыта двумя платежами: зачетом аванса и наличными. Напишем рабочий код для 1С 7.7:


// Инициализируем документ на ККТ
ОбъектECR.NewDocument();
ОбъектECR.Mode = 1;
ОбъектECR.SetMode();
ОбъектECR.CheckType = 1; // Чек прихода
ОбъектECR.CheckMode = 1; // Фискальный чек
ОбъектECR.OpenCheck();

// Регистрация товарной позиции
ОбъектECR.BeginItem();
ОбъектECR.Name = "Телевизор ЖК";
ОбъектECR.Price = 5000.00;
ОбъектECR.Quantity = 1;
ОбъектECR.Summ = 5000.00;

// Указываем, что это товар (ItemType = 1)
ОбъектECR.ItemType = 1; 

// Указываем признак способа расчета: Полная оплата с учетом аванса (PaymentMode = 4)
ОбъектECR.PaymentMode = 4; 

ОбъектECR.Department = 0;
ОбъектECR.TaxTypeNumber = 3; // Укажите ваш номер налоговой ставки
ОбъектECR.EndItem();

// ВАЖНО: Сумма по позициям = 5000.00. Мы должны распределить ее целиком по типам оплат!

// 1. Отражаем зачет ранее внесенного аванса (TypeClose = 2) на сумму 1000 руб.
ОбъектECR.TypeClose = 2; // Предварительная оплата (зачет аванса)
ОбъектECR.Summ = 1000.00;
ОбъектECR.Payment();

// 2. Отражаем доплату наличными (TypeClose = 0) на сумму 4000 руб.
ОбъектECR.TypeClose = 0; // Наличные
ОбъектECR.Summ = 4000.00;
ОбъектECR.Payment();

// Закрываем чек. Теперь касса примет документ без ошибки -3897
ОбъектECR.CloseCheck();

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

Часть 3. Как правильно работать со скидками в ФФД 1.05

Проанализируем еще одно существенное изменение законодательства, коснувшееся работы со скидками. В старых версиях драйверов АТОЛ программисты часто использовали встроенные свойства драйвера DiscountValue и DiscountType для автоматического распределения скидки по позициям чека силами самой кассы.

Начиная с ФФД 1.05, использование данных свойств ККТ запрещено или не рекомендуется производителем. Кассовый аппарат больше не должен самостоятельно рассчитывать распределение скидок. Всю математику необходимо производить на стороне товароучетной системы (в нашем случае — в 1С 7.7).

Рекомендуемый алгоритм работы со скидками выглядит следующим образом:

  1. В модуле проведения чека в 1С 7.7 мы самостоятельно рассчитываем конечную цену позиции с учетом всех примененных скидок и бонусов.
  2. Округляем полученное значение цены до двух знаков после запятой (до копеек).
  3. Передаем в свойства драйвера Price (Цена) и Summ (Сумма) уже очищенные, готовые значения.
  4. Если покупателю необходимо наглядно продемонстрировать размер предоставленной скидки, мы выводим эту информацию в чек в виде обычных информационных (нефискальных) текстовых строк с помощью методов PrintString().

Рассмотрим, как красиво оформить такой чек в коде:


// Пример расчета цены со скидкой на стороне 1С 7.7
ЦенаБезСкидки = 150.00;
ПроцентСкидки = 10; // 10%
СуммаСкидки = Окр(ЦенаБезСкидки * ПроцентСкидки / 100, 2);
КонечнаяЦена = ЦенаБезСкидки - СуммаСкидки;

ОбъектECR.BeginItem();
ОбъектECR.Name = "Концентрат универсальный";
ОбъектECR.Price = КонечнаяЦена; // Передаем итоговую цену: 135.00
ОбъектECR.Quantity = 1;
ОбъектECR.Summ = КонечнаяЦена;
ОбъектECR.TaxTypeNumber = 3;
ОбъектECR.EndItem();

// Выводим нефискальный текст для информирования покупателя
ОбъектECR.Caption = "В том числе скидка 10%: " + СокрЛП(СуммаСкидки) + " руб.";
ОбъектECR.PrintString();
ОбъектECR.Caption = "Цена товара без скидки: " + СокрЛП(ЦенаБезСкидки) + " руб.";
ОбъектECR.PrintString();

Часть 4. Переход на ДТО 10 и подготовка к ФФД 1.2

Разработчикам, поддерживающим решения на базе платформы 1С 7.7, важно смотреть на перспективу. Драйвер АТОЛ 8-й версии (ДТО 8) официально признан устаревшим и больше не развивается производителем. Он не поддерживает требования маркировки товаров («Честный Знак») и новый формат фискальных данных ФФД 1.2.

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

Подключение 10-го драйвера к 1С 7.7 реализуется через COM-объект нового поколения. Проанализируем базовый пример инициализации объекта ДТО 10:


Попытка
    // Инициализируем COM-объект ДТО 10
    Драйвер10 = СоздатьОбъект("AddIn.Fptr10");
Исключение
    Предупреждение("Не удалось загрузить драйвер АТОЛ ДТО 10! Проверьте регистрацию библиотеки fptr10.dll.");
    Возврат;
КонецПопытки;

// Настройка связи с кассой выполняется через передачу JSON-параметров или свойств объекта
Драйвер10.setSingleSetting(Драйвер10.LIBFPTR_SETTING_MODEL, Строка(Драйвер10.LIBFPTR_MODEL_ATOL_AUTO));
Драйвер10.setSingleSetting(Драйвер10.LIBFPTR_SETTING_PORT, Строка(Драйвер10.LIBFPTR_PORT_USB));
Драйвер10.applySingleSettings();

// Соединение с устройством
Драйвер10.open();

Если Драйвер10.isOpened() = 0 Тогда
    Сообщить("Касса не подключена!", "!");
Иначе
    Сообщить("Успешное подключение к ККТ через ДТО 10!");
    // Закрываем соединение при завершении работы
    Драйвер10.close();
КонецЕсли;

Переход на ДТО 10 позволяет использовать все преимущества современных операционных систем (включая стабильную работу в 64-битных средах и RDP-сессиях), а также гарантирует полное соответствие вашего торгового решения на базе проверенной временем платформы 1С 7.7 актуальным требованиям фискального законодательства РФ.

← На главную