В процессе работы торговых точек на базе конфигурации 1С:Розница 2.2 (и более поздних версий) после обновления платформы, конфигурации или драйверов торгового оборудования пользователи часто сталкиваются с неприятной проблемой. При пробитии чека на кассовом аппарате (ККТ) внезапно возникает ошибка: «Тег "Оплата" не заполнен». При этом повторная попытка пробития того же чека обычно проходит успешно, но ошибка продолжает стабильно воспроизводиться несколько раз в день или «через раз».
Особенно остро эта проблема проявляется в распределенных информационных базах (РИБ) на периферийных кассовых узлах. В этой статье мы подробно разберем природу данной ошибки, выясним техническую причину её возникновения и рассмотрим надежное программное решение, которое навсегда избавит ваших кассиров от этого сбоя.
Для начала проанализируем ситуацию и поймем, как этот процесс устроен изнутри. Ошибка связана с передачей фискальных данных на ККТ. Согласно формату фискальных документов (ФФД), каждый чек должен содержать информацию о типе оплаты (наличные, безналичные, аванс и т.д.). За это отвечает соответствующий тег в структуре XML-пакета, отправляемого драйверу ККТ.
Многие системные администраторы начинают решать проблему «в лоб»: обновляют прошивку кассового аппарата, переустанавливают драйверы (например, переходят на ДТО АТОЛ 9.x или 10.x), перенастраивают параметры связи. Однако это приносит лишь временное облегчение или не помогает вовсе. На самом деле корень проблемы лежит на стыке поведения пользователя (кассира) и особенностей интерфейса 1С.
Проанализируем пошагово действия кассира и реакцию системы в момент сбоя:
ОплатитьТовары. Но поскольку платежные данные для текущего чека уже были отправлены в ККТ и очищены в оперативной памяти программы, система пытается инициировать транзакцию с «пустой» таблицей оплат.Почему в распределенных базах (РИБ) эта ошибка возникает гораздо чаще? Ответ прост: компьютеры на кассовых точках в розничных магазинах зачастую уступают по производительности серверу основной базы. Небольшие задержки (лаги) при выполнении кода 1С увеличивают то самое «временное окно» между отправкой чека на печать и полной блокировкой интерфейса. Это дает кассиру больше времени на то, чтобы случайно совершить повторное нажатие клавиши.
Если вы хотите убедиться, что проблема именно в этом, рекомендуем изучить файлы логов драйвера ККТ. Например, для драйверов АТОЛ 9-й версии лог-файл располагается по пути:
C:\Users\[ИмяПользователя]\AppData\Roaming\ATOL\drivers9\logs\fptr1c_log.txt
Проанализировав временные метки (timestamp) отправки команд в логе, вы увидите, что команды фискализации чека и вызовы методов драйвера происходят дублировано с разницей в доли секунды. Это подтверждает теорию о «двойном клике» кассира.
Самый простой совет кассирам — «не нажимать Enter дважды и дожидаться печати чека» — на практике работает плохо. В условиях высокой нагрузки и очередей человеческий фактор победить устными инструкциями невозможно. Поэтому проблему необходимо решать на программном уровне.
Нам нужно сделать так, чтобы при первом же нажатии кнопки оплаты фокус ввода мгновенно уходил с этой кнопки на любой нейтральный элемент формы РМК, который не вызывает никаких действий при нажатии Enter (например, на декоративную картинку, неактивную надпись или кнопку главного меню).
Для реализации этого решения лучше всего использовать механизм расширений конфигурации. Это позволит сохранить конфигурацию 1С на поддержке и избежать сложностей при последующих обновлениях программы.
Разберем процесс создания решения по шагам:
ФиксОшибкиОплаты), синоним и назначение — Адаптация. Нажмите ОК.РМКУправляемыйРежим (или аналогичную обработку РМК, используемую в вашей версии конфигурации).ФормаРМК).Теперь нам нужно перехватить вызов процедуры оплаты. В форме РМК за этот процесс отвечает процедура ОплатитьТовары. Мы добавим обработчик &Перед, который будет выполняться самым первым при вызове оплаты.
Рассмотрим пример кода, который необходимо поместить в модуль заимствованной формы расширения:
&Перед("ОплатитьТовары")
Процедура Расш1_ПередОплатитьТовары(Параметр1 = Неопределено, Параметр2 = Неопределено)
// Выясним причину вызова и перенесем фокус ввода на декоративный элемент формы.
// В стандартном РМК в качестве нейтрального элемента отлично подходит картинка меню.
Попытка
ТекущийЭлемент = Элементы.КартинкаЧО01Меню;
Исключение
// Если элемент с таким именем отсутствует в вашей версии формы,
// перенаправьте фокус на любой другой доступный неактивный элемент.
СистематизироватьЛогОшибки = Истина;
КонецПопытки;
КонецПроцедуры
Проанализируем, как работает этот код. В момент, когда кассир нажимает клавишу Enter для подтверждения оплаты, система активирует обработчик ОплатитьТовары. Программа заходит в нашу процедуру &Перед и мгновенно переназначает свойство формы ТекущийЭлемент. Фокус клавиатуры уходит с кнопки подтверждения платежа на элемент КартинкаЧО01Меню.
Если в следующую миллисекунду кассир совершает повторное нажатие клавиши Enter, это нажатие уходит «в пустоту» — декоративная картинка не имеет обработчиков нажатия и никак не реагирует. Повторный запуск процедуры фискализации чека блокируется. Чек печатается штатно, без ошибок ККТ.
После сохранения расширения запустите базу в пользовательском режиме и протестируйте работу кассы. Ошибка «Тег "Оплата" не заполнен» больше не побеспокоит ваших сотрудников, а пробитие чеков станет стабильным даже на медленных компьютерах розничной сети.