Почему не обновляется признак проведения документа по ссылке и как это исправить?

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

При разработке на управляемых формах 1С часто возникает ситуация, когда в табличной части одного документа выводится ссылка на другой документ и через точку отображаются его свойства — например, системный реквизит Проведен (путь к данным вида Объект.ТабличнаяЧасть.ДокументСсылка.Проведен). Если выполнить отмену проведения или перепроведение этого связанного документа программно из текущей формы, статус в таблице нередко остается прежним, даже после вызовов стандартных методов перечитывания.

Разберем причины такого поведения платформы «1С:Предприятие 8.3» и рассмотрим надежные способы принудительного обновления отображаемых данных.

Почему стандартные методы обновления не срабатывают

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

  1. Клиентский кэш данных «через точку»: для оптимизации сетевого трафика и снижения нагрузки на сервер платформа кэширует значения, полученные через разыменование ссылки на клиенте. Механизм рассчитан на отображение относительно постоянных реквизитов (код, артикул, наименование).
  2. Область действия методов перечитывания: вызовы ЭтотОбъект.Прочитать() или Элементы.ИмяТаблицы.Обновить() считывают заново только данные основного редактируемого объекта. Они не сбрасывают кэш значений связанных сторонних документов.
  3. Ограничения ОбновитьОтображениеДанных(): данный метод лишь инициирует перерисовку элементов интерфейса на основе уже имеющихся в памяти клиента данных и не выполняет повторный запрос к базе для обновления кэша ссылок.

Способ 1. Использование глобального метода ОповеститьОбИзменении

Наиболее простое и быстрое решение — уведомить клиентское приложение о том, что ссылочный объект был изменен. Метод ОповеститьОбИзменении() принудительно очищает клиентский кэш представлений и значений полей «через точку» для указанной ссылки.

Рассмотрим пример реализации команды отмены проведения подчиненного документа:


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

&НаСервереБезКонтекста
Процедура ОтменитьПроведениеНаСервере(СсылкаНаДокумент)
    
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    Если ДокументОбъект <> Неопределено Тогда
        ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
    КонецЕсли;
    
КонецПроцедуры

Важно: вызов ОповеститьОбИзменении() должен происходить именно в клиентском контексте после завершения транзакции записи на сервере.

Способ 2. Добавление вычисляемой колонки в таблицу формы

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

Разберем по шагам, как настроить этот вариант:

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

Посмотрим на пример кода серверного пересчета статусов строк:


&НаСервере
Процедура ЗаполнитьСтатусыПроведенияНаСервере()
    
    // Формируем массив ссылок из табличной части формы
    МассивСсылок = Новый Массив;
    Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧасть Цикл
        Если ЗначениеЗаполнено(СтрокаТЧ.ДокументСсылка) Тогда
            МассивСсылок.Добавить(СтрокаТЧ.ДокументСсылка);
        КонецЕсли;
    КонецЦикла;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Док.Ссылка КАК Ссылка,
        |	Док.Проведен КАК Проведен
        |ИЗ
        |	Документ.ВторойДокумент КАК Док
        |ГДЕ
        |	Док.Ссылка В(&МассивСсылок)";
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    
    ТаблицаСтатусов = Запрос.Выполнить().Выгрузить();
    ТаблицаСтатусов.Индексы.Добавить("Ссылка");
    
    Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧасть Цикл
        НайденнаяСтрока = ТаблицаСтатусов.Найти(СтрокаТЧ.ДокументСсылка, "Ссылка");
        Если НайденнаяСтрока <> Неопределено Тогда
            СтрокаТЧ.Проведен = НайденнаяСтрока.Проведен;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Способ 3. Механизм оповещений открытых форм

Если второй документ может открываться и редактироваться пользователем в отдельном окне параллельно с первым документом, используем связку событийного механизма:

  1. В модуле формы второго документа при записи отправляем оповещение:
    
    &НаКлиенте
    Процедура ПослеЗаписи(ПараметрыЗаписи)
        Оповестить("ИзмененДокумент2", Новый Структура("Ссылка, Проведен", Объект.Ссылка, Объект.Проведен));
    КонецПроцедуры
    
  2. В модуле формы первого документа описываем обработчик ОбработкаОповещения:
    
    &НаКлиенте
    Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
        
        Если ИмяСобытия = "ИзмененДокумент2" И ТипЗнч(Параметр) = Тип("Структура") Тогда
            Для Каждого СтрокаТЧ Из Объект.ТабличнаяЧасть Цикл
                Если СтрокаТЧ.ДокументСсылка = Параметр.Ссылка Тогда
                    СтрокаТЧ.Проведен = Параметр.Проведен;
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
        
    КонецПроцедуры
    

Такой подход обеспечивает синхронность интерфейса без лишних запросов к базе данных и исключает проблемы с кэшированием платформы.

← На главную