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