При интеграции интернет-магазина на CMS 1C-Битрикс с конфигурациями 1С («1С:Управление торговлей», «1С:Комплексная автоматизация», «1С:ERP») разработчики часто сталкиваются с неприятной ситуацией: контрагенты создаются при обмене корректно, контактные данные отображаются в карточке, но стоит открыть карточку клиента и нажать кнопку «Записать» или «Записать и закрыть», как телефоны, email или адреса полностью исчезают.
Разберем детально механизм возникновения этой ошибки и выясним, как правильно исправить хранение контактной информации в базе.
В современных конфигурациях на платформе 1С:Предприятие 8.3, использующих Библиотеку стандартных подсистем (БСП), контактная информация хранится в табличной части КонтактнаяИнформация соответствующих справочников (СправочникСсылка.Контрагенты, СправочникСсылка.Партнеры, СправочникСсылка.ФизическиеЛица). Строка контактной информации состоит из нескольких ключевых реквизитов:
ВидДляСписка / Вид — ссылка на справочник ВидыКонтактнойИнформации.Представление — строковое значение контакта, видимое глазу (например, адрес или номер телефона).ЗначенияПолей — скрытая структурированная XML-строка, сформированная по специальной XDTO-схеме подсистемы БСП.Значение — внутреннее представление в формате JSON (в более свежих версиях БСП).Проанализируем цепочку событий при загрузке и последующем открытии карточки:
КонтактнаяИнформация объекта, заполняя только поле Представление, оставляя ЗначенияПолей пустым (или передавая поврежденный XML без обязательных полей).ОбменДанными.Загрузка = Истина. Платформа 1С в этом режиме пропускает встроенные валидации, и объект успешно сохраняется в базу.ЗначенияПолей (или Значение). Не обнаружив валидной структуры, форма оставляет свои внутренние реквизиты пустыми.Представление пустыми значениями.Чтобы избежать очистки данных, модуль интеграции при создании или обновлении контрагента должен формировать корректные структурированные данные контактной информации. Рассмотрим, как программно преобразовать строковое представление в валидную структуру с помощью штатных процедур и функций БСП.
Посмотрим на пример заполнения контактной информации в коде обработки загрузки:
// Получаем ссылку на нужный вид контактной информации
ВидКонтакта = Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента;
ТекстАдреса = "г. Москва, ул. Ленина, д. 10, оф. 5";
// Формируем валидный XML с помощью БСП
СтруктураXML = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияXMLПоПредставлению(ТекстАдреса, ВидКонтакта);
// Заполняем строку табличной части контрагента
СтрокаКИ = КонтрагентОбъект.КонтактнаяИнформация.Добавить();
СтрокаКИ.Вид = ВидКонтакта;
СтрокаКИ.Тип = ВидКонтакта.Тип;
СтрокаКИ.Представление = ТекстАдреса;
СтрокаКИ.ЗначенияПолей = СтруктураXML;
Если в конфигурации используется процедура записи контактной информации верхнего уровня, используем штатный метод менеджера:
УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(
КонтрагентОбъект,
СтруктураXML,
ВидКонтакта,
ВидКонтакта.Тип
);
Если в базе уже накопилось множество контрагентов с пустым полем ЗначенияПолей, исправим их с помощью групповой обработки. Разберем по шагам логику восстановления данных:
Представление, но отсутствует поле ЗначенияПолей.Рассмотрим пример кода для исправления существующих записей:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтрагентыКИ.Ссылка КАК Ссылка,
| КонтрагентыКИ.НомерСтроки КАК НомерСтроки,
| КонтрагентыКИ.Вид КАК Вид,
| КонтрагентыКИ.Представление КАК Представление
|ИЗ
| Справочник.Контрагенты.КонтактнаяИнформация КАК КонтрагентыКИ
|ГДЕ
| КонтрагентыКИ.Представление <> """"
| И (КонтрагентыКИ.ЗначенияПолей ЕСТЬ NULL ИЛИ КонтрагентыКИ.ЗначенияПолей = """")";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
КонтрагентОбъект = Выборка.Ссылка.ПолучитьОбъект();
Для Каждого СтрокаКИ Из КонтрагентОбъект.КонтактнаяИнформация Цикл
Если Не ПустаяСтрока(СтрокаКИ.Представление) И ПустаяСтрока(СтрокаКИ.ЗначенияПолей) Тогда
СтрокаКИ.ЗначенияПолей = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияXMLПоПредставлению(
СтрокаКИ.Представление,
СтрокаКИ.Вид
);
КонецЕсли;
КонецЦикла;
КонтрагентОбъект.ОбменДанными.Загрузка = Истина;
КонтрагентОбъект.Записать();
КонецЦикла;
При анализе подобных сбоев обратим внимание на следующие архитектурные особенности:
Партнеры, а в справочнике Контрагенты хранятся только юридические реквизиты. Если модуль обмена запишет вид контактной информации партнера в табличную часть контрагента, форма не сможет его отобразить.ВидыКонтактнойИнформации. Если при некорректном переносе или обновлении предопределенные элементы продублировались, форма объекта связывает поля ввода с одним элементом, а обмен заполняет строки с другим, что также приводит к визуальной потере данных при интерактивной записи.