В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда данные в базе данных изменены, но пользователь видит на экране старые значения. Особенно остро эта проблема проявляется при работе с управляемыми формами и ссылочными объектами, такими как серии номенклатуры. В данной статье мы разберем, почему не обновляются представления объектов, как принудительно обновить данные на клиенте и как модифицировать сложный механизм подбора товаров в типовых решениях уровня ERP и Комплексная автоматизация 2.
Рассмотрим стандартную ситуацию: в документе-приемнике программно изменяются реквизиты серии (например, дата производства). Несмотря на то что в справочнике СерииНоменклатуры данные успешно обновились и название серии сформировалось заново, в открытой форме документа пользователь продолжает видеть старое наименование. Почему так происходит? Выясним причину.
Дело в том, что платформа 1С для оптимизации трафика между клиентом и сервером кэширует так называемые представления ссылочных объектов. Когда форма отрисовывает поле, содержащее ссылку на серию, она не запрашивает данные с сервера каждый раз. Если ссылка (GUID) объекта не изменилась, клиентское приложение считает, что и текстовое представление осталось прежним. Нажатие клавиши F5 или перезапуск сессии принудительно очищают этот кэш, но нам необходимо добиться автоматического обновления программным путем.
Проанализируем наиболее эффективный способ решения проблемы — использование метода ОповеститьОбИзменении(). Этот метод предназначен именно для того, чтобы сообщить всем открытым формам о том, что данные конкретного объекта в базе данных были изменены.
Разберем по шагам, как это работает. Когда мы вызываем этот метод и передаем в него ссылку на измененную серию, платформа инвалидирует (сбрасывает) кэш представлений для этой ссылки во всех активных окнах пользователя. Посмотрим на пример кода, который должен быть выполнен после модификации объекта:
// На сервере выполняем изменение объекта
СерияОбъект = СтрокаДокумента.Серия.ПолучитьОбъект();
СерияОбъект.ДатаПроизводства = НоваяДата;
СерияОбъект.Записать();
// На клиенте (или через оповещение) вызываем обновление
ОповеститьОбИзменении(СерияОбъект.Ссылка);
Важно помнить, что ОповеститьОбИзменении() работает глобально для текущего клиентского сеанса. Это означает, что если серия отображается не только в документе, но и в списке справочника или в другом отчете, данные обновятся везде одновременно.
Иногда требуется обновить не только строковое представление ссылки, но и состояние элементов формы в целом (например, условное оформление или видимость колонок). В этом случае рассмотрим метод ОбновитьОтображениеДанных(). В отличие от предыдущего метода, он не сбрасывает кэш ссылок, а заставляет текущую форму перечитать данные из своих реквизитов и обновить экран.
Посмотрим на нюансы: если вы изменили реквизит объекта в базе данных напрямую (через запрос или другой сеанс), этот метод может не помочь, так как данные в реквизитах формы (объекте ДокументОбъект) останутся старыми. Его целесообразно использовать совместно с перечитыванием данных с сервера.
Теперь проанализируем более сложную задачу: добавление пользовательского поля в типовой механизм подбора товаров. В современных конфигурациях (УТ 11, КА 2, ERP) подбор реализован через сложную систему обработок и вспомогательных форм. Рассмотрим ситуацию, когда в расширении необходимо добавить поле КоличествоВсего (Дефицит) в форму запроса количества и серий и передать эти данные в специфическую табличную часть документа, минуя стандартную "Корзину".
Разберем архитектуру этого процесса. Стандартный путь данных выглядит так: Форма подбора -> Форма запроса количества -> Корзина (внутри формы подбора) -> Документ. Чтобы внедрить свою логику, нам нужно модифицировать несколько этапов.
Сначала добавим в форму ЗапросКоличестваИСерий наше новое поле ввода. Чтобы данные вернулись в основную форму подбора, необходимо перехватить процедуру завершения ввода. Рассмотрим пример изменения структуры возвращаемых параметров:
&После("ЗаполнитьПараметрыПодобранногоТовара")
Процедура Расш_ЗаполнитьПараметрыПодобранногоТовара(ПараметрыПодбора)
// Добавляем наше значение в структуру, которая вернется в форму подбора
ПараметрыПодбора.Вставить("КоличествоВсего", ЭтотОбъект.КоличествоВсего);
КонецПроцедуры
Далее выясним, как форма подбора реагирует на получение этих данных. В форме обработки ПодборТоваровВДокументыПродажи существует таблица, которая временно хранит товары. Нам нужно добавить в эту таблицу колонку КоличествоВсего через расширение. При получении оповещения от формы ввода количества данные будут записаны в эту временную таблицу.
Самый ответственный момент — перенос данных в документ (например, Заказ клиента). Когда пользователь нажимает "Перенести в документ", вызывается обработчик в модуле формы документа. Рассмотрим, как программно заполнить нашу кастомную табличную часть Спрос:
ОбработкаВыбора в форме документа. Обычно она вызывает экспортный метод переноса данных из обработки подбора.&После для процедуры переноса.Пример программного заполнения может выглядеть так:
&После("ПеренестиПодобранныеТоварыВДокумент")
Процедура Расш_ПеренестиПодобранныеТоварыВДокумент(МассивПодобранныхТоваров)
Для Каждого ТекущийТовар Из МассивПодобранныхТоваров Цикл
Если ТекущийТовар.Свойство("КоличествоВсего") Тогда
НоваяСтрока = Объект.Спрос.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущийТовар);
НоваяСтрока.Количество = ТекущийТовар.КоличествоВсего;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный момент: при работе с сериями всегда проверяйте настройки политики учета серий. Если в программе не включен учет по сериям для конкретного склада или вида номенклатуры, формы запроса серий могут просто не открываться, и ваша логика не сработает.
Подведем итог. Для решения проблем с обновлением отображения всегда начинайте с метода ОповеститьОбИзменении(), так как он наиболее "экологичен" для платформы и эффективно управляет кэшем. При кастомизации подбора используйте расширения для модификации структур данных (Структура, ТаблицаЗначений), передаваемых между формами. Это позволит сохранить поддержку типовой конфигурации и обеспечит корректную работу вашего функционала.