При работе с онлайн-кассами «Штрих-М» через платформу 1С 7.7 программисты часто сталкиваются с загадочным поведением: касса периодически «теряет» позиции в чеке. Чаще всего не печатается первая строка, а вторая и последующие выходят нормально. При этом итоговая сумма оплаты и сдача на чеке могут быть верными, что приводит к расхождению между фискальным документом и фактической продажей. Проанализируем ситуацию и разберем по шагам, как исправить программный код для стабильной работы.
Разберем типичную ошибку в алгоритме. В большинстве случаев код написан так, что проверка кода ошибки (ResultCode) происходит только в самом конце, после вызова метода CloseCheck(). Рассмотрим пример проблемного кода:
// Ошибочный подход
ДокОснование.ВыбратьСтроки();
Пока ДокОснование.ПолучитьСтроку() > 0 Цикл
глФР.Quantity = ДокОснование.Количество;
глФР.Price = Окр(ДокОснование.Сумма / ДокОснование.Количество, 2);
глФР.Sale(); // Команда может вернуть ошибку, но цикл пойдет дальше
КонецЦикла;
глФР.CloseCheck();
ОтветДрайвера(); // Проверка только в конце!
Если при регистрации первой позиции произошла ошибка (например, из-за некорректной цены, превышения длины наименования или таймаута связи), метод Sale() вернет ненулевое значение. Однако программа проигнорирует это и перейдет к следующей строке. В итоге вторая позиция регистрируется успешно, чек закрывается, и драйвер в конце сообщает, что «Ошибок нет», так как последняя операция (закрытие чека) прошла удачно.
Решение: необходимо внедрить проверку ResultCode сразу после каждого вызова Sale(). Если команда не выполнена, нужно прерывать цикл и выводить сообщение об ошибке, иначе чек будет фискализирован не полностью.
Проанализируем техническую особенность драйверов «Штрих-М». В новых версиях прошивок под ФФД 1.05 и 1.2 критически важен порядок установки свойств объекта драйвера перед вызовом метода продажи. Опытные разработчики отмечают, что свойство StringForPrinting (наименование товара) должно устанавливаться до цены и количества, либо быть первым в списке параметров.
Выясним причину: современные аппараты воспринимают текст, переданный в StringForPrinting до команды Sale(), именно как наименование товарной позиции для передачи в ОФД. Если передать его после числовых параметров или в конце, оно может быть интерпретировано как «рекламный текст», а позиция уйдет в фискальный накопитель с пустым названием или вовсе будет отвергнута кассой.
Рассмотрим правильный порядок заполнения свойств:
ДокОснование.ВыбратьСтроки();
Пока ДокОснование.ПолучитьСтроку() > 0 Цикл
глФР.Password = 30;
// Сначала устанавливаем наименование
глФР.StringForPrinting = СокрЛП(ДокОснование.Номенклатура.Наименование);
глФР.Quantity = ДокОснование.Количество;
глФР.Price = Окр(ДокОснование.Сумма / ДокОснование.Количество, 2);
глФР.Tax1 = 1; // Укажите актуальную ставку НДС
глФР.Sale();
// Обязательная проверка после каждой строки!
Если глФР.ResultCode <> 0 Тогда
Сообщить("Ошибка при печати позиции: " + глФР.ResultCodeDescription);
глФР.CancelCheck(); // Аннулируем чек в случае сбоя
Возврат;
КонецЕсли;
КонецЦикла;
Метод Sale() является «наследием» старых протоколов. Для современных онлайн-касс (Ф-модели, Штрих-М-01Ф и др.) рекомендуется использовать методы, специально предназначенные для работы с Фискальным Накопителем (ФН). Рассмотрим использование команд FNOperation() и FNCloseCheckEx().
Эти методы позволяют передавать расширенные атрибуты, требуемые законодательством (признак способа расчета, предмет расчета и т.д.). Использование FNOperation повышает стабильность передачи данных в ФН. Посмотрим на пример реализации с учетом новых команд:
// Внутри цикла продажи
глФР.ItemType = 1; // Товар
глФР.PaymentType = 4; // Полный расчет
глФР.FNOperation(); // Регистрация операции в ФН
Перед закрытием чека также рекомендуется использовать FNCloseCheckEx(), который более корректно обрабатывает финализацию документа в контексте передачи данных в ОФД.
Проанализируем ситуацию, когда Цена * Количество не совпадает с итоговой суммой строки. В 1С 7.7 часто хранятся только Сумма и Количество, а цена вычисляется делением. При округлении до 2 знаков может возникнуть погрешность в копейку. Современные кассы «Штрих-М» жестко контролируют математику чека. Если касса при перемножении цены на количество получает результат, отличный от переданной суммы, она может вернуть ошибку «Сумма позиций не совпадает с суммой оплаты».
Если вы не проверяете ResultCode после первой позиции, и касса её отвергла из-за копеечного расхождения, она просто «проглотит» вторую позицию, а на оплату выставит общую сумму чека. В итоге получится чек с одной позицией, но огромной суммой оплаты, где разница уйдет в сдачу.
Совет: Всегда проверяйте, чтобы Окр(Цена * Количество, 2) == СуммаСтроки. Если есть расхождение, корректируйте цену или используйте скидки/надбавки на уровне драйвера для выравнивания суммы.
Если касса подключена через USB-кабель в режиме RNDIS (эмуляция сетевой карты), операционная система Windows может переводить этот «сетевой адаптер» в режим энергосбережения при бездействии. Рассмотрим, что происходит: когда вы нажимаете кнопку «Пробить чек», первая команда Sale() уходит в канал связи, который только начинает «просыпаться». Команда теряется или возвращается по таймауту. Вторая позиция идет следом, когда канал уже активен, и она печатается успешно.
Чтобы исключить этот фактор, выполните следующие действия:
SHTRIH-M RNDIS...).Для надежной печати чеков в 1С 7.7 на аппаратах Штрих-М выполните следующие шаги:
во-первых, обеспечьте очистку строки наименования от спецсимволов (кавычки, лишние слеши), во-вторых, строго соблюдайте последовательность установки свойств (сначала текст, потом цифры), и в-третьих, внедрите обязательную проверку ResultCode после каждой значимой команды драйвера.
Пример надежной функции проверки:
Процедура ПроверитьОшибкуФР(Контекст)
Если глФР.ResultCode <> 0 Тогда
Сообщить("Ошибка ФР: " + глФР.ResultCodeDescription, "!");
СтатусВозврата(0);
Прервать;
КонецЕсли;
КонецПроцедуры
Такой системный подход позволит избежать ситуаций, когда кассир выдает покупателю неполный чек, а данные в фискальном накопителе не соответствуют учетным данным в базе 1С.