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