Загрузка данных
//++Варнин А.А. Задача №72300 - редакция 2, наборы по вариантам комплектации
//
// ВНИМАНИЕ, проверить в конфигураторе три имени метаданных — я их взял по типовой УТ 11.5:
// 1. Перечисление.ТипыНоменклатуры.Набор - значение типа номенклатуры "Набор"
// 2. Справочник.ВариантыКомплектацииНоменклатуры - справочник вариантов комплектации
// 3. ...ВариантыКомплектацииНоменклатуры.Содержание - имя табличной части с составом
// Если у вас ТЧ называется иначе (встречается "Комплектующие") — поправить в ТекстЗапроса.
//
// Изменения относительно редакции 1:
// - Убран фильтр по "не использовать" (позиции переводятся в тип "Набор").
// - Якорь расчёта расширен: остатки + компоненты наборов + сами наборы.
// Раньше всё висело на ТоварыНаСкладах > 0, и наборы (у которых остатка нет)
// не попали бы в выгрузку в принципе, а компоненты с нулём — выпали бы.
// - Наборы исключены из расчёта по поступлениям и считаются вторым проходом
// как сумма уже посчитанных цен компонентов с учётом количества.
// - Порядок арифметики как в постановке: компонент округляется до копеек,
// затем умножается на количество, затем всё складывается.
// - Поддержаны наборы из наборов (итеративные проходы) и защита от зацикливания.
#Область РегламентноеЗадание_кор_ВыгрузкаЗакупочныхЦен
Процедура ВыполнитьВыгрузкуЗакупочныхЦен() Экспорт
ИмяСобытия = "Выгрузка закупочных цен";
НачалоРаботы = ТекущаяУниверсальнаяДатаВМиллисекундах();
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Информация, , , "Старт выгрузки.");
ЦеныТЗ = СформироватьТаблицуЦен();
Если ЦеныТЗ.Количество() = 0 Тогда
ТекстОшибки = "Запрос не вернул ни одной строки. Выгрузка не выполнена.";
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецЕсли;
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Информация, , ,
СтрШаблон("Сформировано строк: %1. Время расчёта: %2 мс.",
ЦеныТЗ.Количество(), ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоРаботы));
РезультатОтправки = ОтправитьВKafka(ЦеныТЗ);
ВыгрузитьВExcel(ЦеныТЗ);
ЗаписьЖурналаРегистрации(ИмяСобытия,
?(РезультатОтправки.Успех, УровеньЖурналаРегистрации.Информация, УровеньЖурналаРегистрации.Ошибка),
, , СтрШаблон("Финиш. %1 Общее время: %2 мс.",
РезультатОтправки.Текст, ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоРаботы));
Если НЕ РезультатОтправки.Успех Тогда
ВызватьИсключение РезультатОтправки.Текст;
КонецЕсли;
КонецПроцедуры
Функция СформироватьТаблицуЦен()
ВидЦены = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "ЗакупочнаяЦена");
Если НЕ ЗначениеЗаполнено(ВидЦены) Тогда
ВызватьИсключение "Не найден вид цены с идентификатором ""ЗакупочнаяЦена"".";
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапросаБезНДС());
Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
Запрос.УстановитьПараметр("КонецПериода", ТекущаяДатаСеанса());
Запрос.УстановитьПараметр("СвойствоOEM", НайтиДополнительныйРеквизит("OEMНомер"));
Запрос.УстановитьПараметр("СвойствоАртикулМП", НайтиДополнительныйРеквизит("АртикулМаркетплейсов"));
Результаты = Запрос.ВыполнитьПакет();
// Два последних запроса пакета: [-2] — цены обычной номенклатуры, [-1] — состав наборов.
// Если будете добавлять запросы в пакет — добавляйте ВЫШЕ этих двух.
ЦеныТЗ = Результаты[Результаты.Количество() - 2].Выгрузить();
СоставТЗ = Результаты[Результаты.Количество() - 1].Выгрузить();
// Единственное округление обычных позиций. Наборы округляются в ДополнитьЦенамиНаборов.
Для Каждого СтрЦена Из ЦеныТЗ Цикл
СтрЦена.СредняяЦена = Окр(СтрЦена.СредняяЦена, 2, РежимОкругления.Окр15как20);
СтрЦена.Цена = Окр(СтрЦена.Цена, 2, РежимОкругления.Окр15как20);
КонецЦикла;
ДополнитьЦенамиНаборов(ЦеныТЗ, СоставТЗ);
ЦеныТЗ.Сортировать("Код");
Возврат ЦеныТЗ;
КонецФункции
// Досчитывает цены наборов как сумму цен компонентов с учётом количества.
//
// Порядок арифметики соответствует постановке:
// цена компонента (уже округлённая) * количество, затем сумма, затем округление итога.
//
// Наборы, вложенные в наборы, разбираются последовательными проходами:
// на каждом проходе считаются те наборы, все компоненты которых уже известны.
//
Процедура ДополнитьЦенамиНаборов(ЦеныТЗ, СоставТЗ)
ИмяСобытия = "Выгрузка закупочных цен. Наборы";
Если СоставТЗ.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Быстрый доступ к уже посчитанным ценам.
ИзвестныеЦены = Новый Соответствие;
Для Каждого СтрЦена Из ЦеныТЗ Цикл
ИзвестныеЦены.Вставить(СтрЦена.Номенклатура,
Новый Структура("СредняяЦена, Цена", СтрЦена.СредняяЦена, СтрЦена.Цена));
КонецЦикла;
// У набора может быть несколько вариантов комплектации.
// СоставТЗ упорядочен по набору и представлению варианта, поэтому берём первый
// и предупреждаем, если вариантов больше одного.
ВыбранныйВариант = Новый Соответствие;
НаборыСНесколькимиВариантами = Новый Массив;
Для Каждого СтрСостав Из СоставТЗ Цикл
Вариант = ВыбранныйВариант[СтрСостав.Набор];
Если Вариант = Неопределено Тогда
ВыбранныйВариант.Вставить(СтрСостав.Набор, СтрСостав.Вариант);
ИначеЕсли Вариант <> СтрСостав.Вариант
И НаборыСНесколькимиВариантами.Найти(СтрСостав.Набор) = Неопределено Тогда
НаборыСНесколькимиВариантами.Добавить(СтрСостав.Набор);
КонецЕсли;
КонецЦикла;
Если НаборыСНесколькимиВариантами.Количество() > 0 Тогда
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Предупреждение, , ,
"У этих наборов несколько вариантов комплектации, взят первый по наименованию:"
+ Символы.ПС + ПредставлениеСписка(НаборыСНесколькимиВариантами, 30));
КонецЕсли;
// Реквизиты наборов и их состав в разрезе выбранного варианта.
РеквизитыНаборов = Новый Соответствие;
СоставНабора = Новый Соответствие;
Для Каждого СтрСостав Из СоставТЗ Цикл
Если СтрСостав.Вариант <> ВыбранныйВариант[СтрСостав.Набор] Тогда
Продолжить;
КонецЕсли;
Если РеквизитыНаборов[СтрСостав.Набор] = Неопределено Тогда
Реквизиты = Новый Структура("Наименование, Код, Артикул, Марка, OEMНомер, АртикулМаркетплейса");
ЗаполнитьЗначенияСвойств(Реквизиты, СтрСостав);
РеквизитыНаборов.Вставить(СтрСостав.Набор, Реквизиты);
СоставНабора.Вставить(СтрСостав.Набор, Новый Массив);
КонецЕсли;
СоставНабора[СтрСостав.Набор].Добавить(
Новый Структура("Компонент, Количество", СтрСостав.Компонент, СтрСостав.Количество));
КонецЦикла;
// Наборы, которые ещё предстоит посчитать.
Осталось = Новый Массив;
Для Каждого КлючЗначение Из СоставНабора Цикл
Осталось.Добавить(КлючЗначение.Ключ);
КонецЦикла;
НомерПрохода = 0;
ПоследняяПричина = Новый Соответствие;
Пока Осталось.Количество() > 0 Цикл
НомерПрохода = НомерПрохода + 1;
ПосчитаноЗаПроход = 0;
НеПосчитанные = Новый Массив;
Для Каждого Набор Из Осталось Цикл
СредняяИтог = 0;
ЦенаИтог = 0;
НедостающийКомпонент = Неопределено;
Для Каждого Строка Из СоставНабора[Набор] Цикл
ЦеныКомпонента = ИзвестныеЦены[Строка.Компонент];
Если ЦеныКомпонента = Неопределено Тогда
НедостающийКомпонент = Строка.Компонент;
Прервать;
КонецЕсли;
СредняяИтог = СредняяИтог + ЦеныКомпонента.СредняяЦена * Строка.Количество;
ЦенаИтог = ЦенаИтог + ЦеныКомпонента.Цена * Строка.Количество;
КонецЦикла;
Если НедостающийКомпонент <> Неопределено Тогда
НеПосчитанные.Добавить(Набор);
ПоследняяПричина.Вставить(Набор, НедостающийКомпонент);
Продолжить;
КонецЕсли;
Если СредняяИтог <= 0 ИЛИ ЦенаИтог <= 0 Тогда
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Предупреждение, , ,
"Набор " + Строка(Набор) + ": итоговая цена нулевая, в выгрузку не попал.");
Продолжить;
КонецЕсли;
СредняяИтог = Окр(СредняяИтог, 2, РежимОкругления.Окр15как20);
ЦенаИтог = Окр(ЦенаИтог, 2, РежимОкругления.Окр15как20);
НоваяСтрока = ЦеныТЗ.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, РеквизитыНаборов[Набор]);
НоваяСтрока.Номенклатура = Набор;
НоваяСтрока.СредняяЦена = СредняяИтог;
НоваяСтрока.Цена = ЦенаИтог;
НоваяСтрока.КоличествоДокументов = 0; // у набора своих поступлений нет
ИзвестныеЦены.Вставить(Набор, Новый Структура("СредняяЦена, Цена", СредняяИтог, ЦенаИтог));
ПосчитаноЗаПроход = ПосчитаноЗаПроход + 1;
КонецЦикла;
Осталось = НеПосчитанные;
// Ни один набор не сдвинулся — дальше только вложенные циклы либо
// действительно недостающие компоненты. Выходим.
Если ПосчитаноЗаПроход = 0 Тогда
Прервать;
КонецЕсли;
// Страховка от зацикливания на кривом составе (набор ссылается сам на себя).
Если НомерПрохода > 10 Тогда
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка, , ,
"Превышено 10 проходов по вложенным наборам. Проверьте состав на цикличность.");
Прервать;
КонецЕсли;
КонецЦикла;
Если Осталось.Количество() > 0 Тогда
СтрокиЛога = Новый Массив;
Для Каждого Набор Из Осталось Цикл
СтрокиЛога.Добавить(Строка(Набор) + " — нет цены по компоненту: "
+ Строка(ПоследняяПричина[Набор]));
Если СтрокиЛога.Количество() >= 50 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
ЗаписьЖурналаРегистрации(ИмяСобытия, УровеньЖурналаРегистрации.Ошибка, , ,
СтрШаблон("Не посчитано наборов: %1. Они не попали в выгрузку.%2%3",
Осталось.Количество(), Символы.ПС, СтрСоединить(СтрокиЛога, Символы.ПС)));
КонецЕсли;
КонецПроцедуры
Функция ПредставлениеСписка(Массив, МаксимумСтрок)
Строки = Новый Массив;
Для Каждого Элемент Из Массив Цикл
Строки.Добавить(Строка(Элемент));
Если Строки.Количество() >= МаксимумСтрок Тогда
Строки.Добавить("... и ещё " + (Массив.Количество() - МаксимумСтрок));
Прервать;
КонецЕсли;
КонецЦикла;
Возврат СтрСоединить(Строки, Символы.ПС);
КонецФункции
Функция НайтиДополнительныйРеквизит(ИдентификаторДляФормул)
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту(
"ИдентификаторДляФормул", ИдентификаторДляФормул);
Если НЕ ЗначениеЗаполнено(Свойство) Тогда
ЗаписьЖурналаРегистрации("Выгрузка закупочных цен",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Не найден дополнительный реквизит с идентификатором """ + ИдентификаторДляФормул + """.");
КонецЕсли;
Возврат Свойство;
КонецФункции
Функция ТекстЗапросаБезНДС()
Возврат
"////////////////////////////////////////////////////////////////////////////////
|// Состав наборов из вариантов комплектации.
|ВЫБРАТЬ
| Вариант.Владелец КАК Набор,
| Вариант.Ссылка КАК Вариант,
| СоставТЧ.НомерСтроки КАК НомерСтроки,
| СоставТЧ.Номенклатура КАК Компонент,
| СоставТЧ.Количество КАК Количество
|ПОМЕСТИТЬ ВТ_СоставНаборов
|ИЗ
| Справочник.ВариантыКомплектацииНоменклатуры.Содержание КАК СоставТЧ
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ВариантыКомплектацииНоменклатуры КАК Вариант
| ПО СоставТЧ.Ссылка = Вариант.Ссылка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Наборы
| ПО Вариант.Владелец = Наборы.Ссылка
|ГДЕ
| НЕ Вариант.ПометкаУдаления
| И НЕ Наборы.ПометкаУдаления
| И Наборы.ТипНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.Набор)
| И СоставТЧ.Количество > 0
|
|ИНДЕКСИРОВАТЬ ПО
| Набор,
| Компонент
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// Якорь расчёта: позиции с остатком + компоненты наборов + сами наборы.
|// Компоненты нужны даже при нулевом остатке, иначе набор нечем посчитать.
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВсяНоменклатура.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ ВТ_НоменклатураКРасчету
|ИЗ
| (ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура КАК Номенклатура
| ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода, ) КАК ОстаткиТоваров
| ГДЕ
| ОстаткиТоваров.ВНаличииОстаток > 0
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| ВТ_СоставНаборов.Компонент
| ИЗ
| ВТ_СоставНаборов КАК ВТ_СоставНаборов
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| ВТ_СоставНаборов.Набор
| ИЗ
| ВТ_СоставНаборов КАК ВТ_СоставНаборов) КАК ВсяНоменклатура
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// Пары ""документ-основание + номенклатура"", по которым цена реально установилась.
|ВЫБРАТЬ
| УстановкаЦен.ДокументОснование КАК Основание,
| ЦеныНоменклатуры25.Номенклатура КАК Номенклатура,
| МАКСИМУМ(ЦеныНоменклатуры25.Период) КАК ПериодУстановки
|ПОМЕСТИТЬ ВТ_ДокУстановкаЦен
|ИЗ
| РегистрСведений.ЦеныНоменклатуры25 КАК ЦеныНоменклатуры25
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.УстановкаЦенНоменклатуры КАК УстановкаЦен
| ПО ЦеныНоменклатуры25.Регистратор = УстановкаЦен.Ссылка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_НоменклатураКРасчету КАК ВТ_Номенклатура
| ПО ЦеныНоменклатуры25.Номенклатура = ВТ_Номенклатура.Номенклатура
|ГДЕ
| УстановкаЦен.Проведен
| И УстановкаЦен.ДокументОснование ССЫЛКА Документ.ПриобретениеТоваровУслуг
| И ЦеныНоменклатуры25.ВидЦены = &ВидЦены
| И ЦеныНоменклатуры25.Цена > 0
|
|СГРУППИРОВАТЬ ПО
| УстановкаЦен.ДокументОснование,
| ЦеныНоменклатуры25.Номенклатура
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| Основание
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ДокТовары.Номенклатура КАК Номенклатура,
| Док.Ссылка КАК Ссылка,
| ВТ_ДокУстановкаЦен.ПериодУстановки КАК ПериодУстановки,
| СУММА(ВЫБОР
| КОГДА Док.ЦенаВключаетНДС
| ТОГДА ДокТовары.Сумма - ДокТовары.СуммаНДС
| ИНАЧЕ ДокТовары.Сумма
| КОНЕЦ) КАК СуммаБезНДС,
| СУММА(ДокТовары.Количество) КАК Количество
|ПОМЕСТИТЬ ВТ_ПоДокументам
|ИЗ
| Документ.ПриобретениеТоваровУслуг.Товары КАК ДокТовары
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПриобретениеТоваровУслуг КАК Док
| ПО ДокТовары.Ссылка = Док.Ссылка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ДокУстановкаЦен КАК ВТ_ДокУстановкаЦен
| ПО Док.Ссылка = ВТ_ДокУстановкаЦен.Основание
| И ДокТовары.Номенклатура = ВТ_ДокУстановкаЦен.Номенклатура
|ГДЕ
| Док.Проведен
| И ДокТовары.Количество > 0
| И ДокТовары.Сумма > 0
|
|СГРУППИРОВАТЬ ПО
| ДокТовары.Номенклатура,
| Док.Ссылка,
| ВТ_ДокУстановкаЦен.ПериодУстановки
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ПоДокументам.Номенклатура КАК Номенклатура,
| ВТ_ПоДокументам.Ссылка КАК Ссылка,
| ВТ_ПоДокументам.ПериодУстановки КАК ПериодУстановки,
| ВТ_ПоДокументам.СуммаБезНДС / ВТ_ПоДокументам.Количество КАК ЦенаДокумента
|ПОМЕСТИТЬ ВТ_ЦеныДокументов
|ИЗ
| ВТ_ПоДокументам КАК ВТ_ПоДокументам
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| ПериодУстановки
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ЦеныДокументов.Номенклатура КАК Номенклатура,
| СРЕДНЕЕ(ВТ_ЦеныДокументов.ЦенаДокумента) КАК СредняяЦена,
| КОЛИЧЕСТВО(ВТ_ЦеныДокументов.Ссылка) КАК КоличествоДокументов,
| МАКСИМУМ(ВТ_ЦеныДокументов.ПериодУстановки) КАК ПериодУстановки
|ПОМЕСТИТЬ ВТ_СредняяЦена
|ИЗ
| ВТ_ЦеныДокументов КАК ВТ_ЦеныДокументов
|
|СГРУППИРОВАТЬ ПО
| ВТ_ЦеныДокументов.Номенклатура
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| ПериодУстановки
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ЦеныДокументов.Номенклатура КАК Номенклатура,
| СРЕДНЕЕ(ВТ_ЦеныДокументов.ЦенаДокумента) КАК ТекущаяЦенаБезНДС
|ПОМЕСТИТЬ ВТ_ПоследняяЦена
|ИЗ
| ВТ_ЦеныДокументов КАК ВТ_ЦеныДокументов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_СредняяЦена КАК ВТ_СредняяЦена
| ПО ВТ_ЦеныДокументов.Номенклатура = ВТ_СредняяЦена.Номенклатура
| И ВТ_ЦеныДокументов.ПериодУстановки = ВТ_СредняяЦена.ПериодУстановки
|
|СГРУППИРОВАТЬ ПО
| ВТ_ЦеныДокументов.Номенклатура
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// Доп. реквизиты одним запросом. Строятся по всей номенклатуре к расчёту,
|// включая наборы, — у набора свои OEM и артикул маркетплейса.
|ВЫБРАТЬ
| ДопРеквизиты.Ссылка КАК Номенклатура,
| МАКСИМУМ(ВЫБОР
| КОГДА ДопРеквизиты.Свойство = &СвойствоOEM
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК СТРОКА(150))
| ИНАЧЕ """"
| КОНЕЦ) КАК OEMНомер,
| МАКСИМУМ(ВЫБОР
| КОГДА ДопРеквизиты.Свойство = &СвойствоАртикулМП
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК СТРОКА(150))
| ИНАЧЕ """"
| КОНЕЦ) КАК АртикулМаркетплейса
|ПОМЕСТИТЬ ВТ_ДопРеквизиты
|ИЗ
| Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_НоменклатураКРасчету КАК ВТ_Номенклатура
| ПО ДопРеквизиты.Ссылка = ВТ_Номенклатура.Номенклатура
|ГДЕ
| ДопРеквизиты.Свойство В (&СвойствоOEM, &СвойствоАртикулМП)
|
|СГРУППИРОВАТЬ ПО
| ДопРеквизиты.Ссылка
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// РЕЗУЛЬТАТ 1 (предпоследний в пакете): цены обычной номенклатуры.
|// Наборы сюда не попадают — их считает код по составу.
|ВЫБРАТЬ
| Ном.Ссылка КАК Номенклатура,
| ПРЕДСТАВЛЕНИЕ(Ном.Ссылка) КАК Наименование,
| Ном.Код КАК Код,
| Ном.Артикул КАК Артикул,
| ПРЕДСТАВЛЕНИЕ(Ном.Марка) КАК Марка,
| ВТ_СредняяЦена.СредняяЦена КАК СредняяЦена,
| ВТ_СредняяЦена.КоличествоДокументов КАК КоличествоДокументов,
| ВТ_ПоследняяЦена.ТекущаяЦенаБезНДС КАК Цена,
| ЕСТЬNULL(ВТ_ДопРеквизиты.OEMНомер, """") КАК OEMНомер,
| ЕСТЬNULL(ВТ_ДопРеквизиты.АртикулМаркетплейса, """") КАК АртикулМаркетплейса
|ИЗ
| ВТ_СредняяЦена КАК ВТ_СредняяЦена
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ПоследняяЦена КАК ВТ_ПоследняяЦена
| ПО ВТ_СредняяЦена.Номенклатура = ВТ_ПоследняяЦена.Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
| ПО ВТ_СредняяЦена.Номенклатура = Ном.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДопРеквизиты КАК ВТ_ДопРеквизиты
| ПО ВТ_СредняяЦена.Номенклатура = ВТ_ДопРеквизиты.Номенклатура
|ГДЕ
| НЕ Ном.ПометкаУдаления
| И ВТ_СредняяЦена.СредняяЦена > 0
| И Ном.ТипНоменклатуры <> ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.Набор)
|
|УПОРЯДОЧИТЬ ПО
| Код
|;
|
|////////////////////////////////////////////////////////////////////////////////
|// РЕЗУЛЬТАТ 2 (последний в пакете): состав наборов + реквизиты самих наборов.
|// Порядок важен: код берёт первый вариант комплектации по представлению.
|ВЫБРАТЬ
| ВТ_СоставНаборов.Набор КАК Набор,
| ПРЕДСТАВЛЕНИЕ(Ном.Ссылка) КАК Наименование,
| Ном.Код КАК Код,
| Ном.Артикул КАК Артикул,
| ПРЕДСТАВЛЕНИЕ(Ном.Марка) КАК Марка,
| ЕСТЬNULL(ВТ_ДопРеквизиты.OEMНомер, """") КАК OEMНомер,
| ЕСТЬNULL(ВТ_ДопРеквизиты.АртикулМаркетплейса, """") КАК АртикулМаркетплейса,
| ВТ_СоставНаборов.Вариант КАК Вариант,
| ПРЕДСТАВЛЕНИЕ(ВТ_СоставНаборов.Вариант) КАК ВариантПредставление,
| ВТ_СоставНаборов.НомерСтроки КАК НомерСтроки,
| ВТ_СоставНаборов.Компонент КАК Компонент,
| ВТ_СоставНаборов.Количество КАК Количество
|ИЗ
| ВТ_СоставНаборов КАК ВТ_СоставНаборов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
| ПО ВТ_СоставНаборов.Набор = Ном.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДопРеквизиты КАК ВТ_ДопРеквизиты
| ПО ВТ_СоставНаборов.Набор = ВТ_ДопРеквизиты.Номенклатура
|
|УПОРЯДОЧИТЬ ПО
| Набор,
| ВариантПредставление,
| НомерСтроки";
КонецФункции
Функция ОтправитьВKafka(ЦеныТЗ)
Сообщения = Новый Массив;
Для Каждого СтрЦена Из ЦеныТЗ Цикл
Элемент = Новый Структура;
Элемент.Вставить("name", СокрЛП(СтрЦена.Наименование));
Элемент.Вставить("code", СокрЛП(СтрЦена.Код));
Элемент.Вставить("brand", СокрЛП(СтрЦена.Марка));
Элемент.Вставить("article", СокрЛП(СтрЦена.Артикул));
Элемент.Вставить("article_mp", СокрЛП(СтрЦена.АртикулМаркетплейса));
Элемент.Вставить("oem", СокрЛП(СтрЦена.OEMНомер));
Элемент.Вставить("last_price", СтрЦена.Цена);
Элемент.Вставить("avg_price", СтрЦена.СредняяЦена);
Сообщение = Новый Структура("Ключ, Тело",
Строка(СтрЦена.Номенклатура.УникальныйИдентификатор()),
ОбщегоНазначения.ЗначениеВJSON(Элемент));
Сообщения.Добавить(Сообщение);
КонецЦикла;
Возврат кор_HTTPКоннектор.ОтправитьВКафку(Сообщения);
КонецФункции
Процедура ВыгрузитьВExcel(ЦеныТЗ)
Если НЕ Константы.кор_ВыгружатьЦеныВФайл.Получить() Тогда
Возврат;
КонецЕсли;
Каталог = СокрЛП(Константы.кор_КаталогВыгрузкиЦен.Получить());
Если НЕ ЗначениеЗаполнено(Каталог) Тогда
ЗаписьЖурналаРегистрации("Выгрузка закупочных цен",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Не заполнена константа кор_КаталогВыгрузкиЦен, файл не сохранён.");
Возврат;
КонецЕсли;
КолонкиФайла = "Код,Артикул,Марка,OEMНомер,АртикулМаркетплейса,СредняяЦена,Цена";
Попытка
ТЗДляФайла = ЦеныТЗ.Скопировать(, КолонкиФайла);
ТЗДляФайла.Колонки.OEMНомер.Заголовок = "OEM номер";
ТЗДляФайла.Колонки.АртикулМаркетплейса.Заголовок = "Артикул МП";
ТЗДляФайла.Колонки.СредняяЦена.Заголовок = "Средняя закупочная";
ТЗДляФайла.Колонки.Цена.Заголовок = "Последняя закупочная";
ТабДок = Новый ТабличныйДокумент;
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗДляФайла);
Построитель.Выполнить();
Построитель.Вывести(ТабДок);
ИмяФайла = Каталог
+ ?(Прав(Каталог, 1) = ПолучитьРазделительПути(), "", ПолучитьРазделительПути())
+ "цены_" + Формат(ТекущаяДатаСеанса(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Исключение
ЗаписьЖурналаРегистрации("Выгрузка закупочных цен",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Не удалось сохранить файл: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
#КонецОбласти