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