После обновления платформы 1С:Предприятие до версии 8.3.24 многие администраторы и разработчики, особенно сопровождающие конфигурации на обычных формах (например, УПП 1.3), столкнулись с неприятным изменением в поведении системы. Раньше, если документ был открыт другим сотрудником, при попытке доступа выдавалось сообщение, четко указывающее, кто именно заблокировал объект. Теперь же пользователи видят обезличенное сообщение: "Не удалось заблокировать запись. Действие (изменение, удаление или блокировка записи) не выполнено". В этой статье мы подробно разберем, почему это произошло, проанализируем причины нового поведения платформы и, самое главное, рассмотрим программные и административные способы решения этой проблемы, чтобы вернуть удобство работы пользователям.
Давайте разберем ситуацию. Пользователь пытается открыть документ для редактирования, но он уже открыт у коллеги. Вместо привычного "Заблокировано пользователем Иванов И.И.", система выдает сухой технический отказ без указания виновника. Причина кроется в ужесточении политик безопасности в платформе **8.3.24** (и в некоторых последних сборках 8.3.23). Разработчики платформы реализовали принцип "Security by default" (безопасность по умолчанию). Логика такова:
Таким образом, это не баг, а "фича" новой платформы. Однако для реальной работы в офисе, где нужно позвонить коллеге и попросить закрыть накладную, это создает огромные неудобства.
Если вы не хотите или не можете вносить изменения в код конфигурации, у нас остается штатный механизм поиска виновника блокировки — **Журнал регистрации**. Разберем алгоритм действий системного администратора или пользователя с соответствующими правами:
Также, если база работает в клиент-серверном варианте, администратор может использовать **Консоль администрирования серверов 1С**. В ветке "Блокировки" можно увидеть текущие наложенные блокировки на таблицы базы данных. Это работает быстрее, чем поиск по журналу, но требует доступа к серверу приложений. Минусы метода: Это долго и требует привлечения администратора каждый раз, когда возникает коллизия. Обычному бухгалтеру этот метод недоступен.
Наиболее эффективный способ вернуть пользователям комфорт — перехватить ошибку программно непосредственно в момент открытия формы. Стандартный механизм платформы выдает системное окно ошибки, которое мы не можем контролировать. Однако мы можем попытаться заблокировать объект самостоятельно в коде, и если это не удастся — вывести свое, понятное сообщение.
Рассмотрим пример кода, который необходимо разместить в модуле формы документа. Для обычных форм (УПП, УТ 10.3) используется событие ПриОткрытии.
Заблокировать() для текущего объекта.Попытка ... Исключение.
Процедура ПриОткрытии()
// Получаем доступ к объекту документа
ДокументОбъект = ЭтаФорма.ДокументОбъект;
Попытка
// Пытаемся явно заблокировать объект
ДокументОбъект.Заблокировать();
Исключение
// Если попали сюда, значит объект занят
// Получаем информацию об ошибке
ИнформацияОбОшибке = ИнформацияОбОшибке();
// Формируем текст сообщения.
// Важно: в зависимости от прав и режима совместимости,
// стандартное описание может быть полным или урезанным.
ТекстОшибки = ОписаниеОшибки();
// Более детальный вариант получения причины:
Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
ТекстПричины = КраткоеПредставлениеОшибки(ИнформацияОбОшибке.Причина);
Иначе
ТекстПричины = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
КонецЕсли;
// Выводим сообщение пользователю
Предупреждение("Документ занят! " + Символы.ПС + ТекстПричины);
// Блокируем форму от изменений, раз уж редактировать нельзя
ЭтаФорма.ТолькоПросмотр = Истина;
КонецПопытки;
КонецПроцедуры
Обратите внимание на метод КраткоеПредставлениеОшибки. Он позволяет получить более читаемый текст, чем полный стек вызовов.
Важный нюанс: если у пользователя урезаны права, то даже функция ОписаниеОшибки() внутри клиентского кода может вернуть текст без имени пользователя (платформа фильтрует текст ошибки на лету).
Чтобы гарантированно получить имя пользователя, который заблокировал объект, нам нужно выполнить проверку блокировки "глазами администратора", то есть в **Привилегированном режиме**.
Для этого нам потребуется создать общий модуль (или использовать существующий) с установленными галочками "Сервер" и "Привилегированный". Назовем его, например, УправлениеБлокировкамиПривилегированный.
В привилегированном модуле создаем функцию, которая пытается заблокировать объект по ссылке и возвращает текст ошибки, если блокировка не удалась. Поскольку модуль привилегированный, платформа не будет скрывать имя пользователя.
// Функция в общем модуле с признаком "Привилегированный"
Функция ПопытатьсяЗаблокироватьОбъект(СсылкаНаОбъект) Экспорт
Результат = Новый Структура("Заблокировано, ТекстОшибки", Истина, "");
// Получаем объект по ссылке для попытки блокировки
// Важно: это создает лишнее чтение из БД, используйте с умом
Попытка
Объект = СсылкаНаОбъект.ПолучитьОбъект();
Объект.Заблокировать();
Исключение
Результат.Заблокировано = Ложь;
// Здесь мы получим полный текст ошибки с именем пользователя,
// так как код выполняется под полными правами
Результат.ТекстОшибки = ОписаниеОшибки();
КонецПопытки;
Возврат Результат;
КонецФункции
Теперь модифицируем код в форме документа (из Решения №2), чтобы обращаться к нашему привилегированному модулю.
Процедура ПриОткрытии()
// Если это новый документ, блокировать нечего
Если ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Вызываем серверную функцию (для управляемых форм нужен вызов сервера,
// для обычных форм УПП это сработает напрямую, если модуль доступен)
ПроверкаБлокировки = УправлениеБлокировкамиПривилегированный.ПопытатьсяЗаблокироватьОбъект(Ссылка);
Если НЕ ПроверкаБлокировки.Заблокировано Тогда
// Парсим полученный текст, чтобы оставить только самое важное
// Или выводим как есть
Сообщить("ВНИМАНИЕ! Документ редактируется другим пользователем.");
Предупреждение(ПроверкаБлокировки.ТекстОшибки);
ЭтаФорма.ТолькоПросмотр = Истина;
КонецЕсли;
КонецПроцедуры
При внедрении данного решения следует учитывать несколько моментов:
ПриОткрытии, можно добавить на форму кнопку "Проверить блокировку". Код будет аналогичным, но выполняться только по требованию пользователя, когда он не понимает, почему не может сохранить изменения.Используя подход с привилегированным модулем, вы сможете обойти ограничения безопасности платформы 8.3.24 и вернуть пользователям информативные сообщения о том, кто именно занял документ, не нарушая общую безопасность системы (так как полные права пользователю мы не выдаем).