Как правильно заполнить поле "Вид контрагента" при программном создании в 1С:Управление торговлей 11?

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

При программной работе со справочниками в современных конфигурациях на управляемых формах, таких как 1С:Управление торговлей 11, 1С:ERP Управление предприятием и 1С:Комплексная автоматизация 2, разработчики часто сталкиваются с особенностями их архитектуры. Одним из ярких примеров является разделение сущностей на управленческий учет (справочник Партнеры) и регламентированный/юридический учет (справочник Контрагенты). Понимание взаимосвязи этих справочников критически важно для корректного программного заполнения их реквизитов.

В этой статье мы подробно разберем распространенную проблему, когда после программного создания и записи нового контрагента и партнера поле "Вид контрагента" на управляемой форме контрагента остается пустым. Мы выясним глубинную причину этой ошибки, рассмотрим правильный код инициализации объектов, а также изучим лучшие практики и нюансы программного создания связки «Партнер — Контрагент» в экосистеме 1С.

Анализ исходного кода и выявление логической ошибки

Рассмотрим типичный пример кода, который часто пишут начинающие разработчики или стажеры при программном импорте данных или создании обработки для интеграции:


Контрагент = Справочники.Контрагенты.СоздатьЭлемент();
Контрагент.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;
Контрагент.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо;

Партнер = Справочники.Партнеры.СоздатьЭлемент();
Партнер.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.Компания;
Партнер.Записать();

Контрагент.Партнер = Партнер; // Ошибка здесь!
Контрагент.Записать();

На первый взгляд код выглядит логичным: создаются оба объекта, заполняются их базовые свойства, партнер записывается в базу данных, после чего его значение присваивается реквизиту Партнер справочника Контрагенты, и контрагент также успешно записывается. Однако при интерактивном открытии карточки созданного контрагента в интерфейсе программы поле "Вид контрагента" оказывается абсолютно пустым, несмотря на то что реквизит ЮрФизЛицо был явно указан как юридическое лицо.

Давайте проанализируем ситуацию и разберемся, почему так происходит. Ключевая ошибка кроется в строке:

Контрагент.Партнер = Партнер;

Переменная Партнер в данном контексте представляет собой тип СправочникОбъект.Партнеры, возвращаемый методом СоздатьЭлемент(). В то же время реквизит Партнер в справочнике Контрагенты на уровне метаданных имеет тип ссылки (СправочникСсылка.Партнеры).

Когда мы присваиваем объект ссылочному реквизиту, платформа 1С позволяет временно удерживать этот объект в оперативной памяти. Однако при вызове метода Записать() СУБД не может сохранить сложный объект памяти в поле внешней связи таблицы базы данных. В результате платформа пытается неявно привести типы, что в данном сценарии приводит к записи пустого значения ссылки (ПустаяСсылка). Связь между контрагентом и партнером в базе данных фактически разрывается, хотя программная ошибка или исключение при этом не генерируются.

Почему именно поле "Вид контрагента" остается пустым на форме?

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


Процедура ПриСозданииИЧтенииНаСервере()
    
    НастройкиПодключенияКСервисуИППЗаданы = ПартнерыИКонтрагенты.НастройкиПодключенияКСервисуИППЗаданы();
    ПравоИзмененияОбъекта = ПравоДоступа("Изменение", Метаданные.Справочники.Партнеры);
    
    Если ОбособленноеПодразделение Тогда
        ВидКонтрагента = "ОбособленноеПодразделение";
    ИначеЕсли ЗначениеЗаполнено(ЮрФизЛицо) Тогда
        ВидКонтрагента = ОбщегоНазначения.ИмяЗначенияПеречисления(ЮрФизЛицо);
    КонецЕсли;
    
    УправлениеДоступностью();
    УстановитьЗаголовок();
    
КонецПроцедуры

Как мы видим, поле "Вид контрагента" (переменная ВидКонтрагента) не хранится в физической таблице базы данных. Это чисто виртуальный реквизит формы строкового типа, значение которого рассчитывается на лету. Расчет происходит на сервере при открытии формы на основе реквизита ЮрФизЛицо или флага ОбособленноеПодразделение.

Но почему же тогда ЮрФизЛицо оказывается незаполненным на форме, если мы его записывали? Ответ лежит в процедуре ПриЧтенииНаСервере():


Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    ПартнерыИКонтрагенты.ЗаполнитьДанныеКонтрагентаПартнера(ЭтотОбъект, ТекущийОбъект.Ссылка);
    Запрос = Новый Запрос;
    Запрос.Текст = "
    |ВЫБРАТЬ ПЕРВЫЕ 1
    |    Контрагенты.Ссылка КАК КонтрагентПартнера,
    |    Контрагенты.ЮрФизЛицо КАК ЮрФизЛицо,
    |    Контрагенты.ЮридическоеФизическоеЛицо КАК ЮридическоеФизическоеЛицо,
    |    Контрагенты.ИНН                       КАК ИНН,
    |    Контрагенты.КПП                       КАК КПП,
    |    Контрагенты.ОбособленноеПодразделение КАК ОбособленноеПодразделение
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |    Контрагенты.Партнер = &Партнер";
    
    Запрос.УстановитьПараметр("Партнер", Партнер);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        ЗаполнитьЗначенияСвойств(ЭтотОбъект, Выборка);
    КонецЕсли;
