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