// Псевдокод вызова событий платформой https://github.com/SeiOkami/OneS/issues/313
// Имитаторы системных методов обозначены комментарием "//=== <ТипКотекста>.<Метод> -"
// Вызовы событий обозначены комментарием "//=== <ИмяСобытия> - <ТипКонтекста>"
// Блоксхема https://infostart.ru/1c/articles/1175475/
  
//=== Глобальный.ПолучитьФорму -
//=== Глобальный.ОткрытьФорму - 
// Параметры:
//   ИмяФормы - Строка -
//   Параметры - Структура, Неопределено - :
//    *Ключ - ДокументСсылка - передается для формы объекта
//    *ЗначениеКопирования - ДокументСсылка - передается для формы объекта
// Возвращаемое значение:
//   ФормаКлиентскогоПриложения, Неопределено - 
&НаКлиенте
Функция Глобальный_ОткрытьФорму(ИмяФормы, Параметры)
	Отказ = Ложь;
	ЭтаФорма = ПолучитьФормуНаСервере(ИмяФормы, Параметры, Отказ);
	Если Отказ Тогда Возврат Неопределено КонецЕсли;
	
	//=== ПриОткрытии - Форма
	ЭтаФорма.ПриОткрытии(Отказ); // Обработчик
	Если Отказ Тогда Возврат Неопределено КонецЕсли;
	
	ЭтаФорма.Активизировать();
	Возврат ЭтаФорма;
КонецФункции

&НаСервере
Функция ПолучитьФормуНаСервере(ИмяФормы, Параметры, Отказ) Экспорт
	ВыбраннаяФорма = ИмяФормы;
	Менеджер = Неопределено; // ДокументМенеджер
	Если "ЭтоОтносительноеИмяФормы" Тогда 
		
		//=== ОбработкаПолученияФормы - Объект
		СтандартнаяОбработка = Ложь;
		Менеджер.ОбработкаПолученияФормы(,, ВыбраннаяФорма,, СтандартнаяОбработка); // Обработчик
		Для Каждого ИмяОбработчика Из ПодпискиНаСобытие("ОбработкаПолученияФормы") Цикл
			Выполнить(ИмяОбработчика + "(,, ВыбраннаяФорма,, СтандартнаяОбработка)"); // Подписка
		КонецЦикла;
		// Если СтандартнаяОбработка, то ВыбраннаяФорма = ОсновнаяФорма
	КонецЕсли;
	ЭтаФорма = Новый (ВыбраннаяФорма);
	Если "ЭтоФормаОбъекта" Тогда
		Если ЗначениеЗаполнено(Параметры.Ключ) Тогда
			Объект = Параметры.Ключ.ПолучитьОбъект();
			
			//=== ПриЧтенииНаСервере - Форма
			ЭтаФорма.ПриЧтенииНаСервере(Объект); // Обработчик
		ИначеЕсли ЗначениеЗаполнено(Параметры.ЗначениеКопирования) Тогда
			Объект = Параметры.Ключ.Скопировать();
			
			//=== ПриКопировании - Объект
			Объект.ПриКопировании(); // Обработчик
			Для Каждого ИмяОбработчика Из ПодпискиНаСобытие("ПриКопировании") Цикл
				Выполнить(ИмяОбработчика + "()"); // Подписка
			КонецЦикла;
		Иначе
			Объект = Менеджер.СоздатьДокумент();
			
			//=== ОбработкаЗаполнения - Объект
			СтандартнаяОбработка = Истина;
			Объект.ОбработкаЗаполнения(,, СтандартнаяОбработка); // Обработчик
			Для Каждого ИмяОбработчика Из ПодпискиНаСобытие("ОбработкаЗаполнения") Цикл
				Выполнить(ИмяОбработчика + "(,, СтандартнаяОбработка)"); // Подписка
			КонецЦикла;
			// Если СтандартнаяОбработка, то установка значений всем реквизитам с признаком ЗаполнятьИзДанныхЗаполнения, 
		КонецЕсли;
		ЭтаФорма.ЗначениеВРеквизитФормы(Объект, "Объект");
	КонецЕсли;
	
	// Установка свойств формы от _переданных_ системных параметров
	ЗаполнитьЗначенияСвойств(ЭтаФорма, ЭтаФорма.Параметры, "ЗакрыватьПриВыборе, ЗакрыватьПриЗакрытииВладельца, ТолькоПросмотр, ...");
	
	//=== ПриСозданииНаСервере - Форма
	СтандартнаяОбработка = Ложь;
	ЭтаФорма.ПриСозданииНаСервере(Отказ, СтандартнаяОбработка); // Обработчик
	Если Отказ Тогда Возврат Неопределено КонецЕсли;
	
	Если СтандартнаяОбработка Тогда
		// Установка свойств основного реквизита от _переданных_ системных параметров. https://forum.infostart.ru/forum9/topic214045/
		ЗаполнитьЗначенияСвойств(Элементы.Список, ЭтаФорма.Параметры, "ВыборГруппИЭлементов, Отбор, МножественныйВыбор, ...");
	КонецЕсли;
	
	Если "ЕстьСохраненнаяНастройкаФормы" Тогда // https://github.com/SeiOkami/OneS/issues/270
		
		//=== ПередЗагрузкойДанныхИзНастроекНаСервере - Форма
		ЭтаФорма.ПередЗагрузкойДанныхИзНастроекНаСервере(); // Обработчик
		
		//=== ПриЗагрузкеДанныхИзНастроекНаСервере - Форма
		ЭтаФорма.ПриЗагрузкеДанныхИзНастроекНаСервере(); // Обработчик
	КонецЕсли;
	
	Если "ЭтоФормаДокумента" Тогда
		ЭтаФорма.Объект.Дата = НачалоДня(ТекущаяДатаСеанса());
	ИначеЕсли "ЭтоФормаЗаписиПериодическогоРегистра" Тогда
		ЭтаФорма.Объект.Период = ТекущаяДатаСеанса();
	КонецЕсли;
	// Чтение данных динамических списков
	Возврат ЭтаФорма; 
