При автоматизации розничной торговли с использованием кассового оборудования Атол, подключенного через веб-сервис (Atol Online или локальный драйвер с веб-интерфейсом), разработчики часто сталкиваются с неприятной ошибкой: "Чек закрыт, операция не возможна". Эта проблема особенно обостряется в периоды высокой нагрузки (праздники) или при попытке пробить чеки с большим количеством позиций, особенно если товары подлежат обязательной маркировке («Честный ЗНАК»).
Рассмотрим природу этой ошибки, проанализируем технические ограничения протоколов и выясним, как правильно настроить систему и доработать код в 1С, чтобы избежать подобных сбоев.
Ошибка «Чек закрыт» при использовании веб-сервиса Атол коварна тем, что она является следствием, а не первопричиной. Проанализируем основные факторы, которые приводят к такому состоянию системы:
DataMatrix, который значительно «раздувает» размер запроса. Если в чеке более 100-130 позиций с маркировкой, размер JSON гарантированно превысит лимит, и запрос будет отклонен или обработан некорректно.Таймаут записи или Request Timeout в настройках веб-сервиса установлен на стандартные 5-10 секунд, 1С разрывает соединение, не дождавшись ответа. Однако касса в это время может продолжать печатать чек. При повторной попытке отправить тот же запрос, система видит, что документ уже фискализирован (или находится в процессе), и выдает ошибку «Чек закрыт».Если бизнес-процесс предполагает продажу большого ассортимента одному физическому лицу, самым надежным решением будет принудительное разбиение одного документа на несколько чеков. Разберем, как реализовать логику контроля количества позиций.
Проанализируем пример кода, который ограничивает количество строк в одном пакете для отправки на кассу:
// Определяем максимально допустимое количество строк с маркировкой
МаксКоличествоСтрок = 80;
ВсегоСтрок = Объект.Товары.Количество();
ТекущаяСтрока = 0;
Пока ТекущаяСтрока < ВсегоСтрок Цикл
// Формируем массив позиций для части чека
МассивПозиций = Новый Массив;
Для Итератор = 1 По МаксКоличествоСтрок Цикл
Если ТекущаяСтрока >= ВсегоСтрок Тогда
Прервать;
КонецЕсли;
СтрокаТовара = Объект.Товары[ТекущаяСтрока];
// Логика добавления товара в JSON-структуру...
МассивПозиций.Добавить(СформироватьСтруктуруПозиции(СтрокаТовара));
ТекущаяСтрока = ТекущаяСтрока + 1;
КонецЦикла;
// Отправляем сформированную часть чека на кассу
Результат = ОтправитьЧекНаВебСервисАтол(МассивПозиций);
Если Не Результат.Успех Тогда
ВызватьИсключение "Ошибка при пробитии части чека: " + Результат.ОписаниеОшибки;
КонецЕсли;
КонецЦикла;
Важно: При разделении чека необходимо учитывать, что каждый такой документ будет фискально независимым. Это может создать сложности при возврате товара, так как клиенту придется выдать несколько чеков вместо одного.
Чтобы избежать ситуации, когда 1С «отваливается» раньше, чем касса успевает ответить, необходимо увеличить параметры ожидания. Рассмотрим, где это настраивается:
Таймаут чтения и Таймаут записи не менее 30 000 мс (30 секунд). Для очень длинных чеков рекомендуется 60 000 мс.atol-service.ini или settings.json в папке сервиса) и проверьте параметры requestTimeout.Чтобы не получать ошибку «Чек закрыт», мы должны научить нашу систему проверять, не был ли пробит чек на самом деле, если произошел сетевой сбой. Посмотрим на алгоритм действий:
Перед каждой отправкой чека (особенно в блоке Попытка...Исключение) рекомендуется запрашивать состояние последнего фискального документа. В драйвере Атол за это отвечают методы получения статуса ККТ.
// Псевдокод проверки статуса перед пробитием
СтатусККТ = ПолучитьСтатусПоследнегоДокумента(Касса);
// Если номер последнего ФД в кассе совпадает с тем, что мы пытаемся записать,
// значит чек уже пробит, и отправлять его повторно нельзя.
Если СтатусККТ.НомерПоследнегоФД = МойРегистрируемыйНомер Тогда
ЗафиксироватьУспехВБазе(МойДокумент);
Возврат;
КонецЕсли;
// Если чек не найден, пробуем отправить данные
Попытка
Результат = Касса.СформироватьЧек(ДанныеJSON);
Исключение
// В случае ошибки связи не спешим выводить ошибку пользователю,
// а проверяем статус снова через паузу
Приостановить(2);
// Повторная проверка статуса...
КонецПопытки;
Проанализируем особенности работы с кодами маркировки, которые влияют на стабильность:
UTF-8, каждый символ может занимать более 1 байта. Проверяйте размер строки JSON перед отправкой функцией СтрДлина() или ПолучитьТелоЗапроса().Размер().Таким образом, для решения проблемы «Чек закрыт» требуется комплексный подход: увеличение таймаутов на стороне драйвера, программное ограничение количества позиций в 1С и обязательная проверка статуса ККТ после возникновения любой ошибки связи.