При работе с обменами данными в 1С через механизм Конвертации Данных 2.0 (КД2) часто возникают ситуации, когда необходимо трансформировать или подменять определенные данные. Одна из распространенных задач – это замена одной организации на другую в документах, которые выгружаются из базы-источника в базу-приемник. Например, когда в базе-источнике существует несколько организаций (Орг1, Орг2), а в базе-приемнике должна использоваться только одна – Орг1, независимо от того, какая организация была указана в исходном документе.
Давайте подробно рассмотрим, как решить эту задачу, используя различные подходы и обработчики событий КД2.
Этот подход считается наиболее корректным, так как он позволяет подготовить данные еще до их отправки в базу-приемник. Мы будем работать с Правилами Конвертации Объектов (ПКО) и Правилами Конвертации Свойств (ПКС).
Этот способ позволяет централизованно управлять тем, какая организация будет "представлять" выгружаемую организацию в приемнике. Если в источнике есть Орг1 и Орг2, и мы хотим, чтобы все ссылки на них в приемнике стали ссылками на Орг1, мы можем переопределить выгружаемое значение непосредственно в ПКО для справочника "Организации".
Для этого откроем ПКО справочника "Организации" и найдем обработчик события "ПриВыгрузке". В этом обработчике мы должны явно указать, какая ссылка будет выгружена.
Пример кода:
// В ПКО справочника "Организации", обработчик "ПриВыгрузке"
// Этот код будет выполняться каждый раз, когда КД2 пытается выгрузить объект типа "Организация".
// Мы переопределяем выгружаемое значение на "Орг1" из базы-источника.
// Находим нужную целевую организацию в базе-источнике по наименованию.
ОргСсылка = Справочники.Организации.НайтиПоНаименованию("Орг1");
Если ОргСсылка.Пустая() Тогда
// Если организация "Орг1" не найдена в базе-источнике, это может быть ошибкой
// или свидетельствовать о некорректной настройке.
// В этом случае можно вывести сообщение об ошибке,
// либо присвоить другое значение, либо прервать выгрузку.
Сообщить("Внимание! Целевая организация 'Орг1' не найдена в базе-источнике. " +
"Выгрузка организации может быть некорректной.");
// Если мы не хотим, чтобы вообще какая-либо организация выгружалась
// или чтобы выгружалась исходная Орг2, можно установить Отказ = Истина
// Отказ = Истина;
// Или, в зависимости от логики, можно оставить исходное Значение
Иначе
// Присваиваем Значение целевой организации.
// Это Значение будет использовано при конвертации данного объекта "Организация".
Значение = ОргСсылка;
КонецЕсли;
Важные моменты:
Значение в обработчике "ПриВыгрузке" ПКО определяет, какой объект будет далее конвертирован и передан в приемник. Присвоив ей ссылку на "Орг1" из источника, мы фактически заставляем все ссылки на организации в связанных ПКС указывать на "Орг1".Если мы хотим более гранулированного контроля или если предыдущий подход по какой-то причине не подходит, мы можем изменить значение организации непосредственно в каждом Правиле Конвертации Свойств (ПКС) для реквизита "Организация" каждого документа (например, "РеализацияТоваровУслуг", "ДоговорКонтрагента").
Для этого откроем ПКО нужного документа (например, "РеализацияТоваровУслуг"), найдем ПКС для реквизита Организация и добавим код в обработчик события "ПередВыгрузкой" или "ПриВыгрузке".
Пример кода (в ПКС "Организация" ПКО документа, обработчик "ПередВыгрузкой"):
// В ПКС реквизита "Организация" в ПКО документа (например, РеализацияТоваровУслуг)
// Обработчик "ПередВыгрузкой"
// Этот код выполняется перед конвертацией свойства "Организация" для каждого документа.
// Находим нужную целевую организацию в базе-источнике.
ЦелеваяОрганизация = Справочники.Организации.НайтиПоНаименованию("Орг1");
Если ЦелеваяОрганизация.Пустая() Тогда
// Если "Орг1" не найдена в источнике, необходимо решить, что делать.
// Можно вывести сообщение, прервать выгрузку свойства или всего документа.
Сообщить("Внимание! Организация 'Орг1' не найдена в источнике. " +
"Невозможно подменить организацию для документа: " + Источник.Представление());
Отказ = Истина; // Прервать выгрузку свойства, если это критично
Иначе
// Присваиваем переменной Значение ссылку на нужную организацию.
// Это значение будет передано далее для конвертации.
Значение = ЦелеваяОрганизация;
КонецЕсли;
Пояснения:
Этот подход позволяет гарантировать, что в базе-приемнике новая организация не будет создана, а будет всегда найдена существующая "Орг1".
Код или Наименование.Значение = "Орг1" (или соответствующий код "Орг1", если поиск по коду).Пример кода (в ПКС "Наименование" ПКО "Организации", обработчик "ПередВыгрузкой"):
// В ПКС реквизита "Наименование" в ПКО справочника "Организации"
// Обработчик "ПередВыгрузкой"
// Присваиваем жестко заданное наименование, по которому будет происходить поиск
Значение = "Орг1";
При таком подходе, даже если из источника придет "Орг2", КД2 будет пытаться найти в приемнике организацию с наименованием "Орг1". Если она не будет найдена, а флаг "Не создавать новый объект приемника..." установлен, то новая организация не будет создана, и обмен может завершиться ошибкой или ссылкой на пустую организацию, в зависимости от настроек.
Данный подход применяется, когда нет возможности или желания изменять правила выгрузки в базе-источнике. Мы будем менять данные уже в процессе загрузки в базу-приемник. Хотя этот метод часто называют "моветоном" (не лучшей практикой) из-за потенциальных проблем с консистентностью данных и усложнения логики, иногда он является единственным выходом.
Обработчик "ПриЗагрузке" в ПКО документа выполняется после создания объекта в базе-приемнике, но до его записи. В этот момент мы можем модифицировать реквизиты объекта.
Пример кода (в ПКО документа, обработчик "ПриЗагрузке"):
// В ПКО документа (например, РеализацияТоваровУслуг), обработчик "ПриЗагрузке"
// Объект уже создан в базе-приемнике, но еще не записан.
// Находим нужную целевую организацию в базе-приемнике.
ЦелеваяОрганизацияПриемник = Справочники.Организации.НайтиПоНаименованию("Орг1");
Если ЦелеваяОрганизацияПриемник.Пустая() Тогда
// Если "Орг1" не найдена в приемнике, это критическая ошибка.
// Документ не сможет быть корректно загружен.
Сообщить("Критическая ошибка: Организация 'Орг1' не найдена в базе-приемнике! " +
"Документ " + Объект.Представление() + " будет загружен некорректно.");
Отказ = Истина; // Прерываем загрузку текущего объекта, если это необходимо
Иначе
// Присваиваем реквизиту "Организация" текущего объекта нужную ссылку.
Объект.Организация = ЦелеваяОрганизацияПриемник;
КонецЕсли;
Обработчик "ПослеЗагрузки" выполняется после того, как объект уже записан в базу-приемник. Если мы хотим изменить реквизит после записи, нам потребуется не только присвоить новое значение, но и явно перезаписать объект.
Пример кода (в ПКО документа, обработчик "ПослеЗагрузки"):
// В ПКО документа (например, РеализацияТоваровУслуг), обработчик "ПослеЗагрузки"
// Объект уже загружен и записан в базу-приемник.
// Находим нужную целевую организацию в базе-приемнике.
ЦелеваяОрганизацияПриемник = Справочники.Организации.НайтиПоНаименованию("Орг1");
Если ЦелеваяОрганизацияПриемник.Пустая() Тогда
Сообщить("Критическая ошибка: Организация 'Орг1' не найдена в базе-приемнике! " +
"Документ " + Объект.Представление() + " может быть некорректным.");
// Отказ = Истина; в этом обработчике не отменит запись объекта, если он уже записан.
// В случае критической ошибки, возможно, потребуется пометить объект на удаление.
Иначе
// Присваиваем реквизиту "Организация" текущего объекта нужную ссылку.
Объект.Организация = ЦелеваяОрганизацияПриемник;
// Важно: так как объект уже записан, для сохранения изменений его нужно перезаписать.
Попытка
Объект.Записать();
Исключение
Сообщить("Ошибка при перезаписи документа " + Объект.Представление() + " после смены организации: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Примечание: Использование "ПослеЗагрузки" для изменения уже записанных данных может быть менее производительным, так как требует дополнительной операции записи. Предпочтительнее работать в "ПриЗагрузке".
Существуют также методы, которые не требуют написания кода в обработчиках, но позволяют достичь того же результата.
Система 1С имеет механизм сопоставления объектов. Вы можете вручную или программно сопоставить GUID организации "Орг2" из источника с GUID организации "Орг1" в приемнике.
Это делается через формы сопоставления объектов, доступные в настройках обмена данными. Для большинства типовых конфигураций можно найти пункт меню типа "Настройка синхронизации данных" -> "Соответствие объектов информационных баз". В этом окне вы можете указать, что объект с определенным идентификатором из одной базы соответствует объекту с другим идентификатором в другой базе.
Данный способ удобен для разового или редкого сопоставления, но может быть трудоемким для большого количества объектов или частых изменений.
Для более гибкого сопоставления можно использовать регистр сведений "Публичные идентификаторы". Этот регистр позволяет хранить соответствие УИДов (уникальных идентификаторов) объектов между разными информационными базами. Мы можем прописать, что УИД "Орг2" из базы-источника должен быть сопоставлен с УИД "Орг1" в базе-приемнике.
В оригинальной теме автор пришел к решению, комбинируя несколько подходов, что свидетельствует о гибкости КД2. Автор применил код в обработчике "ПриВыгрузке" ПКО справочника "Организации" и, возможно, дополнительно в ПКС реквизита "Организация" для конкретных документов (таких как "РеализацияТоваровУслуг" и "ДоговорКонтрагента").
Финальный рабочий код, который был использован, следующий:
// В ПКО справочника "Организации", обработчик "ПриВыгрузке"
// И/ИЛИ
// В ПКС реквизита "Организация" в ПКО документа (например, РеализацияТоваровУслуг), обработчик "ПриВыгрузке"
ОргСсылка = Справочники.Организации.НайтиПоНаименованию("Орг1");
Значение = ОргСсылка;
Этот код гарантирует, что при выгрузке, вместо исходной организации документа, будет передана ссылка на организацию с наименованием "Орг1", найденную в базе-источнике.
ПараметрыОбъекта можно передать ИНН и КПП нужной организации из источника и использовать их для поиска в обработчике "При загрузке" в базе-приемнике. Это позволяет находить организацию не только по наименованию, но и по более надежным реквизитам.
Отказ: Всегда помните о переменной Отказ в обработчиках. Она позволяет прервать дальнейшую обработку правила, если условия не выполнены, что может быть полезно для предотвращения некорректной выгрузки или загрузки данных.
Выбор метода зависит от конкретных требований к обмену, доступности баз данных и уровня контроля над ними. Наиболее чистым и рекомендуемым подходом является модификация на стороне выгрузки с использованием ПКО справочника "Организации" или специализированных настроек поиска, предотвращающих создание дублирующихся элементов в базе-приемнике.