Загрузка данных


// Расширение: ЮнитКалькулятор
// Общий модуль: ВыгрузкаСреднихЦенСервер (флаг "Сервер", привилегированный)
// Рег. задание: метод ВыгрузитьСредниеЦены, расписание — ежедневно ~03:00
// Задача Bitrix 72300

// ---- Параметры подключения (при желании вынести в константы расширения) ----
&НаСервере
Функция СтрокаПодключения()
	Возврат "host=SQL_HOST port=5432 dbname=unit_calc user=uc_writer";
	// пароль — в /home/usr1cv8/.pgpass (права 0600)
КонецФункции

Процедура ВыгрузитьСредниеЦены() Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Товары.Номенклатура КАК Номенклатура,
	|	СУММА(Товары.Сумма) / СУММА(Товары.Количество) КАК СредняяЦена
	|ИЗ
	|	Документ.ПередачаТоваровКомиссионеру.Товары КАК Товары
	|ГДЕ
	|	Товары.Ссылка.Проведен
	|	И Товары.Ссылка.Дата >= &НачалоПериода
	|СГРУППИРОВАТЬ ПО
	|	Товары.Номенклатура
	|ИМЕЮЩИЕ
	|	СУММА(Товары.Количество) <> 0";
	Запрос.УстановитьПараметр("НачалоПериода", Дата(2026, 1, 1));

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

	// ---- CSV ----
	ФайлCSV = ПолучитьИмяВременногоФайла("csv");
	Запись = Новый ЗаписьТекста(ФайлCSV, КодировкаТекста.UTF8);
	// первая строка — заголовок: HEADER true в \copy её отбросит,
	// заодно решается вопрос с BOM в начале файла
	Запись.ЗаписатьСтроку("nomenclature_guid;avg_price");

	Счетчик = 0;
	Пока Выборка.Следующий() Цикл
		Запись.ЗаписатьСтроку(
			Строка(Выборка.Номенклатура.УникальныйИдентификатор()) + ";"
			+ Формат(Выборка.СредняяЦена, "ЧДЦ=2; ЧРД=.; ЧГ="));
		Счетчик = Счетчик + 1;
	КонецЦикла;
	Запись.Закрыть();

	// ---- SQL-скрипт для psql ----
	ФайлSQL = ПолучитьИмяВременногоФайла("sql");
	Запись = Новый ЗаписьТекста(ФайлSQL, КодировкаТекста.UTF8);
	Запись.ЗаписатьСтроку("\set ON_ERROR_STOP on");
	Запись.ЗаписатьСтроку("TRUNCATE avg_purchase_price_staging;");
	Запись.ЗаписатьСтроку("\copy avg_purchase_price_staging (nomenclature_guid, avg_price) FROM '"
		+ ФайлCSV + "' WITH (FORMAT csv, DELIMITER ';', HEADER true)");
	Запись.ЗаписатьСтроку("INSERT INTO avg_purchase_price (nomenclature_guid, avg_price, calc_date)");
	Запись.ЗаписатьСтроку("SELECT nomenclature_guid, avg_price, now() FROM avg_purchase_price_staging");
	Запись.ЗаписатьСтроку("ON CONFLICT (nomenclature_guid) DO UPDATE");
	Запись.ЗаписатьСтроку("  SET avg_price = EXCLUDED.avg_price, calc_date = EXCLUDED.calc_date;");
	Запись.Закрыть();

	// ---- Запуск psql ----
	КодВозврата = 0;
	Команда = "psql """ + СтрокаПодключения() + """ -f " + ФайлSQL;
	ЗапуститьПриложение(Команда, , Истина, КодВозврата);

	УдалитьФайлы(ФайлCSV);
	УдалитьФайлы(ФайлSQL);

	Если КодВозврата = 0 Тогда
		ЗаписьЖурналаРегистрации("ЮнитКалькулятор.ВыгрузкаЦен",
			УровеньЖурналаРегистрации.Информация, , ,
			"Выгружено позиций: " + Счетчик);
	Иначе
		ЗаписьЖурналаРегистрации("ЮнитКалькулятор.ВыгрузкаЦен",
			УровеньЖурналаРегистрации.Ошибка, , ,
			"psql завершился с кодом " + КодВозврата);
	КонецЕсли;

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