Как реализовать подписку на событие для автоматического заполнения комментария в документах?

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

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

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

Анализ типичных ошибок в коде обработчика подписки

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


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

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

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

Пошаговая настройка метаданных подписки

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

  1. Свойства общего модуля: Модуль, в котором размещается процедура, обязательно должен иметь включенный флаг «Сервер» (Server Call / Сервер). Запись документов происходит на сервере, и клиентский модуль платформа вызвать не сможет.
  2. Выбор события: Изменять реквизиты объекта можно только в событии ПередЗаписью. Если ошибочно выбрать событие ПриЗаписи, объект к этому моменту уже записан в таблицы базы данных. Любые изменения реквизитов внутри ПриЗаписи будут проигнорированы и не сохранятся в базе.
  3. Указание источников: В объекте конфигурации «ПодпискаНаСобытие» в поле «Источник» необходимо выбирать типы объектов, то есть ДокументОбъект (или список конкретных документов), а не ссылочные типы ДокументСсылка.
  4. Проверка через отладку: Если при записи ничего не происходит и ошибок нет, необходимо проверить, доходит ли выполнение до процедуры. Для этого убедимся, что на сервере 1С включен режим отладки (параметр запуска службы -debug), ставим точку останова внутри процедуры общего модуля и выполняем запись документа в пользовательском режиме.

Корректный пример реализации подписки на событие

Рассмотрим правильный код процедуры общего модуля, учитывающий все архитектурные требования платформы 1С:


// Обработчик подписки на событие ПередЗаписью для документов
Процедура КомментарийВоВсехДокументахПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    // Пропускаем обработку при фоновом обмене или переносе данных
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверяем наличие реквизита в метаданных документа
    Если Источник.Метаданные().Реквизиты.Найти("Комментарий") <> Неопределено Тогда
        
        ТекстЛога = "Документ записан " + Формат(ТекущаяДатаСеанса(), "ДЛФ=DT") + " пользователем " + ИмяПользователя();
        
        // Добавляем запись без затирания введенных пользователем данных
        Если ПустаяСтрока(Источник.Комментарий) Тогда
            Источник.Комментарий = ТекстЛога;
        Иначе
            Источник.Комментарий = Источник.Комментарий + Символы.ПС + ТекстЛога;
        КонецЕсли;
        
    КонецЕсли;

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

Альтернативное решение: использование типового журнала регистрации

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

← На главную