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