При программном создании элементов справочника Партнеры в конфигурации «1С:Управление торговлей 11» разработчики нередко сталкиваются с ситуацией: в коде реквизит Клиент явно устанавливается в значение Истина, запись проходит успешно, но в интерфейсе («CRM и маркетинг» — «Клиенты») новый партнер не отображается. При этом в общем списке всех партнеров элемент виден, галочка «Клиент» установлена, а если снять её и установить вручную в режиме «1С:Предприятие» — партнер мгновенно появляется в нужном списке. Разберем внутренние механизмы платформы и типовой конфигурации, выясним причину такого поведения и рассмотрим правильный способ программного создания клиентов.
Рассмотрим типовой фрагмент кода, в котором возникает эта ошибка:
Функция прНайтиСоздатьПартнера(ДанныеКонтрагент, Контрагент)
ПартнерОбъект = Справочники.Партнеры.СоздатьЭлемент();
ПартнерОбъект.УстановитьНовыйКод();
ПартнерОбъект.Наименование = СокрЛП(ДанныеКонтрагент.Наименование);
ПартнерОбъект.НаименованиеПолное = ПартнерОбъект.Наименование;
ПартнерОбъект.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.ЧастноеЛицо;
ПартнерОбъект.Клиент = Истина;
ПартнерОбъект.ДатаРегистрации = ТекущаяДата();
ПартнерОбъект.Комментарий = "Создан автоматически при загрузке заказов";
ПартнерОбъект.ОбменДанными.Загрузка = Истина;
ПартнерОбъект.Записать();
КонецФункции
На первый взгляд реквизиты заполнены корректно. Однако обратим внимание на строчку ПартнерОбъект.ОбменДанными.Загрузка = Истина;. Именно она является корнем проблемы.
Флаг ОбменДанными.Загрузка = Истина переводит объект в специальный режим обмена, при котором отключаются проверки заполнения, события ПередЗаписью, ПриЗаписи, а также все подписки на события. В типовых конфигурациях линейки «1С:Управление торговлей», «1С:Комплексная автоматизация» и «1С:ERP» справочник Партнеры тесно связан со служебными подсистемами, которые не могут инициализироваться без вызова стандартных процедур записи:
ИерархияПартнеров. Записи в этот регистр создаются именно в процедуре ПриЗаписи модуля объекта. Если запись выполняется в режиме загрузки, регистр остается пустым, и динамический список клиентов физически не может вывести элемент.Для корректного отображения партнера в списке клиентов достаточно убрать взведение флага ОбменДанными.Загрузка, чтобы дать конфигурации выполнить все необходимые служебные движения. Кроме того, при создании нового элемента рекомендуется инициализировать значения по умолчанию вызовом процедуры Заполнить(), которая выполняет логику обработчика ОбработкаЗаполнения.
Посмотрим на исправленный вариант программного кода:
Функция прНайтиСоздатьПартнера(ДанныеКонтрагент, Контрагент)
ПартнерОбъект = Справочники.Партнеры.СоздатьЭлемент();
// Инициализируем стандартные реквизиты значениями по умолчанию
ПартнерОбъект.Заполнить(Неопределено);
ПартнерОбъект.УстановитьНовыйКод();
ПартнерОбъект.Наименование = СокрЛП(ДанныеКонтрагент.Наименование);
ПартнерОбъект.НаименованиеПолное = ПартнерОбъект.Наименование;
ПартнерОбъект.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.ЧастноеЛицо;
ПартнерОбъект.Клиент = Истина;
ПартнерОбъект.ДатаРегистрации = ТекущаяДата();
ПартнерОбъект.Комментарий = "Создан автоматически при загрузке заказов";
// Записываем объект в стандартном режиме, без ОбменДанными.Загрузка = Истина
ПартнерОбъект.Записать();
Возврат ПартнерОбъект.Ссылка;
КонецФункции
Разберем еще один важный архитектурный аспект УТ 11 — разделение управленческой сущности (Партнеры) и регламентированной (Контрагенты). В зависимости от настройки базы поведение может различаться:
Контрагенты обязательно должен быть заполнен реквизит Партнер.Если для партнера уже подготовлен или создается контрагент, свяжем их программно:
// Создание и привязка контрагента к партнеру
КонтрагентОбъект = Справочники.Контрагенты.СоздатьЭлемент();
КонтрагентОбъект.Заполнить(Неопределено);
КонтрагентОбъект.Партнер = ПартнерСсылка; // Указываем ссылку на созданного партнера
КонтрагентОбъект.Наименование = ПартнерОбъект.Наименование;
КонтрагентОбъект.НаименованиеПолное = ПартнерОбъект.НаименованиеПолное;
КонтрагентОбъект.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.ЧастноеЛицо;
КонтрагентОбъект.Записать();
Иногда при массовом импорте тысяч записей разработчики вынуждены использовать ОбменДанными.Загрузка = Истина ради скорости. Если вы применяете этот режим, помните, что база данных переходит в неконсистентное состояние с точки зрения вспомогательных регистров. В таком случае необходимо выполнить один из следующих шагов:
Записать() в штатном режиме без признака загрузки.ИерархияПартнеров.Для разового создания или штатной интеграции с сайтом/внешней системой всегда используйте обычную запись объектов, позволяя типовым механизмам конфигурации поддерживать целостность данных.