Почему очищается контактная информация при программном создании контрагента в 1С:УТ 11 и как это сделать правильно

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке интеграций и программном переносе данных в конфигурациях на базе Библиотеки стандартных подсистем (БСП), таких как «1С:Управление торговлей 11», «1С:ERP» или «1С:Комплексная автоматизация», разработчики часто сталкиваются со следующей проблемой. При программном добавлении строки в табличную часть КонтактнаяИнформация контрагента или партнера данные успешно записываются в базу данных, однако при открытии карточки в интерфейсе поля КИ оказываются пустыми. Более того, при первом же интерактивном сохранении (нажатии кнопки «Записать и закрыть») программно добавленные данные бесследно исчезают.

В этой статье мы подробно разберем внутренние механизмы работы подсистемы КИ в БСП, выясним причины очистки табличной части и рассмотрим правильные, архитектурно верные способы программного заполнения контактной информации.

Выясняем причину: почему очищается табличная часть?

Попытка заполнить табличную часть простым добавлением строк напрямую, как показано в примере ниже, является главной ошибкой:


// Ошибочный подход прямого заполнения табличной части
НоваяСтрока = СоздатьНовогоКонтрагента.КонтактнаяИнформация.Добавить();
НоваяСтрока.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
НоваяСтрока.Вид = Справочники.ВидыКонтактнойИнформации.EmailКонтрагента;
НоваяСтрока.Представление = "test@email.ru";
СоздатьНовогоКонтрагента.Записать();

Чтобы понять, почему этот код не работает в долгосрочной перспективе, проанализируем архитектуру хранения КИ в БСП:

  1. Служебное поле ЗначенияПолей. БСП не считывает напрямую колонку Представление или АдресЭП для отображения данных на управляемой форме. Вместо этого используется служебная колонка ЗначенияПолей, где подробный состав контактной информации (индексы, города, улицы, коды стран и телефонов) хранится в сериализованном XML- или JSON-формате. Если это поле остается пустым, управляемая форма считает, что контактная информация не заполнена вовсе.
  2. Логика формы элемента. При открытии формы карточки контрагента срабатывает инициализация динамических реквизитов КИ. Программа парсит строку ЗначенияПолей. Поскольку при прямом заполнении ТЧ это поле было пустым, поля ввода на форме остаются незаполненными.
  3. Очистка при записи. При сохранении объекта из формы срабатывает обработчик ПередЗаписьюНаСервере. Система сопоставляет данные на форме с данными в объекте. Так как на форме визуальные поля ввода КИ пусты, платформа считает их актуальными и затирает существующие строки в табличной части, перезаписывая их пустыми значениями.
  4. Массив СкрываемыеВиды. В коде формы существует проверка видимости видов КИ. Если массив скрываемых видов пуст, срабатывает типовой алгоритм очистки: Объект.КонтактнаяИнформация.Очистить(), после чего табличная часть заполняется заново на основании того, что было введено на форме.

Для корректного сохранения данных нам необходимо использовать специализированный программный интерфейс (API) Библиотеки стандартных подсистем.

Способ 1. Использование универсального метода ДобавитьКонтактнуюИнформацию

Самый простой и надежный способ программного добавления контактной информации для нового или существующего объекта — использование метода публичного модуля УправлениеКонтактнойИнформацией. Этот метод берет на себя всю рутину по формированию правильной XML/JSON-структуры для поля ЗначенияПолей.

Рассмотрим пример создания контрагента и заполнения его Email-адреса:


// 1. Создаем объект контрагента
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйКонтрагент.Наименование = "ООО Ромашка";
НовыйКонтрагент.НаименованиеПолное = "Общество с ограниченной ответственностью 'Ромашка'";

// Для новых (еще не записанных) объектов крайне важно предварительно получить и установить ссылку,
// так как контактная информация должна ссылаться на владельца.
НоваяСсылка = Справочники.Контрагенты.ПолучитьСсылку();
НовыйКонтрагент.УстановитьСсылкуНового(НоваяСсылка);

// 2. Определяем параметры контактной информации
EmailАдрес = "romashka@example.com";
ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагента;

// 3. Используем штатный метод БСП для добавления информации в объект
УправлениеКонтактнойИнформацией.ДобавитьКонтактнуюИнформацию(
    НовыйКонтрагент, 
    EmailАдрес, 
    ВидКИ, 
    ТекущаяДатаСеанса(), 
    Ложь // Признак того, что запись производится в объект (в ТЧ), а не напрямую в регистр сведений
);

// 4. Записываем сам объект контрагента
НовыйКонтрагент.Записать();

Важное примечание: Обратите внимание на выбор вида контактной информации. Для контрагента необходимо указывать строго Справочники.ВидыКонтактнойИнформации.EmailКонтрагента, а для партнера — Справочники.ВидыКонтактнойИнформации.EmailПартнера. Ошибка в выборе предопределенного вида КИ приведет к тому, что информация будет записана в базу, но не отобразится в карточке соответствующего справочника.

