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

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

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

В этой статье мы разберем, как с помощью механизма расширений и программного кода реализовать полноценное копирование номенклатуры вместе со всеми её характеристиками.

Анализ технической сложности

Разберем, почему нельзя просто «подцепить» характеристики в момент нажатия кнопки копирования. Основная сложность заключается в иерархии объектов:

  1. Пока новый элемент номенклатуры не записан в базу данных, у него нет уникальной ссылки (Ссылка).
  2. Справочник ХарактеристикиНоменклатуры жестко подчинен справочнику Номенклатура. Поле Владелец является обязательным для заполнения.
  3. Следовательно, мы не можем создать или скопировать характеристики, пока не зафиксируем создание самой номенклатуры и не получим её новую ссылку.

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

Шаг 1. Перехват источника копирования

Для того чтобы знать, какие характеристики копировать, нам нужно запомнить «оригинал». В управляемых формах 1С при копировании в процедуру ПриСозданииНаСервере передается параметр ЗначениеЗаполнения. Нам необходимо сохранить эту ссылку в реквизит формы, чтобы использовать её позже.

Проанализируем код, который необходимо добавить в расширение формы элемента номенклатуры:


&НаСервере
Процедура Расш_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    // Проверяем, что объект создается копированием
    Если Параметры.Ключ.Пустая() И ЗначениеЗаполнено(Параметры.ЗначениеЗаполнения) Тогда
        // Сохраняем ссылку на оригинал в реквизит формы (нужно заранее создать реквизит "ИсточникКопирования")
        ЭтотОбъект.ИсточникКопирования = Параметры.ЗначениеЗаполнения;
    КонецЕсли;
КонецПроцедуры

Шаг 2. Запуск процесса после записи объекта

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

Рассмотрим реализацию логики:


&НаКлиенте
Процедура Расш_ПослеЗаписиПосле(ПараметрыЗаписи)
    Если ЗначениеЗаполнено(ИсточникКопирования) Тогда
        Оповещение = Новый ОписаниеОповещения("ПослеВопросаОКопированииХарактеристик", ЭтотОбъект);
        ПоказатьВопрос(Оповещение, "Скопировать характеристики из исходной номенклатуры?", РежимДиалогаВопрос.ДаНет);
    КонецЕсли;
КонецПроцедуры

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

Шаг 3. Программное копирование характеристик

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

Посмотрим на пример кода:


&НаСервере
Процедура КопироватьХарактеристикиНаСервере()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Характеристики.Ссылка КАК Ссылка
        |ИЗ
        |   Справочник.ХарактеристикиНоменклатуры КАК Характеристики
        |ГДЕ
        |   Характеристики.Владелец = &Источник";
    
    Запрос.УстановитьПараметр("Источник", ИсточникКопирования);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Копируем объект характеристики
        НоваяХарактеристика = Выборка.Ссылка.Скопировать();
        
        // Устанавливаем нового владельца (текущий объект формы)
        НоваяХарактеристика.Владелец = Объект.Ссылка;
        
        // Записываем новую характеристику
        Попытка
            НоваяХарактеристика.Записать();
        Исключение
            ЗаписьЖурналаРегистрации("КопированиеХарактеристик", УровеньЖурналаРегистрации.Ошибка, , , КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
    КонецЦикла;
    
КонецПроцедуры

Важные нюансы и дополнения

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

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

Альтернативный подход через БСП

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

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

← На главную