Разработчики, занимающиеся интеграцией 1С с интернет-магазинами и внешними CRM-системами, часто сталкиваются со следующей проблемой. При выгрузке контрагентов на сайт необходимо передавать уникальные идентификаторы (GUID) их контактной информации (адресов доставки, телефонов и т.д.). Однако стандартные механизмы Библиотеки стандартных подсистем (БСП) в 1С при записи объекта полностью очищают табличную часть КонтактнаяИнформация и перезаписывают её заново на основе данных формы.
Это приводит к тому, что любые добавленные вручную реквизиты строк (например, строковые уникальные идентификаторы) очищаются при каждом сохранении элемента справочника. В этой статье мы подробно разберем, почему это происходит, и рассмотрим два эффективных способа решения данной проблемы: штатный механизм БСП и альтернативный вариант с минимальной доработкой системы.
Для начала проанализируем, как работает подсистема управления контактной информацией в БСП. На управляемой форме элемента (например, контрагента) физически нет привычной таблицы контактной информации. Вместо этого механизмы БСП динамически создают реквизиты на форме и выводят их в удобном для пользователя виде. При этом один вид контактной информации (например, «Адрес доставки») может быть множественным — пользователь может добавлять неограниченное количество адресов.
Перед записью объекта на сервере срабатывает процедура общего модуля:
УправлениеКонтактнойИнформацией.ПередЗаписьюНаСервере(Форма, Объект, Отказ = Ложь)
Этот обработчик собирает измененные данные с формы, полностью очищает табличную часть КонтактнаяИнформация у записываемого объекта и заполняет её заново. Из-за этого дефолтного поведения любые попытки просто «добавить колонку ГУИД в ТЧ» и записывать её стандартными методами обречены на неудачу — при первой же интерактивной перезаписи объекта данные в этой колонке будут потеряны.
---
Мало кто знает, но в современных версиях БСП уже предусмотрен стандартный механизм для сопоставления строк табличной части контактной информации. Он разработан специально для того, чтобы соотносить строки на форме и в базе данных, предотвращая их «перемешивание» при перезаписи.
Для реализации этого механизма выполним следующие шаги:
Контрагенты). В его табличную часть КонтактнаяИнформация добавим новый реквизит ИдентификаторСтрокиТабличнойЧасти с типом данных Число (7, 0).УправлениеКонтактнойИнформацией автоматически распознают этот реквизит. При записи объекта БСП больше не будет хаотично перетирать строки. Она сопоставит строки формы и строки табличной части по этому идентификатору.Как получить стабильный GUID для сайта на основе этого механизма?
Поскольку сайту обычно требуется именно UUID в формате строки, мы можем генерировать так называемый детерминированный GUID «на лету» прямо в процессе выгрузки данных. В качестве основы мы возьмем уникальный идентификатор самого контрагента и числовой идентификатор строки.
Рассмотрим пример функции, которая генерирует стабильный уникальный идентификатор для сайта:
Функция ПолучитьДетерминированныйГУИД(СсылкаВладельца, ИдентификаторСтроки) Экспорт
// Получаем строковое представление ГУИДа контрагента
ГУИДВладельца = Строка(СсылкаВладельца.УникальныйИдентификатор());
// Преобразуем числовой идентификатор строки в строку фиксированной длины (с ведущими нулями)
Суффикс = Формат(ИдентификаторСтроки, "ЧГ=0");
Суффикс = Прав("000000000000" + Суффикс, 12);
// Заменяем последние 12 символов исходного ГУИДа на наш уникальный суффикс строки КИ
НовыйГУИДСтрока = Лев(ГУИДВладельца, 24) + Суффикс;
Возврат Новый УникальныйИдентификатор(НовыйГУИДСтрока);
КонецФункции
Этот подход гарантирует, что для одной и той же строки адреса у конкретного контрагента всегда будет генерироваться один и тот же GUID, который не изменится при перезаписи данных в 1С. При этом база данных не засоряется избыточными строковыми реквизитами.
---
Если вам по каким-то причинам принципиально хранить физический УникальныйИдентификатор непосредственно в строках табличной части базы данных (например, этого жестко требует существующая архитектура интеграции), придется пойти по пути кастомизации конфигурации.
Разберем по шагам, как реализовать этот подход:
КонтактнаяИнформация справочника Контрагенты реквизит ИдентификаторСтроки с типом Строка (36) или УникальныйИдентификатор.УправлениеКонтактнойИнформацией найдем процедуры, отвечающие за перенос данных из формы в объект (например, ЗаписатьКонтактнуюИнформациюОбъекта). Нам необходимо дописать сопоставление и заполнение нашего реквизита.Пример кода, который необходимо внедрить в логику заполнения табличной части перед записью:
// В цикле обхода данных контактной информации перед записью объекта:
Если НЕ ЗначениеЗаполнено(СтрокаТаблицыОбъекта.ИдентификаторСтроки) Тогда
СтрокаТаблицыОбъекта.ИдентификаторСтроки = Новый УникальныйИдентификатор();
КонецЕсли;
При использовании этого способа обязательно убедитесь, что при копировании строк или создании новых адресов на форме новые идентификаторы генерируются корректно и не дублируются.
---
Посмотрим на практический пример того, как мы можем выбрать данные контактной информации контрагента вместе с их уникальными идентификаторами для последующей отправки на сайт:
Процедура ВыгрузитьКонтактнуюИнформацию(СсылкаКонтрагента)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтрагентыКонтактнаяИнформация.Ссылка КАК Контрагент,
| КонтрагентыКонтактнаяИнформация.Вид КАК ВидКИ,
| КонтрагентыКонтактнаяИнформация.Представление КАК Представление,
| КонтрагентыКонтактнаяИнформация.ИдентификаторСтрокиТабличнойЧасти КАК ИдентификаторСтроки
|ИЗ
| Справочник.Контрагенты.КонтактнаяИнформация КАК КонтрагентыКонтактнаяИнформация
|ГДЕ
| КонтрагентыКонтактнаяИнформация.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаКонтрагента);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем детерминированный стабильный ГУИД для интеграции
ГУИДСтрокиКИ = ПолучитьДетерминированныйГУИД(Выборка.Контрагент, Выборка.ИдентификаторСтроки);
// Формируем структуру для отправки на сайт
ДанныеАдреса = Новый Структура;
ДанныеАдреса.Вставить("ID", Строка(ГУИДСтрокиКИ));
ДанныеАдреса.Вставить("Type", Строка(Выборка.ВидКИ));
ДанныеАдреса.Вставить("Value", Выборка.Представление);
// Отправка данных на сайт (внешний HTTP-запрос)...
КонецЦикла;
КонецПроцедуры
Используя первый (штатный) метод БСП, вы полностью сохраните типовую конфигурацию на поддержке и избавите себя от сложных процедур обновления общего модуля КИ в будущем. Второй метод больше подойдет для кастомных конфигураций, где логика БСП значительно переработана под нужды конкретного бизнеса.