Как правильно рассчитать тариф на основе итоговых значений и настроить условия в СКД

Программист 1С v8.3 (Управляемые формы) Сфера услуг, туризм и социальный сектор
← На главную

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда вычисляемые поля или условия в запросе работают не так, как ожидалось. Типичный пример — расчет тарифа, который должен зависеть от итоговой суммы времени по документу или контрагенту, но вместо этого выдает результат, основываясь на данных каждой отдельной строки. В этой статье мы подробно разберем, как избежать подобных ошибок, правильно настроить вложенные условия и корректно обращаться к объектам базы данных.

Разбор проблемы: Почему условие в запросе работает «построчно»

Рассмотрим ситуацию, когда в тексте запроса используется конструкция ВЫБОР КОГДА СУММА(ВремяВыполнения) .... На первый взгляд кажется, что система должна сложить все показатели и применить условие к итогу. Однако, если в запросе присутствует группировка по детальным записям (например, по ссылке на документ или номенклатуре), функция СУММА() будет вычисляться только в рамках этой конкретной строки или группы. Если ваша цель — получить значение тарифа исходя из общего итога по всей таблице отчета или крупной группировке, расчет в тексте запроса может быть неэффективен.

Выясним причину: В языке запросов агрегатные функции работают в контексте текущей выборки. Чтобы условие анализировало итоговое значение в отчете, логику расчета тарифа следует перенести из текста запроса в Ресурсы СКД. Поля, описанные на вкладке «Ресурсы», рассчитываются системой уже после получения данных, что позволяет оперировать реальными итогами группировок.

Корректное сравнение числовых диапазонов

Частой ошибкой является попытка использовать математическую запись диапазона, привычную по школьной программе, например: 0 < Значение <= 2.5. Система компоновки данных и язык запросов 1С не поддерживают двойное сравнение в одной операции. Проанализируем правильный подход.

Для корректной работы условия необходимо разделять проверки оператором И (AND). Рассмотрим пример правильной структуры:


ВЫБОР
    КОГДА СУММА(ВремяВыполнения) > 0 И СУММА(ВремяВыполнения) <= 2.5 ТОГДА "ТП1"
    КОГДА СУММА(ВремяВыполнения) > 2.5 И СУММА(ВремяВыполнения) <= 6.5 ТОГДА "ТП2"
    КОГДА СУММА(ВремяВыполнения) > 6.5 И СУММА(ВремяВыполнения) <= 10 ТОГДА "ТП3"
    ИНАЧЕ "ТП_Стандарт"
КОНЕЦ

Существует и более элегантный способ — каскадная проверка. Так как условия в конструкции ВЫБОР проверяются последовательно до первого совпадения, мы можем упростить код, проверяя значения на «меньше или равно» по возрастанию:


ВЫБОР
    КОГДА СУММА(ВремяВыполнения) <= 2.5 ТОГДА "ТП1"
    КОГДА СУММА(ВремяВыполнения) <= 6.5 ТОГДА "ТП2"
    КОГДА СУММА(ВремяВыполнения) <= 10 ТОГДА "ТП3"
    ИНАЧЕ "ТП4"
КОНЕЦ

В этом случае, если значение равно 4.78, система сначала проверит первое условие (ложно), затем второе (истинно) и сразу вернет "ТП2", не выполняя дальнейших проверок.

Поиск контрагента: ошибка функции ЗНАЧЕНИЕ()

Посмотрим на распространенную ошибку при попытке найти конкретного контрагента в запросе или вычисляемом поле. Использование конструкции ЗНАЧЕНИЕ(Справочники.Контрагенты.НайтиПоНаименованию("РогаИКопыта")) приведет к синтаксической ошибке «Ожидается )».

Разберем по шагам, почему это происходит:

  1. Функция ЗНАЧЕНИЕ() в 1С работает только с предопределенными данными (теми, что созданы в Конфигураторе), именами перечислений или пустыми ссылками.
  2. Метод НайтиПоНаименованию() — это функция встроенного языка, которая не существует внутри SQL-запроса.

Как решить задачу правильно: Лучший способ — использовать параметры. На вкладке «Параметры» в СКД создайте параметр (например, &НужныйКонтрагент). Если вы хотите, чтобы поиск происходил автоматически по строке, в поле «Выражение» для этого параметра можно прописать код: Справочники.Контрагенты.НайтиПоНаименованию("РогаИКопыта"). Тогда в самом запросе или ресурсе условие будет выглядеть максимально просто: Контрагент = &НужныйКонтрагент.

Настройка вложенных условий ВЫБОР

Если логика требует сначала проверить контрагента, а затем применить тарифную сетку, используются вложенные конструкции. Основная сложность здесь заключается в соблюдении парности операторов ВЫБОР и КОНЕЦ. Проанализируем правильную структуру вложенности:


ВЫБОР
    КОГДА Контрагент = &НужныйКонтрагент
    ТОГДА
        ВЫБОР
            КОГДА СУММА(ВремяВыполнения) <= 2.5 ТОГДА "ТП1"
            КОГДА СУММА(ВремяВыполнения) <= 6.5 ТОГДА "ТП2"
            ИНАЧЕ "ТП_Прочее"
        КОНЕЦ
    ИНАЧЕ "БазовыйТариф"
КОНЕЦ

Важный момент: Каждый вложенный ВЫБОР должен иметь свой собственный завершающий КОНЕЦ. Если вы получаете ошибку о недостающей скобке, в 90% случаев проблема именно в пропущенном КОНЕЦ или попытке начать новое условие КОГДА внутри блока ТОГДА без инициации нового ВЫБОР.

Практические советы по работе с ресурсами в СКД

Чтобы итоговое поле «Тариф» отображалось корректно, выполните следующие действия в схеме компоновки данных:

  1. Перейдите на закладку «Ресурсы».
  2. Перенесите ваше поле «Тариф» в список ресурсов.
  3. В колонке «Выражение» впишите конструкцию ВЫБОР..., которую мы разобрали выше.
  4. В колонке «Рассчитывать по...» укажите конкретные группировки, для которых этот тариф актуален. Если тариф должен считаться и в общих итогах, оставьте поле пустым или выберите «Все уровни».

Такой подход гарантирует, что система сначала произведет агрегацию данных (сложит ВремяВыполнения), а уже потом определит строковое значение тарифа для каждой группы отчета. Это решит проблему, когда вместо ожидаемого значения «ТП2» (для суммы 4.78) выводилось «ТП1» (так как система ошибочно проверяла каждую строку документа в отдельности).

Проанализируем типичную ситуацию с типами данных: При использовании условий в блоке ИНАЧЕ старайтесь возвращать пустое значение того же типа, что и основные результаты. Если тариф — это строка, пишите ИНАЧЕ "". Это поможет СКД правильно определить тип колонки и избежать конфликтов при выводе отчета в Excel или просмотре в браузере.

← На главную