Как правильно рассчитать процент отгрузки по заказу клиента в динамическом списке 1С?

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

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

Разберем типичные ошибки при построении таких запросов, выясним их причины и сформируем готовое оптимизированное решение.

Анализ основных ошибок в запросе

Рассмотрим, какие именно ошибки приводят к исчезновению строк или неверному расчету:

  1. Неправильный порядок соединения таблиц: Если виртуальная таблица остатков указана первой, а таблица документов присоединяется к ней, то при полном исполнении заказа остаток в регистре становится равным 0, и запись из виртуальной таблицы Остатки исчезает. В результате исчезает и сам документ из выборки. Чтобы этого избежать, ведущей таблицей должен выступать документ Документ.ЗаказКлиента, к которому левым соединением подключается таблица остатков.
  2. Некорректная проверка на NULL: В языке запросов 1С конструкция вида Поле = NULL всегда возвращает Ложь (FALSE), так как NULL обозначает отсутствие значения и не может быть равен ничему, даже самому себе. Для проверки необходимо использовать функцию ЕСТЬNULL() или оператор Поле ЕСТЬ NULL.
  3. Неправильная формула расчета процентов: Деление разницы сумм на константу 100 вместо суммы документа приводит к неверным числам. Для вычисления доли необходимо находить отношение отгруженной суммы к общей сумме документа и умножать результат на 100.
  4. Обращение через точку в условии соединения: Конструкция ЗаказыКлиентовОстатки.ЗаказКлиента.Ссылка создает неявное дополнительное соединение с базовой таблицей документа. Поле измерения ЗаказКлиента уже содержит ссылку, поэтому соединять следует напрямую: ЗаказыКлиентовОстатки.ЗаказКлиента.
  5. Сброс основной таблицы динамического списка: При переключении на произвольный запрос в динамическом списке свойство ОсновнаяТаблица может очиститься. Без указания основной таблицы платформа не может определить ключевые поля, отключаются стандартные механизмы динамического считывания, а также контекстные команды списка.

Пошаговое исправление и составление корректного запроса

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

Посмотрим на пример логики вычисления процента:


ВЫБРАТЬ
    ДокументЗаказ.Ссылка КАК Ссылка,
    ДокументЗаказ.Номер КАК Номер,
    ДокументЗаказ.Дата КАК Дата,
    ДокументЗаказ.СуммаДокумента КАК СуммаДокумента,
    ВЫБОР
        КОГДА ДокументЗаказ.СуммаДокумента = 0
            ТОГДА ВЫБОР
                КОГДА ЗаказыОстатки.КоличествоОстаток ЕСТЬ NULL
                    ТОГДА 100
                ИНАЧЕ 0
            КОНЕЦ
        ИНАЧЕ ВЫРАЗИТЬ((ДокументЗаказ.СуммаДокумента - ЕСТЬNULL(ЗаказыОстатки.СуммаОстаток, 0)) / ДокументЗаказ.СуммаДокумента * 100 КАК ЧИСЛО(5, 2))
    КОНЕЦ КАК ПроцентОтгрузки
ИЗ
    Документ.ЗаказКлиента КАК ДокументЗаказ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыКлиентов.Остатки КАК ЗаказыОстатки
        ПО ДокументЗаказ.Ссылка = ЗаказыОстатки.ЗаказКлиента
ГДЕ
    ДокументЗаказ.Проведен

Разберем, как работает данная конструкция:

  1. Если сумма заказа равна 0, проверяется наличие товарного остатка. Отсутствие записи в регистре (ЕСТЬ NULL) говорит о том, что заказ отгружен полностью (100%), иначе выводится 0%.
  2. Если сумма больше 0, из суммы документа вычитается остаток из регистра (с защитой от NULL через ЕСТЬNULL(..., 0)), делится на исходную сумму и умножается на 100.
  3. Функция ВЫРАЗИТЬ(... КАК ЧИСЛО(5, 2)) защищает от бесконечных периодических дробей в интерфейсе.

Устранение дублирования строк при нескольких позициях в заказе

Таблица РегистрНакопления.ЗаказыКлиентов.Остатки возвращает данные в разрезе всех измерений (номенклатура, характеристика, склад и т. д.). Если в заказе несколько позиций номенклатуры, левое соединение вернет несколько строк на один документ. В результате в динамическом списке строки заказа начнут двоиться или троиться.

Чтобы избежать дублирования, свернем остатки во вложенном запросе по измерению ЗаказКлиента:


ВЫБРАТЬ
    ДокументЗаказ.Ссылка КАК Ссылка,
    ДокументЗаказ.Номер КАК Номер,
    ДокументЗаказ.Дата КАК Дата,
    ДокументЗаказ.СуммаДокумента КАК СуммаДокумента,
    ВЫБОР
        КОГДА ДокументЗаказ.СуммаДокумента = 0
            ТОГДА ВЫБОР
                КОГДА СвернутыеОстатки.СуммаОстаток ЕСТЬ NULL
                    ТОГДА 100
                ИНАЧЕ 0
            КОНЕЦ
        ИНАЧЕ ВЫРАЗИТЬ((ДокументЗаказ.СуммаДокумента - ЕСТЬNULL(СвернутыеОстатки.СуммаОстаток, 0)) / ДокументЗаказ.СуммаДокумента * 100 КАК ЧИСЛО(5, 2))
    КОНЕЦ КАК ПроцентОтгрузки
ИЗ
    Документ.ЗаказКлиента КАК ДокументЗаказ
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Остатки.ЗаказКлиента КАК ЗаказКлиента,
            СУММА(Остатки.СуммаОстаток) КАК СуммаОстаток
        ИЗ
            РегистрНакопления.ЗаказыКлиентов.Остатки КАК Остатки
        СГРУППИРОВАТЬ ПО
            Остатки.ЗаказКлиента
    ) КАК СвернутыеОстатки
        ПО ДокументЗаказ.Ссылка = СвернутыеОстатки.ЗаказКлиента

Рекомендации по настройке динамического списка и производительности

При внедрении запроса в форму списка обратим внимание на следующие технические моменты:

  1. Заполнение основной таблицы: В палитре свойств динамического списка в поле ОсновнаяТаблица обязательно указываем Документ.ЗаказКлиента. Если платформа блокирует редактирование запроса или ругается на поля, временно снимем флаг «Произвольный запрос», укажем основную таблицу, затем снова включим флаг и вставим текст запроса.
  2. Оптимизация скорости работы: Соединение с виртуальной таблицей остатков без параметров заставляет СУБД рассчитывать остатки по всему регистру. Если база содержит большой объем данных, список может открываться медленно. В высоконагруженных системах процент отгрузки рассчитывают при проведении документов и сохраняют в специальный регистр сведений либо вычисляют порционно в событии формы ПриПолученииДанныхНаСервере.
← На главную