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