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