Поступила такая задача:
Необходимо сделать внешнюю обработку для анализа цен.
В обработке необходимо предусмотреть условия:
- для выбора вида цены, с которым будет происходить сравнение (вид цены обязательный к заполнению).
- для фильтрации данных по покупателю и периоду (период обязательный к заполнению).
Обработка должна состоять из двух таблиц:
1) артикул, наименование, характеристика, остаток нач, остаток кон, цена, продано кол, продано сум, откл. от цены.
2) дата, документ, продано кол, продано сум, цена продажи, откл. от цены.
В первой таблице в зависимости от фильтров должна отображаться информация по товарах, остатках и расчёт отклонения цены, выбранной в условии на текущую дату от средней цены продажи.
Во второй таблице должна быть настроена расшифровка, то есть выделяем какую-то строку в первой таблице - во второй отображается расшифровка по товару и характеристике.
Доп. условия: необходимо отбирать только товары, услуги не нужны; и только те, которые используют характеристики товаров.
С УТ 11 не был плотно знаком, немного поизучал на тестовой базе от 1С, конфигурация 11.5.11.70. Платформа 8.3.24.1667.
Технически обработка функционирует. Прошу оценить правильность получения необходимых для решения данных и оптимальность запроса.
Вводные:
Контрагента фильтрую Отбором в таблице на форме, но можно делать это в запросе
По Организации, Складу фильтровать - в задаче не указано.
Данные для анализа беру из регистра ВыручкаИСебестоимостьПродаж, остатки - регистр ТоварыОрганизаций
По ВыручкаИСебестоимостьПродаж беру все документы. Можно сделать фильтрацию по документам или ХозОперации, тк там присутствуют и Возврат, и Передача товаров и тд
В УТ 11 два регистра с Ценами номенклатуры - для расчета сравнительной цены на форму добавлен реквизит НовоеЦенообразование.
Цену сравнения вычисляю на дату движения. Цену реализации рассчитываю из регистра как Сумма выручки / Количество, причем если Цена для сравнения включает НДС, то беру сумму выручки с НДС.
Фильтр подчиненной таблицы реализовал так:
&НаКлиенте
Процедура ТЗЗапросаИтогиПриАктивизацииСтроки(Элемент)
//Фильтруем подчиненную таблицу
Данные = ЭтаФорма.Элементы.ТЗЗапросаИтоги.ТекущиеДанные;
Если Данные = Неопределено Тогда
//ничего не выводим
ЭтаФорма.Элементы.ТЗПодробно.ОтборСтрок = Новый ФиксированнаяСтруктура("АналитикаУчетаНоменклатуры", ПредопределенноеЗначение("Справочник.КлючиАналитикиУчетаНоменклатуры.ПустаяСсылка"));
Возврат;
КонецЕсли;
ЭтаФорма.Элементы.ТЗПодробно.ОтборСтрок = Новый ФиксированнаяСтруктура("АналитикаУчетаНоменклатуры, Контрагент", Данные.АналитикаУчетаНоменклатуры, Данные.Контрагент);
КонецПроцедуры
При двойном клике на документе откроется его форма.
Сам запрос:
&НаСервере
Процедура СформироватьОтчетНаСервере()
Запрос = Новый Запрос();
МВТ = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МВТ;
// Выберем движения по регистраторам
ТекстЗапроса = "ВЫБРАТЬ
| ВыручкаИСебестоимостьПродажОбороты.Период КАК Период,
| ВыручкаИСебестоимостьПродажОбороты.Регистратор КАК Регистратор,
| ВыручкаИСебестоимостьПродажОбороты.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| КлючиАналитики.Номенклатура КАК Номенклатура,
| КлючиАналитики.Характеристика КАК Характеристика,
| ВыручкаИСебестоимостьПродажОбороты.КоличествоОборот КАК КоличествоОборот,
| ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиСНДСРеглОборот КАК СуммаВыручкиСНДСРеглОборот,
| ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиРеглОборот КАК СуммаВыручкиРеглОборот,
| ВЫБОР
| КОГДА ВыручкаИСебестоимостьПродажОбороты.КоличествоОборот = 0
| ТОГДА ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиСНДСРеглОборот
| ИНАЧЕ ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиСНДСРеглОборот / ВыручкаИСебестоимостьПродажОбороты.КоличествоОборот
| КОНЕЦ КАК ЦенаСНДС,
| ВЫБОР
| КОГДА ВыручкаИСебестоимостьПродажОбороты.КоличествоОборот = 0
| ТОГДА ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиРеглОборот
| ИНАЧЕ ВыручкаИСебестоимостьПродажОбороты.СуммаВыручкиРеглОборот / ВыручкаИСебестоимостьПродажОбороты.КоличествоОборот
| КОНЕЦ КАК ЦенаБезНДС,
//| КлючиАналитики.Организация КАК Организация, // Это только тут есть -> КлючиАналитикиУчетаПоПартнерам
//| КлючиАналитики.Контрагент КАК Контрагент,
//| КлючиАналитики.Партнер КАК Клиент // Нужен ли нам Клиент??
| КлючиАналитикиУчетаПоПартнерам.Организация КАК Организация,
| КлючиАналитикиУчетаПоПартнерам.Контрагент КАК Контрагент,
| КлючиАналитикиУчетаПоПартнерам.Партнер КАК Клиент
|ПОМЕСТИТЬ ВтОборотыБезЦены
|ИЗ
| РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(&Начало, &Окончание, Регистратор, ) КАК ВыручкаИСебестоимостьПродажОбороты
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КлючиАналитикиУчетаНоменклатуры КАК КлючиАналитики
| ПО АналитикаУчетаНоменклатуры = КлючиАналитики.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КлючиАналитикиУчетаПоПартнерам КАК КлючиАналитикиУчетаПоПартнерам
| ПО ВыручкаИСебестоимостьПродажОбороты.АналитикаУчетаПоПартнерам = КлючиАналитикиУчетаПоПартнерам.Ссылка
|ГДЕ
| Характеристика <> ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| Характеристика,
| Период
|;
|";
// Получаем цены из регистра ЦеныНоменклатуры на дату каждого документа
// Выберем макс дату цены на каждое движение из регистра цен для дальнейше подстановки
// также цену Реализации будем считать с НДС или без в зависимости от того, включает ли НДС выбранная для сравнения цена -> (ВидЦены.ЦенаВключаетНДС)
ТекстЗапроса = ТекстЗапроса +"
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВтОборотыБезЦены.Период КАК Период,
| МАКСИМУМ(ЦеныНоменклатуры.Период) КАК ПериодЦены,
| ВтОборотыБезЦены.Регистратор КАК Регистратор,
| ВтОборотыБезЦены.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| ВтОборотыБезЦены.Номенклатура КАК Номенклатура,
| ВтОборотыБезЦены.Характеристика КАК Характеристика,
| МАКСИМУМ(ВтОборотыБезЦены.КоличествоОборот) КАК КоличествоОборот,
| МАКСИМУМ(ВтОборотыБезЦены.СуммаВыручкиСНДСРеглОборот) КАК СуммаВыручкиСНДСРеглОборот,
| МАКСИМУМ(ВтОборотыБезЦены.СуммаВыручкиРеглОборот) КАК СуммаВыручкиРеглОборот,
| МАКСИМУМ(ВтОборотыБезЦены.ЦенаСНДС) КАК ЦенаСНДС,
| МАКСИМУМ(ВтОборотыБезЦены.ЦенаБезНДС) КАК ЦенаБезНДС,
| ВЫБОР
| КОГДА &ЦенаВклНДС
| ТОГДА МАКСИМУМ(ВтОборотыБезЦены.ЦенаСНДС)
| ИНАЧЕ МАКСИМУМ(ВтОборотыБезЦены.ЦенаБезНДС)
| КОНЕЦ КАК ЦенаПродажиИзРеализации,
| ВтОборотыБезЦены.Организация КАК Организация,
| ВтОборотыБезЦены.Контрагент КАК Контрагент,
| ВтОборотыБезЦены.Клиент КАК Клиент
|ПОМЕСТИТЬ ВтДокументыМаксПериодЦены
|ИЗ
| ВтОборотыБезЦены КАК ВтОборотыБезЦены
|";
Если НовоеЦенообразование Тогда
// возможно правильнее (дабы не было обращение чз две точки) сделать соединение со справочником ХарактеристикиНоменклатуры
// Не знаю как правильнее... нужно тестировать производительность
ТекстЗапроса = ТекстЗапроса + "
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиСпр
| ПО ВтОборотыБезЦены.Характеристика = ХарактеристикиСпр.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры25 КАК ЦеныНоменклатуры
| ПО ВтОборотыБезЦены.Номенклатура = ЦеныНоменклатуры.Номенклатура
| И ВтОборотыБезЦены.Период >= ЦеныНоменклатуры.Период
| И ХарактеристикиСпр.ХарактеристикаНоменклатурыДляЦенообразования = ЦеныНоменклатуры.ХарактеристикаЦО
| И (ЦеныНоменклатуры.ВидЦены = &ВидЦены)";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
| ПО ВтОборотыБезЦены.Номенклатура = ЦеныНоменклатуры.Номенклатура
| И ВтОборотыБезЦены.Период >= ЦеныНоменклатуры.Период
| И ВтОборотыБезЦены.Характеристика = ЦеныНоменклатуры.Характеристика
| И (ЦеныНоменклатуры.ВидЦены = &ВидЦены)";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|
|СГРУППИРОВАТЬ ПО
| ВтОборотыБезЦены.Период,
| ВтОборотыБезЦены.Регистратор,
| ВтОборотыБезЦены.АналитикаУчетаНоменклатуры,
| ВтОборотыБезЦены.Номенклатура,
| ВтОборотыБезЦены.Характеристика,
| ВтОборотыБезЦены.Организация,
| ВтОборотыБезЦены.Контрагент,
| ВтОборотыБезЦены.Клиент
|
|ИНДЕКСИРОВАТЬ ПО
| Номенклатура,
| ПериодЦены,
| Характеристика
|
|;
| ";
//Эта будет использоваться для нижней тз на форме - подробно
ТекстЗапроса = ТекстЗапроса +"
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВтДокументыМаксПериодЦены.Период КАК Период,
| ВтДокументыМаксПериодЦены.ПериодЦены КАК ПериодЦены,
| ЕСТЬNULL(ЦеныНоменклатуры.ВидЦены, ЗНАЧЕНИЕ(Справочник.ВидыЦен.ПустаяСсылка)) КАК ВидЦены,
| ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) КАК ЦенаПоВиду,
| ВЫБОР КОГДА ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) = 0 ТОГДА 100
| ИНАЧЕ (ВтДокументыМаксПериодЦены.ЦенаПродажиИзРеализации*100/ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) - 100)
| КОНЕЦ КАК Отклонение,
| ВтДокументыМаксПериодЦены.Регистратор КАК Регистратор,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(ВтДокументыМаксПериодЦены.Регистратор) КАК РегистраторСтр,
| ВтДокументыМаксПериодЦены.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| ВтДокументыМаксПериодЦены.Номенклатура КАК Номенклатура,
| ВтДокументыМаксПериодЦены.Характеристика КАК Характеристика,
| ВтДокументыМаксПериодЦены.КоличествоОборот КАК КоличествоОборот,
| ВтДокументыМаксПериодЦены.СуммаВыручкиСНДСРеглОборот КАК СуммаВыручкиСНДСРеглОборот,
| ВтДокументыМаксПериодЦены.СуммаВыручкиРеглОборот КАК СуммаВыручкиРеглОборот,
| ВтДокументыМаксПериодЦены.ЦенаСНДС КАК ЦенаСНДС,
| ВтДокументыМаксПериодЦены.ЦенаБезНДС КАК ЦенаБезНДС,
| ВтДокументыМаксПериодЦены.ЦенаПродажиИзРеализации КАК ЦенаПродажиИзРеализации,
| ВтДокументыМаксПериодЦены.Организация КАК Организация,
| ВтДокументыМаксПериодЦены.Контрагент КАК Контрагент,
| ВтДокументыМаксПериодЦены.Клиент КАК Клиент
|ПОМЕСТИТЬ ВтДокументыСЦенойПодробно
|ИЗ
| ВтДокументыМаксПериодЦены КАК ВтДокументыМаксПериодЦены
|";
Если НовоеЦенообразование Тогда
ТекстЗапроса = ТекстЗапроса + "
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиСпр
| ПО ВтДокументыМаксПериодЦены.Характеристика = ХарактеристикиСпр.Ссылка
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры25 КАК ЦеныНоменклатуры
| ПО ВтДокументыМаксПериодЦены.Номенклатура = ЦеныНоменклатуры.Номенклатура
| И ВтДокументыМаксПериодЦены.ПериодЦены = ЦеныНоменклатуры.Период
| И ХарактеристикиСпр.ХарактеристикаНоменклатурыДляЦенообразования = ЦеныНоменклатуры.ХарактеристикаЦО
| И (ЦеныНоменклатуры.ВидЦены = &ВидЦены)";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
| ПО ВтДокументыМаксПериодЦены.Номенклатура = ЦеныНоменклатуры.Номенклатура
| И ВтДокументыМаксПериодЦены.ПериодЦены = ЦеныНоменклатуры.Период
| И ВтДокументыМаксПериодЦены.Характеристика = ЦеныНоменклатуры.Характеристика
| И (ЦеныНоменклатуры.ВидЦены = &ВидЦены)";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ИНДЕКСИРОВАТЬ ПО
| Период,
| АналитикаУчетаНоменклатуры,
| Номенклатура,
| Организация
//| Контрагент
|;
|";
// Остатки
ТекстЗапроса = ТекстЗапроса +"
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТоварыОрганизацийОстаткиИОбороты.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| ТоварыОрганизацийОстаткиИОбороты.Организация КАК Организация,
| ТоварыОрганизацийОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
| ТоварыОрганизацийОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
| ТоварыОрганизацийОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
| ТоварыОрганизацийОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток
|ПОМЕСТИТЬ ВтОстатки
|ИЗ
| РегистрНакопления.ТоварыОрганизаций.ОстаткиИОбороты(&Начало, &Окончание, Период, , ) КАК ТоварыОрганизацийОстаткиИОбороты
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КлючиАналитикиУчетаНоменклатуры КАК КлючиАналитики
| ПО ТоварыОрганизацийОстаткиИОбороты.АналитикаУчетаНоменклатуры = КлючиАналитики.Ссылка
|ГДЕ
| КлючиАналитики.Характеристика <> ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
|
|ИНДЕКСИРОВАТЬ ПО
| АналитикаУчетаНоменклатуры,
| Организация
|;";
// для верхней таблицы Анализа - Итоговые обороты за период отчета в разрезе группировок
ТекстЗапроса = ТекстЗапроса +"
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Документы.АналитикаУчетаНоменклатуры КАК АналитикаУчетаНоменклатуры,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(Документы.Номенклатура) КАК Номенклатура,
| Документы.Характеристика КАК Характеристика,
| СУММА(Документы.КоличествоОборот) КАК КоличествоОборот,
| СУММА(Документы.СуммаВыручкиСНДСРеглОборот) КАК СуммаВыручкиСНДС,
| СУММА(Документы.СуммаВыручкиРеглОборот) КАК СуммаВыручки,
| СРЕДНЕЕ(Документы.ЦенаСНДС) КАК ЦенаСНДС,
| СРЕДНЕЕ(Документы.ЦенаПоВиду) КАК ЦенаПоВиду,
| СРЕДНЕЕ(Документы.ЦенаБезНДС) КАК ЦенаБезНДС,
| СРЕДНЕЕ(Документы.ЦенаПродажиИзРеализации) КАК ЦенаПродажиИзРеализации,
| СРЕДНЕЕ(Документы.Отклонение) КАК Отклонение,
| Документы.Организация КАК Организация,
| Документы.Контрагент КАК Контрагент,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(Документы.Организация) КАК ОрганизацияСтр,
| ПРЕДСТАВЛЕНИЕССЫЛКИ(Документы.Контрагент) КАК КонтрагентСтр,
| МАКСИМУМ(ВтОстатки.КоличествоНачальныйОстаток) КАК НачальныйОстаток,
| МАКСИМУМ(ВтОстатки.КоличествоПриход) КАК КоличествоПриход,
| МАКСИМУМ(ВтОстатки.КоличествоРасход) КАК КоличествоРасход,
| МАКСИМУМ(ВтОстатки.КоличествоКонечныйОстаток) КАК КонечныйОстаток,
| МАКСИМУМ(СпрНоменклатура.Артикул) КАК Артикул
|
|ИЗ
| ВтДокументыСЦенойПодробно КАК Документы
| ЛЕВОЕ СОЕДИНЕНИЕ ВтОстатки КАК ВтОстатки
| ПО (Документы.АналитикаУчетаНоменклатуры = ВтОстатки.АналитикаУчетаНоменклатуры)
| И (Документы.Организация = ВтОстатки.Организация)
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СпрНоменклатура
| ПО Документы.Номенклатура = СпрНоменклатура.Ссылка
|
|СГРУППИРОВАТЬ ПО
| Документы.АналитикаУчетаНоменклатуры,
| Документы.Номенклатура,
| Документы.Организация,
| Документы.Характеристика,
| Документы.Контрагент
|
|
|УПОРЯДОЧИТЬ ПО
| Номенклатура.Наименование,
| АналитикаУчетаНоменклатуры
|
|";
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("Начало",ПериодОтчета.ДатаНачала);
Запрос.УстановитьПараметр("Окончание",ПериодОтчета.ДатаОкончания);
Запрос.УстановитьПараметр("ВидЦены",ВидЦены);
Запрос.УстановитьПараметр("ЦенаВклНДС",?(ЗначениеЗаполнено(ВидЦены),ВидЦены.ЦенаВключаетНДС,Истина));
// Выводим данные на форму
// Стараемся не выводить ссылочные объекты, используем ПРЕДСТАВЛЕНИЕССЫЛКИ
ТЗЗапросаИтоги.Загрузить(Запрос.Выполнить().Выгрузить());
//ТЗПодробно.Загрузить(Запрос.МенеджерВременныхТаблиц.Таблицы[2].ПолучитьДанные().Выгрузить());
ТЗПодробно.Загрузить(Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ВтДокументыСЦенойПодробно").ПолучитьДанные().Выгрузить());
КонецПроцедуры
Проверено на следующих конфигурациях и релизах:
- Управление торговлей, редакция 11, релизы 11.5.20.66, 11.5.11.70