///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

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

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

#Область ДляВызоваИзДругихПодсистем

// СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

// Возвращает реквизиты объекта, которые разрешается редактировать
// с помощью обработки группового изменения реквизитов.
//
// Возвращаемое значение:
//  Массив из Строка
//
Функция РеквизитыРедактируемыеВГрупповойОбработке() Экспорт

	РедактируемыеРеквизиты = Новый Массив;
	РедактируемыеРеквизиты.Добавить("Комментарий");

	Возврат РедактируемыеРеквизиты;

КонецФункции

// Конец СтандартныеПодсистемы.ГрупповоеИзменениеОбъектов

// СтандартныеПодсистемы.УправлениеДоступом

// Параметры:
//   Ограничение - см. УправлениеДоступомПереопределяемый.ПриЗаполненииОграниченияДоступа.Ограничение.
//
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

	Ограничение.Текст =
	"РазрешитьЧтение
	|ГДЕ
	|	ЧтениеОбъектаРазрешено(Владелец.ВладелецФайла)
	|;
	|РазрешитьИзменениеЕслиРазрешеноЧтение
	|ГДЕ
	|	ИзменениеОбъектаРазрешено(Владелец.ВладелецФайла)";

	Ограничение.ТекстДляВнешнихПользователей = Ограничение.Текст;

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

// Конец СтандартныеПодсистемы.УправлениеДоступом

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

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

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

Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
	Если ВидФормы = "ФормаОбъекта" Тогда
		СтандартнаяОбработка = Ложь;
		ВыбраннаяФорма       = "Обработка.РаботаСФайлами.Форма.ВерсияПрисоединенногоФайла";
	КонецЕсли;
КонецПроцедуры

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

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

// Регистрирует на плане обмена ОбновлениеИнформационнойБазы объекты,
// которые необходимо обновить на новую версию.
//
// Параметры:
//  Параметры - Структура - служебный параметр для передачи в процедуру ОбновлениеИнформационнойБазы.ОтметитьКОбработке.
//
Процедура ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию(Параметры) Экспорт

	ПараметрыВыборки = Параметры.ПараметрыВыборки;
	ПараметрыВыборки.ПолныеИменаОбъектов = "Справочник.ВерсииФайлов";
	ПараметрыВыборки.СпособВыборки = ОбновлениеИнформационнойБазы.СпособВыборкиСсылки();

	ТекстЗапроса =
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	ВерсииФайлов.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.ВерсииФайлов КАК ВерсииФайлов
	|ГДЕ
	|	ВерсииФайлов.Ссылка > &Ссылка
	|	И ВерсииФайлов.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)
	|
	|УПОРЯДОЧИТЬ ПО
	|	Ссылка";

	ОтработаныВсеФайлы = Ложь;

	Запрос = Новый Запрос(ТекстЗапроса);
	Ссылка = ПустаяСсылка(); 
	Пока Не ОтработаныВсеФайлы Цикл

		Запрос.УстановитьПараметр("Ссылка", Ссылка);
		//@skip-check query-in-loop - Порционная регистрация данных для обработки
		ВерсииДляОбработки = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
		ОбновлениеИнформационнойБазы.ОтметитьКОбработке(Параметры, ВерсииДляОбработки);
		
		КоличествоСсылок = ВерсииДляОбработки.Количество();
		Если КоличествоСсылок < 1000 Тогда
			ОтработаныВсеФайлы = Истина;
		ИначеЕсли КоличествоСсылок > 0 Тогда
			Ссылка = ВерсииДляОбработки[КоличествоСсылок - 1];
		КонецЕсли;

	КонецЦикла;

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

Процедура ОбработатьДанныеДляПереходаНаНовуюВерсию(Параметры) Экспорт

	ВыбранныеДанные = ОбновлениеИнформационнойБазы.ДанныеДляОбновленияВМногопоточномОбработчике(Параметры);

	ПроблемныхОбъектов = 0;
	ОбъектовОбработано = 0;

	Для Каждого Строка Из ВыбранныеДанные Цикл
		
		Если ОбработатьВерсиюФайла(Строка.Ссылка) Тогда
			ОбъектовОбработано = ОбъектовОбработано + 1;
		Иначе
			ПроблемныхОбъектов = ПроблемныхОбъектов + 1;
		КонецЕсли;

	КонецЦикла;

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

	ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(), 
		УровеньЖурналаРегистрации.Информация, , ,
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Обработана очередная порция файлов: %1'"),
			ОбъектовОбработано));
	Параметры.ОбработкаЗавершена = ОбновлениеИнформационнойБазы.ОбработкаДанныхЗавершена(Параметры.Очередь, "Справочник.ВерсииФайлов");

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

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

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

Функция ОбработатьВерсиюФайла(ВерсияСсылка)

	Результат = Истина;
	ПредставлениеСсылки = Строка(ВерсияСсылка);
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("Справочник.ВерсииФайлов");
	ЭлементБлокировки.УстановитьЗначение("Ссылка", ВерсияСсылка);

	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		
		ВерсияОбъект = Неопределено;
		ТребуетсяЗаписать = Ложь;
		
		// @skip-check query-in-loop - Порционная обработка большого объема данных.
		ПутьКФайлу = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВерсияСсылка, "ПутьКФайлу");
		Если СтрНачинаетсяС(ПутьКФайлу, "/") Или СтрНачинаетсяС(ПутьКФайлу, "\") Тогда
			НовыйПутьКФайлу = Сред(ПутьКФайлу, 2);

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

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

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();

		Результат = Ложь;
		ОбновлениеИнформационнойБазы.ЗаписатьОшибкуВЖурналРегистрации(ВерсияСсылка,
			ПредставлениеСсылки, ИнформацияОбОшибке());

	КонецПопытки;

	Возврат Результат;

КонецФункции

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

#КонецЕсли