Как запретить ручную запись в регистр сведений и оставить только программный ввод из справочника

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки в среде «1С:Предприятие 8» часто возникает классическая задача: необходимо организовать хранение информации в регистре сведений таким образом, чтобы все записи создавались исключительно программно (например, при записи элемента определенного справочника). При этом пользователи ни в коем случае не должны иметь возможности зайти напрямую в форму списка этого регистра и вручную добавить, отредактировать или удалить строки.

В этой статье мы подробно разберем, как правильно реализовать подобное ограничение. Мы проанализируем различные подходы — от настройки прав доступа на уровне метаданных до манипуляций с управляемыми формами и программного контроля транзакций.

Метод 1. Разграничение прав доступа и использование привилегированного режима

Это наиболее надежный, «чистый» и рекомендуемый платформой способ решения задачи. Он базируется на механизме ролей и не требует написания сложного кода для блокировки интерфейса.

Выясним, как это работает на практике. В конфигураторе 1С для нужного регистра сведений в настройках ролей пользователей выполним следующие действия:

  1. Откроем роль, назначенную обычным пользователям.
  2. Найдем в списке объектов наш регистр сведений.
  3. Снимем галочку с права «Интерактивное добавление» (или полностью снимем права на «Изменение», оставив только «Чтение» и «Просмотр»).

Если убрать право Интерактивное добавление, кнопка «Создать» автоматически исчезнет из формы списка и формы записи регистра для этого пользователя. При этом программная запись под этой ролью все еще будет доступна, если она вызывается стандартным образом.

Если же мы полностью забираем у пользователя права на изменение регистра, то при попытке записать в него данные из справочника система выдаст ошибку нарушения прав доступа. Чтобы обойти это ограничение, программную запись из модуля справочника необходимо выполнять в привилегированном режиме.

Рассмотрим пример кода, который вызывается в модуле справочника для безопасной программной записи в регистр под управлением привилегированного модуля:


// Этот код должен располагаться в общем модуле с установленными свойствами "Сервер" и "Привилегированный"
Процедура ЗаписатьДанныеВРегистрПривилегированно(ПараметрыЗаписи) Экспорт
    
    НаборЗаписей = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Владелец.Установить(ПараметрыЗаписи.Владелец);
    
    НоваяСтрока = НаборЗаписей.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, ПараметрыЗаписи);
    
    // Запись происходит в привилегированном режиме, проверки прав игнорируются
    НаборЗаписей.Записать();
    
КонецПроцедуры

Метод 2. Блокировка изменений на уровне свойств управляемой формы

Если по каким-то причинам изменять права доступа в ролях нежелательно, мы можем ограничить действия пользователя непосредственно на форме списка регистра сведений. Рассмотрим, какие настройки формы помогут нам решить задачу без программирования.

Откроем форму списка регистра сведений в конфигураторе и настроим следующие свойства:

  1. Изменять состав строк: Снимем этот флаг у таблицы динамического списка на форме. После этого действия кнопки «Добавить», «Скопировать» и «Удалить» станут недоступны для пользователя в этой конкретной форме.
  2. Только просмотр: Установим свойство ТолькоПросмотр в значение Истина для всей формы списка. Это переведет форму в режим чтения, исключая любое интерактивное редактирование данных.
  3. Доступность: Снятие флага доступности у формы полностью заблокирует ввод данных, однако этот вариант менее удобен, так как лишает пользователя возможности комфортного скроллинга и поиска по списку.
  4. Состав команд: В свойствах командной панели формы можно вручную исключить стандартные команды создания и редактирования.

Важно понимать, что данные ограничения работают только на уровне конкретной формы. Если пользователь сможет открыть запись регистра через другую форму или внешнюю обработку, эти запреты не сработают. Поэтому интерфейсные методы рекомендуется совмещать с программными.

Метод 3. Программный контроль в событии «ПередЗаписью» с использованием дополнительных свойств

Проанализируем ситуацию: как сделать так, чтобы код в модуле регистра сведений сам понимал, кто пытается сделать запись — пользователь вручную или система программно из модуля справочника?

Для реализации этого сценария мы можем использовать встроенный механизм платформы — коллекцию ДополнительныеСвойства, которая присутствует у всех наборов записей.

Разберем этот алгоритм по шагам:

Шаг 1. В модуле справочника (например, в обработчике ПередЗаписью справочника) при формировании набора записей регистра мы принудительно внедряем специальный маркер программной записи:


