К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как работает подписка на событие в 1С

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

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

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

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

Как устроен механизм подписок на события

Подписка состоит из трёх обязательных элементов. Источник — тип или набор типов объектов, за которыми ведётся наблюдение (например, «ДокументОбъект.РеализацияТоваровУслуг» или сразу несколько видов документов). Событие — момент жизненного цикла объекта: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаПроверкиЗаполнения и другие. Обработчик — экспортная процедура в общем модуле, которая получает параметры события.

Когда пользователь или код записывает объект, платформа формирует цепочку вызовов: сначала обработчик в модуле объекта, затем обработчики всех подписок, зарегистрированных на это событие и этот тип. Подписки получают тот же объект (Источник) по ссылке на область памяти, поэтому могут читать и изменять его реквизиты до фиксации в базе — если событие это позволяет.

Важно понимать транзакционный контекст. События ПередЗаписью и ПриЗаписи выполняются внутри транзакции записи объекта. Если обработчик подписки вызывает исключение, транзакция откатывается, и объект не будет записан. Это мощный инструмент контроля, но и источник блокировок, если обработчик работает долго.

Какие события доступны для подписки

Набор событий зависит от типа объекта. Для документов доступны: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаУдаленияПроведения, ОбработкаПроверкиЗаполнения, ПриКопировании, ПриУстановкеНовогоНомера. Для справочников — ПередЗаписью, ПриЗаписи, ПередУдалением, ПриКопировании, ОбработкаПроверкиЗаполнения, ПриУстановкеНовогоКода. Для регистров сведений — ПередЗаписью и ПриЗаписи набора записей.

Наиболее востребованы ПередЗаписью и ПриЗаписи. Разница принципиальна: в ПередЗаписью данные ещё не зафиксированы, объект можно изменить, а запись — отменить через параметр Отказ. В ПриЗаписи объект уже записан в базу (в рамках транзакции), менять его реквизиты поздно, зато уместно выполнять побочные действия: регистрацию к обмену, создание связанных объектов, отправку уведомлений.

ОбработкаПроведения позволяет добавлять собственные движения в регистры или проверки перед проведением документа. Это типовой способ добавить к документу дополнительный регистр накопления, не трогая модуль объекта.

Как создать подписку на событие в конфигураторе

Создание подписки выполняется в дереве конфигурации. Откройте ветку «Общие → Подписки на события» и добавьте новый объект. В свойствах задайте имя (например, «ПриЗаписиДокументаРеализация»), выберите источник — один или несколько типов объектов, укажите событие и назначьте обработчик: платформа предложит создать процедуру в выбранном общем модуле.

Общий модуль для обработчиков подписок должен иметь установленный флаг «Сервер». Для событий, работающих в транзакции, обычно снимают флаг «Вызов сервера» не требуется, но важно, чтобы модуль был серверным и не был клиентским. Флаги «Привилегированный режим» ставят, если обработчику нужно обращаться к данным, на которые у пользователя нет прав.

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

Порядок создания подписки
  1. 1
    Создайте или выберите общий серверный модуль для обработчиков
  2. 2
    В ветке «Общие → Подписки на события» добавьте новую подписку
  3. 3
    Задайте имя, выберите источник (типы объектов) и событие
  4. 4
    Нажмите кнопку выбора обработчика — платформа создаст шаблон процедуры в модуле
  5. 5
    Напишите логику обработчика, обновите конфигурацию базы данных
  6. 6
    Запишите тестовый объект и убедитесь, что обработчик сработал

Пример обработчика и работа с параметрами

Обработчик подписки получает те же параметры, что и одноимённое событие модуля объекта. Для ПриЗаписи это Источник (сам объект) и Отказ. Для ОбработкаПроведения — Источник, Отказ и РежимПроведения. Процедура должна быть экспортной, иначе платформа не сможет её вызвать.

Типичный пример — автоматическое заполнение комментария или регистрация изменений:

Процедура ПриЗаписиДокументаРегистрация(Источник, Отказ) Экспорт

Если Отказ Тогда

Возврат;

КонецЕсли;

Если Источник.ДополнительныеСвойства.Свойство("НеРегистрировать") Тогда

Возврат;

КонецЕсли;

ЗаписьЖурналаРегистрации("Изменение документа",

УровеньЖурналаРегистрации.Информация,

Источник.Метаданные(),

Источник.Ссылка,

"Записан документ № " + Источник.Номер);

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

Обратите внимание на свойство ДополнительныеСвойства — стандартный способ передавать в обработчики служебные флаги и отключать логику подписки при программной записи. Без такого «предохранителя» массовая обработка данных может спровоцировать тысячи лишних срабатываний.

