В процессе эксплуатации информационных систем на базе 1С, особенно таких нагруженных, как «Бухгалтерия предприятия 3.0», администраторы часто сталкиваются с проблемой избыточного обмена данными. Типичная ситуация: пользователю необходимо, чтобы документ регистрировался для обмена при его создании или ручном редактировании (сохранении), но при этом массовое перепроведение документов (например, при закрытии месяца или выполнении групповых обработок) не должно приводить к «вываливанию» тысяч неизменных объектов в очередь обмена. Рассмотрим подробно, как решить эту задачу программно.
Для начала разберем внутреннюю механику платформы 1С. Важно понимать, что метод Провести() не существует в вакууме — он всегда инициирует запись объекта. Таким образом, когда пользователь нажимает «Провести и закрыть», срабатывает целая цепочка событий: ПередЗаписью, ПриЗаписи, а внутри этой транзакции — логика проведения. Если в плане обмена для данного документа установлено свойство «Авторегистрация — Разрешить», платформа регистрирует изменения автоматически в момент фиксации транзакции записи.
Проблема, озвученная в обсуждении, заключается в том, что стандартная попытка удалить регистрацию в событии ПриПроведении часто оказывается неэффективной или запоздалой. Выясним причину: событие ПриПроведении срабатывает уже после того, как основные механизмы регистрации «пометили» объект. Кроме того, удаление регистрации внутри транзакции может конфликтовать с автоматическими механизмами платформы.
Самый надежный и «чистый» способ предотвратить регистрацию — это управление коллекцией ОбменДанными.Получатели непосредственно перед тем, как платформа начнет процесс записи. Проанализируем, как это реализовать через подписку на событие ПередЗаписью.
Алгоритм действий следующий:
ПередЗаписью для интересующих нас документов.Посмотрим на пример кода:
Процедура ПередЗаписьюДокументаДляОбмена(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Если это не проведение, ничего не трогаем
Если РежимЗаписи <> РежимЗаписиДокумента.Проведение Тогда
Возврат;
КонецЕсли;
// Отключаем автоматическое заполнение списка получателей
Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
// Очищаем коллекцию, чтобы регистрация не создалась
Источник.ОбменДанными.Получатели.Очистить();
КонецПроцедуры
Этот метод хорош тем, что он предотвращает само создание записи в таблице изменений, а не пытается удалить её постфактум. Это экономит ресурсы сервера и исключает блокировки таблиц регистрации.
Рассмотрим ситуацию, когда логика определения «нужна ли регистрация» более сложная и рассредоточена по разным модулям. Мы можем использовать свойство ДополнительныеСвойства объекта для передачи флага между событиями ПередЗаписью и ПриЗаписи.
Разберем по шагам:
ПередЗаписью анализируем контекст. Например, если это проведение, устанавливаем наш флаг.ПриЗаписи (когда ссылка документа уже точно существует в базе) проверяем наличие флага и выполняем удаление регистрации.Пример реализации в модуле документа или подписке:
// В обработчике ПередЗаписью
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
Источник.ДополнительныеСвойства.Вставить("ОтказОтРегистрацииПриПроведении", Истина);
КонецЕсли;
// В обработчике ПриЗаписи
Если Источник.ДополнительныеСвойства.Свойство("ОтказОтРегистрацииПриПроведении")
И Источник.ДополнительныеСвойства.ОтказОтРегистрацииПриПроведении Тогда
УзелОбмена = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоКоду("001");
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, Источник.Ссылка);
КонецЕсли;
Важный нюанс: как было отмечено в сообщении №8 форума, при таком подходе есть риск «потерять» важные изменения. Если пользователь одновременно изменил сумму в документе и нажал «Провести», то отмена регистрации при проведении приведет к тому, что новые данные не попадут в обмен. Поэтому данный метод стоит использовать с осторожностью или дополнять проверкой модифицированности данных.
Если ваша конфигурация построена на Библиотеке стандартных подсистем (БСП), как в случае с БП 3.0, лучше всего использовать встроенные механизмы правил регистрации объектов. В БСП можно настроить регистрацию так, чтобы она срабатывала только при изменении значимых реквизитов (например, контрагента, суммы или даты).
Проанализируем преимущества этого подхода:
Для настройки этого механизма не нужно писать код. Достаточно зайти в раздел Администрирование — Синхронизация данных — Состав отправляемых данных и настроить правила регистрации для конкретных объектов, указав список контролируемых полей. Для автоматизации регулярной отправки зарегистрированных объектов по расписанию без изменения конфигураций можно использовать программу регулярного обмена данными между базами 1С.
Выясним причину неудачи автора темы (сообщение №7). Когда мы вызываем УдалитьРегистрациюИзменений внутри процедуры ПриПроведении, транзакция записи объекта еще не завершена. Платформа 1С работает таким образом, что автоматическая регистрация изменений (согласно настройкам плана обмена) может быть «накатана» финальным аккордом в момент завершения всей транзакции (Commit). Таким образом, ваш программный вызов удаления срабатывает раньше, чем платформа завершает свою автоматическую операцию записи изменений. Именно поэтому управление коллекцией Источник.ОбменДанными.Получатели в событии ПередЗаписью является более приоритетным и корректным методом.
Для решения задачи «Запись — регистрируем, проведение — нет» мы рекомендуем придерживаться следующей стратегии:
ПередЗаписью с очисткой ОбменДанными.Получатели, но только при условии, что РежимЗаписи = РежимЗаписиДокумента.Проведение.ОбработкаПроведения).Используя эти методы, вы сможете существенно снизить нагрузку на каналы связи и ускорить процессы закрытия периода в 1С. Чтобы гарантировать отсутствие расхождений в учете после оптимизации правил регистрации, рекомендуется выполнять автоматическую сверку бухгалтерских проводок между базами 1С.