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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

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

Причина такого поведения заключается в том, что спецификации номенклатуры в 1С:Бухгалтерии 3.0 хранятся не в табличной части самого элемента номенклатуры, а в отдельном справочнике – СпецификацииНоменклатуры. Эти спецификации связаны с элементом номенклатуры через реквизит «Владелец». Стандартный механизм копирования элементов справочников не предусматривает автоматическое копирование связанных объектов из других справочников, если это явно не запрограммировано.

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

Пошаговое внедрение решения

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

  1. Создание расширения

    Если у вас еще нет расширения, создайте его. Откройте конфигуратор, перейдите в меню "Конфигурация" -> "Расширения конфигурации" -> "Добавить расширение". Присвойте ему осмысленное имя и включите его использование.

  2. Добавление реквизита "ЗначениеКопирования" на форму элемента номенклатуры

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

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

    • Имя: ЗначениеКопирования
    • Тип: СправочникСсылка.Номенклатура

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

  3. Код для формы элемента номенклатуры

    Далее мы добавим обработчики событий на форму элемента номенклатуры. Эти обработчики будут выполняться на сервере.

    Расш1_ПриСозданииНаСервереПосле

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

    
    &НаСервере
    Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
        ЭтотОбъект.ЗначениеКопирования = Параметры.ЗначениеКопирования;
    КонецПроцедуры
    

    Расш1_ПередЗаписьюНаСервереПосле

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

    Мы проверяем, что объект новый (Объект.Ссылка.Пустая) и что мы копируем из другого элемента (Не ЭтотОбъект.ЗначениеКопирования.Пустая). Если эти условия выполняются, мы добавляем в ДополнительныеСвойства текущего объекта ссылку на исходную номенклатуру и, если у нее была основная спецификация, ссылку на нее и новую уникальную ссылку, которую получит скопированная основная спецификация.

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

    Теперь перейдем к модулю объекта справочника Номенклатура. Здесь мы будем выполнять основную логику копирования спецификаций (подобным образом настраивается и автоматическое создание штрихкодов к номенклатуре).

    Расш1_ПриЗаписи

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

    В этом обработчике мы проверяем, было ли выполнено копирование (наличие ЗначениеКопирования в ДополнительныеСвойства) и, если да, вызываем нашу процедуру Расш1_СкопироватьСпецификации.

    
    &После("ПриЗаписи")
    Процедура Расш1_ПриЗаписи(Отказ)
        Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ЗначениеКопирования") Тогда
            Расш1_СкопироватьСпецификации;
        КонецЕсли;
    КонецПроцедуры
    

    Расш1_СкопироватьСпецификации

    Это основная процедура, которая выполняет копирование всех спецификаций. Мы действуем по следующему алгоритму:

    1. Получаем исходную номенклатуру: Мы извлекаем ссылку на исходную номенклатуру из ДополнительныеСвойства.
    2. Выполняем запрос: Создаем запрос к справочнику СпецификацииНоменклатуры, чтобы найти все спецификации, связанные с исходной номенклатурой (по полю Владелец).
    3. Итерируем по спецификациям: В цикле обходим все найденные спецификации.
    4. Копируем каждую спецификацию: Для каждой исходной спецификации мы вызываем метод Скопировать(). Этот метод создает новый, еще не записанный в базу данных объект спецификации, который является точной копией исходного по всем реквизитам.
    5. Устанавливаем нового владельца: Это самый важный шаг. Мы присваиваем реквизиту Владелец новой спецификации ссылку на новую номенклатуру (ЭтотОбъект.Ссылка), которую мы только что записали. Без этого шага спецификация останется без владельца или будет указывать на старую номенклатуру.
    6. Обрабатываем основную спецификацию: Если в ДополнительныеСвойства было указано, что копируемая спецификация является основной, и мы заранее подготовили для нее новую уникальную ссылку, то мы используем метод УстановитьСсылкуНового(). Это гарантирует, что поле ОсновнаяСпецификацияНоменклатуры в только что созданной номенклатуре будет корректно указывать на именно эту скопированную спецификацию.
    7. Записываем новую спецификацию: Вызываем метод Записать() для новой спецификации, чтобы сохранить ее в базе данных.
    
    &НаСервере
    Процедура Расш1_СкопироватьСпецификации
        Запрос = Новый Запрос;
        Запрос.УстановитьПараметр("Владелец", ЭтотОбъект.ДополнительныеСвойства.ЗначениеКопирования);
        Запрос.Текст = 
            "ВЫБРАТЬ
            |    Таблица.Ссылка КАК Ссылка
            |ИЗ
            |    Справочник.СпецификацииНоменклатуры КАК Таблица
            |ГДЕ
            |    Таблица.Владелец = &Владелец";
                
        Выборка = Запрос.Выполнить().Выбрать();
        Пока Выборка.Следующий Цикл
            НовОбт = Выборка.Ссылка.Скопировать();
            НовОбт.Владелец = ЭтотОбъект.Ссылка;
                    
            Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ЗначениеКопированияОсновнаяСпецификация") Тогда
                Если Выборка.Ссылка = ЭтотОбъект.ДополнительныеСвойства.ЗначениеКопированияОсновнаяСпецификация Тогда
                    НовОбт.УстановитьСсылкуНового(ЭтотОбъект.ДополнительныеСвойства.СпецификацииНоменклатурыНоваяСсылка);
                КонецЕсли;
            КонецЕсли;
                    
            НовОбт.Записать();
        КонецЦикла;
    КонецПроцедуры
    
  5. Привязка обработчиков событий

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

Объяснение ключевых концепций 1С

Для лучшего понимания представленного решения, используя справочник методов Бухгалтерии предприятия 3.0, давайте подробнее рассмотрим некоторые ключевые механизмы платформы 1С:Предприятие 8:

Альтернативные подходы к копированию спецификаций

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

  1. Ручное копирование спецификаций

    Вы можете скопировать спецификацию вручную. Для этого перейдите в раздел "Справочники" -> "Номенклатура", откройте нужный элемент номенклатуры, а затем перейдите по ссылке "Спецификации" или "Материалы" (в зависимости от настроек). В открывшемся списке спецификаций выберите нужную, откройте ее и нажмите кнопку "Скопировать". После этого обязательно измените поле "Владелец" новой спецификации на новую номенклатуру и сохраните ее.

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

  2. Использование внешних обработок

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

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

  3. Открытие формы с параметром "ЗначениеКопирования"

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

Важные моменты и рекомендации

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

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

← На главную