Привет!
Имеет место быть следующая ситуация.Ваня уходит в отпуск (на больничный, в командировку едет и т.п.) и на время отсутствия Вани его обязанности выполняет Петя. Но так получается, что у Вани доступ в 1С шире, чем у Пети, т.е. если говорить более предметно - то ролей у него в 1С больше, чем у Пети. Но на время его отсутствия Пете нужно дать те роли, которые стоят у Вани.
Что имеем "из коробки"?Назначаем Пете роли, где-то записываем себе (или запоминаем) когда их у него требуется отобрать. Но часто про это забывается и в контексте 1С Петя становится Ваней. Непорядок.
Что надо?Было бы хорошо, если бы была возможность назначать роли по расписанию: кому когда дать, когда забрать.
Как сделать?Добавляем в систему перечисление ДействияИзмененияРолей со значениями Добавить, Убрать.
Добавляем в систему периодический (мне было достаточно в пределах дня) регистр сведений РасписаниеИзмененияРолейПользователей:
- измерения: ИмяПользователя (строка), Роль (строка)
- ресурсы: Действие (ПеречислениеСсылка.ДействияИзмененияРолей), Выполнено (булево)
Добавляем регламентное задание, которое выполняет следующий код:
Процедура ИзменениеРолейПользователей() Экспорт
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());
Запрос.Текст =
"ВЫБРАТЬ
| РасписаниеИзмененияРолейПользователейСрезПоследних.Период,
| РасписаниеИзмененияРолейПользователейСрезПоследних.ИмяПользователя КАК ИмяПользователя,
| РасписаниеИзмененияРолейПользователейСрезПоследних.Роль,
| РасписаниеИзмененияРолейПользователейСрезПоследних.Действие
|ИЗ
| РегистрСведений.РасписаниеИзмененияРолейПользователей.СрезПоследних(&ТекущаяДата, ) КАК РасписаниеИзмененияРолейПользователейСрезПоследних
|ГДЕ
| НЕ РасписаниеИзмененияРолейПользователейСрезПоследних.Выполнено
|ИТОГИ ПО
| ИмяПользователя";
Выборка0 = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока Выборка0.Следующий() Цикл
ПользовательИБ = Неопределено;
Попытка
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(СокрЛП(Выборка0.ИмяПользователя));
Исключение
Прервать;
КонецПопытки;
Если ПользовательИБ = Неопределено Тогда
Возврат;
КонецЕсли;
РолиПользователя = ПользовательИБ.Роли;
Выборка1 = Выборка0.Выбрать();
Пока Выборка1.Следующий() Цикл
Роль = Метаданные.Роли.Найти(Выборка1.Роль);
Если Роль = Неопределено Тогда
Возврат;
КонецЕсли;
Если Выборка1.Действие = Перечисления.ДействияИзмененияРолей.Добавить Тогда
Если НЕ РолиПользователя.Содержит(Роль) Тогда
РолиПользователя.Добавить(Роль);
КонецЕсли;
ИначеЕсли Выборка1.Действие = Перечисления.ДействияИзмененияРолей.Убрать Тогда
Если РолиПользователя.Содержит(Роль) Тогда
РолиПользователя.Удалить(Роль);
КонецЕсли;
КонецЕсли;
Запись = РегистрыСведений.РасписаниеИзмененияРолейПользователей.СоздатьМенеджерЗаписи();
Запись.Период = Выборка1.Период;
Запись.ИмяПользователя = Выборка1.ИмяПользователя;
Запись.Роль = Выборка1.Роль;
Запись.Прочитать();
Запись.Выполнено = Истина;
Запись.Записать(Истина);
КонецЦикла;
ПользовательИБ.Записать();
КонецЦикла;
КонецПроцедуры
Готово. На всякий случай суть этого всего в двух словах: в регистр добавляем запись, которая определяет когда, кому, какую роль добавить или убрать; а регламентное задание уже непосредственно выполняет эту работу.
Этим можно было бы ограничиться. Но мы же делаем всё для людей, верно? Поэтому для удобства работы добавляем в наш регистр форму записи. В моем случае это управляемая форма, но в обычной суть такая же.
Добавляем на форму новый реквизит типа СправочникСсылка.Пользователи. Делаем это для того, чтобы пользователь нашей системы мог выбрать нужного пользователя из списка, а не вбивать его имя руками. Но т.к. в регистре у нас пользователь имеет тип Строка, то выполняем следующее:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
ТекущийОбъект.ИмяПользователя = Пользователь.Код;
КонецПроцедуры
Наводим красоту дальше. В поле Роль назначаем обработчик события НачалоВыбора:
&НаКлиенте
Процедура РольНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ДанныеВыбора = ПолучитьСписокРолей();
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСписокРолей()
СписокРолей = Новый СписокЗначений;
Для Каждого Роль ИЗ Метаданные.Роли Цикл
СписокРолей.Добавить(Роль.Имя, Роль.Синоним);
КонецЦикла;
Возврат СписокРолей;
КонецФункции
Таким образом роль мы теперь тоже выбираем из списка, а не заносим руками.
И последний штрих. Т.к. у нас на форме поле Пользователь - это ссылка на справочник, а в регистре хранится в виде строки - то нам надо при открытии существующей записи конвертировать эту строку в нужный элемент справочника:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
Пользователь = Справочники.Пользователи.НайтиПоКоду(Запись.ИмяПользователя);
КонецПроцедуры
Всё что выше было написано - должно работать на любой типовой конфигурации. На любой не типовой будет работать если там есть справочник Пользователи и процесс авторизации и работа с этим справочником происходит как в типовой. Но даже если это не так - то не составит труда адаптировать вышенаписанное под свой конкретный случай.
Спасибо за внимание.