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

Программист
← На главную

В типовых конфигурациях 1С:Предприятие 8 часто возникает ситуация, когда два и более пользователя одновременно открывают один и тот же документ, вносят в него изменения, но сохранить свои правки может только тот, кто нажал кнопку «Записать» первым. Второй пользователь при попытке сохранения получает досадную ошибку: «Данные были изменены или удалены другим пользователем». Рассмотрим, почему это происходит, и как настроить систему так, чтобы второй пользователь даже не мог начать редактирование, если документ уже занят коллегой.

Понимание механизмов блокировки: Оптимистическая vs Пессимистическая

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

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

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

Реализация блокировки в Обычных формах

Если вы работаете в конфигурации на обычных формах, как автор темы, наиболее эффективным решением будет использование метода Заблокировать(). Рассмотрим пошагово, как это реализовать в модуле формы документа.

Нам необходимо перехватить момент открытия формы. Для этого используем обработчик события ПриОткрытии. Основная идея заключается в том, чтобы попытаться наложить блокировку на объект 1С. Если объект уже заблокирован кем-то другим, система вызовет исключение, которое мы обработаем, запретив редактирование второму пользователю.

Разберем пример кода:


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

В данном примере, если первый пользователь уже открыл документ, у второго пользователя сработает блок Исключение. Свойство ТолькоПросмотр = Истина заблокирует все элементы управления на форме, предотвращая случайное редактирование.

Как узнать, кто именно занял документ?

Просто сообщить о том, что «документ занят», часто бывает недостаточно — пользователи начнут звонить друг другу и выяснять, кто забыл закрыть окно. Платформа 1С при возникновении ошибки блокировки передает информацию о сеансе, который удерживает объект. Проанализируем, как извлечь имя пользователя из системного сообщения:


Процедура ПриОткрытии()
    Попытка
        ЭтотОбъект.Заблокировать();
    Исключение
        // Получаем подробное описание ошибки
        ТекстОшибки = ОписаниеОшибки();
        
        // Выводим пользователю информативное сообщение
        Сообщить("Документ заблокирован! " + ТекстОшибки);
        ЭтаФорма.ТолькоПросмотр = Истина;
    КонецПопытки;
КонецПроцедуры

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

Особенности для Управляемых форм (8.3)

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

Рассмотрим пример для управляемой формы:


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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если ОбъектЗаблокирован Тогда
        ЭтаФорма.ТолькоПросмотр = Истина;
        ПоказатьПредупреждение(, "Документ редактируется другим пользователем!");
    КонецЕсли;
КонецПроцедуры

Важные нюансы и риски

Выясним причины, по которым пессимистическая блокировка не всегда является идеальным решением, и к чему нужно быть готовым:

  1. Зависшие сеансы: Если у пользователя аварийно завершится работа 1С (выключили свет, пропал интернет), блокировка может «повиснуть» на сервере. В этом случае документ будет недоступен для редактирования всем, пока администратор не сбросит зависший сеанс в консоли кластера.
  2. Человеческий фактор: Пользователь может открыть важный документ, отвлечься на телефонный звонок или уйти на обед, оставив форму открытой. В это время весь отдел будет ждать, пока он вернется, так как документ будет заблокирован.
  3. Производительность: В системах с очень большим количеством активных пользователей (сотни человек) постоянные блокировки в базе данных могут создавать дополнительную нагрузку на СУБД.

Рекомендация по улучшению

Чтобы избежать ситуации «ушел на обед и всё заблокировал», мы рекомендуем накладывать блокировку не в момент ПриОткрытии, а в момент начала изменения данных. В обычных формах это можно реализовать через обработчик ПриИзменении для основных реквизитов или через подписки на события. Таким образом, если человек просто открыл документ «посмотреть», он не будет мешать другим коллегам вносить правки.

Использование метода ЭтотОбъект.Заблокировать() является надежным и проверенным способом гарантировать целостность данных в условиях совместной работы. Несмотря на то что 1С по умолчанию склоняется к оптимистическому подходу, для критически важных участков учета пессимистическая блокировка остается незаменимым инструментом разработчика.

← На главную