В практике разработки в среде «1С:Предприятие 8» часто возникает задача жесткого контроля за печатью документов. Особенно остро эта проблема стоит при автоматизации складской логистики и маркировки продукции, когда пользователю (например, кладовщику или оператору упаковки) требуется распечатать ровно один экземпляр этикетки на принтере этикеток. Свободная повторная печать может привести к пересортице, дублированию штрихкодов или злоупотреблениям.
В этой статье мы подробно разберем, почему стандартные диалоговые окна операционной системы не позволяют решить эту задачу, и выстроим надежную программно-аппаратную архитектуру защиты от повторной печати.
Если мы просто выводим сформированный макет на экран пользователя с помощью метода Показать(), система предоставляет пользователю полный доступ к стандартному командному интерфейсу платформы. Пользователь может:
Для предотвращения этих действий нам понадобится комплексный подход, состоящий из ограничения прав платформы, прямой отправки макета на принтер и фиксации события печати в базе данных.
Для того чтобы пользователь не мог сохранить документ на диск или скопировать его содержимое, мы должны программно запретить вывод табличного документа во внешние источники. В платформе «1С:Предприятие» за это отвечает свойство Вывод объекта ТабличныйДокумент.
Рассмотрим пример кода, в котором мы инициализируем макет и жестко блокируем для него возможность копирования и сохранения:
// Создаем табличный документ для формирования этикетки
ТабДок = Новый ТабличныйДокумент;
// Заполняем параметры макета и выводим области
// ... (код формирования макета)
// Блокируем стандартные интерактивные функции платформы
ТабДок.Вывод = ИспользованиеВывода.Запретить;
Когда свойство Вывод установлено в значение ИспользованиеВывода.Запретить, у пользователя при просмотре табличного документа на экране кнопки «Печать», «Предварительный просмотр» и «Сохранить» в главном меню программы станут неактивными.
Важное примечание: Если вам требуется ограничить права пользователя глобально во всей системе, лучшим решением будет снять флажок с роли пользователя в Конфигураторе для права «Вывод». В этом случае пользователь вообще не сможет сохранять файлы из 1С на диск, если в коде явно не прописано обратное (ИспользованиеВывода.Разрешить).
Чтобы исключить возможность ручного изменения количества копий, мы должны полностью отказаться от показа табличного документа на экране монитора. Программа должна отправить документ напрямую на принтер.
Рассмотрим, как реализовать моментальную отправку на печать одной копии:
// Настраиваем параметры печати табличного документа
ТабДок.ИмяПринтера = "Zebra_TLP2844"; // Указываем точное имя принтера в системе
ТабДок.КоличествоКопий = 1; // Жестко ограничиваем тираж одной копией
// Отправляем документ на печать без вывода диалогового окна Windows
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
Параметр РежимИспользованияДиалогаПечати.НеИспользовать гарантирует, что система не покажет стандартное окно настроек принтера, в котором пользователь мог бы вручную исправить цифру «1» в поле «Количество копий».
Для того чтобы система «помнила» о том, что документ уже распечатывался, нам понадобится создать в конфигураторе независимый непериодический Регистр сведений. Назовем его ИсторияПечатиДокументов.
Настроим структуру регистра следующим образом:
ДокументСсылка (тип данных: ссылка на контролируемый документ, например, ДокументСсылка.ЗаказПокупателя).Пользователь (тип данных: СправочникСсылка.Пользователи).ДатаПечати (тип данных: Дата, состав даты: Время и Дата).Рассмотрим логику работы кнопки печати на форме. Перед отправкой макета на принтер нам необходимо выполнить запрос к регистру сведений. Если запись о печати данного документа уже существует, мы блокируем действие.
&НаСервере
Функция ДокументУжеРаспечатан(СсылкаНаДокумент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИсторияПечати.ДокументСсылка КАК ДокументСсылка
|ИЗ
| РегистрСведений.ИсторияПечатиДокументов КАК ИсторияПечати
|ГДЕ
| ИсторияПечати.ДокументСсылка = &ДокументСсылка";
Запрос.УстановитьПараметр("ДокументСсылка", СсылкаНаДокумент);
РезультатЗапроса = Запрос.Выполнить();
Возврат Не РезультатЗапроса.Пустой();
КонецФункции
&НаСервере
Процедура ЗафиксироватьФактПечати(СсылкаНаДокумент)
МенеджерЗаписи = РегистрыСведений.ИсторияПечатиДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ДокументСсылка = СсылкаНаДокумент;
МенеджерЗаписи.Пользователь = Пользователи.ТекущийПользователь();
МенеджерЗаписи.ДатаПечати = ТекущаяДата();
// Записываем информацию в базу данных
МенеджерЗаписи.Записать(Истина);
КонецПроцедуры
Теперь объединим проверку и печать в один общий обработчик нажатия кнопки на клиенте:
&НаКлиенте
Процедура КомандаПечать(Команда)
СсылкаНаДокумент = Объект.Ссылка;
// Проверяем, печатался ли документ ранее
Если ДокументУжеРаспечатан(СсылкаНаДокумент) Тогда
ПоказатьПредупреждение(, "Этот документ уже был распечатан! Повторная печать запрещена.");
Возврат;
КонецЕсли;
// Формируем табличный документ на сервере
ТабДок = СформироватьМакетНаСервере(СсылкаНаДокумент);
// Отправляем на принтер напрямую
ТабДок.Напечатать(РежимИспользованияДиалогаПечати.НеИспользовать);
// Записываем информацию о выполненной операции в регистр
ЗафиксироватьФактПечати(СсылкаНаДокумент);
ПоказатьОповещениеПользователя("Успешно", , "Документ отправлен на печать", БиблиотекаКартинок.Информация);
КонецПроцедуры
На практике физические принтеры часто выходят из строя: заминается бумага, заканчивается красящая лента (риббон), засоряется печатающая головка или происходит сбой питания. Если документ физически не напечатался, а система уже заблокировала повторный вызов, процесс работы склада остановится.
Рассмотрим два основных архитектурных решения этой проблемы:
Для повторной печати рядовой сотрудник должен обратиться к старшему смены или администратору, у которого в настройках прав (ролях) нет ограничений на количество копий. Программа при попытке повторной печати может выводить окно ввода пароля администратора:
&НаСервереБезКонтекста
Функция ПроверитьПарольАдминистратора(ВведенныйПароль)
// Проверка соответствия пароля ответственного лица в базе данных
// Возвращает Истина, если авторизация успешна
КонецФункции
Если бизнес-процесс допускает повторную печать, но требует обязательной визуальной идентификации копии, мы можем программно модифицировать макет при повторном обращении. Если запись в регистре найдена, мы выводим на этикетку фоновую надпись или крупный текст «ДУБЛИКАТ» или «КОПИЯ №...». Это позволит использовать наклеенную этикетку повторно, но защитит от подлога оригинального документа.
Опытные пользователи могут попытаться обойти ограничения 1С на уровне операционной системы Windows. Проанализируем эти уязвимости и перекроем их:
Напечатать()). Если макет не отображается на мониторе, сделать его снимок невозможно.Многие ведущие специалисты по автоматизации учета рекомендуют переносить логику контроля уникальности с момента печати на момент использования (сканирования) штрихкода.
Рассмотрим, как работает эта схема:
Такой подход полностью снимает проблему замятия бумаги на принтере и гарантирует 100% защиту от повторного использования копий документов без усложнения интерфейса печати для пользователей.