Мы часто сталкиваемся со сценариями, где данные необходимо передавать между различными конфигурациями 1С, например, из сильно переписанной 1С:Управление торговлей 10.3 в типовую 1С:Бухгалтерия предприятия 3.0, которая находится "на замке". В таких случаях возникает острая необходимость в надежной идентификации объектов, таких как контрагенты и договоры, чтобы избежать дублирования и ошибок при загрузке документов. Стандартные методы идентификации, такие как ИНН, КПП, номер и дата договора, а также наименование, оказываются ненадежными, поскольку эти данные могут внезапно меняться. В этой ситуации на помощь приходят внутренние уникальные идентификаторы ГУИД (GUID). Мы подробно рассмотрим, как их использовать для связывания баз и как решить специфические проблемы, возникающие при работе с ГУИД в запросах через COM-соединение.
Прежде чем углубляться в использование ГУИД, давайте разберем, почему традиционные методы сопоставления объектов часто подводят, особенно в реальных условиях эксплуатации:
В условиях, когда данные создаются и корректируются "как кому хочется", автоматизировать процесс сопоставления на основе таких изменчивых параметров практически невозможно. Здесь требуется универсальный и неизменный идентификатор, и ГУИД прекрасно справляется с этой задачей, обеспечивая уникальность объекта вне зависимости от его изменяющихся реквизитов.
После того как мы приняли решение использовать ГУИД для надежной идентификации, возникает вопрос: как хранить этот ГУИД из одной базы в другой? Мы рассмотрим два основных подхода, оба из которых являются типовым функционалом платформы 1С.
Это типовой и рекомендуемый подход для решения задач по сопоставлению объектов при обмене данными. РегистрСведений.СоответствияОбъектовИнформационныхБаз специально создан в конфигурациях, использующих Библиотеку стандартных подсистем (БСП), для хранения связей между объектами в разных информационных базах. Он предназначен для управления синхронизацией данных и является центральным элементом механизма обмена.
УникальногоИдентификатора текущей базы и УникальногоИдентификатора другой базы, а также служебные поля для управления синхронизацией.ГУИД происходит автоматически, минимизируя ручное вмешательство.Если конфигурация базы-приемника (например, БП 3.0) находится "на замке" и вы хотите избежать глубокой интеграции с механизмом синхронизации БСП, или если вам требуется лишь простое хранилище для ГУИД из исходной базы без сложной логики сопоставления, то дополнительные реквизиты могут быть более простым и наглядным решением.
1С:Бухгалтерии 3.0 (и многих других конфигурациях на БСП) предусмотрен функционал создания дополнительных реквизитов и сведений для справочников и документов без изменения конфигурации. Мы можем добавить новый дополнительный реквизит для справочника Контрагенты и ДоговорыКонтрагентов, например, с именем ГУИДИсточника, тип значения которого будет Строка. Выбираем тип Строка, так как он гарантированно позволяет хранить строковое представление ГУИД, полученное из другой базы.ГУИД контрагента и договора в УТ (например, через УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Ссылка)), а затем записывать его строковое представление в соответствующий дополнительный реквизит созданного или найденного контрагента/договора в БП.ГУИД отображается непосредственно в форме элемента справочника, что может быть удобно для отладки и ручной проверки.РегистраСведений.СоответствияОбъектовИнформационныхБаз.ГУИД всегда записывался в одном и том же строковом формате.Еще один подход, который относится к "классике синхронизации при обменах", состоит в том, чтобы сразу присваивать нужный ГУИД из исходной базы при создании нового элемента в базе-приемнике. Этот метод актуален для сценариев, где ГУИД является основным ключом идентификации объекта в обеих системах.
ГУИД отсутствует в БП, вместо того чтобы создавать новый элемент со своим внутренним ГУИД, мы явно присваиваем новому элементу в БП ГУИД, полученный из УТ. Для этого используются методы создания нового элемента, позволяющие передать ему уже существующий уникальный идентификатор, например:
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйКонтрагент.УстановитьСсылку(НовыйКонтрагент.ПолучитьСсылку(GUIDИзУТ));
// или
НовыйКонтрагент.УстановитьСсылку(Новый КонтрагентСсылка(GUIDИзУТ));
ГУИД в обеих базах, что значительно упрощает сопоставление и поиск. Отпадает необходимость в дополнительных полях для "чужого" ГУИД.ГУИД, так как он становится "родным". Поиск по ссылке (которая основана на ГУИД) является самым быстрым.ГУИД при создании объекта. Для типовой БП "на замке" это может быть проблематично без использования расширений.ГУИД (что маловероятно для новых ГУИД, но возможно при ошибках в логике обмена или ручном вмешательстве).ГУИД. Это также основной принцип, лежащий в основе работы распределенных информационных баз (РИБ).После того как мы успешно сохранили ГУИД из УТ в БП (будь то в дополнительном реквизите, регистре соответствий или присвоив его напрямую), следующая задача — использовать этот ГУИД для поиска объектов в запросах, особенно когда запрос выполняется через COM-соединение из внешней системы (или из УТ в БП).
Представим, что у нас есть такой фрагмент кода, где мы пытаемся получить данные о контрагенте по его ГУИД:
Если ЗначениеЗаполнено(ДанныеКонтрагента.ГУИДконтрагента) Тогда
УсловиеЗапроса = " | И ПРЕДСТАВЛЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(РеализацияТоваровУслугУслуги.Ссылка.Контрагент.Ссылка)) = &ГУИДКонтрагента ";
Иначе
УсловиеЗапроса = " | И РеализацияТоваровУслугУслуги.Ссылка.Контрагент.ИНН=&ИНН | И РеализацияТоваровУслугУслуги.Ссылка.Контрагент.КПП=&КПП";
КонецЕсли;
ЗапросБД = СоединениеБД.NewObject("Запрос");
ЗапросБД.Текст ="ВЫБРАТЬ
| РеализацияТоваровУслугУслуги.Ссылка КАК Ссылка,
| ПРЕДСТАВЛЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(РеализацияТоваровУслугУслуги.Ссылка.Контрагент.Ссылка)) КАК ГУИДКонтрагента,
// ... другие поля ...
|ИЗ
| Документ.РеализацияТоваровУслуг.Услуги КАК РеализацияТоваровУслугУслуги
|ГДЕ
// ... остальные условия ...
";
ЗапросБД.Текст = ЗапросБД.Текст + УсловиеЗапроса;
// ... установка параметров ...
ЗапросБД.УстановитьПараметр("ГУИДконтрагента",ДанныеКонтрагента.ГУИДконтрагента);
Однако такой подход часто не срабатывает. Давайте выясним причину и рассмотрим возможные решения.
УНИКАЛЬНЫЙИДЕНТИФИКАТОР(): Эта функция возвращает объект встроенного типа УникальныйИдентификатор. Это внутренний тип 1С, предназначенный для хранения GUID, и он не является строкой.ПРЕДСТАВЛЕНИЕ(): Применение функции ПРЕДСТАВЛЕНИЕ() к объекту типа УникальныйИдентификатор преобразует его в строковое представление. Однако формат этого строкового представления может быть специфичным для 1С (например, XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX без скобок) и не всегда совпадать с тем, как GUID представлен в строке, переданной из внешней системы или полученной другим способом (например, с фигурными скобками {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}). Даже небольшие отличия в форматировании (наличие/отсутствие дефисов, регистр символов) приведут к тому, что строки не будут считаться равными.&ГУИДКонтрагента через COM: Если вы передаете ГУИД как обычную строку через COM-соединение, то для 1С этот параметр является именно строкой. Сравнение ПРЕДСТАВЛЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(...)) (строка 1С) с &ГУИДКонтрагента (внешняя строка-параметр) может не дать ожидаемого результата из-за различий в форматировании или из-за особенностей неявных преобразований типов в COM-соединении.Суть проблемы: Мы пытаемся сравнить строковое представление ГУИД, полученное внутренними средствами 1С, со строковым значением, переданным как параметр. Эти строковые представления могут не быть идентичными по формату, что приводит к некорректной работе условия в запросе. 1С не "понимает", что две разные строки могут представлять один и тот же ГУИД, если их форматы отличаются.
Для корректного сравнения необходимо убедиться, что оба значения, участвующие в сравнении, имеют один и тот же тип и формат. В запросах 1С мы можем использовать функцию ВЫРАЗИТЬ для приведения к стандартному строковому виду, или, что предпочтительнее, сравнивать объекты типа УникальныйИдентификатор напрямую.
УникальныйИдентификатор: Это самый надежный способ. Если есть возможность, лучше передавать параметр не как строку, а как объект типа УникальныйИдентификатор 1С. Для этого в коде на стороне, выполняющей запрос через COM, нужно сначала преобразовать строковый ГУИД в объект УникальныйИдентификатор 1С:
// Предположим, ДанныеКонтрагента.ГУИДконтрагента - это строка, например, "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
ГУИДДляЗапроса = СоединениеБД.NewObject("УникальныйИдентификатор", ДанныеКонтрагента.ГУИДконтрагента);
ЗапросБД.УстановитьПараметр("ГУИДКонтрагента", ГУИДДляЗапроса);
УсловиеЗапроса = " | И РеализацияТоваровУслугУслуги.Ссылка.Контрагент.Ссылка = &ГУИДКонтрагента ";
Ссылка (которая по своей сути является УникальныйИдентификатор для объекта базы данных) с параметром типа УникальныйИдентификатор. Это наиболее эффективный и корректный способ.УникальныйИдентификатор в строку с фиксированным форматом: Если по каким-то причинам преобразовать параметр в УникальныйИдентификатор не получается, и вы вынуждены сравнивать строки, используйте ВЫРАЗИТЬ для получения гарантированного строкового формата ГУИД:
УсловиеЗапроса = " | И ВЫРАЗИТЬ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(РеализацияТоваровУслугУслуги.Ссылка.Контрагент.Ссылка) КАК СТРОКА(36)) = &ГУИДКонтрагента ";
ГУИД будет представлен в стандартном формате XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX (32 шестнадцатеричные цифры, разделенные четырьмя дефисами). При работе с внешними строковыми параметрами убедитесь, что они также представлены в этом формате. Например, если внешняя система передает GUID в формате с фигурными скобками (например, {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}), вам потребуется либо удалить эти скобки из параметра перед передачей в 1С, либо соответственно изменить строку запроса, включив их в выражение.Если прямое сравнение в запросе с преобразованием типов через COM вызывает затруднения или не работает так, как ожидается из-за специфики среды или ограничений, можно использовать обходное решение. Оно менее эффективно, поскольку предполагает выгрузку всех данных для последующего сравнения в клиентской части, но может быть полезно в безвыходных ситуациях или при небольших объемах данных.
ГУИД непосредственно в условии запроса 1С, мы сначала выполняем отдельный запрос для получения всех необходимых ГУИД объектов из базы 1С в виде строк. Затем выгружаем эти данные во временную таблицу значений и уже в коде на стороне клиента (или в вызывающей обработке, которая инициирует COM-соединение) выполняем перебор этой таблицы и сравнение с переданным строковым ГУИД.
Если ЗначениеЗаполнено(ДанныеКонтрагента.ГУИДконтрагента) Тогда
Запрос_БД = СоединениеБД.NewObject("Запрос");
Запрос_БД.Текст ="ВЫБРАТЬ
| ПРЕДСТАВЛЕНИЕ(УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Контрагенты.Ссылка)) КАК ГУИДКонтрагента,
| Контрагенты.ИНН КАК ИНН,
| Контрагенты.КПП КАК КПП
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
// Выполняем запрос и выгружаем результат в ТаблицуЗначений
ТЗ = Запрос_БД.Выполнить().Выгрузить();
Для Каждого Стр Из ТЗ Цикл
Если Стр.ГУИДКонтрагента = ДанныеКонтрагента.ГУИДконтрагента Тогда
ДляПоискаИНН = Стр.ИНН;
ДляПоискаКПП = Стр.КПП;
Прервать; // Нашли соответствие, выходим из цикла
КонецЕсли;
КонецЦикла;
Иначе
// Если ГУИД не заполнен, используем ИНН/КПП как резервный вариант
ДляПоискаИНН = ДанныеКонтрагента.ИНН;
ДляПоискаКПП = ДанныеКонтрагента.КПП;
КонецЕсли;
// Далее, используя ДляПоискаИНН и ДляПоискаКПП, формируется основной запрос
// к базе 1С, который уже будет использовать ИНН/КПП для поиска
ИНН, КПП и строковым представлением ГУИД.ТЗ), которая передается обратно через COM.ГУИД из таблицы (Стр.ГУИДКонтрагента) с ГУИД, переданным из исходной базы (ДанныеКонтрагента.ГУИДконтрагента). Здесь сравнение происходит уже в среде, инициирующей COM-соединение, где строковые сравнения более предсказуемы.ИНН и КПП найденного контрагента и используем их для формирования дальнейшего основного запроса к базе 1С, который уже будет использовать более привычные ИНН и КПП.COM.В современных реалиях, особенно при интеграции между различными системами или при работе с клиентскими приложениями на Linux, COM-соединение постепенно уступает место более гибким и производительным технологиям. Мы рекомендуем рассмотреть веб-сервисы как альтернативный механизм обмена данными.
Веб-сервисы позволяют:
COM, где преобразование типов может быть неочевидным, веб-сервисы часто используют стандартизированные форматы (например, XML, JSON) и позволяют более четко определять типы данных, упрощая их сопоставление.Хотя переход на веб-сервисы требует переработки существующих механизмов обмена и изучения новых технологий, в долгосрочной перспективе это может значительно упростить поддержку и развитие системы интеграции, сделав ее более гибкой и производительной.
Чтобы обеспечить стабильность и корректность обмена данными между УТ и БП, помимо технических аспектов, важно уделить внимание организационным моментам:
ГУИД, хранящийся в доп. реквизите), эта информация должна быть передана в БП до загрузки документов, ссылающихся на эти объекты. Игнорирование этого правила может привести к созданию дубликатов или ошибкам при загрузке.1С:Управление торговлей 10.3 существует обработка "Регистрация изменений для обмена". Используйте ее для контроля, какие объекты будут выгружены. Будьте осторожны при ручной регистрации изменений справочников, чтобы случайно не выгрузить документы без сопутствующей номенклатуры или контрагентов, или не отправить уже существующие объекты без изменений.ГУИД или дополнительными реквизитами.Связывание баз 1С:Управление торговлей 10.3 и 1С:Бухгалтерия предприятия 3.0 по ГУИД является надежным способом обеспечения целостности данных, особенно при наличии нестабильных идентификаторов. Мы рассмотрели различные подходы к хранению ГУИД в базе-приемнике: от типового регистра СоответствияОбъектовИнформационныхБаз до использования дополнительных реквизитов. Особое внимание было уделено проблеме сравнения ГУИД в запросах через COM-соединение и предложено как рекомендуемое решение с приведением типов, так и обходной путь для сложных ситуаций. Помните, что помимо чисто технических решений, критически важны дисциплина ведения учета и внимательность при работе с данными и настройке обменов.