Как в журнал документов добавить только часть документов одного вида по определенной операции?

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

При проектировании систем на платформе 1С:Предприятие 8 разработчики часто сталкиваются с архитектурным ограничением стандартного объекта метаданных Журнал документов. На этапе конфигурирования мы можем жестко задать список входящих в него документов, но платформа не позволяет выполнять условную регистрацию «на лету». Иными словами, если документ определенного типа включен в журнал, СУБД запишет туда абсолютно все его экземпляры, независимо от реквизитов (например, от «Вида операции»).

В этой статье мы подробно разберем, как обойти это ограничение, проанализируем различные подходы — от простых интерфейсных решений до серьезной перестройки архитектуры базы данных, используемой в промышленных конфигурациях (ЕРП, КА, УТ).

В чем сложность стандартного механизма?

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


Решение 1. Виртуальный журнал на базе регистра сведений (Стандарт 1С:БСП)

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

Разберем реализацию этого механизма по шагам:

  1. Создадим подчиненный или независимый Регистр сведений (назовем его, например, ЖурналОпределенныхДокументов). В качестве измерения укажем Документ (тип — ссылка на наш документ). В ресурсы или реквизиты вынесем поля, которые нужно отображать в списке (Дата, Номер, Контрагент, Сумма и т. д.).
  2. Создадим Подписку на событие ПриЗаписи (или ОбработкаПроведения) для нашего документа.
  3. В обработчике подписки пропишем алгоритм условной регистрации:

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

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

Преимущества: Высокая скорость работы. В базе данных хранятся и индексируются только те документы, которые удовлетворяют нашему условию. Мы можем выводить в такой виртуальный журнал любые дополнительные данные, которых изначально нет в шапках документов.


Решение 2. Разделение одного универсального документа на несколько специализированных

В ходе обсуждения на форуме в сообщении (20) прозвучала важная мысль: часто необходимость «вырезать» часть документов из общего списка говорит о методологической ошибке на этапе проектирования метаданных. Если у вас один документ выполняет слишком разные бизнес-роли (разные проводки, разные печатные формы, разные права доступа), правильнее разделить его на несколько отдельных документов конфигурации.

Чтобы такое разделение прошло безболезненно для разработчика и пользователей, задействуем следующие платформенные механизмы:

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


Решение 3. Настройка динамического списка формы с произвольным запросом

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

Рассмотрим, как правильно настроить отбор, чтобы форма не зависала на больших объемах данных:

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

Критически важный момент оптимизации: Избегайте жесткого прописывания фильтра в секции ГДЕ текста запроса динамического списка (например, ГДЕ Ссылка.ВидОперации = &НужныйВид). При таком подходе СУБД будет вынуждена сканировать таблицы, что приведет к сильным задержкам при росте базы данных. Вместо этого настроим отбор через систему компоновки данных (СКД) динамического списка:


// В модуле формы при создании на сервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Получаем элемент отбора динамического списка
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ВидОперации");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = Перечисления.ВидыОпераций.НужныйВид;
    ЭлементОтбора.Использование = Истина;
    ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

КонецПроцедуры

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


Решение 4. Использование механизма «Критерии отбора»

В случае, если выделяемая группа документов определяется не перечислением «Вид операции», а конкретным ссылочным реквизитом (например, документы по конкретному Проекту, Складу или Договору), идеальным решением будет использование стандартного объекта метаданных Критерии отбора.

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


Сравнительный анализ решений

Выберем наиболее подходящий вариант в зависимости от условий вашей задачи:

← На главную