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

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

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

Что такое подписки на события в 1С, как они работают, когда их использовать вместо модулей объектов. Пошаговая настройка, примеры кода, типичные ошибки и FAQ.

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

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

Механизм активно используется и в собственных разработках: он помогает централизовать сквозную логику (заполнение ответственного, проверка уникальности, регистрация изменений для обмена), не дублируя её в десятках модулей объектов.

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

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

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

Обработчик получает те же параметры, что и одноимённое событие модуля объекта. Например, для события «ПриЗаписи» процедура получает параметры «Источник» (сам объект) и «Отказ». Установка Отказ = Истина внутри подписки прерывает запись точно так же, как в модуле объекта.

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

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

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

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

Когда подписки нужны, а когда лучше изменить модуль объекта

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

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

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

Подписка или модуль объекта

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

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

Модуль объекта

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

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

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

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

Рассмотрим практический пример: при записи документа «Реализация товаров и услуг» нужно автоматически проставлять признак отправки в интеграционную систему. Все действия выполняются в конфигураторе на копии базы.

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

Пример кода обработчика в общем модуле:

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

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

Возврат;

КонецЕсли;

Если Источник.ОбменДанными.Загрузка Тогда

Возврат; // не срабатываем при загрузке через обмен

КонецЕсли;

// Проверка и заполнение реквизита

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

РегистрыСведений.ОчередьИнтеграции.ДобавитьВОчередь(Источник.Ссылка);

КонецЕсли;

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

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

Проверка результата и отладка

Проверить работу подписки проще всего через журнал регистрации: добавьте в обработчик вызов ЗаписьЖурналаРегистрации с текстом события, запишите документ и убедитесь, что запись появилась. Для отладки установите точку останова в обработчике и запустите отладку — платформа остановится в процедуре при записи объекта.

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

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

Срабатывание обработчика
Норма

В журнале регистрации есть запись из обработчика после записи документа

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

Записи нет — проверьте тип источника, событие и то, что конфигурация БД обновлена

Отказ от записи
Норма

При Отказ = Истина документ не записывается, пользователь видит сообщение

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

Документ записывается несмотря на Отказ — вероятно, обработчик не вызывается или Отказ сбрасывается позже

Работа при обмене
Норма

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

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

Обмен зацикливается или создаёт лишние записи — отсутствует проверка ОбменДанными.Загрузка

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

Время записи документа выросло незначительно

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

Запись замедлилась в разы — в обработчике тяжёлые запросы или запись других объектов

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

Типичные ошибки и риски

Типичные ошибки
01
Запись других объектов внутри подписки ПриЗаписи без необходимости — это удлиняет транзакцию, повышает риск взаимоблокировок и может вызвать каскадное срабатывание других подписок.
02
Отсутствие проверки ОбменДанными.Загрузка — при обмене данными выполняется бизнес-логика, что приводит к зацикливанию обменов и дублированию данных.
03
Тяжёлые запросы в обработчике — каждая запись документа замедляется, при пакетной записи тысяч документов система практически останавливается.
04
Зависимость одной подписки от результата другой — порядок вызова подписок не гарантирован платформой, логика периодически ломается.
05
Изменение Источника в событии ПриЗаписи — изменения реквизитов на этом этапе могут не сохраниться; для модификации данных используйте ПередЗаписью.
06
Дублирование логики: одна и та же проверка реализована и в модуле объекта, и в подписке — при изменении требований правится только одно место, возникает рассинхронизация.

Отдельный риск — рекурсия. Если в обработчике ПриЗаписи документа вы записываете тот же или связанный документ, на который тоже есть подписка, можно получить бесконечный цикл вызовов. Защищайтесь проверками через ДополнительныеСвойства или признаки в параметрах сеанса.

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

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

Ограничения механизма: подписки не перехватывают события форм, не работают на клиенте, не позволяют задать порядок выполнения и не вызываются при прямом изменении данных вне объектной модели (например, запросом с конструкцией ИЗМЕНЕНИЕ — хотя такая практика сама по себе запрещена для ссылочных объектов). Также подписка не сработает, если запись выполняется с установленным ОбменДанными.Загрузка = Истина и обработчик сам это учитывает — помните об этом при проектировании интеграций.

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

Альтернативы подпискам на события

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

Маршрут решения

Как выбрать действие

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

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

Подписка на событие связывает событие объекта с процедурой в общем модуле и позволяет расширять логику без изменения типового кода. Всегда проверяйте ОбменДанными.Загрузка, не размещайте тяжёлый код в транзакции записи, помните о негарантированном порядке вызова подписок и тестируйте на копии базы.

Частые вопросы

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

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

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

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

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

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

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

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

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

Функционально обработчик подписки получает те же параметры и может делать то же самое. Различия: подписка хранится отдельно от объекта и не требует снятия с поддержки; вызывается после обработчика модуля объекта; одна подписка может обслуживать сразу несколько типов объектов.

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

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