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

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

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

Анализ проблемы: почему сравнение не работает?

Рассмотрим ситуацию, описанную в теме. Разработчик пытается в процедуре ПередЗаписью модуля объекта проверить, является ли текущий пользователь тем самым «Ответственным», который указан в документе. Однако стандартная проверка вида Если Ответственный = ПользователиИнформационнойБазы.ТекущийПользователь().ПолноеИмя часто не срабатывает. Выясним причину.

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

Способ 1. Использование параметров сеанса

Для повышения производительности и удобства во многих конфигурациях (как типовых, так и созданных «с нуля») используется параметр сеанса ТекущийПользователь. Этот параметр хранит ссылку на текущего пользователя из справочника «Пользователи», что позволяет выполнять прямое сравнение без лишних преобразований. Проанализируем пример кода:


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

    // Проверяем, что происходит именно проведение документа
    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        // Сравниваем ссылку из реквизита со ссылкой в параметрах сеанса
        Если Ответственный = ПараметрыСеанса.ТекущийПользователь Тогда
            ДатаОтправки = ТекущаяДата();
        КонецЕсли;
        
    КонецЕсли;

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

Этот метод считается наиболее быстрым, так как обращение к параметру сеанса не требует выполнения запроса к базе данных при каждой проверке. Важно помнить: перед использованием убедитесь, что параметр сеанса ТекущийПользователь определен в вашей конфигурации и инициализируется при запуске системы.

Способ 2. Использование Библиотеки стандартных подсистем (БСП)

Если вы работаете в современной типовой конфигурации (например, ERP, УТ 11, БП 3.0), лучшим решением будет использование программного интерфейса БСП. Общий модуль Пользователи предоставляет готовую функцию для получения ссылки на текущего авторизованного сотрудника.

Разберем, как это выглядит в коде:


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

    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        // Получаем ссылку через стандартный метод БСП
        ТекущийПользовательСсылка = Пользователи.ТекущийПользователь();
        
        Если Ответственный = ТекущийПользовательСсылка Тогда
            ДатаОтправки = ТекущаяДата();
        КонецЕсли;
        
    КонецЕсли;

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

Преимущество этого метода в его универсальности. БСП берет на себя все проверки безопасности и корректное определение ссылки, независимо от того, как настроена авторизация в системе.

Способ 3. Гибкая настройка через дополнительные права

Иногда жесткая привязка к полю «Ответственный» может быть неудобной. Например, если ответственный сотрудник ушел в отпуск и его документ проводит руководитель или коллега. В таком случае логика может «сломаться». Рассмотрим альтернативный вариант: использование ролей или специальных настроек пользователя.

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


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

    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        // Проверяем наличие определенной роли у текущего пользователя
        Если РольДоступна("ИзменениеДатыОтправки") Тогда
             ДатаОтправки = ТекущаяДата();
        КонецЕсли;
        
    КонецЕсли;

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

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

Архитектурные рекомендации и безопасность

При реализации механизмов автоматического заполнения реквизитов в модуле объекта следует придерживаться нескольких правил:

  1. Проверка ОбменДанными.Загрузка. Всегда ставьте эту проверку в начале обработчика. Если документ загружается через синхронизацию (РИБ, обмен с другой базой), код не должен выполняться, иначе данные из другой базы будут затерты значениями текущего технического пользователя.
  2. Использование событий ПередЗаписью против ПриЗаписи. Для изменения реквизитов самого объекта всегда используйте ПередЗаписью. Это позволяет изменить данные до того, как они будут зафиксированы в таблицах базы данных, и не требует повторного вызова метода Записать(), что исключает бесконечную рекурсию.
  3. Подписки на события. Если подобную логику нужно внедрить для целого ряда документов, не копируйте код в каждый модуль. Создайте одну Подписку на событие ПередЗаписью, укажите в качестве источника нужные типы документов и опишите логику в одном общем модуле. Это значительно упростит поддержку и обновление системы.
  4. Расширения конфигурации. Если вы работаете с типовым решением, которое находится на поддержке, реализуйте этот функционал через расширение. Используйте аннотацию &Перед("ПередЗаписью"). Это позволит сохранить возможность легкого обновления основной конфигурации.

Проверка типов в отладчике

Если ваше условие всё равно не срабатывает, воспользуйтесь отладчиком. Проанализируем ситуацию по шагам:

  1. Установите точку останова на строке с условием Если.
  2. В окне Вычислить выражение посмотрите значение переменной Ответственный и ее тип.
  3. Там же посмотрите значение и тип того, с чем вы сравниваете (например, ПараметрыСеанса.ТекущийПользователь).
  4. Убедитесь, что типы совпадают (оба должны быть СправочникСсылка.Пользователи).

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

Таким образом, мы рассмотрели основные способы реализации контроля за заполнением реквизитов в зависимости от текущего сеанса. Выбор конкретного метода зависит от архитектуры вашей конфигурации и требований к гибкости настройки прав доступа.

← На главную