Как сделать отбор списка заказов по состоянию подчиненных документов в обычных формах

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

При работе в среде обычных форм 1С разработчики часто сталкиваются с ограничением: стандартный механизм отбора в объекте ДокументСписок позволяет фильтровать данные только по реквизитам самого документа. Но что делать, если условие отбора находится в «будущем» — например, нужно найти Заказы покупателей, для которых созданы Заявки на расходование средств, имеющие пометку на удаление? Разберем эту задачу подробно и проанализируем доступные программные методы реализации.

Проблема обратной связи в обычных формах

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

Выясним причину, почему простым кликом мышки это не настроить: в конфигураторе в свойствах отбора вы видите только поля текущего объекта. Для решения задачи нам придется применить программные методы.

Решение 1: Программная установка отбора «В списке»

Это самый популярный и эффективный метод для списков среднего объема. Рассмотрим подробнее алгоритм действий:

  1. Сначала мы должны выполнить запрос, который найдет все Заказы, удовлетворяющие нашему условию.
  2. Результат запроса (ссылки на заказы) мы поместим в СписокЗначений.
  3. Установим этот список в качестве значения отбора для поля Ссылка нашего списка документов.

Посмотрим на пример кода, который можно разместить, например, в обработчике нажатия кнопки «Обновить» или при изменении параметров фильтрации на форме:


// 1. Формируем запрос для получения списка подходящих заказов
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ЗаявкаНаРасходованиеСредств.ДокументОснование КАК ЗаказСсылка
    |ИЗ
    |	Документ.ЗаявкаНаРасходованиеСредств КАК ЗаявкаНаРасходованиеСредств
    |ГДЕ
    |	ЗаявкаНаРасходованиеСредств.ПометкаУдаления = ИСТИНА
    |	И ЗаявкаНаРасходованиеСредств.ДокументОснование ССЫЛКА Документ.ЗаказПокупателя";

РезультатЗапроса = Запрос.Выполнить();
СписокЗаказов = Новый СписокЗначений;
СписокЗаказов.ЗагрузитьЗначения(РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("ЗаказСсылка"));

// 2. Устанавливаем отбор в табличном поле (имя данных ДокументСписок)
ЭлементОтбора = СправочникСписок.Отбор.Ссылка;
ЭлементОтбора.ВидСравнения = ВидСравнения.ВСписке;
ЭлементОтбора.Значение = СписокЗаказов;
ЭлементОтбора.Использование = ИСТИНА;

Важный нюанс: если документов в списке окажется слишком много (десятки тысяч), производительность формы может снизиться. Однако для оперативной работы менеджеров этот метод является наиболее гибким.

Решение 2: Использование Таблицы Значений (ТЗ)

Если логика отбора настолько сложна, что её невозможно эффективно поддерживать через ДокументСписок.Отбор, мы можем полностью заменить источник данных для табличного поля. Вместо типа ДокументСписок будем использовать ТаблицаЗначений.

Разберем по шагам процесс реализации:

  1. Создаем на форме табличное поле.
  2. В качестве типа значения указываем ТаблицаЗначений.
  3. При открытии формы или по команде пользователя программно заполняем эту таблицу результатом запроса.

Этот метод дает полный контроль над данными, но у него есть существенный минус — вы теряете «динамичность». Обычный ДокументСписок считывает данные порциями при скроллинге, а ТаблицаЗначений загружает всё сразу в память клиента. Проанализируем риски: если в базе сотни тысяч заказов, форма будет открываться очень долго.

Решение 3: Денатурализация данных (Добавление реквизита)

В ходе дискуссии на форуме предлагался вариант добавления в Заказ покупателя специального булевого реквизита, например, ЕстьУдаленныеЗаявки. Рассмотрим этот подход критически:

Многие разработчики считают это плохой практикой (как было отмечено в сообщении 28), так как перезапись старых (закрытых) периодов может привести к конфликтам блокировок и нежелательному изменению метаданных документа (дата изменения, автор правки). Однако, если бизнес-процесс позволяет, этот метод имеет право на жизнь.

Решение 4: Вспомогательный регистр сведений

Чтобы избежать прямой модификации документа «Заказ», но сохранить скорость отбора, мы можем использовать Регистр сведений. Это более «чистый» архитектурный подход.

Посмотрим на схему реализации:

  1. Создаем непериодический регистр сведений СостоянияСвязанныхДокументов.
  2. Измерения: Заказ. Ресурсы: СодержитУдаленныеЗаявки (Булево).
  3. В модуле объекта Заявка на расходование средств в процедуре ПередЗаписью или ПриЗаписи прописываем код, который обновляет запись в этом регистре для соответствующего заказа.
  4. В форме списка заказов можно использовать соединение с этим регистром (если используется динамический список в 8.2/8.3) или сначала получать список ссылок из регистра и подставлять их в отбор, как в Решении 1.

Резюме по выбору метода

Выясним, какой путь лучше выбрать именно вам:

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

← На главную