Как программно изменить дополнительные реквизиты объекта без срабатывания подписок на событие ПриЗаписи

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ проблемы: почему срабатывают подписки

Проанализируем ситуацию. В современных конфигурациях на базе БСП для работы с дополнительными реквизитами чаще всего используется общий модуль УправлениеСвойствами. Типовой вызов выглядит так:

УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаОбъект, ТаблицаСвойств);

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

Решение 1: Прямая работа с табличной частью объекта

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

Рассмотрим пошаговый алгоритм реализации этого метода во внешней обработке:

  1. Получаем объект документа или справочника через метод ПолучитьОбъект().
  2. Находим нужную строку в табличной части по ссылке на свойство (ПланВидовХарактеристик ДополнительныеРеквизитыИСведения).
  3. Если строка найдена — обновляем значение. Если нет — добавляем новую строку.
  4. Устанавливаем свойство ОбменДанными.Загрузка = Истина.
  5. Вызываем метод Записать().

Проанализируем пример кода:


// ОбъектСсылка - ссылка на документ, который нужно изменить
// СвойствоСсылка - ссылка на ПВХ ДополнительныеРеквизитыИСведения
// НовоеЗначение - значение, которое нужно установить

ОбъектДок = ОбъектСсылка.ПолучитьОбъект();

// Поиск существующего реквизита в табличной части
ПараметрыОтбора = Новый Структура("Свойство", СвойствоСсылка);
НайденныеСтроки = ОбъектДок.ДополнительныеРеквизиты.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() > 0 Тогда
    СтрокаРеквизита = НайденныеСтроки[0];
Иначе
    СтрокаРеквизита = ОбъектДок.ДополнительныеРеквизиты.Добавить();
    СтрокаРеквизита.Свойство = СвойствоСсылка;
КонецЕсли;

СтрокаРеквизита.Значение = НовоеЗначение;

// Ключевой момент для отключения подписок
ОбъектДок.ОбменДанными.Загрузка = Истина;

Попытка
    ОбъектДок.Записать();
Исключение
    Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
КонецПопытки;

Важно: Установка ОбменДанными.Загрузка = Истина является стандартным сигналом для платформы и разработчиков конфигураций о том, что объект записывается в режиме обмена или программной загрузки. В 99% типовых подписок в начале кода стоит проверка: Если Источник.ОбменДанными.Загрузка Тогда Возврат; КонецЕсли;. Именно это позволяет нам миновать выполнение лишней логики.

Решение 2: Адаптация функций БСП внутри обработки

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

В этом случае мы берем код из общего модуля, переносим его в модуль обработки и в том месте, где вызывается Объект.Записать(), принудительно добавляем установку флага Загрузка.

Решение 3: Разница между реквизитами и сведениями

Разберем важный нюанс. В БСП существует два типа свойств:

Если ваша задача позволяет использовать сведения вместо реквизитов, то проблема с подписками отпадает сама собой. При записи сведений через УправлениеСвойствами.ЗаписатьСведенияУОбъекта сам объект документа не перезаписывается, а значит, подписка ПриЗаписи на документ не срабатывает. Работа идет исключительно с набором записей регистра.

Риски использования режима Загрузка = Истина

Проанализируем ситуацию с точки зрения безопасности данных. При использовании ОбменДанными.Загрузка = Истина отключаются не только ваши подписки, но и:

  1. Стандартные платформенные проверки (например, проверка уникальности кодов, если она не переопределена).
  2. Типовые проверки БСП на заполнение обязательных полей.
  3. Механизм версионирования (изменение может не попасть в историю изменений объекта).
  4. Автоматическое формирование движений, если оно привязано к событию записи.

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

Резюме

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

← На главную