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