Разработка и Конфигурация · 13 мин
Как работает подписка на событие в 1С
Как работает подписка на событие в 1С: механизм вызова обработчиков, настройка в конфигураторе, типовые события, примеры кода, ошибки и проверка результата.
Подписка на событие в 1С — это механизм конфигурации, который позволяет выполнять собственный код при наступлении определённых событий объектов: записи документа, проведении, сохранении элемента справочника, установке пометки удаления. Вместо того чтобы встраивать логику в модули самих объектов, разработчик создаёт отдельный объект метаданных «Подписка на событие», указывает источник (какие объекты отслеживаются), событие и процедуру-обработчик в общем модуле.
Главная ценность механизма — неинвазивность. Обработчик живёт отдельно от типового кода, поэтому при обновлении конфигурации доработки не конфликтуют с изменениями поставщика. Именно поэтому подписки считаются предпочтительным способом расширения типовой логики наряду с расширениями конфигурации.
Механизм работает на сервере в момент, когда платформа выполняет соответствующее действие с объектом. При записи документа, например, сначала вызываются обработчики событий самого модуля объекта, затем — обработчики подписок на аналогичные события. Порядок вызова нескольких подписок на одно событие не гарантирован, и это нужно учитывать при проектировании.
Как устроен механизм подписок на события
Подписка состоит из трёх обязательных элементов. Источник — тип или набор типов объектов, за которыми ведётся наблюдение (например, «ДокументОбъект.РеализацияТоваровУслуг» или сразу несколько видов документов). Событие — момент жизненного цикла объекта: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаПроверкиЗаполнения и другие. Обработчик — экспортная процедура в общем модуле, которая получает параметры события.
Когда пользователь или код записывает объект, платформа формирует цепочку вызовов: сначала обработчик в модуле объекта, затем обработчики всех подписок, зарегистрированных на это событие и этот тип. Подписки получают тот же объект (Источник) по ссылке на область памяти, поэтому могут читать и изменять его реквизиты до фиксации в базе — если событие это позволяет.
Важно понимать транзакционный контекст. События ПередЗаписью и ПриЗаписи выполняются внутри транзакции записи объекта. Если обработчик подписки вызывает исключение, транзакция откатывается, и объект не будет записан. Это мощный инструмент контроля, но и источник блокировок, если обработчик работает долго.
Какие события доступны для подписки
Набор событий зависит от типа объекта. Для документов доступны: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаУдаленияПроведения, ОбработкаПроверкиЗаполнения, ПриКопировании, ПриУстановкеНовогоНомера. Для справочников — ПередЗаписью, ПриЗаписи, ПередУдалением, ПриКопировании, ОбработкаПроверкиЗаполнения, ПриУстановкеНовогоКода. Для регистров сведений — ПередЗаписью и ПриЗаписи набора записей.
Наиболее востребованы ПередЗаписью и ПриЗаписи. Разница принципиальна: в ПередЗаписью данные ещё не зафиксированы, объект можно изменить, а запись — отменить через параметр Отказ. В ПриЗаписи объект уже записан в базу (в рамках транзакции), менять его реквизиты поздно, зато уместно выполнять побочные действия: регистрацию к обмену, создание связанных объектов, отправку уведомлений.
ОбработкаПроведения позволяет добавлять собственные движения в регистры или проверки перед проведением документа. Это типовой способ добавить к документу дополнительный регистр накопления, не трогая модуль объекта.
Как создать подписку на событие в конфигураторе
Создание подписки выполняется в дереве конфигурации. Откройте ветку «Общие → Подписки на события» и добавьте новый объект. В свойствах задайте имя (например, «ПриЗаписиДокументаРеализация»), выберите источник — один или несколько типов объектов, укажите событие и назначьте обработчик: платформа предложит создать процедуру в выбранном общем модуле.
Общий модуль для обработчиков подписок должен иметь установленный флаг «Сервер». Для событий, работающих в транзакции, обычно снимают флаг «Вызов сервера» не требуется, но важно, чтобы модуль был серверным и не был клиентским. Флаги «Привилегированный режим» ставят, если обработчику нужно обращаться к данным, на которые у пользователя нет прав.
После сохранения конфигурации подписка начинает действовать сразу — перезапуск сеансов не требуется для обновления метаданных, но уже открытые сеансы пользователей могут работать со старой версией до перезахода. Проверьте результат, записав тестовый объект в отладке с точкой останова внутри обработчика.
- 1Создайте или выберите общий серверный модуль для обработчиков
- 2В ветке «Общие → Подписки на события» добавьте новую подписку
- 3Задайте имя, выберите источник (типы объектов) и событие
- 4Нажмите кнопку выбора обработчика — платформа создаст шаблон процедуры в модуле
- 5Напишите логику обработчика, обновите конфигурацию базы данных
- 6Запишите тестовый объект и убедитесь, что обработчик сработал
Пример обработчика и работа с параметрами
Обработчик подписки получает те же параметры, что и одноимённое событие модуля объекта. Для ПриЗаписи это Источник (сам объект) и Отказ. Для ОбработкаПроведения — Источник, Отказ и РежимПроведения. Процедура должна быть экспортной, иначе платформа не сможет её вызвать.
Типичный пример — автоматическое заполнение комментария или регистрация изменений:
Процедура ПриЗаписиДокументаРегистрация(Источник, Отказ) Экспорт
Если Отказ Тогда
Возврат;
КонецЕсли;
Если Источник.ДополнительныеСвойства.Свойство("НеРегистрировать") Тогда
Возврат;
КонецЕсли;
ЗаписьЖурналаРегистрации("Изменение документа",
УровеньЖурналаРегистрации.Информация,
Источник.Метаданные(),
Источник.Ссылка,
"Записан документ № " + Источник.Номер);
КонецПроцедуры
Обратите внимание на свойство ДополнительныеСвойства — стандартный способ передавать в обработчики служебные флаги и отключать логику подписки при программной записи. Без такого «предохранителя» массовая обработка данных может спровоцировать тысячи лишних срабатываний.
Типичные сценарии использования
Контроль и запрет записи
Подписка на ПередЗаписью позволяет проверить условия и отказать в записи: например, запретить проведение документов закрытого периода или изменение элементов справочника с определённым признаком. Для отказа достаточно установить Отказ = Истина и вывести сообщение пользователю через Сообщить или вызвать исключение.
Дополнительные движения документа
Через ОбработкаПроведения добавляют записи в собственные регистры: Источник.Движения содержит коллекцию наборов записей, к которым можно обратиться по имени регистра и заполнить. Набор нужно включить в состав движений документа в метаданных — иначе платформа не создаст его в коллекции.
Интеграция и обмен данными
Подписки на ПриЗаписи используют для регистрации объектов в планах обмена или постановки сообщений в очередь интеграции. Здесь критична производительность: обработчик выполняется синхронно в транзакции пользователя, поэтому тяжёлые операции (отправку HTTP-запросов, формирование файлов) лучше выносить в фоновые задания, а в подписке лишь фиксировать факт изменения.
Способы расширения логики объектов
Подходит для серверной логики записи и проведения; не меняет типовые модули; ограничение — нет гарантии порядка вызова между подписками
Даёт полный контроль и порядок вызова, но усложняет обновление типовой конфигурации
Позволяет переопределять обработчики с аннотациями &ИзменениеИКонтроль; удобно, но требует контроля совместимости при обновлениях
Производительность, права и ограничения
Каждая подписка добавляет время к каждой операции записи охваченных объектов. Если источником выбрано много типов документов, а обработчик выполняет запросы к базе, интерактивная запись замедлится ощутимо. Правило простое: в обработчике — минимум логики, проверка условий выхода в первую очередь, тяжёлые операции — асинхронно через фоновые задания.
Права доступа — частый источник проблем. Обработчик выполняется в контексте текущего пользователя. Если пользователю запрещено чтение регистра, к которому обращается подписка, запись документа завершится ошибкой. Решение — выполнять чувствительный код в привилегированном режиме: либо ставить флаг на общем модуле, либо оборачивать фрагмент в УстановитьПривилегированныйРежим(Истина).
Ещё одно ограничение — отладка. Подписки срабатывают и при фоновых заданиях, и при обменах, поэтому ошибка может проявляться только в регламентных операциях. Для диагностики добавляйте в обработчик запись в журнал регистрации с уровнем «Ошибка» в блоке Попытка/Исключение — это позволит увидеть сбой, не останавливая работу пользователей.
Типичные ошибки и как их избежать
Самая распространённая ошибка — рекурсивная запись: в обработчике ПриЗаписи вызывается Источник.Записать() или записывается объект, который снова попадает в ту же подписку. Платформа может выдать ошибку зацикливания или уйти в глубокую рекурсию. Защита — флаг в ДополнительныеСвойства или проверка условия, исключающего повторное срабатывание.
Вторая ошибка — неэкспортная процедура обработчика или общий модуль без флага «Сервер». В этом случае при записи объекта возникает ошибка «Процедура не обнаружена», и запись становится невозможной вообще. Проверяйте свойства модуля сразу после создания подписки.
Третья группа ошибок — логические: обработчик рассчитан на один вид документа, а источником назначено несколько типов, и обращение к специфичному реквизиту падает на объектах, где его нет. Всегда проверяйте тип Источника или используйте безопасный доступ к реквизитам через метаданные.
Как проверить, что подписка работает корректно
Базовая проверка — отладка: поставьте точку останова в первой строке обработчика и запишите объект нужного типа. Если точка не сработала, проверьте: обновлена ли конфигурация базы данных, совпадает ли тип источника с типом записываемого объекта, не отключена ли подписка (снято свойство использования в расширениях).
Функциональная проверка — тестовый сценарий: запишите объект вручную, программно через обработку и через обмен, если он используется. Обработчик должен срабатывать во всех трёх случаях, а флаги в ДополнительныеСвойства — корректно отключать логику там, где это предусмотрено. Завершите проверку анализом журнала регистрации на предмет ошибок за период тестирования.
Как проверить результат
Точка останова в отладчике останавливается на первой строке процедуры
Объект записывается без входа в обработчик — проверьте источник и обновление конфигурации
Обработчик срабатывает или корректно пропускается по флагу в ДополнительныеСвойства
Массовая обработка вызывает лишние срабатывания и замедляется
Нет ошибок вызова обработчика и ошибок доступа
Ошибки «процедура не обнаружена» или нарушение прав доступа
Частые вопросы о подписках на события
В каком порядке вызываются несколько подписок на одно событие?
Платформа не гарантирует порядок вызова подписок друг относительно друга. Если логика зависит от последовательности, объедините обработчики в одну подписку и управляйте порядком внутри неё, либо передавайте промежуточные результаты через ДополнительныеСвойства объекта.
Можно ли отменить запись объекта из подписки?
Да, в событиях ПередЗаписью, ОбработкаПроведения и ОбработкаПроверкиЗаполнения установите параметр Отказ = Истина. Транзакция записи будет отменена, объект не сохранится. В ПриЗаписи отмена тоже технически работает через исключение, но это менее корректный способ.
Нарушит ли подписка обновление типовой конфигурации?
Нет, подписки — самостоятельные объекты метаданных и не изменяют типовые модули. При обновлении они сохраняются. Риск возникает только если типовая логика изменилась настолько, что обработчик обращается к переименованным или удалённым реквизитам — такие места проверяйте после каждого обновления.
Срабатывает ли подписка при обмене данными и загрузке из файлов?
Да, подписки вызываются при любой записи объекта, включая обмены и пакетную загрузку. Чтобы обработчик не мешал обмену, проверяйте в нём условие Источник.ОбменДанными.Загрузка — при загрузке через механизмы обмена этот флаг обычно установлен, и логику нужно пропускать.
Как временно отключить подписку без удаления?
Если подписка создана в основной конфигурации, отключить её без изменения конфигурации нельзя — только удалить обработчик или добавить в код условие-переключатель (например, константу «ОтключитьПодписки»). Если логика вынесена в расширение, достаточно снять с расширения флаг активности или удалить из него подписку.
Чем подписка отличается от обработчика в модуле объекта?
Обработчик модуля объекта — часть типового кода, его изменение усложняет обновление. Подписка вызывается после обработчика модуля объекта и хранится отдельно. Функционально они получают одинаковые параметры, но подписка предпочтительнее для доработок, а модуль объекта — для базовой логики самого объекта.
Что важно запомнить
Подписка на событие связывает событие объекта с процедурой в серверном общем модуле и срабатывает автоматически при записи или проведении. Держите обработчик коротким, защищайтесь от рекурсии флагами в ДополнительныеСвойства, учитывайте права пользователей и тестируйте на копии базы перед включением в работе.