При настройке прав пользователей в платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с задачей разграничения доступа к отдельным полям экранной формы. Типичная бизнес-ситуация: сотруднику разрешено просматривать чужие документы, но редактировать ключевые параметры (например, сумму платежного поручения) он должен только в тех документах, которые создал лично сам. При этом часть реквизитов вовсе должна быть закрыта от ручных правок.
В платформе 1С 7.7 отсутствует механизм ограничения доступа на уровне записей и полей (RLS), привычный разработчикам по версии 8. Поэтому любые подобные задачи решаются исключительно программным путем в модуле формы или модуле самого документа. Рассмотрим по шагам, почему в коде возникают синтаксические ошибки при проверке автора и как правильно настроить управление доступностью элементов формы.
Разберем типичную ошибку, с которой столкнулся автор вопроса при попытке проверить авторство:
Если( глПользователь <> Автор.Документ.ПлатежноеПоручение() = "Бухгалтер_по_платежам") Тогда
Форма.Сумма.Доступность(1);
КонецЕсли;
При попытке сохранения модуля платформа выдает синтаксическую ошибку Ожидается символ ')'. Выясним причину такого поведения встроенного языка:
А <> Б = В синтаксически некорректна. Операторы сравнения не могут следовать подряд без логических связок И / ИЛИ.Автор.Документ.ПлатежноеПоручение() не имеет смысла в объектной модели 1С 7.7. Реквизит Автор в модуле формы документа уже доступен напрямую как переменная контекста документа или через точку от ссылки. Попытка вызвать имя вида документа через круглые скобки приводит к аварийному завершению синтаксического анализатора.глПользователь в типовых конфигурациях обычно содержит ссылку на элемент справочника (например, Справочник.Пользователи), тогда как "Бухгалтер_по_платежам" является обычной строкой. Нельзя напрямую сравнивать ссылку и строковый литерал.Проанализируем базовый сценарий, когда ограничение накладывается в предопределенной процедуре ПриОткрытии() формы документа ПлатежноеПоручение.
Логика работы строится следующим образом: сначала для целевого пользователя блокируются все запрещенные к изменению реквизиты (включая реквизит Сумма), а затем выполняется проверка авторства. Если текущий пользователь совпадает с автором документа, доступность поля Сумма возвращается в активное состояние.
Посмотрим на пример кода, предложенный на форуме и доработанный автором:
Процедура ПриОткрытии()
// Проверяем, относится ли текущий сеанс к нужному пользователю
Если ИмяПользователя() = "Бухгалтер_по_платежам" Тогда
// Блокируем поля, которые пользователю запрещено менять в любом случае
Форма.ДатаДок.Доступность(0);
Форма.НомерДок.Доступность(0);
Форма.СуммаНДС.Доступность(0);
Форма.СтавкаНДС.Доступность(0);
// По умолчанию закрываем редактирование суммы
Форма.Сумма.Доступность(0);
// Если автор совпадает с текущим пользователем — открываем сумму для правок
Если СокрЛП(Автор) = ИмяПользователя() Тогда
Форма.Сумма.Доступность(1);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим подробнее нюансы, которые могут нарушить работу приведенного выше простого условия:
Автор имеет тип Справочник.Пользователи. При вызове функции СокрЛП(Автор) платформа неявно преобразует ссылку в строковое наименование элемента. Если наименование в справочнике отличается хотя бы одним регистром, пробелом или содержит полное ФИО сотрудника, а системный логин (возвращаемый функцией ИмяПользователя()) является коротким сетевым именем, условие СокрЛП(Автор) = ИмяПользователя() вернет Ложь.глПользователь, более надежно сравнивать именно ссылки объектов:
Если Автор = глПользователь Тогда
Форма.Сумма.Доступность(1);
КонецЕсли;
Выбран() возвращает 0. Если реквизит Автор заполняется только в процедуре ВводНового() или ПриЗаписи(), на момент открытия он может оказаться пустым. В результате бухгалтер не сможет ввести сумму даже в создаваемый им документ. Поэтому важно предусмотреть проверку на новый объект:
Если (Выбран() = 0) ИЛИ (Автор = глПользователь) Тогда
Форма.Сумма.Доступность(1);
КонецЕсли;
СуммаНДС). Если поле НДС заблокировано жестко через Доступность(0), сумма НДС должна автоматически пересчитываться при изменении основной суммы в обработчике реквизита.Важно помнить, что отключение доступности элементов через метод Форма.<Реквизит>.Доступность(0) работает только в диалоговом окне. Пользователь может обойти визуальное ограничение с помощью групповой обработки документов или сторонних внешних обработок. Кроме того, жесткое кодирование логина "Бухгалтер_по_платежам" непосредственно в модуле делает конфигурацию уязвимой при смене сотрудника или переименовании учетной записи.
Для создания полноценной защиты разберем более надежный алгоритм проверки, выполняемый в предопределенной процедуре ПриЗаписи() в модуле документа:
Процедура ПриЗаписи()
// Заполняем автора для нового документа, если он еще не задан
Если ПустоеЗначение(Автор) = 1 Тогда
Автор = глПользователь;
КонецЕсли;
// Если документ уже был ранее записан в базу, контролируем изменение суммы
Если Выбран() = 1 Тогда
// Проверяем роль или конкретного пользователя
Если ИмяПользователя() = "Бухгалтер_по_платежам" Тогда
// Создаем объект для чтения первоначального состояния документа из базы
ДокБаза = СоздатьОбъект("Документ.ПлатежноеПоручение");
Если ДокБаза.НайтиДокумент(ТекущийДокумент()) = 1 Тогда
// Проверяем, изменилась ли сумма и является ли пользователь автором
Если (ДокБаза.Сумма <> Сумма) И (ДокБаза.Автор <> глПользователь) Тогда
Предупреждение("Вам запрещено изменять сумму в документах других авторов!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой подход гарантирует, что пользователь не сможет перезаписать чужой документ с измененной финансовой частью, даже если визуальная блокировка на форме по какой-либо причине не сработала.