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