Почему не отображаются все записи в отборе динамического списка в веб-клиенте 1С

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

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда один и тот же код ведет себя по-разному в тонком клиенте и веб-клиенте. Одной из наиболее коварных проблем является некорректная фильтрация данных в динамических списках. Рассмотрим ситуацию: вы программно устанавливаете отбор (например, по периоду), в тонком клиенте видите все положенные 5 записей, а в браузере — только 3. При этом ручная настройка того же самого отбора через стандартное меню списка работает корректно в обоих случаях.

В этой статье мы разберем, почему возникает этот программный «пробел», проанализируем влияние платформенных механизмов и выясним, как правильно реализовать установку отборов, чтобы они работали стабильно вне зависимости от типа клиентского приложения.

Анализ проблемы: клиентская часть против серверной

Давайте проанализируем исходный код, который вызывает проблему на стороне веб-клиента. В примере рассматривается установка отбора по реквизиту ДатаНачала в границах текущей недели. Программист пытается выполнить это непосредственно в процедуре с директивой &НаКлиенте.

Посмотрим на пример кода, который работает в тонком клиенте, но «теряет» данные в веб-клиенте:


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

На первый взгляд код выглядит абсолютно корректным. Однако именно здесь кроется корень проблемы при работе через браузер. Выясним основные причины такого поведения:

  1. Сериализация дат и часовые пояса. В веб-клиенте функции ТекущаяДата(), НачалоНедели() и КонецНедели(), вызванные в контексте &НаКлиенте, используют системное время локальной машины пользователя и настройки браузера. При передаче этих данных на сервер 1С через протокол JSON может происходить смещение времени из-за разницы часовых поясов или особенностей округления секунд. В итоге границы фильтра «плывут», и записи, попадающие на 00:00:00 или 23:59:59, отсекаются.
  2. Кэширование динамического списка. Веб-клиент работает с данными порционно и агрессивно кэширует их. При программном изменении КомпоновщикНастроек на клиенте уведомление сервера о необходимости полной пересборки запроса иногда отрабатывает некорректно, особенно в старых версиях платформы (например, 8.3.13).
  3. Особенности платформы 8.3.13. В данной ветке платформы были зафиксированы ошибки, связанные с тем, что программное изменение ФиксированныеНастройки в веб-клиенте не всегда инициировало корректное обновление схемы компоновки данных.

Решение проблемы: перенос логики на сервер

Рассмотрим правильный подход. Чтобы гарантировать идентичность работы отборов, формирование настроек необходимо выполнять на стороне сервера. Это исключает влияние локальных настроек времени браузера и гарантирует, что 1С сформирует SQL-запрос к базе данных с использованием серверного контекста.

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


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

&НаКлиенте
Процедура ВыполнитьУстановкуОтбора(Команда)
    УстановитьОтборНаСервере();
КонецПроцедуры

Почему это работает лучше?

Проанализируем преимущества серверного подхода:

Работа с Фиксированными настройками и пересечение отборов

Важно помнить о поведении ФиксированныеНастройки. Как только вы программно устанавливаете отбор в эту коллекцию, пользователь теряет возможность изменять отбор по этому же полю через стандартную форму «Настройка списка». Если пользователь попытается это сделать, платформа может выдать предупреждение о пересечении отборов или просто проигнорировать пользовательское условие.

Если ваша задача — установить начальное значение, которое пользователь сможет изменить, используйте Список.КомпоновщикНастроек.Настройки.Отбор. Однако для жесткой фильтрации данных (например, ограничение прав доступа или работа строго в рамках одного периода) ФиксированныеНастройки являются единственно верным инструментом.

Совет: Если вы все же вынуждены работать на клиенте в веб-интерфейсе, старайтесь избегать использования ГруппаЭлементовОтбораКомпоновкиДанных без крайней необходимости. Плоские списки условий в веб-клиенте иногда обрабатываются стабильнее, чем вложенные иерархии групп компоновки. Но лучшим решением всегда остается вынос этой логики в процедуру &НаСервере.

Подводя итог, можно сказать: если вы столкнулись с «магическим» исчезновением записей в веб-клиенте при использовании динамических списков — первым делом проверьте, где формируется отбор. Перенос формирования КомпоновщикНастроек на сервер решает 90% подобных проблем, связанных с типами данных и платформенными различиями клиентских приложений.

← На главную