Способ 2. Запись контактной информации напрямую в базу данных (для существующих объектов)

Если объект уже существует в базе данных и у вас есть его ссылка, вам не обязательно получать объект, изменять его табличную часть и перезаписывать весь элемент целиком. БСП предоставляет возможность внести КИ напрямую через транзакционную запись.

Давайте разберем, как обновить адрес электронной почты существующего контрагента:


СсылкаНаКонтрагента = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7701020304");

Если Не СсылкаНаКонтрагента.Пустая() Тогда
    
    EmailАдрес = "info@romashka.ru";
    ВидКИ = Справочники.ВидыКонтактнойИнформации.EmailКонтрагента;
    ТипКИ = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
    
    // Формируем XML-представление структуры полей КИ
    ОбъектXDTO = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(EmailАдрес, ТипКИ);
    ЗначенияПолейXML = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTO);
    
    // Выполняем запись КИ без перезаписи самого контрагента
    УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(
        СсылкаНаКонтрагента, 
        ЗначенияПолейXML, 
        ВидКИ, 
        ТипКИ
    );
    
КонецЕсли;

Использование этого метода существенно повышает производительность системы при массовой загрузке КИ (например, при первоначальном переносе данных из других систем), так как минимизирует количество блокировок и транзакций по записи тяжелых справочников.

Способ 3. Пакетная подготовка таблицы КИ через УстановитьКонтактнуюИнформациюОбъекта

В случаях, когда необходимо программно заполнить сразу множество различных видов контактной информации (например, телефон, юридический адрес, фактический адрес и веб-сайт), удобно подготовить таблицу значений КИ и применить ее к объекту одним методом.

Проанализируем пример комплексного заполнения КИ для нового партнера:


НовыйПартнер = Справочники.Партнеры.СоздатьЭлемент();
НовыйПартнер.Наименование = "Торговый Дом Вектор";
НовыйПартнер.Клиент = Истина;

СсылкаПартнера = Справочники.Партнеры.ПолучитьСсылку();
НовыйПартнер.УстановитьСсылкуНового(СсылкаПартнера);

// Получаем пустую таблицу структуры КИ, соответствующую структуре объекта
ТаблицаКИ = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(НовыйПартнер, , ТекущаяДатаСеанса());

// Заполняем Телефон
СтрокаТелефон = ТаблицаКИ.Добавить();
СтрокаТелефон.Объект = СсылкаПартнера;
СтрокаТелефон.Вид = Справочники.ВидыКонтактнойИнформации.ТелефонПартнера;
СтрокаТелефон.Тип = Перечисления.ТипыКонтактнойИнформации.Телефон;
СтрокаТелефон.Представление = "+7 (999) 111-22-33";
// Создаем XML структуру для телефона
ОбъектXDTOТелефон = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(СтрокаТелефон.Представление, СтрокаТелефон.Тип);
СтрокаТелефон.ЗначенияПолей = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOТелефон);

// Заполняем Email
СтрокаEmail = ТаблицаКИ.Добавить();
СтрокаEmail.Объект = СсылкаПартнера;
СтрокаEmail.Вид = Справочники.ВидыКонтактнойИнформации.EmailПартнера;
СтрокаEmail.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
СтрокаEmail.Представление = "sales@vector.ru";
СтрокаEmail.АдресЭП = "sales@vector.ru";
// Создаем XML структуру для почты
ОбъектXDTOEmail = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOПоПредставлению(СтрокаEmail.Представление, СтрокаEmail.Тип);
СтрокаEmail.ЗначенияПолей = УправлениеКонтактнойИнформациейСлужебный.КонтактнаяИнформацияXDTOВXML(ОбъектXDTOEmail);

// Переносим заполненную таблицу обратно в объект партнера
УправлениеКонтактнойИнформацией.УстановитьКонтактнуюИнформациюОбъекта(НовыйПартнер, ТаблицаКИ, Истина);

// Сохраняем партнера
НовыйПартнер.Записать();

Рекомендации по интеграции в УТ 11

Помните о разделении сущностей Партнеры (управленческий учет) и Контрагенты (регламентированный учет, юридические лица). Если вы создаете полноценного контрагента, в системе УТ 11 обязательно должен быть создан связанный с ним партнер.

Для корректного сопоставления КИ между партнером и контрагентом рекомендуется использовать встроенный метод:

ПартнерыИКонтрагенты.ЗаполнитьКонтактнуюИнформациюКонтрагентаПартнера()

Это позволит синхронизировать данные КИ и избежать расхождений в реквизитах при работе менеджеров в интерфейсе программы.

← На главную