В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача автоматического заполнения или перезаполнения определенных полей документа при выполнении пользователем каких-либо действий. Одной из классических ситуаций является необходимость зафиксировать дату или статус в тот момент, когда документ проводится пользователем, указанным в качестве ответственного. В данной статье мы подробно разберем, как правильно реализовать эту логику, избежав типичных ошибок новичков, связанных с типами данных и архитектурой системы.
Рассмотрим ситуацию, описанную в теме. Разработчик пытается в процедуре ПередЗаписью модуля объекта проверить, является ли текущий пользователь тем самым «Ответственным», который указан в документе. Однако стандартная проверка вида Если Ответственный = ПользователиИнформационнойБазы.ТекущийПользователь().ПолноеИмя часто не срабатывает. Выясним причину.
В большинстве типовых и самописных конфигураций реквизит Ответственный имеет тип СправочникСсылка.Пользователи. В то же время метод ПолноеИмя возвращает текстовую строку. Платформа 1С не может приравнять ссылку на объект справочника к строковому значению, поэтому условие всегда будет ложным, даже если имена совпадают. Разберем правильные способы реализации этой проверки.
Для повышения производительности и удобства во многих конфигурациях (как типовых, так и созданных «с нуля») используется параметр сеанса ТекущийПользователь. Этот параметр хранит ссылку на текущего пользователя из справочника «Пользователи», что позволяет выполнять прямое сравнение без лишних преобразований. Проанализируем пример кода:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Обязательная проверка на режим обмена данными
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, что происходит именно проведение документа
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
// Сравниваем ссылку из реквизита со ссылкой в параметрах сеанса
Если Ответственный = ПараметрыСеанса.ТекущийПользователь Тогда
ДатаОтправки = ТекущаяДата();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот метод считается наиболее быстрым, так как обращение к параметру сеанса не требует выполнения запроса к базе данных при каждой проверке. Важно помнить: перед использованием убедитесь, что параметр сеанса ТекущийПользователь определен в вашей конфигурации и инициализируется при запуске системы.
Если вы работаете в современной типовой конфигурации (например, ERP, УТ 11, БП 3.0), лучшим решением будет использование программного интерфейса БСП. Общий модуль Пользователи предоставляет готовую функцию для получения ссылки на текущего авторизованного сотрудника.
Разберем, как это выглядит в коде:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
// Получаем ссылку через стандартный метод БСП
ТекущийПользовательСсылка = Пользователи.ТекущийПользователь();
Если Ответственный = ТекущийПользовательСсылка Тогда
ДатаОтправки = ТекущаяДата();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущество этого метода в его универсальности. БСП берет на себя все проверки безопасности и корректное определение ссылки, независимо от того, как настроена авторизация в системе.
Иногда жесткая привязка к полю «Ответственный» может быть неудобной. Например, если ответственный сотрудник ушел в отпуск и его документ проводит руководитель или коллега. В таком случае логика может «сломаться». Рассмотрим альтернативный вариант: использование ролей или специальных настроек пользователя.
Как предложили в обсуждении, можно добавить пользователям специальный признак (настройку или роль) ОтветственныйЗаДату. Посмотрим на логику реализации:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
// Проверяем наличие определенной роли у текущего пользователя
Если РольДоступна("ИзменениеДатыОтправки") Тогда
ДатаОтправки = ТекущаяДата();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой подход делает систему более масштабируемой. Вы сможете управлять правами на автоматическое заполнение реквизитов через конфигуратор или профили групп доступа, не меняя программный код при каждом изменении штатного расписания.
При реализации механизмов автоматического заполнения реквизитов в модуле объекта следует придерживаться нескольких правил:
ПередЗаписью. Это позволяет изменить данные до того, как они будут зафиксированы в таблицах базы данных, и не требует повторного вызова метода Записать(), что исключает бесконечную рекурсию.ПередЗаписью, укажите в качестве источника нужные типы документов и опишите логику в одном общем модуле. Это значительно упростит поддержку и обновление системы.&Перед("ПередЗаписью"). Это позволит сохранить возможность легкого обновления основной конфигурации.Если ваше условие всё равно не срабатывает, воспользуйтесь отладчиком. Проанализируем ситуацию по шагам:
Если.Ответственный и ее тип.ПараметрыСеанса.ТекущийПользователь).СправочникСсылка.Пользователи).Помните, что ПользователиИнформационнойБазы.ТекущийПользователь() возвращает объект типа ПользовательИнформационнойБазы, который является системным объектом и никогда не будет равен ссылке из справочника напрямую. Связующим звеном между ними является либо уникальный идентификатор, либо имя пользователя, но в коде 1С правильнее всего работать именно со ссылками на справочник Пользователи.
Таким образом, мы рассмотрели основные способы реализации контроля за заполнением реквизитов в зависимости от текущего сеанса. Выбор конкретного метода зависит от архитектуры вашей конфигурации и требований к гибкости настройки прав доступа.