НаборЗаписей = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.СправочникСсылка.Установить(ЭтотОбъект.Ссылка);

// Добавляем маркер, сигнализирующий о том, что запись инициирована кодом справочника
НаборЗаписей.ДополнительныеСвойства.Вставить("ПрограммнаяЗапись", Истина);

НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.СправочникСсылка = ЭтотОбъект.Ссылка;
НоваяЗапись.РеквизитДанных = ЭтотОбъект.РеквизитДанных;

НаборЗаписей.Записать();

Шаг 2. В модуле набора записей самого регистра сведений мы перехватываем событие записи и проверяем наличие нашего секретного маркера:


Процедура ПередЗаписью(Отказ, Замещение)
    
    // Пропускаем запись, если она выполняется в процессе обмена данными
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем наличие и значение нашего признака
    ПрограммныйВвод = Ложь;
    Если ДополнительныеСвойства.Свойство("ПрограммнаяЗапись") Тогда
        ПрограммныйВвод = ДополнительныеСвойства.ПрограммнаяЗапись;
    КонецЕсли;
    
    // Если запись инициирована не из справочника (вручную пользователем) — отменяем транзакцию
    Если Не ПрограммныйВвод Тогда
        Отказ = Истина;
        ВызватьИсключение "Непосредственное изменение записей этого регистра запрещено. Запись возможна только из карточки справочника!";
    КонецЕсли;
    
КонецПроцедуры

Данный подход гарантирует 100% защиту данных на уровне СУБД. Даже если пользователь найдет лазейку в интерфейсе или попытается применить стороннюю обработку для изменения регистра, система заблокирует транзакцию и вызовет исключение.

Метод 4. Использование подписок на события (для типовых конфигураций)

Если вы работаете в типовой конфигурации, находящейся на поддержке, напрямую менять код модуля регистра сведений крайне нежелательно. Чтобы не снимать объект с поддержки, воспользуемся Подпиской на событие.

Создадим новую подписку на событие со следующими параметрами:

Код обработчика подписки будет практически идентичен коду из третьего метода:


Процедура ПередЗаписьюРегистраСведенийПередЗаписью(Источник, Отказ, Замещение) Экспорт
    
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    ПрограммныйВвод = Ложь;
    Если Источник.ДополнительныеСвойства.Свойство("ПрограммнаяЗапись") Тогда
        ПрограммныйВвод = Источник.ДополнительныеСвойства.ПрограммнаяЗапись;
    КонецЕсли;
    
    Если Не ПрограммныйВвод Тогда
        Отказ = Истина;
        Сообщить("Интерактивное изменение регистра запрещено конфигурацией!");
    КонецЕсли;
    
КонецПроцедуры

Особенности удаления записей в регистре сведений

В процессе обсуждения данной задачи часто возникает вопрос: «А как быть с удалением записей? Сможет ли пользователь удалить их вручную кнопкой Delete?».

Необходимо четко понимать важное отличие регистров от справочников или документов. Записи в регистрах сведений не помечаются на удаление — они удаляются физически и безвозвратно. При этом любое интерактивное удаление строки пользователем в форме списка технически является операцией записи пустого набора записей или записью набора с уменьшенным количеством строк.

Следовательно, описанный нами в Методе 3 и Методе 4 механизм контроля через событие ПередЗаписью автоматически защитит регистр и от ручного удаления строк. Поскольку при нажатии клавиши Delete пользователь инициирует интерактивную запись, в коллекции ДополнительныеСвойства не окажется флага ПрограммнаяЗапись, и система заблокирует операцию.

Если же требуется удалить запись регистра автоматически при удалении самого элемента справочника, мы должны прописать аналогичное программное удаление с передачей признака в обработчике ПередУдалением нашего справочника:


Процедура ПередУдалением(Отказ)
    
    // Очищаем записи регистра при удалении элемента справочника
    НаборЗаписей = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.СправочникСсылка.Установить(ЭтотОбъект.Ссылка);
    
    // Передаем признак программной записи для прохождения проверки контроля
    НаборЗаписей.ДополнительныеСвойства.Вставить("ПрограммнаяЗапись", Истина);
    
    // Записываем пустой набор, что фактически удаляет данные из БД
    НаборЗаписей.Записать();
    
КонецПроцедуры

Резюме и рекомендации

Мы рассмотрели все основные способы защиты регистра сведений от ручного вмешательства. Выбор конкретного метода зависит от архитектуры вашей системы:

← На главную