Как в динамическом запросе формы подбора УНФ вывести цену с учетом ценовых групп договора?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет Торговля и дистрибуция
← На главную

При доработке формы подбора номенклатуры в конфигурации 1С:Управление нашей фирмой часто возникает задача выводить актуальные цены для конкретного контрагента. Если в договоре контрагента заданы уточнения цен по определенным ценовым группам, в списке должна отображаться индивидуальная цена из договора, а для остальных позиций — основной вид цен документа. Разберем, как правильно составить динамический запрос для списка номенклатуры, избежать дублирования строк и корректно обработать срез последних цен.

Анализ проблемы и типичные ошибки при построении запроса

Проанализируем типовые ошибки, которые возникают при попытке соединить справочник номенклатуры с регистром сведений ЦеныНоменклатуры:

  1. Отбор списком в параметрах среза последних: Если передать в виртуальную таблицу РегистрСведений.ЦеныНоменклатуры.СрезПоследних условие вида ВидЦен В (...), регистр вернет срез по каждой комбинации измерений. Если для товара существуют записи по нескольким видам цен из этого списка, левое соединение только по номенклатуре приведет к размножению строк в динамическом списке.
  2. Ограничения динамического списка: Платформа 1С в динамических списках не поддерживает пакетные запросы с созданием временных таблиц через конструкцию ПОМЕСТИТЬ. Вся выборка должна строиться в рамках единого запроса с левыми соединениями.
  3. Неверная связь табличной части договора: Данные по индивидуальным ценам хранятся в табличной части ЦеновыеГруппы справочника ДоговорыКонтрагентов. Соединение с ней должно производиться строго по двум полям — ссылке на текущий договор и ценовой группе номенклатуры.

Пошаговое решение задачи

Разберем по шагам правильную схему соединения таблиц в запросе динамического списка.

  1. Подключение табличной части договора: Выполним левое соединение со справочником ДоговорыКонтрагентов.ЦеновыеГруппы с отбором по параметру &Договор и ценовой группе товара.
  2. Определение результирующего вида цен: С помощью функции ЕСТЬNULL проверим, задан ли вид цены для ценовой группы в договоре. Если задан — берем его, иначе подставляем основной вид цен из параметра &ОсновнойВидЦен (или &ВидЦен).
  3. Соединение со срезом последних: Соединяем виртуальную таблицу цен не только по ссылке на номенклатуру, но и по рассчитанному виду цены.

Итоговый текст запроса для динамического списка

Посмотрим на практическую реализацию полного запроса с учетом остатков, резервов и вычисления индивидуальной цены:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ВЫБОР
        КОГДА СправочникНоменклатура.ЭтоГруппа ТОГДА
            ВЫБОР КОГДА СправочникНоменклатура.ПометкаУдаления ТОГДА 13 ИНАЧЕ 12 КОНЕЦ
        ИНАЧЕ -1 + ВЫБОР КОГДА СправочникНоменклатура.ПометкаУдаления ТОГДА 1 ИНАЧЕ 0 КОНЕЦ
                + ВЫБОР КОГДА СправочникНоменклатура.ИспользоватьХарактеристики = ЛОЖЬ ТОГДА 1 ИНАЧЕ 3 КОНЕЦ
    КОНЕЦ КАК ИндексКартинки,
    СправочникНоменклатура.Ссылка КАК НоменклатураСсылка,
    ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка) КАК ХарактеристикаСсылка,
    СправочникНоменклатура.Родитель КАК Родитель,
    СправочникНоменклатура.Код КАК Код,
    СправочникНоменклатура.Наименование КАК Наименование,
    СправочникНоменклатура.Артикул КАК Артикул,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения, СправочникНоменклатура.ЕдиницаИзмерения) КАК ЕдиницаИзмерения,
    СправочникНоменклатура.ЦеноваяГруппа КАК ЦеноваяГруппа,
    ЕСТЬNULL(ВЫРАЗИТЬ(ЦеныНоменклатурыСрезПоследних.Цена * (&ВалютаВидаЦенКурс * &ВалютаДокументаКратность) / (&ВалютаДокументаКурс * &ВалютаВидаЦенКратность) КАК ЧИСЛО(15, 2)), 0) КАК Цена,
    ВЫБОР
        КОГДА ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения ССЫЛКА Справочник.ЕдиницыИзмерения
            ТОГДА ЕСТЬNULL(ОстаткиЗапасов.КоличествоОстаток, 0) / ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения.Коэффициент
        ИНАЧЕ ЕСТЬNULL(ОстаткиЗапасов.КоличествоОстаток, 0)
    КОНЕЦ КАК Остаток,
    ВЫБОР
        КОГДА ЕСТЬNULL(РезервыЗапасов.КоличествоОстаток, 0) = 0 ТОГДА 1 ИНАЧЕ 0
    КОНЕЦ КАК Резерв,
    ВЫБОР
        КОГДА ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения ССЫЛКА Справочник.ЕдиницыИзмерения
            ТОГДА (ЕСТЬNULL(ОстаткиЗапасов.КоличествоОстаток, 0) - ЕСТЬNULL(РезервыЗапасов.КоличествоОстаток, 0)) / ЦеныНоменклатурыСрезПоследних.ЕдиницаИзмерения.Коэффициент
        ИНАЧЕ ЕСТЬNULL(ОстаткиЗапасов.КоличествоОстаток, 0) - ЕСТЬNULL(РезервыЗапасов.КоличествоОстаток, 0)
    КОНЕЦ КАК Свободно,
    ЕСТЬNULL(ДоговорЦеновыеГруппы.ВидЦен, &ВидЦен) КАК ВидЦен
