При настройке синхронизации данных между конфигурациями 1С (например, выполняя регистрацию объектов для обмена между "Управление торговлей" и "Бухгалтерия предприятия") часто возникает задача частичного обновления объектов. Распространенный сценарий: элементы справочников должны создаваться автоматически, если они новые, но если элемент уже существует в базе-приемнике, его наименование не должно перезаписываться данными из источника. Это актуально, когда бухгалтеры переименовывают номенклатуру или контрагентов для своего удобства (например, добавляют пометки), и стандартный обмен постоянно "затирает" эти изменения.
Разберем подробно, как реализовать такую логику, используя механизмы конвертации Enterprise Data (ED) и возможности платформы 1С.
Стандартная логика обмена через универсальный формат (Enterprise Data) предполагает, что если объект найден по ключевым полям (обычно это УникальныйИдентификатор), то все его поля обновляются значениями из пришедшего файла XML. В некоторых случаях, когда типовой механизм не справляется, может использоваться специализированная обработка для загрузки в Бухгалтерию 3.0 в формате XML. Нам же необходимо вмешаться в сам процесс загрузки.
В ходе обсуждения мы выяснили, что наиболее подходящим местом для внедрения своей логики является обработчик события, которое возникает непосредственно перед записью данных в базу. В современных конфигурациях на базе БСП, к которым относится БП 3.0, это событие ПередЗаписьюПолученныхДанных.
Давайте рассмотрим, где находится этот код и как его правильно модифицировать. Если при настройке взаимодействия возникают технические проблемы, рекомендуем изучить исправление ошибок синхронизации между Бухгалтерией 3.0 и УТ 10.3.
Данный обработчик располагается в Модуле менеджера конкретного объекта (справочника или документа). Именно там происходит преобразование данных из объекта XDTO (формат обмена) в объект информационной базы.
Основная идея решения, предложенная коллегами, заключается в следующем: мы подменяем значение наименования, пришедшее из обмена, на то значение, которое уже есть в базе данных.
Рассмотрим базовый пример кода, который нужно поместить в расширение конфигурации (в модуль менеджера справочника, например, "Номенклатура"):
Процедура ПередЗаписьюПолученныхДанных(ПолученныеДанные, ДанныеИБ, ПараметрыОбмена, Отказ)
// ПолученныеДанные - это структура с данными, пришедшими из файла (то, что планируется записать)
// ДанныеИБ - это ссылка или объект, который уже существует в базе (или Новый, если его нет)
// Внимание! Этот код требует доработки (см. ниже), но демонстрирует принцип:
ПолученныеДанные.Наименование = ДанныеИБ.Наименование;
КонецПроцедуры
Однако, если использовать этот код "в лоб", мы столкнемся с серьезной ошибкой: новые элементы будут создаваться с пустыми наименованиями. Давайте разберем этот нюанс.
Когда в базу приходит совершенно новый элемент, переменная ДанныеИБ хоть и существует как объект в памяти, но в базе её еще нет, и её реквизиты могут быть не заполнены. Если мы безусловно присвоим ПолученныеДанные.Наименование = ДанныеИБ.Наименование, то для нового товара наименование станет пустым. Неправильная настройка сопоставления на этом этапе — частая проблема, из-за которой позже может потребоваться замена дублей договоров или организаций в документах.
Поэтому критически важно добавить условие проверки новизны объекта. Нам поможет метод ЭтоНовый().
Правильный алгоритм действий:
ДанныеИБ) и подставляем его в структуру загружаемых данных (ПолученныеДанные).Скорректированный код будет выглядеть так:
Процедура ПередЗаписьюПолученныхДанных(ПолученныеДанные, ДанныеИБ, ПараметрыОбмена, Отказ)
// Проверяем, записан ли объект в базе
Если Не ДанныеИБ.ЭтоНовый() Тогда
// Если объект старый, сохраняем наше текущее наименование
ПолученныеДанные.Наименование = ДанныеИБ.Наименование;
КонецЕсли;
КонецПроцедуры
Еще один важный вопрос: "А не сломает ли это другие обмены?". Действительно, этот код в модуле менеджера сработает для любого обмена через Enterprise Data (Синхронизация с УТ, с ЗУП или использование правил обмена БП 3.0 — УНФ 3.0).
Если вам нужно, чтобы правило действовало только при обмене с конкретной базой, необходимо использовать параметр ПараметрыОбмена. Чтобы убедиться, что данные после такой фильтрации остаются корректными, можно использовать способ сверки документов между конфигурациями через http-сервис.
Доработаем наш пример, добавив проверку плана обмена:
Процедура ПередЗаписьюПолученныхДанных(ПолученныеДанные, ДанныеИБ, ПараметрыОбмена, Отказ)
// Примерная проверка, нужно подставить свой план обмена и код узла
НужныйУзел = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоКоду("UT01");
Если ПараметрыОбмена.Отправитель = НужныйУзел И Не ДанныеИБ.ЭтоНовый() Тогда
ПолученныеДанные.Наименование = ДанныеИБ.Наименование;
КонецЕсли;
КонецПроцедуры
В современных версиях БСП существует еще более элегантный способ, который не требует перезаписывать данные, а просто говорит системе "не трогай это поле".
Наиболее надежным и простым методом для типовых конфигураций остается именно явное присвоение значения в ПолученныеДанные, как показано в примерах выше, так как структура ПолученныеДанные формируется непосредственно перед заполнением объекта.
Чтобы не снимать конфигурацию с поддержки, мы настоятельно рекомендуем использовать Расширения конфигурации.
Номенклатура или Контрагенты).Правильный шаблон для расширения:
&После("ПередЗаписьюПолученныхДанных")
Процедура Расш_ПередЗаписьюПолученныхДанных(ПолученныеДанные, ДанныеИБ, ПараметрыОбмена, Отказ)
Если Не ДанныеИБ.ЭтоНовый() Тогда
// Восстанавливаем наименование, которое было в базе
// Важно: проверяем, есть ли такое свойство в полученных данных
Если ПолученныеДанные.Свойство("Наименование") Тогда
ПолученныеДанные.Наименование = ДанныеИБ.Наименование;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Используя этот подход, вы безопасно решите проблему перезаписи наименований, сохранив возможность автоматического создания новых элементов при обмене.