Untitled

 avatar
unknown
plain_text
2 months ago
11 kB
7
Indexable
// =========================================================
// РАЗОВОЕ ВОССТАНОВЛЕНИЕ СТК
// Перенос значений "Остатки СТК" из старого ROSMA-реквизита
// в новый реквизит Сантехкомплекта
//
// Перед запуском:
// 1. Остановить регламент ROSMA
// 2. Сделать копию базы, если возможно
// =========================================================

Процедура ПеренестиОстаткиСТКИзРосмаВСантех() Экспорт

	ИмяСобытия = "STK_RECOVERY";

	// Вид номенклатуры, который нужно восстановить
	ИмяВидаСантех = "Товары (Сантехкомплект)";

	// СТАРЫЙ реквизит, где сейчас лежат данные
	// Это ROSMA-дубликат
	ИмяСвойстваИсточник = "ОстаткиСантехкомплект_a9e75ac763514baaab82a0827cdb7961";

	// НОВЫЙ/ПРАВИЛЬНЫЙ реквизит Сантехкомплекта
	ИмяСвойстваПриемник = "ОстаткиСантехкомплект_a9ef44d49f464a7aa3a8e0bc5ef720bb";

	ВидСантех = Справочники.ВидыНоменклатуры.НайтиПоНаименованию(ИмяВидаСантех, Истина);
	Если ВидСантех.Пустая() Тогда
		ВызватьИсключение "Не найден вид номенклатуры: " + ИмяВидаСантех;
	КонецЕсли;

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

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

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Номенклатура.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	НЕ Номенклатура.ЭтоГруппа
	|	И Номенклатура.ВидНоменклатуры = &ВидНоменклатуры";

	Запрос.УстановитьПараметр("ВидНоменклатуры", ВидСантех);

	Выборка = Запрос.Выполнить().Выбрать();

	СчетчикВсего = 0;
	СчетчикПеренесено = 0;
	СчетчикПропущено = 0;
	СчетчикОшибок = 0;
	РазмерПорции = 100;
	СчетчикВПорции = 0;

	ЗаписьЖурналаРегистрации(
		ИмяСобытия,
		УровеньЖурналаРегистрации.Информация,,,
		"Старт переноса Остатки СТК из ROSMA-реквизита в STK-реквизит."
	);

	НачатьТранзакцию();

	Попытка

		Пока Выборка.Следующий() Цикл

			СчетчикВсего = СчетчикВсего + 1;

			Попытка

				ОбъектНоменклатуры = Выборка.Ссылка.ПолучитьОбъект();

				СтрокаИсточник = НайтиСтрокуДопРеквизита(ОбъектНоменклатуры, СвойствоИсточник);
				Если СтрокаИсточник = Неопределено Тогда
					СчетчикПропущено = СчетчикПропущено + 1;
					Продолжить;
				КонецЕсли;

				ЗначениеИсточник = СтрокаИсточник.Значение;

				// Для числового реквизита переносим даже 0,
				// но только если строка-источник реально есть.
				СтрокаПриемник = НайтиСтрокуДопРеквизита(ОбъектНоменклатуры, СвойствоПриемник);

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

					ОбъектНоменклатуры.Записать();
					СчетчикПеренесено = СчетчикПеренесено + 1;

				Иначе

					// Не перезаписываем уже заполненное значение,
					// кроме случая, когда в приемнике пусто/0, а в источнике не 0
					Если НужноПереноситьЧисловоеЗначение(СтрокаПриемник.Значение, ЗначениеИсточник) Тогда
						СтрокаПриемник.Значение = ЗначениеИсточник;

						ОбъектНоменклатуры.Записать();
						СчетчикПеренесено = СчетчикПеренесено + 1;
					Иначе
						СчетчикПропущено = СчетчикПропущено + 1;
					КонецЕсли;

				КонецЕсли;

				СчетчикВПорции = СчетчикВПорции + 1;
				Если СчетчикВПорции >= РазмерПорции Тогда
					ЗафиксироватьТранзакцию();
					СчетчикВПорции = 0;
					НачатьТранзакцию();
				КонецЕсли;

			Исключение
				СчетчикОшибок = СчетчикОшибок + 1;

				ЗаписьЖурналаРегистрации(
					ИмяСобытия,
					УровеньЖурналаРегистрации.Ошибка,,,
					"Ошибка переноса по товару " + Строка(Выборка.Ссылка) + ": " + ОписаниеОшибки()
				);
			КонецПопытки;

		КонецЦикла;

		Если ТранзакцияАктивна() Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;

		ЗаписьЖурналаРегистрации(
			ИмяСобытия,
			УровеньЖурналаРегистрации.Информация,,,
			"Перенос Остатки СТК завершен. Всего: " + Строка(СчетчикВсего)
			+ "; перенесено: " + Строка(СчетчикПеренесено)
			+ "; пропущено: " + Строка(СчетчикПропущено)
			+ "; ошибок: " + Строка(СчетчикОшибок)
		);

	Исключение

		Если ТранзакцияАктивна() Тогда
			ОтменитьТранзакцию();
		КонецЕсли;

		ВызватьИсключение "Критическая ошибка переноса Остатки СТК: " + ОписаниеОшибки();

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

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


Функция НайтиДопРеквизитПоИмениРазработчика(ИмяРазработчика) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Свойства.Ссылка КАК Ссылка
	|ИЗ
	|	ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК Свойства
	|ГДЕ
	|	Свойства.Имя = &Имя";

	Запрос.УстановитьПараметр("Имя", ИмяРазработчика);

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

	Возврат ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПустаяСсылка();

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


Функция НайтиСтрокуДопРеквизита(ОбъектНоменклатуры, Свойство) Экспорт

	Для Каждого СтрокаРеквизита Из ОбъектНоменклатуры.ДополнительныеРеквизиты Цикл
		Если СтрокаРеквизита.Свойство = Свойство Тогда
			Возврат СтрокаРеквизита;
		КонецЕсли;
	КонецЦикла;

	Возврат Неопределено;

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


Функция НужноПереноситьЧисловоеЗначение(ЗначениеПриемника, ЗначениеИсточника) Экспорт

	// Если значения одинаковые - перенос не нужен
	Если ЗначениеПриемника = ЗначениеИсточника Тогда
		Возврат Ложь;
	КонецЕсли;

	// Если приемник пустой/неопределённый - переносим
	Если ЗначениеПриемника = Неопределено Тогда
		Возврат Истина;
	КонецЕсли;

	// Для числового реквизита 0 часто означает "пусто после разделения",
	// а в источнике может лежать реальное значение
	Попытка
		Если ТипЗнч(ЗначениеПриемника) = Тип("Число")
			И ТипЗнч(ЗначениеИсточника) = Тип("Число") Тогда

			Если ЗначениеПриемника = 0 И ЗначениеИсточника <> 0 Тогда
				Возврат Истина;
			КонецЕсли;
		КонецЕсли;
	Исключение
	КонецПопытки;

	Возврат Ложь;

КонецФункции
Editor is loading...
Leave a Comment