Рассмотрим частую задачу, с которой сталкиваются разработчики при автоматизации бизнес-процессов в 1С: необходимо на основании одного исходного документа (например, Заказ покупателя) сформировать не один, а сразу несколько целевых документов (например, несколько документов Заказ поставщику, разнесенных по разным контрагентам или группам товаров).
Штатный механизм платформы 1С — событие ОбработкаЗаполнения в модуле объекта — рассчитан на стандартную инициализацию одного нового документа. Если требуется сформировать пакет документов, стандартной кнопки «Создать на основании» недостаточно. Разберем основные подходы к решению этой задачи на управляемых формах.
Если документов создается много или пользователь не должен вручную проверять каждый из них перед сохранением, оптимальным решением является пакетное создание документов на сервере в фоновом или безынтерфейсном режиме.
Выясним алгоритм работы данного подхода:
СоздатьДокумент() для каждого нового объекта.Записать().Посмотрим на пример серверной процедуры создания пакета документов:
&НаСервере
Процедура СформироватьЗаказыПоставщикамНаСервере(СсылкаНаЗаказПокупателя)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказТовары.Поставщик КАК Поставщик,
| ЗаказТовары.Номенклатура КАК Номенклатура,
| ЗаказТовары.Количество КАК Количество
|ИЗ
| Документ.ЗаказПокупателя.Товары КАК ЗаказТовары
|ГДЕ
| ЗаказТовары.Ссылка = &СсылкаНаЗаказПокупателя
|ИТОГИ ПО
| Поставщик";
Запрос.УстановитьПараметр("СсылкаНаЗаказПокупателя", СсылкаНаЗаказПокупателя);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаПоставщик = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПоставщик.Следующий() Цикл
НовыйЗаказ = Документы.ЗаказПоставщику.СоздатьДокумент();
НовыйЗаказ.Дата = ТекущаяДата();
НовыйЗаказ.Партнер = ВыборкаПоставщик.Поставщик;
НовыйЗаказ.ДокументОснование = СсылкаНаЗаказПокупателя;
ВыборкаДетали = ВыборкаПоставщик.Выбрать();
Пока ВыборкаДетали.Следующий() Цикл
НоваяСтрока = НовыйЗаказ.Товары.Добавить();
НоваяСтрока.Номенклатура = ВыборкаДетали.Номенклатура;
НоваяСтрока.Количество = ВыборкаДетали.Количество;
КонецЦикла;
Попытка
НовыйЗаказ.Записать(РежимЗаписиДокумента.Запись);
Исключение
ВызватьИсключение "Ошибка при записи документа для поставщика " + ВыборкаПоставщик.Поставщик;
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если необходимо, чтобы создаваемый документ открывался интерактивно для проверки пользователем, используется механизм передаваемых параметров формы. В этом случае на клиенте формируется структура с данными и передается в ключ Основание при открытии формы целевого документа.
Рассмотрим, как это реализуется шаг за шагом:
ОткрытьФорму(), передавая структуру в параметрах.ОбработкаЗаполнения обрабатываем входящую структуру и заполняем реквизиты.Проанализируем код клиентской части:
&НаКлиенте
Процедура ОткрытьЗаказПоставщикуСДанными(ЗаказПокупателяСсылка, Поставщик)
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("ЗаказПокупателя", ЗаказПокупателяСсылка);
СтруктураПараметров.Вставить("Поставщик", Поставщик);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Основание", СтруктураПараметров);
ОткрытьФорму("Документ.ЗаказПоставщику.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры
В модуле объекта создаваемого документа ЗаказПоставщику описываем событие ОбработкаЗаполнения:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
Если ДанныеЗаполнения.Свойство("ЗаказПокупателя") Тогда
// Вызываем процедуру заполнения по данным из структуры
ЗаполнитьПоЗаказуПокупателя(ДанныеЗаполнения.ЗаказПокупателя, ДанныеЗаполнения.Поставщик);
КонецЕсли;
ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
// Стандартная обработка, если передана прямая ссылка
ЗаполнитьПоЗаказуПокупателя(ДанныеЗаполнения);
КонецЕсли;
КонецПроцедуры
В типовых конфигурациях (например, 1С:Управление торговлей, 1С:ERP, 1С:Комплексная автоматизация) заполнение документов часто выносится в отдельные экспортные процедуры общих модулей или модулей менеджеров.
Пример вызова экспортной процедуры из типовых решений для заполнения реквизитов:
// Процедура предназначена для заполнения общих реквизитов документов по документу-основанию.
// Вызывается в обработчиках событий "ОбработкаЗаполнения" в модулях документов.
Процедура ЗаполнитьПоОснованию(ДокументОбъект, ДокументОснование, КопироватьПодразделение = Истина) Экспорт
// Алгоритм копирования шапки и связанных реквизитов
ДокументОбъект.ЗаполнитьЗначенияСвойств(ДокументОснование);
КонецПроцедуры
При реализации сложных алгоритмов ввода на основании важно четко разделять контексты выполнения кода:
СоздатьДокумент()).При вызове создания сразу нескольких документов всегда выносите логику формирования выборки и записи объектов на сервер, возвращая на клиент лишь результаты выполнения операции.