// Расширение: ЮнитКалькулятор
// Общий модуль: ВыгрузкаСреднихЦенСервер (флаг "Сервер", привилегированный)
// Рег. задание: метод ВыгрузитьСредниеЦены, расписание — ежедневно ~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 завершился с кодом " + КодВозврата);
КонецЕсли;
КонецПроцедуры