Как в 1С 7.7 ограничить доступ к полям документа в зависимости от его автора

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

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

Анализ синтаксической ошибки при обращении к реквизитам

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


Если( глПользователь <> Автор.Документ.ПлатежноеПоручение() = "Бухгалтер_по_платежам") Тогда
    Форма.Сумма.Доступность(1);
КонецЕсли;

При попытке сохранения модуля платформа выдает синтаксическую ошибку Ожидается символ ')'. Выясним причину такого поведения встроенного языка:

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

Решение задачи на уровне формы документа

Проанализируем базовый сценарий, когда ограничение накладывается в предопределенной процедуре ПриОткрытии() формы документа ПлатежноеПоручение.

Логика работы строится следующим образом: сначала для целевого пользователя блокируются все запрещенные к изменению реквизиты (включая реквизит Сумма), а затем выполняется проверка авторства. Если текущий пользователь совпадает с автором документа, доступность поля Сумма возвращается в активное состояние.

Посмотрим на пример кода, предложенный на форуме и доработанный автором:


Процедура ПриОткрытии()
    // Проверяем, относится ли текущий сеанс к нужному пользователю
    Если ИмяПользователя() = "Бухгалтер_по_платежам" Тогда
        // Блокируем поля, которые пользователю запрещено менять в любом случае
        Форма.ДатаДок.Доступность(0); 
        Форма.НомерДок.Доступность(0);
        Форма.СуммаНДС.Доступность(0);
        Форма.СтавкаНДС.Доступность(0);
        
        // По умолчанию закрываем редактирование суммы
        Форма.Сумма.Доступность(0);
        
        // Если автор совпадает с текущим пользователем — открываем сумму для правок
        Если СокрЛП(Автор) = ИмяПользователя() Тогда
            Форма.Сумма.Доступность(1);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Тонкости и подводные камни строкового сравнения

Рассмотрим подробнее нюансы, которые могут нарушить работу приведенного выше простого условия:

  1. Тип реквизита «Автор»: в абсолютном большинстве конфигураций 1С 7.7 (включая типовые «Бухгалтерский учет» и «Торговля и Склад») реквизит Автор имеет тип Справочник.Пользователи. При вызове функции СокрЛП(Автор) платформа неявно преобразует ссылку в строковое наименование элемента. Если наименование в справочнике отличается хотя бы одним регистром, пробелом или содержит полное ФИО сотрудника, а системный логин (возвращаемый функцией ИмяПользователя()) является коротким сетевым именем, условие СокрЛП(Автор) = ИмяПользователя() вернет Ложь.
  2. Корректное сравнение ссылок: если в конфигурации используется типовая переменная глПользователь, более надежно сравнивать именно ссылки объектов:
    
    Если Автор = глПользователь Тогда
        Форма.Сумма.Доступность(1);
    КонецЕсли;
    
  3. Создание нового документа: если пользователь создает новый документ, в момент открытия он еще не сохранен в информационной базе, то есть метод Выбран() возвращает 0. Если реквизит Автор заполняется только в процедуре ВводНового() или ПриЗаписи(), на момент открытия он может оказаться пустым. В результате бухгалтер не сможет ввести сумму даже в создаваемый им документ. Поэтому важно предусмотреть проверку на новый объект:
    
    Если (Выбран() = 0) ИЛИ (Автор = глПользователь) Тогда
        Форма.Сумма.Доступность(1);
    КонецЕсли;
    
  4. Связанные реквизиты: как справедливо отмечено участниками обсуждения, если пользователю разрешено корректировать сумму платежа, необходимо продумать логику пересчета связанных реквизитов (например, СуммаНДС). Если поле НДС заблокировано жестко через Доступность(0), сумма НДС должна автоматически пересчитываться при изменении основной суммы в обработчике реквизита.

Обеспечение надежности: контроль целостности в процедуре ПриЗаписи

Важно помнить, что отключение доступности элементов через метод Форма.<Реквизит>.Доступность(0) работает только в диалоговом окне. Пользователь может обойти визуальное ограничение с помощью групповой обработки документов или сторонних внешних обработок. Кроме того, жесткое кодирование логина "Бухгалтер_по_платежам" непосредственно в модуле делает конфигурацию уязвимой при смене сотрудника или переименовании учетной записи.

Для создания полноценной защиты разберем более надежный алгоритм проверки, выполняемый в предопределенной процедуре ПриЗаписи() в модуле документа:


Процедура ПриЗаписи()
    // Заполняем автора для нового документа, если он еще не задан
    Если ПустоеЗначение(Автор) = 1 Тогда
        Автор = глПользователь;
    КонецЕсли;

    // Если документ уже был ранее записан в базу, контролируем изменение суммы
    Если Выбран() = 1 Тогда
        // Проверяем роль или конкретного пользователя
        Если ИмяПользователя() = "Бухгалтер_по_платежам" Тогда
            // Создаем объект для чтения первоначального состояния документа из базы
            ДокБаза = СоздатьОбъект("Документ.ПлатежноеПоручение");
            Если ДокБаза.НайтиДокумент(ТекущийДокумент()) = 1 Тогда
                // Проверяем, изменилась ли сумма и является ли пользователь автором
                Если (ДокБаза.Сумма <> Сумма) И (ДокБаза.Автор <> глПользователь) Тогда
                    Предупреждение("Вам запрещено изменять сумму в документах других авторов!");
                    СтатусВозврата(0);
                    Возврат;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

← На главную