Как в управляемой форме 1С узнать, что документ был изменен на сервере?

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

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

Разберем детально, как на стороне клиента вовремя выявить факт изменения объекта на сервере, какие механизмы платформы позволяют избежать конфликта версий и как архитектурно правильно выстроить совместную работу пользователей и фоновых заданий.

Способ 1. Сравнение свойства ВерсияДанных на клиенте и сервере

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

Рассмотрим, как выполнить программную проверку версий перед выполнением клиентских действий или перед интерактивной записью документа:


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

&НаКлиенте
Процедура ПроверитьИзменениеДокумента()
    Если Объект.Ссылка.Пустая() Тогда
        Возврат;
    КонецЕсли;
    
    ВерсияСервера = ПолучитьАктуальнуюВерсиюОбъекта(Объект.Ссылка);
    ВерсияКлиента = Объект.ВерсияДанных;
    
    Если ВерсияСервера <> Неопределено И ВерсияСервера <> ВерсияКлиента Тогда
        ПоказатьПредупреждение(, "Документ был изменен другим процессом на сервере. Обновите данные!");
    КонецЕсли;
КонецПроцедуры

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

Способ 2. Использование штатных методов формы ПроверитьВерсиюДанных() и Прочитать()

Платформа 1С:Предприятие 8.3 предоставляет встроенные методы управляемой формы для работы с версиями данных без необходимости писать собственные серверные функции.

  1. Метод формы ПроверитьВерсиюДанных() выполняет сверку текущей версии данных основного реквизита формы с версией объекта в базе данных и возвращает значение Истина, если версии совпадают, или Ложь, если объект в базе данных уже изменился.
  2. Метод формы Прочитать() позволяет программно перечитать данные из базы в форму, обновляя отображаемые реквизиты и табличные части без интерактивного нажатия стандартной кнопки «Перечитать».

Посмотрим на пример их совместного применения:


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

Способ 3. Защита от конфликтов через пессимистическую блокировку данных

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


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

Если при открытии формы документа на клиенте используется стандартный режим автоблокировки (свойство формы БлокировкаДанныхДляРедактирования установлено в Авто), платформа накладывает пессимистическую блокировку. Фоновое задание не сможет перехватить документ во время активной работы пользователя.

Способ 4. Организация оповещения клиента об изменениях

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

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

Архитектурные рекомендации по разделению данных

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

← На главную