Каталог решений - Фикс процедуры заполнения документа Формирование книги продаж для КА 1.1.81.3

Фикс процедуры заполнения документа Формирование книги продаж для КА 1.1.81.3

Фикс процедуры заполнения документа Формирование книги продаж для КА 1.1.81.3

В наличии

Неоптимальный отбор с использованием ПостроителяЗапроса

Категория:

Описание

В одном из обновлений от 1С доработан модуль заполнения документа Формирование записей книги продаж после чего время ожидания стало неприлично долгим. Замер производительности показал 1063,478002 (это 17 минут) — после оптимизации кода 66,239374 (1 минута).

Проблема в процедуре модуля документа РаспределитьОплатыПоДеревуСФ(). Тут в цикле создается таблица значений с помощью ПостроителяЗапроса — это результат отбора строк. Для оптимизации достаточно заменить несколько строк кода.

После внесения правок можно использовать типовой алгоритм заполнения  — для этого достаточно в комментарий документа написать » [ТиповойАлгоритмЗаполнения] » и сохранить его.

Платформа 1С 8.2, MSSQL.

Надеюсь эта маленькая правка кому-нибудь сэкономит время! 🙂

// Процедура вызывается из тела процедуры "ЗаполнитьРазделРеализация".
// В процессе работы процедуры общая сумма НДС, которая может быть признана
// в качестве вычета распределяется по конкретным событиям оплаты, для того
// чтобы сопоставить факт признания вычета по НДС и факт оплаты поставщику, связанный
// с этим признанием.
Процедура РаспределитьОплатыПоДеревуСФ(Дерево_НДСНачисленный, ТаблицаРезультатов, СписокСчетовФактур, РаспределенныеОплаты, ОтражатьВРеестре = Истина, ОтражатьВидНачисления = Ложь )
	
	НДСНалоговыйПериод = Неопределено;
	
	Построитель_РаспределенныеОплаты = Новый построительЗапроса();
	Построитель_РаспределенныеОплаты.ИсточникДанных = Новый ОписаниеИсточникаДанных(РаспределенныеОплаты);
	
	// Подготовка структуры отбора
	Отбор = Построитель_РаспределенныеОплаты.Отбор;
	Отбор.Добавить("СчетФактура");
	Отбор.СчетФактура.Использование = Истина;
	Отбор.Добавить("РаспределеннаяОплата");
	Отбор.РаспределеннаяОплата.ВидСравнения = ВидСравнения.Больше;
	Отбор.РаспределеннаяОплата.Значение = 0;
	Отбор.РаспределеннаяОплата.Использование = Истина;
	
	Построитель_РаспределенныеОплаты.Порядок.Добавить("ДатаОплаты");
	
	ТаблицаОплат = Новый ТаблицаЗначений();
	ТаблицаОплат.Колонки.Добавить("ДокументОплаты");
	ТаблицаОплат.Колонки.Добавить("ДатаОплаты",Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));
	ТаблицаОплат.Колонки.Добавить("СуммаОплаты",Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15,2)));
	
	ТаблицаИсточникаПостроителя = Построитель_РаспределенныеОплаты.ИсточникДанных.ИсточникДанных;
	МоментОпределения_ПоОтгрузке = Перечисления.МоментыОпределенияНалоговойБазыНДС.ПоОтгрузке;
	
	//[+] -> ДОБАВЛЯЕМ СВОИ ПЕРЕМЕННЫЕ
	ВремТаблицаИсточникаПостроителя = ТаблицаИсточникаПостроителя.СкопироватьКолонки();
	ИспользоватьТиповойАлгоритм     = (СтрЧислоВхождений(Ссылка.Комментарий, "[ТиповойАлгоритмЗаполнения]") > 0);
	//[+] <-
	
	Для каждого СтрокаСФ Из Дерево_НДСНачисленный.Строки Цикл
		
		ТаблицаОплат.Очистить();
		
		Если УчетНДС.ДляСчетаФактурыНеТребуетсяОплата(СтрокаСФ.СчетФактура) Тогда
			НаличиеОплатыНеТребуется = Истина;
		Иначе
			НаличиеОплатыНеТребуется = (СтрокаСФ.Строки[0].МоментОпределенияНалоговойБазыНДС = МоментОпределения_ПоОтгрузке) Или Дата >= '20080101';
			
			//[*] -> МЕНЯЕМ ТИПОВОЙ АЛГОРИТМ...
			//Отбор = Построитель_РаспределенныеОплаты.Отбор;
			//Отбор.СчетФактура.Значение = СтрокаСФ.СчетФактура;
			//Отбор.РаспределеннаяОплата.ВидСравнения = ?(СтрокаСФ.СуммаСНДС>0,ВидСравнения.Больше,ВидСравнения.Меньше);
			//
			//Построитель_РаспределенныеОплаты.Выполнить();
			//Если Построитель_РаспределенныеОплаты.Результат.Пустой() и не НаличиеОплатыНеТребуется и СтрокаСФ.СуммаСНДС	>= 0 Тогда
			//	// Оплата не обнаружена
			//	Продолжить;
			//КонецЕсли; 
			//
			//ВыборкаОплат = Построитель_РаспределенныеОплаты.Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой);
			
			//...С СОХРАНЕНИЕМ ФУНКЦИОНАЛЬНОСТИ ТИПОВОГО ЗАПОЛНЕНИЯ
			//
			Если ИспользоватьТиповойАлгоритм Тогда
				Отбор = Построитель_РаспределенныеОплаты.Отбор;
				Отбор.СчетФактура.Значение = СтрокаСФ.СчетФактура;
				Отбор.РаспределеннаяОплата.ВидСравнения = ?(СтрокаСФ.СуммаСНДС>0,ВидСравнения.Больше,ВидСравнения.Меньше);
				
				Построитель_РаспределенныеОплаты.Выполнить();
				Если Построитель_РаспределенныеОплаты.Результат.Пустой() и не НаличиеОплатыНеТребуется и СтрокаСФ.СуммаСНДС	>= 0 Тогда
					// Оплата не обнаружена
					Продолжить;
				КонецЕсли; 
				
				ВыборкаОплат = Построитель_РаспределенныеОплаты.Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой);
			Иначе
				ПоискОтбор   = Новый Структура();
				ПоискОтбор.Вставить("СчетФактура", СтрокаСФ.СчетФактура);
				ПоискОплат   = ТаблицаИсточникаПостроителя.НайтиСтроки(ПоискОтбор);
				ВыборкаОплат = ВремТаблицаИсточникаПостроителя.Скопировать();
				Если ПоискОплат.Количество() > 0 Тогда
					Для каждого СтрокаПоиска Из ПоискОплат Цикл
						Если СтрокаСФ.СуммаСНДС > 0 Тогда
							Если СтрокаПоиска.РаспределеннаяОплата > 0 Тогда
								СтрокаВыборки = ВыборкаОплат.Добавить();
								ЗаполнитьЗначенияСвойств(СтрокаВыборки, СтрокаПоиска);
							КонецЕсли;	
						Иначе
							Если СтрокаПоиска.РаспределеннаяОплата < 0 Тогда
								СтрокаВыборки = ВыборкаОплат.Добавить();
								ЗаполнитьЗначенияСвойств(СтрокаВыборки, СтрокаПоиска);
							КонецЕсли;	
						КонецЕсли;
					КонецЦикла;		
				КонецЕсли;
				
				Если ВыборкаОплат.Количество() = 0 Тогда
					Если (НЕ НаличиеОплатыНеТребуется И СтрокаСФ.СуммаСНДС >= 0) Тогда
						// Оплата не обнаружена
						Продолжить;
					КонецЕсли;	
				КонецЕсли;
			КонецЕсли;
			//[*] <-
				
			СуммаКПогашению = СтрокаСФ.СуммаСНДС;

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

P.S.: ну а дальше запросы, но это уже совсем другая история…

has been added to your cart:
Оформление заказа