КонецФункции

&НаСервере
Функция ПодпискиНаСобытие(ИмяСобытия)
КонецФункции

//=== ФормаКлиентскогоПриложения.Записать -
// Параметры:
//   ПараметрыЗаписи - Структура - :
//    *РежимЗаписи - РежимЗаписиДокумента - для документа
// Возвращаемое значение:
//   Булево - 
&НаКлиенте
Функция ФормаОбъектаБД_Записать(ПараметрыЗаписи)

	//=== ПередЗаписью - Форма
	Отказ = Ложь;
	ЭтаФорма.ПередЗаписью(Отказ, ПараметрыЗаписи); // Обработчик
	Если Отказ Тогда Возврат Ложь КонецЕсли;
	
	ФормаОбъектаБД_ЗаписатьНаСервере(ПараметрыЗаписи, Отказ);
	Если Отказ Тогда Возврат Ложь КонецЕсли;

	//=== ПослеЗаписи - Форма
	ЭтаФорма.ПослеЗаписи(ПараметрыЗаписи); // Обработчик

	Возврат Истина;
КонецФункции

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

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

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

&НаСервере
Процедура УдалитьСвязанныеОбъекты(Запрос, Объект)
	Запрос.УстановитьПараметр("Объект", Объект.Ссылка);
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Объект = Выборка.Ссылка.ПолучитьОбъект();
		Объект.ОбменДанными = Объект.ОбменДанными;
		Объект_Удалить(Объект);
	КонецЦикла;
КонецПроцедуры

//=== ФормаКлиентскогоПриложения.Закрыть - 
&НаКлиенте
Функция Форма_Закрыть(ЗавершениеРаботы)
	Отказ = Ложь;
	СтандартнаяОбработка = Истина;
	ТекстПредупреждения = "";

	//=== ПередЗакрытием - Форма - https://its.1c.ru/db/pubv8devui/content/210/hdoc
	ЭтаФорма.ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка); // Обработчик
	Если Отказ Тогда Возврат Неопределено КонецЕсли;
	// Если СтандартнаяОбработка, то для модифицированной формы объекта БД предлагается записать

	//=== ПриЗакрытии - Форма
	ЭтаФорма.ПриЗакрытии(ЗавершениеРаботы); // Обработчик

	Если Истина
		И Не ЗавершениеРаботы 
		И ЭтаФорма.АвтоматическоеСохранениеДанныхВНастройках
		И ЭтаФорма.СохраняемыеВНастройкахДанныеМодифицированы // https://partners.v8.1c.ru/forum/t/1057116/m/1057145
	Тогда 
		Форма_ЗакрытьНаСервере(ЗавершениеРаботы);
	КонецЕсли;
КонецФункции

&НаСервере
Функция Форма_ЗакрытьНаСервере(ЗавершениеРаботы) Экспорт
	//=== ПриСохраненииДанныхВНастройкахНаСервере - Форма
	ЭтаФорма.ПриСохраненииДанныхВНастройкахНаСервере(); // Обработчик
КонецФункции
