Как программно создать характеристику в 1С:УТ 11 и избежать ошибок в подписках на события

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

При разработке в среде 1С:Управление торговлей 11.4 программисты часто сталкиваются с ситуацией, когда стандартный код создания элемента справочника, который годами работал в старых редакциях, внезапно вызывает фатальную ошибку. Рассмотрим ситуацию: нам необходимо программно создать характеристику номенклатуры (например, для учета товара в разных упаковках — «количество в блоке» или «количество в коробке»), но при вызове метода СоздатьЭлемент() система выдает ошибку: «Обработчик события не найден». Проанализируем, почему это происходит и как правильно реализовать эту задачу.

Выясняем причину ошибки: конфликт контекстов

Основная причина ошибки, с которой столкнулся автор темы, заключается в попытке создания объекта справочника на клиенте (даже если используется толстый клиент в режиме управляемого приложения). Разберем по шагам, что происходит в системе в этот момент:

  1. Метод Справочники.ХарактеристикиНоменклатуры.СоздатьЭлемент() инициирует создание объекта в памяти.
  2. В конфигурации УТ 11.4 настроено множество подписок на события. Одна из них — ЗарегистрироватьИзмененияСправочникаДляОбменаСМПТорговыйПредставитель (событие ПередЗаписью или инициализация).
  3. Обработчик этой подписки находится в общем модуле, у которого в свойствах установлен флаг «Сервер», но отсутствует флаг «Клиент (управляемое приложение)».
  4. Поскольку код выполняется на стороне клиента, платформа пытается найти процедуру обработчика, но «не видит» серверный модуль, что и приводит к ошибке отсутствия обработчика.

Проанализируем ситуацию: даже если вы просто создаете элемент без записи, платформа может проверять условия регистрации изменений. Решение здесь однозначное: любые манипуляции с типами данных «Объект» (СправочникОбъект, ДокументОбъект) должны выполняться строго на сервере.

Шаг 1: Перенос кода на сервер

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


&НаКлиенте
Процедура СоздатьХарактеристику(Команда)
    СоздатьХарактеристикуНаСервере(Объект.НоменклатураСсылка);
КонецПроцедуры

&НаСервере
Процедура СоздатьХарактеристикуНаСервере(НоменклатураСсылка)
    // Здесь будет основной код создания
КонецПроцедуры

Перенос кода в директиву &НаСервере автоматически решит проблему с видимостью модулей подписок на события, так как серверный контекст имеет доступ ко всем необходимым процедурам обмена данными.

Шаг 2: Установка владельца и ключевых реквизитов

В 1С:УТ 11 характеристики имеют важную особенность: их владельцем может выступать либо конкретная Номенклатура, либо Вид номенклатуры. Это зависит от настроек, заданных в карточке вида номенклатуры (использование характеристик: «Индивидуальные для номенклатуры» или «Общие для вида номенклатуры»).

Разберем процесс создания с учетом этой специфики:


НоваяХарактеристика = Справочники.ХарактеристикиНоменклатуры.СоздатьЭлемент();

// Важно! Сначала устанавливаем владельца
НоваяХарактеристика.Владелец = НоменклатураСсылка; 

// Если характеристики общие для вида номенклатуры, 
// владельцем должна быть ссылка на Справочник.ВидыНоменклатуры

Шаг 3: Работа с дополнительными реквизитами

В современных конфигурациях на базе 1С:Библиотека стандартных подсистем (БСП), таких как УТ 11.4, характеристики редко хранят данные в обычных реквизитах. Чаще всего «Количество в блоке» или «Размер» — это Дополнительные реквизиты. Попытка записать их «через точку» приведет к ошибке, так как их нет в структуре метаданных как отдельных полей.

Посмотрим, как правильно заполнить дополнительные реквизиты программно:


// Находим ссылку на дополнительный реквизит (ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения)
СвойствоКолВо = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Кол-во в блоке");

Если Не СвойствоКолВо.Пустая() Тогда
    НоваяСтрока = НоваяХарактеристика.ДополнительныеРеквизиты.Добавить();
    НоваяСтрока.Свойство = СвойствоКолВо;
    НоваяСтрока.Значение = 25; // Ваше значение
КонецЕсли;

Обратите внимание, что значения дополнительных реквизитов могут быть как простыми типами (число, строка), так и ссылками на справочники (например, «Значения свойств объектов»).

Шаг 4: Формирование наименования по шаблону

В УТ 11 реализован механизм автоматической генерации рабочего наименования характеристики на основе ее свойств. Если мы просто запишем объект с пустым наименованием, пользователям будет неудобно работать в списках. Мы можем воспользоваться встроенными методами конфигурации.

Проанализируем, как вызвать стандартное формирование наименования:


// В типовых решениях часто используется вызов из модуля менеджера или общего модуля
// Например, для формирования рабочего наименования по доп. реквизитам:
НоваяХарактеристика.Наименование = Справочники.ХарактеристикиНоменклатуры.СформироватьРабочееНаименование(
    НоваяХарактеристика.ДополнительныеРеквизиты, 
    НоваяХарактеристика.Владелец
);

Шаг 5: Итоговый алгоритм создания

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


&НаСервере
Функция СоздатьИндивидуальнуюХарактеристику(ТоварСсылка, ЧислоВБлоке)
    
    ХарактеристикаОбъект = Справочники.ХарактеристикиНоменклатуры.СоздатьЭлемент();
    ХарактеристикаОбъект.Владелец = ТоварСсылка;
    
    // Заполнение дополнительных реквизитов (пример)
    СвойствоБлок = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("КолВоВБлоке");
    Если Не СвойствоБлок.Пустая() Тогда
        Стр = ХарактеристикаОбъект.ДополнительныеРеквизиты.Добавить();
        Стр.Свойство = СвойствоБлок;
        Стр.Значение = ЧислоВБлоке;
    КонецЕсли;
    
    // Генерируем наименование, чтобы оно соответствовало стандартам системы
    // В УТ 11.4 часто используется следующий подход:
    ХарактеристикаОбъект.Наименование = "Блок " + ЧислоВБлоке + " шт.";
    
    Попытка
        ХарактеристикаОбъект.Записать();
        Возврат ХарактеристикаОбъект.Ссылка;
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при записи: " + ОписаниеОшибки());
        Возврат Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка();
    КонецПопытки;
    
КонецФункции

Важные рекомендации по бизнес-логике

Разберем ситуацию, описанную в теме: автору нужны характеристики для учета остатков в разных упаковках (блоки/короба), которые меняются от поставки к поставке. Рассмотрим два совета, которые помогут избежать проблем в будущем:

  1. Упаковки vs Характеристики: Стандартно в УТ 11 для таких целей предназначен справочник УпаковкиНоменклатуры. Однако он не позволяет вести раздельный учет остатков (нельзя увидеть на складе «5 коробок по 20 штук» и «3 коробки по 30 штук» как разные позиции, если товар один и тот же). Если вам критичен именно остаток в разрезе фасовок — использование характеристик оправдано.
  2. Серии: Если упаковка меняется динамически и вам нужно знать, в какой именно коробке пришел товар в конкретной партии, рассмотрите использование Серий номенклатуры. Серия может хранить информацию о фасовке и позволяет видеть остатки в разрезе каждой пришедшей партии без создания бесконечного списка характеристик.

Таким образом, мы выяснили, что ошибка «Обработчик события не найден» — это явный сигнал о нарушении контекста выполнения кода. Перенос операций в серверный модуль и правильная работа с коллекцией дополнительных реквизитов позволяют корректно автоматизировать создание характеристик в 1С:Управление торговлей 11.4.

← На главную