Как реализовать отображение статуса ознакомления в динамическом списке 1С

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

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

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

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

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

Правильная структура запроса с использованием LEFT JOIN

Для решения задачи нам необходимо соединить основную таблицу документов с регистром сведений, в котором фиксируются факты ознакомления. Мы будем использовать ЛЕВОЕ СОЕДИНЕНИЕ, чтобы не потерять документы, по которым еще нет записей в регистре.

Проанализируем оптимальный текст запроса для динамического списка:


ВЫБРАТЬ
    ДокументКанц.Ссылка КАК Ссылка,
    ДокументКанц.Дата КАК Дата,
    ДокументКанц.Номер КАК Номер,
    ДокументКанц.СтатусСогласования КАК СтатусСогласования,
    ВЫБОР
        КОГДА РегистрОзнакомления.Документ ЕСТЬ NULL 
            ТОГДА "Не прочитано"
        ИНАЧЕ "Прочитано"
    КОНЕЦ КАК СтатусОзнакомления
ИЗ
    Документ.Канц_РКК КАК ДокументКанц
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Канц_ОзнакомлениеСДокументами КАК РегистрОзнакомления
        ПО ДокументКанц.Ссылка = РегистрОзнакомления.Документ
            И РегистрОзнакомления.ДолжностноеЛицо = &ТекущийПользователь

Разберем, что здесь происходит. Мы присоединяем регистр сведений по двум условиям: соответствие ссылки документа и соответствие пользователя. Если для конкретного документа и текущего пользователя записи в регистре нет, поле РегистрОзнакомления.Документ примет значение NULL. Именно это мы и проверяем в конструкции ВЫБОР.

Установка параметров в программном коде

Поскольку в условии соединения мы использовали параметр &ТекущийПользователь, его необходимо инициализировать при создании формы. Рассмотрим пример кода в модуле формы списка:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Устанавливаем текущего пользователя из параметров сеанса
    // Это значение будет подставлено в запрос динамического списка
    Список.Параметры.УстановитьЗначениеПараметра("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
    
КонецПроцедуры

Использование ПараметрыСеанса — самый надежный и быстрый способ получить текущего пользователя на стороне сервера без лишних вызовов.

Борьба с дублированием строк

В процессе обсуждения на форуме возникла проблема: «Обнаружено дублирование ключевых значений в колонках Ссылка». Выясним причину этой ошибки. Она возникает, если ЛЕВОЕ СОЕДИНЕНИЕ находит более одной подходящей записи в присоединяемой таблице.

Если в вашем регистре сведений на один документ и одного пользователя может быть записано несколько строк (например, с разными датами ознакомления), то запрос «размножит» строки документа в списке. Чтобы этого избежать, проанализируем структуру регистра. Если в регистре измерениями являются только Документ и Пользователь, дублей не будет. Если же есть другие измерения (например, Дата), необходимо предварительно сгруппировать записи регистра или использовать вложенный запрос с выбором максимальной даты. Однако самый производительный способ — перенести условие по пользователю именно в секцию ПО (как показано в примере выше), что позволит SQL-серверу эффективно использовать индексы.

Улучшение интерфейса: Условное оформление

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

  1. Перейдем в свойства динамического списка Список на форме.
  2. Откроем настройки «Условного оформления».
  3. Добавим новое правило:
    • Оформление: Шрифт — Жирный.
    • Условие: СтатусОзнакомления Равно "Не прочитано".
    • Оформляемые поля: Выбираем нужные колонки или всю строку.

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

Динамическое обновление данных

Представим ситуацию: пользователь открыл документ из списка, ознакомился с ним и закрыл форму. Статус в списке должен мгновенно измениться на «Прочитано». Чтобы это произошло автоматически, проанализируем работу метода ОповеститьОбИзменении().

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


// В форме документа
ОповеститьОбИзменении(Тип("Документ.Канц_РКК"));
// Или оповестить конкретную форму, если используется механизм оповещений
Оповестить("ДокументПрочитан", Ссылка);

Динамический список «услышит» это оповещение и инициирует обновление текущей строки, пересчитав значение в поле СтатусОзнакомления на лету.

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

Для того чтобы список работал быстро даже при миллионах записей, проанализируем следующие моменты:

1. Индексация регистра. Убедитесь, что в регистре сведений Канц_ОзнакомлениеСДокументами измерения Документ и ДолжностноеЛицо проиндексированы. Это критически важно для скорости выполнения LEFT JOIN. 2. Основная таблица. Всегда указывайте свойство Основная таблица в настройках динамического списка. Это позволит платформе использовать стандартные механизмы выборки данных и корректно работать с правами доступа (RLS). 3. Минимум вложенных запросов. Старайтесь избегать конструкций ГДЕ Ссылка В (ВЫБРАТЬ...). Плоские соединения через ЛЕВОЕ СОЕДИНЕНИЕ оптимизируются СУБД гораздо лучше.

Следуя этим правилам, мы получим быстрый, удобный и надежный инструмент для работы пользователей с документами компании.

← На главную