новое событие
Информационный поток
Задания вакансии материалы разработки сообщения форума

Автоматическое создание/изменение связанных документов

  • Добавить свою публикацию
  • для этого требуется регистрация

Предисловие

Решим практическую задачу. Необходимо при проведении документа "Перемещение товаров" для ордерных

складов автоматически создавать на основании документ "Расходный ордер на товары". 

Изображение

При последующих изменения документа перемещения нужно изменять и расходный ордер. Доработка выполняется на конфигурации "Управление производственным предприятием" редакции 1.3.

Общий принцип

Изменение связанных от записываемого/проводимого документа лучше всего выполнять в обработчике "ПриЗаписи", чтобы не влиять на процедуру проведения документа. Рекомендация действительна только в тех случаях, когда это позволяет логика прикладного решения. 

На следующем листинге показан пример обрабочика изменения связанного документа:

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

Коментарии достаточно подробны. Рассмотрим работу алгоритма на практической задаче, которая была озвучена выше.

Реализация

В типовой конфигурации "Управление произвосдвенным предприятием" для автосоздания документа расходного ордера товаров созадим подписку на событие "ПриЗаписиДокументаПеремещения" на событие "ПриЗаписи" со следующим обработчиком:

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

Сама процедура заполнения зависимого расходного ордера очень проста:

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

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

Заключение

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

 
0
Еще от автора
≡ к списку статей