В процессе автоматизации торговых операций часто возникает задача разграничения прав не только на уровне целых документов или справочников, но и на уровне конкретных реквизитов табличных частей. Одной из таких задач является запрет выбора упаковок (единиц измерения с коэффициентом, отличным от единицы) для определенных категорий сотрудников. Например, это может быть актуально для поваров или рядовых сотрудников склада, которые должны работать только с базовыми единицами измерения («штуки», «кг»), чтобы избежать ошибок при вводе данных. Рассмотрим подробнее, как реализовать этот механизм в современных конфигурациях на платформе 1С:Предприятие 8.3.
Проанализируем наиболее гибкий и современный способ — внесение изменений через расширение конфигурации. Этот метод позволяет не снимать основную конфигурацию с поддержки. Нам необходимо перехватить момент выбора упаковки на форме документа (например, ПриобретениеТоваровУслуг или РеализацияТоваровУслуг).
Разберем логику реализации. Нам потребуется расширить форму документа и создать обработчик события ПриИзменении для колонки Упаковка. В этом обработчике мы будем проверять текущего пользователя. Выясним причину ошибки: если пользователь входит в список «ограниченных», а выбранная упаковка не является базовой, мы должны вернуть значение в исходное состояние или очистить его.
Пример кода для модуля формы в расширении:
&НаКлиенте
Процедура Расш1_ТоварыУпаковкаПриИзмененииПосле(Элемент)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем права пользователя на сервере
Если ПроверитьЗапретИспользованияУпаковок() Тогда
Если ЗначениеЗаполнено(ТекущиеДанные.Упаковка) Тогда
// Если упаковка выбрана, проверяем её коэффициент через серверный вызов
Если ПолучитьКоэффициентУпаковки(ТекущиеДанные.Упаковка) <> 1 Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Вам запрещено выбирать упаковки с коэффициентом отличным от 1!");
ТекущиеДанные.Упаковка = Справочники.УпаковкиЕдиницыИзмерения.ПустаяСсылка();
// При необходимости вызываем штатный пересчет документа
РассчитатьСуммуТабличнойЧасти(ТекущиеДанные);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Посмотрим на ситуацию со стороны прав доступа. Если мы хотим, чтобы пользователи в принципе не видели список доступных упаковок, можно применить механизм RLS (Row Level Security). В этом случае ограничение накладывается непосредственно на справочник Упаковки (или НаборыУпаковок в зависимости от конфигурации).
Для реализации этого метода выполним следующие шаги:
Важный момент: использование RLS может существенно снизить производительность системы, если запросы к базе данных станут слишком сложными. Однако для справочника упаковок, который обычно невелик, это допустимое решение. Главный плюс — пользователю даже не будет предложен выбор в выпадающем списке.
Рассмотрим вариант, при котором мы не хотим менять логику проведения или записи, а хотим лишь визуально ограничить доступ к полю на форме. Это можно сделать через УсловноеОформление или просто программно управляя свойством ТолькоПросмотр.
В процедуре ПриСозданииНаСервере проанализируем текущего пользователя и, если он попадает под критерии запрета, заблокируем колонку:
&НаСервере
Процедура БлокировкаКолонкиУпаковок()
// Проверка принадлежности к роли или списку пользователей
Если ПользователиИнформационнойБазы.ТекущийПользователь().Имя = "ШефПовар" Тогда
ЭлементФормы = Элементы.ТоварыУпаковка;
ЭлементФормы.ТолькоПросмотр = Истина;
// Также можно скрыть колонку вовсе
// ЭлементФормы.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Этот метод считается «мягким», так как он не защищает от записи данных, загруженных, например, через внешние обработки или механизмы обмена, но эффективно работает для обычного интерфейсного ввода.
Чтобы гарантировать 100% соблюдение регламента, независимо от того, как данные попали в документ, необходимо реализовать проверку на уровне объекта. Для этого лучше всего использовать Подписку на событие ПередЗаписью для необходимых типов документов.
Разберем алгоритм работы такой подписки:
Товары.Пример реализации в модуле подписки:
Процедура ПроверитьУпаковкиПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Отказ Или Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Определяем, нужно ли проверять этого пользователя
Если НужноКонтролироватьПользователя(ПараметрыСеанса.ТекущийПользователь) Тогда
Для Каждого СтрокаТЧ Из Источник.Товары Цикл
Если ЗначениеЗаполнено(СтрокаТЧ.Упаковка) Тогда
// Проверяем коэффициент через реквизиты упаковки
Коэффициент = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СтрокаТЧ.Упаковка, "Коэффициент");
Если Коэффициент <> 1 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Строка №" + СтрокаТЧ.НомерСтроки + ": Использование упаковок запрещено!";
Сообщение.Поле = "Товары[" + (СтрокаТЧ.НомерСтроки - 1) + "].Упаковка";
Сообщение.УстановитьДанные(Источник);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Выясним, можно ли решить задачу без программирования. В платформе 1С предусмотрена возможность настройки видимости элементов для конкретных ролей. Если в конфигурации создана специальная роль для этих двух пользователей (например, Роль_БезПраваУпаковок), администратор может зайти в настройки формы документа и в разделе «Права» снять видимость с колонки Упаковка для этой роли.
Однако стоит учитывать, что если у пользователя есть право СохранениеДанныхФорм, он может попытаться вернуть колонку через меню «Изменить форму». Поэтому данный способ рекомендуется сочетать с программным запретом на уровне записи объекта (Метод 4).
Для надежного решения задачи рекомендуется комбинировать подходы: визуально скрывать поле через условное оформление или настройки формы для удобства пользователя и дублировать проверку в подписке на событие ПередЗаписью для обеспечения целостности данных. Использование расширений позволит сохранить чистоту типовой конфигурации и обеспечит легкое обновление системы в будущем.