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