При работе в программе «1С:Управление торговлей 11.4» (особенно в файловом режиме базы данных через терминальный доступ RDP) системные администраторы и программисты иногда сталкиваются с крайне неприятной проблемой. Кассир пробивает чек из рабочего места кассира (РМК), физический фискальный регистратор послушно печатает чек, но в самой программе 1С возникает ошибка блокировки транзакции. Документ на экране остается визуально непробитым. Кассир нажимает кнопку пробития повторно, касса выдает еще один бумажный чек, и только со второго раза документ успешно записывается в программе.
В результате такой ошибки происходит задвоение выручки на кассовом аппарате (что ведет к расхождениям с ОФД и налоговой), а при попытке открыть список чеков ККМ система выдает критическую ошибку: «Поле "Номер" не уникально» или аналогичные сообщения о неуникальности ключевых полей. Проанализируем детально причины этого сбоя и рассмотрим пошаговые методы его устранения и профилактики.
---
Для того чтобы понять природу ошибки, рассмотрим алгоритм работы Библиотеки подключаемого оборудования (БПО) 1С при отправке документа на печать:
ФискальныеОперации или НомераЧековККТ). Эта запись происходит во внешней (независимой) транзакции, которая сразу фиксируется в базе данных.ЧекККМ.Где происходит критический сбой? В файловых базах данных при одновременной работе нескольких пользователей (например, кассира и оператора, проводящего тяжелую реализацию) СУБД блокирует таблицы целиком. Если в момент выполнения шага №4 таблица документов заблокирована другим процессом, транзакция проведения документа ЧекККМ ожидает освобождения ресурса, превышает таймаут (по умолчанию 20 секунд) и откатывается (происходит Rollback).
При этом запись в регистре ФискальныеОперации, сделанная на шаге №3 в независимой транзакции, остается в базе данных. Для программы документ выглядит как непробитый, форма РМК не очищается, кнопка печати активна. Кассир нажимает кнопку повторно. Драйвер ККТ бьет второй физический чек, а 1С записывает вторую запись в регистр фискальных операций для этого же документа-основания. Со второй попытки транзакция документа проходит успешно.
Откуда берется ошибка уникальности номера? Список чеков в 1С строится на базе механизма динамического списка. Запрос этого списка соединяет (посредством оператора ЛЕВОЕ СОЕДИНЕНИЕ) основную таблицу документов ЧекККМ и таблицу регистра ФискальныеОперации. Поскольку для одного и того же документа в регистре теперь находятся две записи с разными номерами чеков, левое соединение возвращает две строки на один документ. Динамический список обнаруживает дублирование ключевого поля (ссылки на документ) и аварийно завершает работу с ошибкой неуникальности.
---
Чтобы вернуть кассиру возможность работать с журналом чеков ККМ, нам необходимо устранить дублирующую запись в регистре сведений. Разберем, как это сделать:
ВЫБРАТЬ
ФискальныеОперации.ДокументОснование КАК ПроблемныйДокумент,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ФискальныеОперации.НомерЧекаККТ) КАК КоличествоЗаписей
ИЗ
РегистрСведений.ФискальныеОперации КАК ФискальныеОперации
СГРУППИРОВАТЬ ПО
ФискальныеОперации.ДокументОснование
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ФискальныеОперации.НомерЧекаККТ) > 1
ФискальныеОперации.
ПроблемныйДокумент = Документы.ЧекККМ.НайтиПоНомеру("НомерВашегоЧека", ТекущаяДата());
НаборЗаписей = РегистрыСведений.ФискальныеОперации.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ДокументОснование.Установить(ПроблемныйДокумент);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 1 Тогда
// Удаляем самую первую запись (которая застряла при ошибке)
// Оставляем только ту, которая соответствует успешному проведению
НаборЗаписей.Удалить(0);
НаборЗаписей.Записать();
Сообщить("Дублирующая запись успешно удалена!");
КонецЕсли;
---
Поскольку конфигурация находится на поддержке и вносить изменения в типовой код нежелательно, рассмотрим системные и архитектурные решения проблемы блокировок.
Использование файлового режима для одновременной работы даже 2–3 активных пользователей в тяжелых конфигурациях на управляемых формах (УТ 11, КА 2, ERP) всегда сопряжено с рисками монопольных блокировок таблиц. Перевод базы данных под управление СУБД (PostgreSQL, MS SQL Server) кардинально меняет работу системы:
Если перевод на SQL невозможен, мы можем обойти ограничение изменения типовой конфигурации с помощью механизма Расширений. Создадим расширение, которое перехватывает попытку повторного пробития чека.
Рассмотрим логику работы расширения: перед вызовом процедуры печати чека мы делаем запрос к регистру ФискальныеОперации. Если запись для текущего документа уже существует и содержит заполненные фискальные реквизиты, мы блокируем отправку повторной команды на ФР и принудительно проводим документ в 1С.
Пример кода модуля расширения для защиты от повторной отправки:
&Перед("ПробитьЧек")
Процедура Расш_ПробитьЧекПеред(ДокументСсылка, Отказ)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ФискальныеОперации.НомерЧекаККТ КАК НомерЧека
|ИЗ
| РегистрСведений.ФискальныеОперации КАК ФискальныеОперации
|ГДЕ
| ФискальныеОперации.ДокументОснование = &ДокументОснование";
Запрос.УстановитьПараметр("ДокументОснование", ДокументСсылка);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Предупреждение("Внимание! Чек уже был фискализирован на кассе (Номер: " + Выборка.НомерЧека + "). Повторная печать заблокирована.");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Работа кассира напрямую в тяжелой центральной базе по RDP — это всегда риск задержек сети и конфликтов блокировок. Разумным архитектурным решением является создание локальной кассовой базы:
Если бюджет ограничен и необходимо оперативно снизить частоту возникновения транзакционных ошибок в файловом режиме, выполните следующие административные действия:
1Cv8.1CD расположен на скоростном твердотельном накопителе (SSD NVMe) сервера. Медленные жесткие диски (HDD) увеличивают время фиксации транзакций в разы.Применение данных методик позволит оперативно устранить последствия сбоя ККТ и гарантировать стабильную работу кассового узла без риска повторных блокировок.