При работе в конфигурации «1С:Управление торговлей 10.3» на обычных формах пользователи часто сталкиваются с крайне неприятной ситуацией. Кассир создает документ Чек ККМ, заполняет его товарами, нажимает кнопку пробития, фискальный регистратор (ККТ) успешно печатает чек, и данные уходят в ОФД. Однако, если после этого форму документа не закрывать, она остается полностью доступной для редактирования. Кассир может изменить номенклатуру, цены, количество товаров или скидки, после чего спокойно перезаписать документ. При этом в базе 1С сохранятся измененные данные, тогда как покупателю будет выдан чек с первоначальным составом, и в ОФД уйдут совсем другие суммы.
В этой статье мы подробно разберем, почему возникает такое поведение системы, какие серьезные риски оно в себе несет, и рассмотрим практические способы устранения этой уязвимости с примерами программного кода.
---
Для того чтобы понять суть проблемы, давайте проанализируем, как работает логика блокировки элементов формы в типовой конфигурации «Управление торговлей 10.3».
В обычных формах за защиту документа от редактирования отвечает проверка реквизита ЧекПробит. Если этот флаг установлен в значение Истина, форма должна переходить в режим «Только чтение». Однако разработчики типовой конфигурации реализовали эту проверку только в обработчиках событий ПриОткрытии или ПередОткрытием формы документа Чек ККМ.
Давайте восстановим хронологию действий пользователя и программы:
ПриОткрытии. Реквизит ЧекПробит равен Ложь, поэтому форма открывается в режиме редактирования.ЧекПробит принимает значение Истина.ПриОткрытии повторно не вызывается. В результате элементы формы (кнопки, табличная часть, поля ввода) остаются активными для изменения.Если же форму закрыть и открыть заново — сработает событие ПриОткрытии, система увидит, что ЧекПробит равен Истина, и заблокирует форму для редактирования. Таким образом, уязвимость существует только в интервале времени между фактическим пробитием чека и моментом закрытия диалогового окна кассиром.
---
Оставлять эту ситуацию без внимания крайне опасно по двум ключевым причинам:
1. Расхождение данных с ОФД и налоговыми органами. В ОФД и ФНС уходит информация, зафиксированная на ККТ в момент пробития. Если после этого документ в 1С будет отредактирован и перезаписан, в вашей учетной системе останутся совершенно другие цифры. Любая налоговая проверка или сверка данных выявит эти грубые расхождения.
2. Угроза злоупотреблений со стороны персонала. Недобросовестный кассир получает легальный инструмент для кражи денежных средств. Схема выглядит просто: клиенту пробивают товар на сумму 10 000 рублей, берут наличные и отдают чек ККТ. Затем, не закрывая форму документа, кассир удаляет часть позиций или уменьшает цену, снижая сумму чека в 1С до 2 000 рублей, и сохраняет документ. Разницу в 8 000 рублей кассир забирает себе. При инвентаризации остатков и сверке кассовой смены в 1С все сойдется, так как по базе прошел документ именно на 2 000 рублей.
---
Мы можем устранить эту уязвимость несколькими путями. Давайте детально разберем каждый из них.
Самое быстрое и логичное решение — доработать модуль формы документа Чек ККМ. Нам нужно сделать так, чтобы сразу после успешной печати чека на ККТ форма либо закрывалась автоматически, либо принудительно переводилась в режим просмотра.
Для этого найдем в модуле формы процедуру, которая отвечает за проведение и пробитие чека (как правило, это обработчик нажатия кнопки «Пробить»). В конце этой процедуры, сразу после успешного вызова фискализации и записи документа, нам нужно добавить программное управление состоянием формы.
Рассмотрим пример реализации такого кода:
// Фрагмент обработчика пробития чека в модуле формы документа
Процедура ОсновныеДействияФормыПробить(Кнопка)
// ... Выполняется типовой алгоритм проведения документа и печати чека ...
// Допустим, переменная "ЧекУспешноПечатан" возвращает Истина после работы с ККТ
Если ЧекПробит Тогда
// Вариант А: Принудительное закрытие формы (наиболее надежный и частый сценарий)
ЭтаФорма.Закрыть();
// Вариант Б: Блокировка элементов формы без её закрытия, если кассиру нужно видеть экран
// ЭтаФорма.ТолькоПросмотр = Истина;
КонецЕсли;
КонецПроцедуры
Преимущества: Простота реализации. Кассир физически теряет возможность что-либо изменить на экране сразу после того, как ККТ выдаст бумажную ленту.
---
Метод работы с формой (Способ 1) защищает нас от действий пользователя на клиенте. Но подготовленный пользователь или программист все равно может программно изменить или перезаписать проведенный чек ККМ в обход экранной формы (например, используя групповую обработку справочников и документов или внешнюю обработку). Чтобы перекрыть эту лазейку раз и навсегда, мы должны внедрить защиту на уровне транзакции записи объекта.
Для этого откроем Модуль объекта документа ЧекККМ и добавим жесткую проверку в предопределенную процедуру ПередЗаписью. Наша задача — запретить запись документа, если он уже был пробит ранее, за исключением одного-единственного случая: когда запись инициирована самим процессом фискализации чека.
Рассмотрим, как это выглядит на практике:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем, существует ли документ уже в базе (не новый ли он)
Если ЗначениеЗаполнено(Ссылка) Тогда
// Получаем текущее состояние реквизита "ЧекПробит" непосредственно из базы данных
// Это исключает обход проверки через подмену реквизитов в памяти
СтарыйСтатусПробит = Ссылка.ЧекПробит;
// Если чек уже был пробит ранее, запрещаем любые изменения,
// кроме случая, когда запись идет непосредственно из процедуры пробития чека ККТ
Если СтарыйСтатусПробит И НЕ ДополнительныеСвойства.Свойство("РазрешитьЗаписьПробитогоЧека") Тогда
Отказ = Истина;
ВызватьИсключение "Ошибка записи! Данный чек ККМ уже был пробит на ККТ. Изменение проведенных и пробитых чеков запрещено конфигурацией!";
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Теперь в модуле формы документа (или в общем модуле), где происходит непосредственное пробитие чека по кассе и его финальная фискальная запись, нам нужно временно разрешать эту запись, взводя специальный флаг в структуре ДополнительныеСвойства объекта:
// Пример кода в процедуре фискализации перед вызовом Записать()
ДокументОбъект = Ссылка.ПолучитьОбъект();
ДокументОбъект.ДополнительныеСвойства.Вставить("РазрешитьЗаписьПробитогоЧека", Истина);
ДокументОбъект.ЧекПробит = Истина;
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Преимущества: Это абсолютная защита данных (на уровне СУБД/бизнес-логики). Ни один пользователь, ни одна групповая обработка не сможет исказить данные пробитого чека.
---
Если вы хотите решить проблему без вмешательства в программный код конфигурации (что особенно важно, если ваша база находится на поддержке и вы не хотите усложнять процесс последующих обновлений), мы рекомендуем перевести работу кассиров на специализированный интерфейс — «Рабочее место кассира» (РМК).
Давайте проанализируем, почему работа в РМК безопасна:
Чеки ККМ, кассир в РМК не открывает форму отдельного документа напрямую.Для настройки этого режима достаточно назначить пользователям-продавцам соответствующий интерфейс и ограничить их права на прямое открытие списка документов через стандартное меню «Документы — Розница — Чеки ККМ».
---
Описанное поведение программы в «1С:Управление торговлей 10.3» — это классический пример компромисса проектирования интерфейсов на обычных формах. Безопасность ваших кассовых данных целиком зависит от того, закрывает ли кассир форму вовремя.
Мы настоятельно рекомендуем выполнить доработку системы с использованием Способа 1 (быстрое закрытие формы на клиенте) в связке со Способом 2 (контроль записи на уровне объекта), либо полностью перевести продажи на интерфейс РМК. Это позволит вам полностью ликвидировать риски расхождения отчетности с ОФД и предотвратить возможные злоупотребления со стороны персонала.