Как программно изменить вид номенклатуры и настроить использование характеристик в 1С?

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

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

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

Разбор типичных ошибок разработчиков при работе с реквизитами справочника

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


// Ошибочный программный код
&НаСервере
Процедура ОбновитьВидНоменклатуры(НоменклатураСсылка)
    ОбъектНоменклатуры = НоменклатураСсылка.ПолучитьОбъект();
    Послуга = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Услуга");
    
    // Ошибка №1: Попытка изменения реквизита через получение его объекта
    ВидНом = ОбъектНоменклатуры.ВидНоменклатуры.ПолучитьОбъект();
    ВидНом = Послуга;
    
    // Ошибка №2: Попытка записать реквизит напрямую
    ОбъектНоменклатуры.ВидНоменклатуры.Записать(); 
КонецПроцедуры

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

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

Архитектура хранения настроек характеристик в современных ERP-системах

Даже если мы полностью исправим синтаксические ошибки и напишем лаконичный код вида:


ОбъектНоменклатуры.ВидНоменклатуры = Послуга;
ОбъектНоменклатуры.Записать();

мы быстро обнаружим, что характеристики у измененных позиций так и не появились в интерфейсе и документах, хотя в самом виде номенклатуры "Услуга" или "Товар" они гарантированно включены. Почему так происходит?

Выясним причину этого поведения. В современных прикладных решениях 1С реквизит ИспользованиеХарактеристик является физическим реквизитом самого справочника Номенклатура. Он имеет тип перечисления ПеречислениеСсылка.ВариантыИспользованияХарактеристикНоменклатуры и может принимать следующие значения:

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

При простом программном изменении значения реквизита ВидНоменклатуры на уровне базы данных код формы не выполняется. В итоге ссылка на вид номенклатуры меняется, но значение реквизита ИспользованиеХарактеристик внутри карточки товара остается старым (например, НеИспользовать). Синхронизация данных нарушается.

Правильный программный метод изменения вида номенклатуры и характеристик

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

Разберем по шагам создание надежной процедуры:


&НаСервере
Процедура ПрограммноИзменитьВидИХарактеристикиНаСервере(СсылкаНаНоменклатуру, СсылкаНаНовыйВид) Экспорт
    
    // Шаг 1. Получаем объект номенклатуры для редактирования
    ОбъектНоменклатуры = СсылкаНаНоменклатуру.ПолучитьОбъект();
    
    Если ОбъектНоменклатуры = Неопределено Тогда
        ВызватьИсключение "Не удалось получить объект номенклатуры. Возможно, элемент был удален.";
    КонецЕсли;
    
    // Шаг 2. Устанавливаем новый вид номенклатуры
    ОбъектНоменклатуры.ВидНоменклатуры = СсылкаНаНовыйВид;
    
    // Шаг 3. Обязательно синхронизируем признак использования характеристик
    // Копируем значение настройки из реквизитов нового вида номенклатуры
    ОбъектНоменклатуры.ИспользованиеХарактеристик = СсылкаНаНовыйВид.ИспользованиеХарактеристик;
    
    // Шаг 4. Копируем другие связанные учетные параметры при необходимости
    ОбъектНоменклатуры.ИспользоватьУпаковки = СсылкаНаНовыйВид.ИспользоватьУпаковки;
    ОбъектНоменклатуры.ЕдиницаИзмерения     = СсылкаНаНовыйВид.ЕдиницаИзмерения;
    
    // Шаг 5. Записываем объект с обработкой возможных исключений
    Попытка
        // Записываем в стандартном режиме для активации всех бизнес-проверок конфигурации
        ОбъектНоменклатуры.Записать();
        Сообщить("Номенклатура """ + ОбъектНоменклатуры.Наименование + """ успешно обновлена.");
    Исключение
        // Перехватываем ошибки транзакции (например, блокировки базы или нарушение уникальности)
        ИнформацияОбОшибке = ИнформацияОбОшибке();
        Сообщить("Не удалось записать изменения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
    КонецПопытки;
    
КонецПроцедуры

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

ОбъектНоменклатуры.ОбменДанными.Загрузка = Истина;

Посмотрим на эту ситуацию критически. Режим загрузки действительно позволяет обойти любые блокировки конфигурации и записать объект без валидации. Но при этом полностью отключаются все обработчики событий (такие как ПередЗаписью в модуле объекта и подписки на события). Использовать этот режим рекомендуется исключительно при массовом техническом переносе данных или восстановлении базы из резервных копий, когда вы на 100% уверены в корректности сопутствующих реквизитов.

Решение проблемы через стандартную обработку «Групповое изменение реквизитов»

Если вам требуется обновить настройки для большого массива товаров в пользовательском режиме без написания дополнительного кода и привлечения программистов, воспользуйтесь типовой обработкой «Групповое изменение реквизитов».

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

  1. Перейдите в раздел НСИ и администрирование -> Обслуживание -> Корректировка данных и запустите обработку Групповое изменение реквизитов.
  2. В поле "Выбирать элементы" укажите справочник Номенклатура. Добавьте необходимые условия отбора (например, по конкретной группе товаров или по старому виду номенклатуры).
  3. Нажмите на гиперссылку или кнопку Дополнительные параметры (в зависимости от релиза конфигурации это может быть кнопка "Настройка" внизу формы).
  4. В открывшемся окне настроек обязательно установите флаг «Показывать служебные реквизиты». После этого нажмите кнопку "ОК" или "Применить".
  5. Теперь в общем списке полей для изменения найдите системный реквизит Использование характеристик и выберите для него целевое значение (например, Индивидуальные для номенклатуры или Общие для вида номенклатуры).
  6. Также найдите реквизит Вид номенклатуры и установите новое значение вида номенклатуры.
  7. Нажмите кнопку Изменить реквизиты для выполнения пакетного обновления объектов базы данных.

Критически важные риски для складского и финансового учета

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

Проанализируем риски ведения учета при некорректном включении характеристик:

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

  1. Перед началом любых технических изменений полностью спишите текущие остатки товаров по корректируемым позициям с помощью документов списания или инвентаризации (например, «Списание товаров»).
  2. Убедитесь, что в системе отсутствуют незакрытые заказы клиентов, заказы поставщикам или незавершенные цепочки документов по данным позициям.
  3. Выполните программное изменение вида номенклатуры и установите правильное значение признака ИспользованиеХарактеристик.
  4. Оприходуйте товар обратно на склады с помощью документа «Оприходование товаров», но теперь уже в обязательном порядке указывайте конкретные, вновь созданные характеристики для каждой единицы продукции.

Соблюдение этих правил позволит вам быстро и безболезненно провести модернизацию ведения учета в базах данных семейства ERP/УТ без привлечения ручных корректировок регистров накопления в конце отчетного периода.

← На главную