ИЗ
    Справочник.Номенклатура КАК СправочникНоменклатура
    
    // Подключаем ценовые группы договора
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов.ЦеновыеГруппы КАК ДоговорЦеновыеГруппы
        ПО ДоговорЦеновыеГруппы.Ссылка = &Договор
        И ДоговорЦеновыеГруппы.ЦеноваяГруппа = СправочникНоменклатура.ЦеноваяГруппа

    // Соединяем со срезом цен по номенклатуре и вычисленному виду цен
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
        &ПериодЦен,
        Актуальность
        И Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
        И ВидЦен В (&МассивВсехИспользуемыхВидовЦен)
    ) КАК ЦеныНоменклатурыСрезПоследних
        ПО СправочникНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
        И ЦеныНоменклатурыСрезПоследних.ВидЦен = ЕСТЬNULL(ДоговорЦеновыеГруппы.ВидЦен, &ВидЦен)

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗапасыНаСкладах.Остатки(, Организация = &Организация) КАК ОстаткиЗапасов
        ПО СправочникНоменклатура.Ссылка = ОстаткиЗапасов.Номенклатура

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Запасы.Остатки(
        ,
        Организация = &Организация
        И СтруктурнаяЕдиница ССЫЛКА Справочник.СтруктурныеЕдиницы
        И ЗаказПокупателя <> ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)
    ) КАК РезервыЗапасов
        ПО СправочникНоменклатура.Ссылка = РезервыЗапасов.Номенклатура
ГДЕ
    НЕ СправочникНоменклатура.ЭтоГруппа
    И СправочникНоменклатура.ТипНоменклатуры В (&ТипНоменклатуры)

Программная установка параметров формы

Рассмотрим, как подготовить и передать параметры в динамический список при открытии формы или изменении договора/вида цен в документе:


&НаСервере
Процедура УстановитьПараметрыСпискаСервер()
    
    // Формируем список всех видов цен, которые могут быть применены
    МассивВидовЦен = Новый Массив;
    МассивВидовЦен.Добавить(ВидЦенДокумента);
    
    Если ЗначениеЗаполнено(ДоговорКонтрагента) Тогда
        Для Каждого Стр Из ДоговорКонтрагента.ЦеновыеГруппы Цикл
            Если ЗначениеЗаполнено(Стр.ВидЦен) И МассивВидовЦен.Найти(Стр.ВидЦен) = Неопределено Тогда
                МассивВидовЦен.Добавить(Стр.ВидЦен);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    // Передаем параметры в динамический список
    Список.Параметры.УстановитьЗначениеПараметра("Договор", ДоговорКонтрагента);
    Список.Параметры.УстановитьЗначениеПараметра("ВидЦен", ВидЦенДокумента);
    Список.Параметры.УстановитьЗначениеПараметра("МассивВсехИспользуемыхВидовЦен", МассивВидовЦен);
    Список.Параметры.УстановитьЗначениеПараметра("ПериодЦен", ТекущаяДата());
    Список.Параметры.УстановитьЗначениеПараметра("Организация", ОрганизацияДокумента);
    
КонецПроцедуры

Такой подход обеспечивает высокую скорость работы динамического списка, исключает задвоение позиций и корректно рассчитывает цены согласно индивидуальным условиям договора с клиентом.

← На главную