Структура серии номенклатуры / Модуль объекта

файл
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
	
#Область СлужебныйПрограммныйИнтерфейс

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

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

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытий

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
	
	НастройкиОсновнойСхемы = КомпоновщикНастроек.ПолучитьНастройки();
	
	ОтборНоменклатура = КомпоновкаДанныхКлиентСервер.ПолучитьПараметр(НастройкиОсновнойСхемы, "Номенклатура").Значение;
	ОтборСерия = КомпоновкаДанныхКлиентСервер.ПолучитьПараметр(НастройкиОсновнойСхемы, "Серия").Значение;
	
	Если НЕ ЗначениеЗаполнено(ОтборНоменклатура) Тогда
		Если ПолучитьФункциональнуюОпцию("ИспользоватьПроизводство") Тогда
			ТекстСообщения = НСтр("ru = 'Поле ""Продукция или полуфабрикат"" не заполнено.'");
		Иначе
			ТекстСообщения = НСтр("ru = 'Поле ""Комплект"" не заполнено.'");
		КонецЕсли; 
		ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения,,,, Отказ); 
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(ОтборСерия) Тогда
		ТекстСообщения = НСтр("ru = 'Поле ""Серия"" не заполнено.'");
		ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения,,,, Отказ); 
	КонецЕсли;
	
