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

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

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

Анализ исходного подхода и его недостатки

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


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

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

Проанализируем этот код. Несмотря на то, что он выполняет задачу, он имеет несколько критических изъянов с точки зрения производительности и стандартов 1С:

  1. Избыточность серверных вызовов: мы сначала создаем объект на сервере, заполняем его, перегоняем в реквизит формы, а затем на клиенте снова копируем эти данные в форму нового документа.
  2. Нарушение жизненного цикла объекта: при таком подходе игнорируются стандартные механизмы инициализации документа, такие как установка префиксов, заполнение значений по умолчанию и проверка прав доступа.
  3. Риск потери связей: в 1С:ERP документы содержат множество служебных реквизитов и скрытых идентификаторов строк. Простое использование ЗаполнитьЗначенияСвойств может не перенести важные ключи связи, что приведет к ошибкам при проведении.

Решение 1: Использование параметра ЗначенияЗаполнения (Рекомендуемое)

Выясним, какой способ является наиболее "чистым". Платформа 1С:Предприятие 8.3 предоставляет штатный механизм передачи данных в открываемую форму. Рассмотрим по шагам, как это реализовать.

Суть метода заключается в подготовке структуры данных на стороне вызывающей формы и передаче её в качестве параметра ЗначенияЗаполнения при вызове ОткрытьФорму. В этом случае платформа автоматически инициирует событие ОбработкаЗаполнения в модуле объекта целевого документа.

Рассмотрим пример реализации на клиенте:


&НаКлиенте
Процедура СоздатьКПНаОсновании(Команда)
    
    // Подготавливаем данные для заполнения
    ДанныеДляЗаполнения = Новый Структура;
    ДанныеДляЗаполнения.Вставить("Партнер", Объект.Партнер);
    ДанныеДляЗаполнения.Вставить("Контрагент", Объект.Контрагент);
    ДанныеДляЗаполнения.Вставить("Организация", Объект.Организация);
    
    // Для табличных частей подготавливаем массив структур
    МассивТоваров = Новый Массив;
    Для Каждого Стр Из Объект.Товары Цикл
        НоваяСтрока = Новый Структура;
        НоваяСтрока.Вставить("Номенклатура", Стр.Номенклатура);
        НоваяСтрока.Вставить("Количество", Стр.Количество);
        НоваяСтрока.Вставить("Цена", Стр.Цена);
        МассивТоваров.Добавить(НоваяСтрока);
    КонецЦикла;
    
    ДанныеДляЗаполнения.Вставить("Товары", МассивТоваров);
    
    // Формируем параметры открытия формы
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗначенияЗаполнения", ДанныеДляЗаполнения);
    
    // Открываем форму нового документа
    ОткрытьФорму("Документ.КоммерческоеПредложениеКлиенту.ФормаОбъекта", ПараметрыФормы);
    
КонецПроцедуры

Теперь проанализируем, что должно происходить на стороне документа КоммерческоеПредложениеКлиенту. В его модуле объекта (не формы!) должен быть обработчик ОбработкаЗаполнения. Если структура передаваемых данных совпадает с именами реквизитов, платформа может заполнить их автоматически, но для сложных случаев (как с табличными частями) лучше прописать логику явно.


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

Решение 2: Использование механизмов БСП (Внешняя обработка заполнения)

Разберем еще один профессиональный подход — использование Библиотеки стандартных подсистем (БСП). В 1С:ERP реализован механизм подключаемых внешних отчетов и обработок. Если мы не хотим менять конфигурацию вообще, нам следует создать Внешнюю обработку заполнения.

Этот метод хорош тем, что:

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

Важные нюансы при работе в ERP

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

Почему это важно? В ERP при создании документа "на основании" система не просто копирует поля. Она пересчитывает цены согласно текущим соглашениям, проверяет остатки, заполняет налоговые ставки в соответствии с учетной политикой организации на текущую дату. Если вы просто скопируете Цена и Сумма из старого заказа, вы можете получить некорректные данные, если с момента создания заказа цены в прайс-листе изменились.

Посмотрим на рекомендации по работе с ТЧ:

Итоги

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

← На главную