Как работает подписка на событие «ПриЗаписи» регистра бухгалтерии и какие нюансы нужно учитывать?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

Работа с подписками на события — это мощный инструмент расширения функционала системы без изменения типовых механизмов. Однако при работе с такими высоконагруженными объектами, как Регистр бухгалтерии, возникает множество вопросов: «Увидит ли запрос новые данные?», «Не уйдет ли система в бесконечный цикл?» и «Как это отразится на скорости закрытия месяца?». Разберем эти аспекты подробно.

Видимость данных внутри транзакции: увидит ли запрос новые движения?

Рассмотрим ситуацию, когда в подписке на событие ПриЗаписи нам необходимо проанализировать данные регистра с помощью запроса. В этот момент выполнение кода происходит внутри транзакции записи. Согласно механизмам платформы 1С, данные физически уже записаны в таблицы базы данных, но транзакция еще не зафиксирована (не выполнен Commit).

Проанализируем, что это означает на практике:

  1. Внутри текущего сеанса: Если мы выполняем запрос к регистру бухгалтерии в той же процедуре (в том же соединении с БД), система увидит новые движения. Это происходит потому, что текущая транзакция имеет доступ к собственным изменениям.
  2. Для других пользователей: До момента полного завершения процедуры подписки и фиксации транзакции документа-регистратора другие пользователи системы эти данные не увидят.
  3. Нюанс с итогами: Важно помнить, что итоги регистра могут пересчитываться в самом конце. Поэтому выполнение запроса к виртуальным таблицам (например, ОстаткиИОбороты) внутри транзакции может быть менее эффективным или давать специфические результаты, если границы периода не указаны явно.

Вывод: Запрос увидит данные, но использовать его нужно крайне осторожно.

Рекурсия и риск бесконечного цикла

Выясним, что произойдет, если внутри подписки ПриЗаписи выполнить метод НаборЗаписей.Записать(). Ответ однозначный: это приведет к повторному вызову этой же самой подписки. Если не предусмотреть защитный механизм, система уйдет в бесконечную рекурсию, что закончится аварийным завершением работы или ошибкой переполнения стека.

Рассмотрим правильный способ решения этой задачи с использованием свойства ДополнительныеСвойства. Этот объект позволяет передавать параметры «сквозь» вызовы процедур в рамках одного экземпляра объекта.

Разберем пример кода для обхода рекурсии:


Процедура ПриЗаписиРегистраБухгалтерии(Источник, Отказ) Экспорт
    
    // Проверяем, не является ли этот вызов техническим (рекурсивным)
    Если Источник.ДополнительныеСвойства.Свойство("ЭтоТехническаяЗапись") Тогда
        Возврат;
    КонецЕсли;
    
    // Выполняем необходимые манипуляции с данными...
    
    // Перед программной записью устанавливаем флаг
    Источник.ДополнительныеСвойства.Вставить("ЭтоТехническаяЗапись", Истина);
    
    Попытка
        Источник.Записать();
    Исключение
        // Обработка ошибки записи
    КонецПопытки;

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

Использование флага в ДополнительныеСвойства — это стандарт де-факто при разработке на платформе 1С для предотвращения зацикливания обработчиков событий.

Двойной вызов события: миф или реальность?

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

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

Производительность и блокировки в Бухгалтерии 3.0

Особое внимание уделим ситуации с документом РегламентнаяОперация при закрытии месяца. Этот документ может порождать тысячи и десятки тысяч проводок. Выполнение тяжелых запросов внутри подписки на каждое такое движение может катастрофически замедлить процесс.

Рассмотрим основные риски:

  1. Блокировки (Deadlocks): В момент записи набора на таблицы регистра накладываются исключительные блокировки. Если ваш запрос внутри подписки попытается прочитать те же таблицы с использованием сложных соединений или виртуальных таблиц, это может привести к взаимной блокировке (Deadlock), особенно при параллельной работе пользователей или фоновых заданий.
  2. Нагрузка на память: Вместо выполнения запроса к базе данных (который снова полезет в таблицы SQL), гораздо эффективнее анализировать сам объект Источник. Это коллекция записей, которая уже находится в оперативной памяти. Пробежаться циклом по Источник и собрать нужные суммы гораздо быстрее, чем дергать СУБД новым запросом.

Проанализируем пример эффективной обработки данных без запроса:


Для Каждого Запись Из Источник Цикл
    Если Запись.СчетДт = ПланыСчетов.Хозрасчетный.ОбщехозяйственныеРасходы Тогда
        // Выполняем логику анализа данных на лету
    КонецЕсли;
КонецЦикла;

Особенности отладки в фоновых заданиях

В современных версиях конфигурации «Бухгалтерия предприятия 3.0» многие регламентные операции выполняются в фоновых заданиях. Если вы поставите точку останова в процедуре подписки и запустите закрытие месяца, отладчик может не сработать. Для анализа работы кода необходимо либо настроить автоматическое подключение к фоновым заданиям в параметрах отладчика, либо использовать запись в ЖурналРегистрации для проверки хода выполнения программы.

Рекомендации

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

← На главную