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

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

Подписка на события в 1С: что это и как использовать

Подписка на события в 1С — что это, как работает, чем отличается от обработчиков в модуле объекта. Примеры кода, типичные ошибки и порядок настройки.

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

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

Механизм доступен во всех конфигурациях на платформе 1С:Предприятие 8 — от самописных решений до типовых «Управление торговлей», «Бухгалтерия предприятия», «ERP». Сами типовые конфигурации активно используют подписки: например, в БСП (Библиотека стандартных подсистем) значительная часть сквозной функциональности построена именно на них.

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

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

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

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

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

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

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

Как создать подписку: пошаговая настройка

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

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

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

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

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

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

Типовой пример — контроль заполнения реквизита перед записью документа. Код проверяет условие и при необходимости отменяет запись с понятным сообщением пользователю.

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

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

Когда подписка лучше, а когда хуже доработки модуля объекта

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

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

Сравнение вариантов

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

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

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

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

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

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

Типичные ошибки и ограничения механизма

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

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

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

Типичные ошибки
01
Вызвать Источник.Записать() внутри обработчика — получается бесконечная рекурсия и аварийное завершение
02
Выбрать в источнике тип Ссылка вместо Объект — подписка никогда не сработает
03
Забыть Экспорт у процедуры обработчика — платформа не найдёт метод и выдаст ошибку при наступлении события
04
Разместить обработчик в клиентском модуле — события записи происходят на сервере, обработчик не вызовется
05
Строить логику на порядке вызова нескольких подписок — он не гарантирован и может меняться

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

Отладка подписок ничем не отличается от отладки обычного серверного кода: поставьте точку останова в обработчике, запустите отладку и выполните запись объекта. Убедитесь, что в настройках отладки включён нужный тип соединения (обычно «Тонкий клиент» и серверные контексты).

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

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

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

Срабатывание подписки
Норма

При записи тестового объекта отладчик останавливается в обработчике

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

Запись проходит, точка останова не срабатывает — проверьте Экспорт, серверность модуля и тип источника

Производительность
Норма

Запись документа занимает примерно столько же времени, что и до добавления подписки

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

Запись заметно замедлилась — в обработчике тяжёлый запрос или цикл

Влияние на обмены
Норма

Обмены и фоновые задания завершаются без новых ошибок в журнале регистрации

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

В журнале появились ошибки из обработчика при обмене — код рассчитан только на интерактивную работу

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

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

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

Можно ли одной подпиской обрабатывать несколько видов документов?

Да. В свойстве «Источник» отметьте все нужные типы. Внутри обработчика различайте объекты через ТипЗнч(Источник) или работайте с общими реквизитами, если они есть у всех выбранных типов.

Почему подписка не срабатывает при обмене данными?

Чаще всего срабатывает, но падает с ошибкой, которая видна только в журнале регистрации, либо объект записывается с параметром ОбменДанными.Загрузка = Истина. Проверьте в начале обработчика: Если Источник.ОбменДанными.Загрузка Тогда Возврат; — и решите осознанно, должна ли логика работать при загрузке.

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

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

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

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

Можно ли создать подписку в расширении конфигурации?

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

Итог

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

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