В типовых конфигурациях 1С:Предприятие 8 часто возникает ситуация, когда два и более пользователя одновременно открывают один и тот же документ, вносят в него изменения, но сохранить свои правки может только тот, кто нажал кнопку «Записать» первым. Второй пользователь при попытке сохранения получает досадную ошибку: «Данные были изменены или удалены другим пользователем». Рассмотрим, почему это происходит, и как настроить систему так, чтобы второй пользователь даже не мог начать редактирование, если документ уже занят коллегой.
Прежде чем переходить к программному коду, разберем теорию, так как без нее сложно понять логику работы платформы 1С. В системе существует два основных подхода к блокировке данных:
Проанализируем ситуацию: если в вашей конфигурации (например, УТП 1.2 или УПП) пользователи жалуются на потерю данных при одновременной работе, значит, нам нужно перевести конкретные объекты из оптимистического режима в пессимистический.
Если вы работаете в конфигурации на обычных формах, как автор темы, наиболее эффективным решением будет использование метода Заблокировать(). Рассмотрим пошагово, как это реализовать в модуле формы документа.
Нам необходимо перехватить момент открытия формы. Для этого используем обработчик события ПриОткрытии. Основная идея заключается в том, чтобы попытаться наложить блокировку на объект 1С. Если объект уже заблокирован кем-то другим, система вызовет исключение, которое мы обработаем, запретив редактирование второму пользователю.
Разберем пример кода:
Процедура ПриОткрытии()
// Попытаемся установить пессимистическую блокировку
Попытка
ЭтотОбъект.Заблокировать();
Исключение
// Если зайти не удалось, значит документ уже кем-то занят
Сообщить("Внимание! Документ редактируется другим пользователем.
|Вы сможете просматривать данные, но не сможете их изменить.");
// Переводим форму в режим только чтение
ЭтаФорма.ТолькоПросмотр = Истина;
КонецПопытки;
КонецПроцедуры
В данном примере, если первый пользователь уже открыл документ, у второго пользователя сработает блок Исключение. Свойство ТолькоПросмотр = Истина заблокирует все элементы управления на форме, предотвращая случайное редактирование.
Просто сообщить о том, что «документ занят», часто бывает недостаточно — пользователи начнут звонить друг другу и выяснять, кто забыл закрыть окно. Платформа 1С при возникновении ошибки блокировки передает информацию о сеансе, который удерживает объект. Проанализируем, как извлечь имя пользователя из системного сообщения:
Процедура ПриОткрытии()
Попытка
ЭтотОбъект.Заблокировать();
Исключение
// Получаем подробное описание ошибки
ТекстОшибки = ОписаниеОшибки();
// Выводим пользователю информативное сообщение
Сообщить("Документ заблокирован! " + ТекстОшибки);
ЭтаФорма.ТолькоПросмотр = Истина;
КонецПопытки;
КонецПроцедуры
В тексте ошибки обычно содержится имя пользователя, имя компьютера и время захвата объекта. Это значительно упрощает коммуникацию внутри отдела.
Если вы используете современную платформу и управляемые формы, механизм будет несколько иным. В управляемом приложении используется метод ЗаблокироватьДанныеДляРедактирования(). Основное отличие в том, что этот метод работает более гибко и предназначен для клиент-серверного взаимодействия.
Рассмотрим пример для управляемой формы:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Проверяем, не заблокирован ли объект уже в этом сеансе
Попытка
ЗаблокироватьДанныеДляРедактирования(ТекущийОбъект.Ссылка);
Исключение
// Если объект занят другим сеансом
ОбъектЗаблокирован = Истина;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ОбъектЗаблокирован Тогда
ЭтаФорма.ТолькоПросмотр = Истина;
ПоказатьПредупреждение(, "Документ редактируется другим пользователем!");
КонецЕсли;
КонецПроцедуры
Выясним причины, по которым пессимистическая блокировка не всегда является идеальным решением, и к чему нужно быть готовым:
Чтобы избежать ситуации «ушел на обед и всё заблокировал», мы рекомендуем накладывать блокировку не в момент ПриОткрытии, а в момент начала изменения данных. В обычных формах это можно реализовать через обработчик ПриИзменении для основных реквизитов или через подписки на события. Таким образом, если человек просто открыл документ «посмотреть», он не будет мешать другим коллегам вносить правки.
Использование метода ЭтотОбъект.Заблокировать() является надежным и проверенным способом гарантировать целостность данных в условиях совместной работы. Несмотря на то что 1С по умолчанию склоняется к оптимистическому подходу, для критически важных участков учета пессимистическая блокировка остается незаменимым инструментом разработчика.