КонецПроцедуры

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

	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);

	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборы, ДанныеРасшифровки, Истина);

	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция СтруктураСерииНоменклатуры(Параметры, ПревышенЛимитСтрок)
	
	СтруктураСерииНоменклатурыДерево = Новый ДеревоЗначений;
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("Характеристика", Новый ОписаниеТипов("СправочникСсылка.ХарактеристикиНоменклатуры"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("Серия", Новый ОписаниеТипов("СправочникСсылка.СерииНоменклатуры"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("Израсходовано", Новый ОписаниеТипов("Число"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("ЕдиницаИзмерения", Новый ОписаниеТипов("Строка"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("НоменклатураПредставление", Новый ОписаниеТипов("Строка"));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("СерияПредставление", Новый ОписаниеТипов("Строка"));
	
	МассивТипов = Новый Массив;
	МассивТипов.Добавить(Новый ОписаниеТипов("УникальныйИдентификатор"));
	МассивТипов.Добавить(Новый ОписаниеТипов("Строка"));
	
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("ИдентификаторЭлемента", Новый ОписаниеТипов(МассивТипов));
	СтруктураСерииНоменклатурыДерево.Колонки.Добавить("ИдентификаторРодителя", Новый ОписаниеТипов(МассивТипов));
	
	СтруктураСерииКоллекция = СтруктураСерииНоменклатурыДерево.Строки;
	
	СписокНоменклатуры = Новый ТаблицаЗначений; // см. ПроизводствоСервер.СлужебнаяСтруктураТаблицыЗначений
	СписокНоменклатуры.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
	СписокНоменклатуры.Колонки.Добавить("Характеристика", Новый ОписаниеТипов("СправочникСсылка.ХарактеристикиНоменклатуры"));
	СписокНоменклатуры.Колонки.Добавить("Серия", Новый ОписаниеТипов("СправочникСсылка.СерииНоменклатуры"));
	СписокНоменклатуры.Колонки.Добавить("Строки");
	
	НоваяСтрока = СписокНоменклатуры.Добавить();
	ЗаполнитьЗначенияСвойств(НоваяСтрока, Параметры);
	НоваяСтрока.Строки = СтруктураСерииКоллекция;
	
	ОтборПоХарактеристике = ЗначениеЗаполнено(Параметры.Характеристика);
	
	УстановитьПривилегированныйРежим(Истина);
	
	СтруктураПоиска = Новый Структура("НоменклатураСписка, ХарактеристикаСписка, СерияСписка");
	КоличествоСтрок = 0;
	ЛимитСтрок = ЛимитСтрок();
	
	Пока СписокНоменклатуры.Количество() <> 0 Цикл
		
		НовыйСписокНоменклатуры = СписокНоменклатуры.СкопироватьКолонки();
		
		ИспользованныеСерии = ИспользованныеСерии(СписокНоменклатуры, ОтборПоХарактеристике);
		ИспользованныеСерии.Индексы.Добавить("НоменклатураСписка, ХарактеристикаСписка, СерияСписка");
		
		Если НЕ ОтборПоХарактеристике Тогда
			
			ОтборПоХарактеристике = Истина;
			
			СписокНоменклатуры.Очистить();
			
			Колонки = "НоменклатураСписка, ХарактеристикаСписка, СерияСписка";
			ИспользованныеСерииКопия = ИспользованныеСерии.Скопировать(, Колонки);
			ИспользованныеСерииКопия.Свернуть(Колонки);
			
			Для каждого Строка Из ИспользованныеСерииКопия Цикл
				
				НоваяСтрока = СписокНоменклатуры.Добавить();
				НоваяСтрока.Номенклатура = Строка.НоменклатураСписка;
				НоваяСтрока.Характеристика = Строка.ХарактеристикаСписка;
				НоваяСтрока.Серия = Строка.СерияСписка;
				НоваяСтрока.Строки = СтруктураСерииКоллекция;
				
			КонецЦикла;
			
		КонецЕсли;
		
		Для каждого СтрокаНоменклатура Из СписокНоменклатуры Цикл
			
			СтруктураПоиска.НоменклатураСписка = СтрокаНоменклатура.Номенклатура;
			СтруктураПоиска.ХарактеристикаСписка = СтрокаНоменклатура.Характеристика;
			СтруктураПоиска.СерияСписка = СтрокаНоменклатура.Серия;
			
			Для каждого СтрокаСерияМатериала Из ИспользованныеСерии.НайтиСтроки(СтруктураПоиска) Цикл
				
				КоличествоСтрок = КоличествоСтрок + 1;
				Если КоличествоСтрок > ЛимитСтрок Тогда
					ПревышенЛимитСтрок = Истина;
					Прервать;
				КонецЕсли;
				
				НоваяСерия = СтрокаНоменклатура.Строки.Добавить();
				ЗаполнитьЗначенияСвойств(НоваяСерия, СтрокаСерияМатериала);
				НоваяСерия.НоменклатураПредставление = НоменклатураКлиентСервер.ПредставлениеНоменклатуры(
					СтрокаСерияМатериала.НоменклатураПредставление,
					СтрокаСерияМатериала.ХарактеристикаПредставление);
					
				Если ЗначениеЗаполнено(НоваяСерия.Серия) Тогда
					
					// Контроль зацикливания
					ЕстьЗацикливание = Ложь;
					
					Родитель = НоваяСерия.Родитель;
					Пока Родитель <> Неопределено Цикл
						Если Родитель.Номенклатура = НоваяСерия.Номенклатура
								И Родитель.Характеристика = НоваяСерия.Характеристика
								И Родитель.Серия = НоваяСерия.Серия Тогда
							ЕстьЗацикливание = Истина;
							Прервать;
						КонецЕслИ;
						Родитель = Родитель.Родитель;
					КонецЦикла;
					
					Если Не ЕстьЗацикливание Тогда
						НоваяНоменклатура = НовыйСписокНоменклатуры.Добавить();
						ЗаполнитьЗначенияСвойств(НоваяНоменклатура, НоваяСерия);
						НоваяНоменклатура.Строки = НоваяСерия.Строки;
					КонецЕсли;
					
				КонецЕсли;
				
			КонецЦикла; 
			Если КоличествоСтрок > ЛимитСтрок Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		Если КоличествоСтрок > ЛимитСтрок Тогда
			Прервать;
		КонецЕсли;
		
		СписокНоменклатуры = НовыйСписокНоменклатуры.Скопировать();
		
	КонецЦикла; 
	
	Возврат СтруктураСерииНоменклатурыДерево;
	
КонецФункции

Функция ИспользованныеСерии(СписокНоменклатуры, ОтборПоХарактеристике)

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

Функция ЛимитСтрок()
	Возврат 100000;
КонецФункции

Процедура ЗаполнитьСлужебныеПоля(СтрокиДерева, Идентификатор)

	Для каждого СтрокаДерева Из СтрокиДерева Цикл
		
		СтрокаДерева.ИдентификаторЭлемента = Новый УникальныйИдентификатор;
		СтрокаДерева.ИдентификаторРодителя = Идентификатор;
		ЗаполнитьСлужебныеПоля(СтрокаДерева.Строки, СтрокаДерева.ИдентификаторЭлемента);
	
	КонецЦикла;

КонецПроцедуры

#КонецОбласти

#КонецЕсли

Связанные материалы