Типичные сценарии использования

Контроль и запрет записи

Подписка на ПередЗаписью позволяет проверить условия и отказать в записи: например, запретить проведение документов закрытого периода или изменение элементов справочника с определённым признаком. Для отказа достаточно установить Отказ = Истина и вывести сообщение пользователю через Сообщить или вызвать исключение.

Дополнительные движения документа

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

Интеграция и обмен данными

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

Способы расширения логики объектов

Подписка на событие

Подходит для серверной логики записи и проведения; не меняет типовые модули; ограничение — нет гарантии порядка вызова между подписками

Доработка модуля объекта

Даёт полный контроль и порядок вызова, но усложняет обновление типовой конфигурации

Расширение конфигурации

Позволяет переопределять обработчики с аннотациями &ИзменениеИКонтроль; удобно, но требует контроля совместимости при обновлениях

Производительность, права и ограничения

Каждая подписка добавляет время к каждой операции записи охваченных объектов. Если источником выбрано много типов документов, а обработчик выполняет запросы к базе, интерактивная запись замедлится ощутимо. Правило простое: в обработчике — минимум логики, проверка условий выхода в первую очередь, тяжёлые операции — асинхронно через фоновые задания.

Права доступа — частый источник проблем. Обработчик выполняется в контексте текущего пользователя. Если пользователю запрещено чтение регистра, к которому обращается подписка, запись документа завершится ошибкой. Решение — выполнять чувствительный код в привилегированном режиме: либо ставить флаг на общем модуле, либо оборачивать фрагмент в УстановитьПривилегированныйРежим(Истина).

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

Типичные ошибки и как их избежать

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

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

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

Типичные ошибки
01
Вызов Записать() у Источника внутри обработчика — рекурсия и зацикливание события
02
Общий модуль без флага «Сервер» — ошибка вызова обработчика и невозможность записи объектов
03
Тяжёлые запросы и HTTP-вызовы в обработчике — замедление каждой записи документа
04
Отсутствие проверки типа Источника при составном источнике — обращение к несуществующим реквизитам
05
Игнорирование прав пользователя — ошибки доступа у части сотрудников при записи

Как проверить, что подписка работает корректно

Базовая проверка — отладка: поставьте точку останова в первой строке обработчика и запишите объект нужного типа. Если точка не сработала, проверьте: обновлена ли конфигурация базы данных, совпадает ли тип источника с типом записываемого объекта, не отключена ли подписка (снято свойство использования в расширениях).

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

Контрольные точки

Как проверить результат

Срабатывание обработчика при ручной записи
Норма

Точка останова в отладчике останавливается на первой строке процедуры

Тревожный признак

Объект записывается без входа в обработчик — проверьте источник и обновление конфигурации

Программная запись через обработку
Норма

Обработчик срабатывает или корректно пропускается по флагу в ДополнительныеСвойства

Тревожный признак

Массовая обработка вызывает лишние срабатывания и замедляется

Журнал регистрации после тестов
Норма

Нет ошибок вызова обработчика и ошибок доступа

Тревожный признак

Ошибки «процедура не обнаружена» или нарушение прав доступа

Частые вопросы о подписках на события

В каком порядке вызываются несколько подписок на одно событие?

Платформа не гарантирует порядок вызова подписок друг относительно друга. Если логика зависит от последовательности, объедините обработчики в одну подписку и управляйте порядком внутри неё, либо передавайте промежуточные результаты через ДополнительныеСвойства объекта.

Можно ли отменить запись объекта из подписки?

Да, в событиях ПередЗаписью, ОбработкаПроведения и ОбработкаПроверкиЗаполнения установите параметр Отказ = Истина. Транзакция записи будет отменена, объект не сохранится. В ПриЗаписи отмена тоже технически работает через исключение, но это менее корректный способ.

Нарушит ли подписка обновление типовой конфигурации?

Нет, подписки — самостоятельные объекты метаданных и не изменяют типовые модули. При обновлении они сохраняются. Риск возникает только если типовая логика изменилась настолько, что обработчик обращается к переименованным или удалённым реквизитам — такие места проверяйте после каждого обновления.

Срабатывает ли подписка при обмене данными и загрузке из файлов?

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

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

Если подписка создана в основной конфигурации, отключить её без изменения конфигурации нельзя — только удалить обработчик или добавить в код условие-переключатель (например, константу «ОтключитьПодписки»). Если логика вынесена в расширение, достаточно снять с расширения флаг активности или удалить из него подписку.

Чем подписка отличается от обработчика в модуле объекта?

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

Итог

Что важно запомнить

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