КонецПроцедуры

При открытии карточки контрагента система выполняет запрос к базе данных, пытаясь получить связанные сведения о контрагенте по его владельцу — партнеру (параметр &Партнер). Поскольку связь была утеряна из-за неверной записи ссылки, этот запрос возвращает пустую выборку. В итоге реквизит формы ЮрФизЛицо инициализируется значением по умолчанию (пустая ссылка перечисления), из-за чего блок кода в ПриСозданииИЧтенииНаСервере() не находит данных для вычисления вида контрагента, оставляя поле пустым.

Решение проблемы: правильное связывание объектов

Для исправления ситуации достаточно применить классическое правило 1С-разработки: ссылочным реквизитам всегда нужно присваивать значения ссылочного типа, а не объекты. Поскольку мы уже записали объект Партнер в базу данных методом Записать(), у него сформировалась уникальная ссылка. Мы должны передать ее свойству контрагента:

Правильный вариант кода:


Партнер.Записать();
Контрагент.Партнер = Партнер.Ссылка; // Присваиваем именно Ссылку!
Контрагент.Записать();

Это простое исправление гарантирует, что связь в базе данных будет корректно сохранена, и при открытии формы все виртуальные и зависимые реквизиты рассчитаются автоматически.

Дополнительные важные нюансы программного создания партнеров и контрагентов

Просто исправить ссылку — это лишь вершина айсберга. При разработке серьезных интеграций в конфигурациях 1С:Управление торговлей 11 / ERP необходимо учитывать архитектурные особенности этих систем. Разберем по шагам ключевые аспекты, которые уберегут вас от скрытых багов.

1. Двойные реквизиты: ЮрФизЛицо и ЮридическоеФизическоеЛицо

В справочнике Контрагенты вы встретите два реквизита со схожими именами. Это сделано намеренно для обеспечения совместимости:

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

2. Оптимизация записи через получение ссылки нового объекта

В классическом сценарии нам приходится сначала записывать объект Партнер, чтобы получить его ссылку, и только потом записывать Контрагент. Это порождает лишнее обращение к СУБД. Платформа 1С позволяет оптимизировать этот процесс с помощью метода ПолучитьСсылку(). Мы можем сгенерировать ссылку в памяти еще до физической записи партнера в базу данных:


// Шаг 1. Генерируем уникальный идентификатор ссылки для партнера
СсылкаНовогоПартнера = Справочники.Партнеры.ПолучитьСсылку();

// Шаг 2. Создаем контрагента и сразу привязываем его к будущему партнеру
Контрагент = Справочники.Контрагенты.СоздатьЭлемент();
Контрагент.Партнер = СсылкаНовогоПартнера; // Ссылка валидна, хотя партнер еще не записан
Контрагент.ЮрФизЛицо = Перечисления.ЮрФизЛицо.ЮрЛицо;
Контрагент.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо;
Контрагент.Записать();

// Шаг 3. Создаем партнера и явно задаем ему сгенерированную ранее ссылку
Партнер = Справочники.Партнеры.СоздатьЭлемент();
Партнер.УстановитьСсылкуНового(СсылкаНовогоПартнера);
Партнер.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.Компания;
Партнер.Записать();

Такой подход делает код более чистым, избавляет СУБД от избыточных транзакций обновления записей и позволяет группировать создание связанных объектов в единую неделимую транзакцию.

3. Проверка функциональной опции "Независимо вести партнеров и контрагентов"

Логика работы справочников напрямую зависит от константы ИспользоватьПартнеровИКонтрагентов. В пользовательском интерфейсе этот флаг называется «Независимо вести партнеров и контрагентов». Проанализируем два сценария:

  1. Опция выключена: В этом режиме сущности партнера и контрагента жестко связаны как один к одному. При программном создании в обход стандартных форм (где это контролирует интерактивный Помощник регистрации) вам необходимо самостоятельно синхронно создавать обе записи.
  2. Опция включена: Это штатный режим работы для крупных торговых компаний, позволяющий реализовывать схемы холдингов. Один партнер (например, сеть "Магнит") может обладать десятками различных контрагентов (конкретных юридических лиц в регионах). В этом случае программный код должен гибко сопоставлять одного партнера со множеством контрагентов.

4. Контактная информация и проверка дублей

Когда вы создаете партнеров и контрагентов программно (например, через внешнюю обработку загрузки из сторонних файлов), платформа обходит встроенные проверки интерактивного ввода. Обратите внимание на следующие моменты:

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

← На главную