Как разрешить добавление новых строк в табличную часть без возможности редактирования существующих данных

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

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

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

Анализ прав доступа: Добавление против Изменения

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

  1. Право «Добавление» (Insert): дает пользователю возможность создать новый объект (элемент справочника) «с нуля».
  2. Право «Изменение» (Update): необходимо для того, чтобы пользователь мог внести любые правки в уже существующий (записанный в базу) объект.

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

Также не забываем про право Интерактивное добавление. Без него в форме списка справочника просто не появится кнопка «Создать», даже если право Добавление у пользователя есть.

Настройка интерфейса и свойств таблицы на форме

Рассмотрим ситуацию, когда мы уже предоставили пользователю необходимые права в конфигураторе. Теперь нам нужно настроить форму так, чтобы интерфейс подсказывал пользователю доступные действия. Выясним причину, по которой стандартная настройка ТолькоПросмотр = Истина нам не подходит: это свойство полностью отключает возможность взаимодействия с таблицей, включая кнопку «Добавить».

Вместо этого мы проанализируем свойства элемента формы Таблица. Нам необходимо установить следующие параметры в палитре свойств или программно:

Такая комбинация позволит пользователю нажимать кнопку «Добавить», вводить данные в новую строку, но не даст возможности кликнуть на старую строку и изменить в ней значение.

Программная реализация в модуле формы

Теперь перейдем к реализации логики через код. Наиболее изящный способ — использовать событие ПриЧтенииНаСервере и обработчики событий табличной части. Рассмотрим подробнее, как это реализовать.

В процедуре ПриЧтенииНаСервере мы проверим, обладает ли текущий пользователь полными правами. Если нет, мы ограничим доступность реквизитов шапки.


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    // Проверяем, является ли пользователь "Рекрутом"
    Если РольДоступна("Рекрут") И НЕ РольДоступна("ПолныеПрава") Тогда
        
        // Запрещаем редактирование основных реквизитов шапки
        Элементы.Наименование.Доступность = Ложь;
        Элементы.Код.Доступность = Ложь;
        Элементы.Организация.Доступность = Ложь;
        
        // Настраиваем таблицу: добавлять можно, менять старое нельзя
        Элементы.ТЧ_Данные.ИзменениеСтрок = Ложь;
        
    КонецЕсли;
    
КонецПроцедуры

Однако свойство ИзменениеСтрок = Ложь может вести себя по-разному в зависимости от версии платформы. Чтобы обеспечить стопроцентную гарантию, мы воспользуемся событием табличной части ПередНачаломИзменения. Разберем этот пример.


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

КонецПроцедуры

Защита на уровне модуля объекта

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

Идея заключается в том, чтобы сравнить данные, которые пришли с формы, с теми данными, которые уже лежат в базе данных. Если пользователь изменил хоть один символ в старых строках — мы отменим транзакцию.


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Если прав недостаточно, проверяем неизменность старых данных
    Если НЕ РольДоступна("ПолныеПрава") Тогда
        
        // Получаем старые данные из базы для сравнения
        СтарыйОбъект = Ссылка.ПолучитьОбъект();
        Если СтарыйОбъект <> Неопределено Тогда
            
            // Проверяем количество строк. Если строк стало меньше - значит было удаление
            Если ЭтотОбъект.ТабличнаяЧасть1.Количество() < СтарыйОбъект.ТабличнаяЧасть1.Количество() Тогда
                Сообщение = Новый СообщениеПользователю;
                Сообщение.Текст = "Удаление существующих строк запрещено!";
                Сообщение.Сообщить();
                Отказ = Истина;
                Возврат;
            КонецЕсли;
            
            // Проверяем содержимое старых строк
            Для Индекс = 0 По СтарыйОбъект.ТабличнаяЧасть1.Количество() - 1 Цикл
                СтараяСтрока = СтарыйОбъект.ТабличнаяЧасть1[Индекс];
                НоваяСтрока = ЭтотОбъект.ТабличнаяЧасть1[Индекс];
                
                // Сравниваем реквизиты строк (например, "Сотрудник" и "Дата")
                Если НоваяСтрока.Сотрудник <> СтараяСтрока.Сотрудник 
                   Или НоваяСтрока.Дата <> СтараяСтрока.Дата Тогда
                    
                    Сообщение = Новый СообщениеПользователю;
                    Сообщение.Текст = "Редактирование существующих записей запрещено! Изменяйте только новые строки.";
                    Сообщение.Сообщить();
                    Отказ = Истина;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Дополнительные рекомендации

Для создания максимально комфортной среды для пользователя рассмотрим еще несколько приемов:

Подведем итог: реализация запрета редактирования при разрешении добавления в 1С требует комплексного подхода. Мы объединили настройку прав роли (обязательное включение Изменение и Интерактивное добавление), визуальную блокировку на уровне формы (свойства таблицы) и строгий контроль целостности данных в модуле объекта. Такой подход гарантирует стабильность системы и выполнение требований безопасности данных.

← На главную