План продаж по категориям / Модуль объекта

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

#Область ПрограммныйИнтерфейс

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

// Устанавливает статус для объекта документа
//
// Параметры:
//	НовыйСтатус - Строка - Имя статуса, который будет установлен у заказов
//	ДополнительныеПараметры - Структура - Структура дополнительных параметров установки статуса.
//
// Возвращаемое значение:
//	Булево - Истина, в случае успешной установки нового статуса.
//
Функция УстановитьСтатус(НовыйСтатус, ДополнительныеПараметры) Экспорт
	
	ЗначениеНовогоСтатуса = Перечисления.СтатусыПланов[НовыйСтатус];
	
	Статус = ЗначениеНовогоСтатуса;
	
	Возврат ПроверитьЗаполнение();
	
КонецФункции

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

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

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
	
	// Пропускаем обработку, чтобы гарантировать получение формы объекта при передаче параметра "АвтоТест".
	Если ДанныеЗаполнения = "АвтоТест" Тогда
		Возврат;
	КонецЕсли;
	
	ИнициализироватьДокумент(ДанныеЗаполнения);
	
КонецПроцедуры

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
	
	МассивНепроверяемыхРеквизитов = Новый Массив;

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

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

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

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

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

Процедура ПриКопировании(ОбъектКопирования)

	Статус = Метаданные().Реквизиты.Статус.ЗначениеЗаполнения;
	Если Не ЗначениеЗаполнено(Дата) Тогда
		Дата = ТекущаяДатаСеанса();
	КонецЕсли;
	ЗаполнитьРеквизитыПланаПоСценариюВидуПлана();
	Для каждого СтрокаТовары Из ТоварныеКатегории Цикл

		СтрокаТовары.Отменено = Ложь;

	КонецЦикла;
	
КонецПроцедуры

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
	ПроведениеДокументов.ОбработкаПроведенияДокумента(ЭтотОбъект, Отказ);
	
КонецПроцедуры

Процедура ОбработкаУдаленияПроведения(Отказ)
	
	ПроведениеДокументов.ОбработкаУдаленияПроведенияДокумента(ЭтотОбъект, Отказ);
	
КонецПроцедуры

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

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

#Область ИнициализацияИЗаполнение

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

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

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

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

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

#КонецЕсли

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