Во-первых, можно определить несколько стратегий запрета редактирования с разными параметрами. Например, запрет в днях, запрет доступа в предыдущие месяцы кварталы и т.п., с указанием отступа от текущей даты.
То есть для некоторых пользователей (рядовых менеджеров) при входе в базе будет устанавливаться запрет по вчерашний день, для других (старших менеджеров) на 5 дней назад, для третьих (администраторов базы или руководителей отдела) — запрет предыдущего месяца с отступом в 10 дней..
Во-вторых, запрет будет устанавливаться для ВСЕХ без исключения пользователей базы данных. Для самых привилегированных это будет максимальная глубина, но запрет будет установлен.
Управление этой системой осуществляется через механизм дополнительных прав пользователей.
При необходимости пользователь с полными правами может открыть для себя закрытый период, но только на текущий сеанс работы.
Многовариантный автоматический запрет редактирования
(для конфигурации УТ 10.3)
В этой статье описывается усовершенствованная технология автоматической установки даты запрета редактирования
Во-первых, можно определить несколько стратегий запрета редактирования с разными параметрами. Например, запрет в днях, запрет доступа в предыдущие месяцы кварталы и т.п., с указанием отступа от текущей даты.
То есть для некоторых пользователей (рядовых менеджеров) при входе в базе будет устанавливаться запрет по вчерашний день, для других (старших менеджеров) на 5 дней назад, для третьих (администраторов базы или руководителей отдела) — запрет предыдущего месяца с отступом в 10 дней..
Во-вторых, запрет будет устанавливаться для ВСЕХ без исключения пользователей базы данных. Для самых привилегированных это будет максимальная глубина, но запрет будет установлен.
Вообще идея автоматического продвижения даты запрета редактирования для всех пользователей кажется мне очень удачной. Мне представляется, что все экономические программы, в том числе все конфигурации на 1С, должны автоматически передвигать дату запрета редактирования с течением времени.
Сейчас мы имеем ситуацию, когда администратор базы должен периодически предпринимать некоторые действия, чтобы передвинуть вперед дату запрета редактирования, например, после составления отчетности за очередной месяц. Но администратор может забыть, заболеть, уволиться, наконец. А новый администратор не сразу вообще поймет важность этого действия по установке даты запрета. А в результате имеем многие проблемы с данными в реальных базах.
А должно быть так, чтобы программа сама, без всяких действий со стороны пользователя, передвигала с течением времени дату запрета для всех пользователей, кому ежедневно, кому ежемесячно (ежеквартально, ежегодно). А уж если надо залезть в закрытый период, то это должны делать только уполномоченные опытные пользователи, которые для этого смогут отодвинуть дату запрета только для себя и только на текущий сеанс работы. А после нового входа в базу дата запрета должна опять установиться автоматически.
В популярной конфигурации «1С:Управление торговлей 10.3» есть механизм установки запрета редактирования по пользователям базы данных.
Я сделал для нее небольшую доработку, в результате которой для некоторых пользователей при входе пользователя в базу автоматически устанавливался запрет редактирования документов до предыдущего дня включительно. Статья на Инфостарте: //infostart.ru/public/80499/.
Но практический опыт показал, что этого мало. Некоторым пользователям закрывать предыдущий день не надо, значит для них база остается открытой. По хорошему должен быть администратор базы, который выполняет регламентные операции, в том числе должен и устанавливать запрет редактирования для всех пользователей. Например, после закрытия месяца надо передвинуть дату запрета на месяц вперед. На практике такой администратор об этом, конечно, знает, но часто не делает: всегда найдется много причин, по которым надо отложить эту передвижку даты запрета, а потом про это и вовсе забывают. База остается открытой для изменения (не всеми пользователями, но все же), что приводит к нехорошим последствиям, например при наличии обменов информацией с другими базами. По хорошему запрет редактирования должен быть установлен для ВСЕХ пользователей. Ну а иногда администратора такого и вовсе нет.
В этой статье описывается усовершенствованная технология автоматической установки даты запрета редактирования
Во-первых, можно определить несколько видов закрываемого периода: день, месяц, квартал и т.п. Думаю, что достаточно дня и месяца, желающие могут доработать для квартала, года и т.д.
Во-вторых, можно определить несколько величин отступа от текущей даты в днях для закрытия предыдущего периода: например, 0 и 10 дней. То есть для некоторых пользователей предыдущий период будет закрываться прямо сегодня, для других — через 10 дней. Если закрываемый период день, то при отступе 0 дней при входе в базу будет закрыт период по предыдущий день включительно, а при отступе 10 дней — по дату на 10 дней меньше текущей. Если закрываемый период месяц, то в первом случае предыдущий месяц закроется первого числа очередного месяца, а во втором случае — 10-го числа
В-третьих, запрет будет устанавливаться ДЛЯ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ базы данных. Для самых привилегированных это будет максимальная глубина из всех предусмотренных, но запрет будет установлен.
Управление этой системой осуществляется через механизм дополнительных прав пользователей.
Итак.
Задача.
Требуется доработать конфигурацию таким образом, чтобы при входе любого пользователя в систему для него автоматически закрывался для редактирования некоторый период согласно сделанным в базе настройкам. Эти настройки должны задаваться с помощью механизма дополнительных прав пользователей. При этом уполномоченные пользователи должны иметь возможность открыть для редактирования любой период при необходимости.
Решение.
1. Вводим дополнительные права пользователя.
Все новые дополнительные права должны иметь вид «Автоматически НЕ закрывать предыдущий : N», где N — величина отступа от текущей даты в днях, положительное число, а может принимать значения «день» и «месяц» (желающие могут добавить еще и «квартал» и «год»).
Например, введем три дополнительных права:
Автоматически НЕ закрывать предыдущий день: 0
Автоматически НЕ закрывать предыдущий день: 5
Автоматически НЕ закрывать предыдущий месяц: 0
Автоматически НЕ закрывать предыдущий месяц: 10
Названия всех прав должны начинаться с текста «Автоматически НЕ закрывать предыдущий :», за которым должно следовать число дней (больше 0).
Работать с дополнительными правами пользователей могут только пользователи с полными правами.
Для этого:
В режиме Предприятие открываем меню «Операции / Планы видов характеристик / Права пользователей»
Добавляем новое право: «Автоматически НЕ закрывать предыдущий день: 0», тип значения – Булево (составной тип отменяется). Во избежание возможных эксцессов при последующих обновлениях код нового элемента лучше установить в «1000», например. Разработчики конфигурации при пополнении списка новыми предопределенными характеристиками вряд ли дойдут до такого кода.
Копируем это право и переименовываем в «Автоматически НЕ закрывать предыдущий период: 5». Копируем еще раз и переименовываем в «Автоматически НЕ закрывать предыдущий месяц: 0». И еще раз копируем и переименовываем в «Автоматически НЕ закрывать предыдущий месяц: 10»
Теперь в меню «Сервис / Пользователи / Настройка дополнительных прав пользователей» появились новые флажки, которые можно устанавливать пользователям.
Установка флажка отменяет закрытие соответствующего периода, значит для нового пользователя будет закрываться максимально возможный период — по вчерашний день включительно.
2. Дорабатываем конфигурацию
Добавляем новый ПРИВИЛЕГИРОВАННЫЙ общий модуль. Назовем его, например, «АЦРК_Привилегированный». В свойствах модуля должны быть установлены галочки «Привилегированный», «Вызов сервера» и «Сервер».
В этом модуле должны быть следующая процедура:
Процедура ЗакрытиеПредыдущегоПериода() Экспорт
л_ПрефиксДополнительногоПрава1 = «Автоматически НЕ закрывать предыдущий день:»;
л_ПрефиксДополнительногоПрава2 = «Автоматически НЕ закрывать предыдущий месяц:»;
л_ТекущийПользователь = УправлениеПользователями.ОпределитьТекущегоПользователя();
Запрос = Новый Запрос;
Запрос.Текст = «ВЫБРАТЬ
| ПраваПользователей.Ссылка КАК ДополнительноеПраво,
| ПраваПользователей.Наименование КАК НаименованиеДополнительногоПрава,
| ЕСТЬNULL(ЗначенияДополнительныхПравПользователя.Значение, ЛОЖЬ) КАК ЗначениеДополнительногоПрава
|ИЗ
| ПланВидовХарактеристик.ПраваПользователей КАК ПраваПользователей
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияДополнительныхПравПользователя КАК ЗначенияДополнительныхПравПользователя
| ПО (ЗначенияДополнительныхПравПользователя.Право = ПраваПользователей.Ссылка)
| И (ЗначенияДополнительныхПравПользователя.Пользователь = &Пользователь)
|ГДЕ
| (ПраваПользователей.Наименование ПОДОБНО &Наименование1
| ИЛИ ПраваПользователей.Наименование ПОДОБНО &Наименование2)»;
Запрос.УстановитьПараметр(«Наименование1″, л_ПрефиксДополнительногоПрава1+»%»);
Запрос.УстановитьПараметр(«Наименование2″, л_ПрефиксДополнительногоПрава2+»%»);
Запрос.УстановитьПараметр(«Пользователь», л_ТекущийПользователь);
Результат = Запрос.Выполнить();
л_ТаблицаДополнительныхПрав = Результат.Выгрузить();
Если л_ТаблицаДополнительныхПрав.Количество() = 0 Тогда
// если такой настройки в принципе в базе нет, то ничего и не делаем
Сообщить(«Отсутствуют дополнительные права пользователей «»Автоматически НЕ закрывать предыдущий период: N»» или «»Автоматически НЕ закрывать предыдущий месяц: N»»»,СтатусСообщения.Информация);
Сообщить(«Добвьте нужное количество дополнительных прав пользователя вида «»Автоматически НЕ закрывать предыдущий период: N»» или «»Автоматически НЕ закрывать предыдущий месяц: N»», где N — глубина запрета в днях.»);
Возврат;
КонецЕсли;
л_ТаблицаДополнительныхПрав.Колонки.Добавить(«ДатаЗапрета»,Новый ОписаниеТипов(«Дата»));
л_ТаблицаДополнительныхПрав.Колонки.Добавить(«ГлубинаЗапрета»,Новый ОписаниеТипов(«Число»));
л_МаксимальнаяГлубина = 0;
л_Сутки = 24*60*60;
Для Каждого л_СтрокаТЗ из л_ТаблицаДополнительныхПрав Цикл
л_НаименованиеДополнительногоПрава = л_СтрокаТЗ.НаименованиеДополнительногоПрава;
Если Найти(л_НаименованиеДополнительногоПрава,л_ПрефиксДополнительногоПрава1) > 0 Тогда
л_ПараметрДополнительногоПрава = СокрЛП(Сред(л_НаименованиеДополнительногоПрава,44));
л_СтрокаТЗ.ГлубинаЗапрета = Число(л_ПараметрДополнительногоПрава);
л_СтрокаТЗ.ДатаЗапрета = ТекущаяДата() — л_СтрокаТЗ.ГлубинаЗапрета*л_Сутки;
ИначеЕсли Найти(л_НаименованиеДополнительногоПрава,л_ПрефиксДополнительногоПрава2) > 0 Тогда
л_ПараметрДополнительногоПрава = СокрЛП(Сред(л_НаименованиеДополнительногоПрава,45));
л_СтрокаТЗ.ГлубинаЗапрета = Число(л_ПараметрДополнительногоПрава);
л_СтрокаТЗ.ДатаЗапрета = НачалоМесяца(ТекущаяДата() — л_СтрокаТЗ.ГлубинаЗапрета*л_Сутки) — 1;
КонецЕсли;
Если л_МаксимальнаяГлубина < л_СтрокаТЗ.ГлубинаЗапрета Тогда
л_МаксимальнаяГлубина = л_СтрокаТЗ.ГлубинаЗапрета;
КонецЕсли;
КонецЦикла;
л_МассивСтрокТЗ = л_ТаблицаДополнительныхПрав.НайтиСтроки(Новый Структура(«ГлубинаЗапрета»,л_МаксимальнаяГлубина));
Для Каждого л_СтрокаТЗ из л_МассивСтрокТЗ Цикл
// Для максимальной глубины запрет не может быть отменен
// то ест ьдля ВСЕХ пользователей будет действовать установка запрета редактирования, хотя бы на максимальную глубину
л_СтрокаТЗ.ЗначениеДополнительногоПрава = Ложь;
КонецЦикла;
л_ТаблицаДополнительныхПрав.Сортировать(«ЗначениеДополнительногоПрава Возр, ДатаЗапрета Убыв»);
Если л_ТаблицаДополнительныхПрав[0].ЗначениеДополнительногоПрава = Истина Тогда
// отменена установка запретов редактирования для всех глубин, то есть ничего для этого пользователя не делаем.
// такого не будет
л_УстановитьЗапрет = Ложь;
Иначе
л_УстановитьЗапрет = Истина;
л_ДатаЗапрета = КонецДня(л_ТаблицаДополнительныхПрав[0].ДатаЗапрета);
Если л_ДатаЗапрета >= КонецДня(ТекущаяДата()) Тогда
л_ДатаЗапрета = НачалоДня(НачалоДня(ТекущаяДата()) — 1);
КонецЕсли;
КонецЕсли;
Если л_УстановитьЗапрет Тогда
л_Запись = РегистрыСведений.ГраницыЗапретаИзмененияДанных.СоздатьМенеджерЗаписи();
л_Запись.Пользователь = л_ТекущийПользователь;
л_Запись.ГраницаЗапретаИзменений = л_ДатаЗапрета;
л_Запись.Записать();
//Сообщить(«Дата запрета = «+л_ДатаЗапрета);
КонецЕсли;
ПолныеПрава.УстановитьПараметрГраницыЗапретаИзмененияДанных();
КонецПроцедуры
Вставляем одну строку в модуль обычного приложения, перед окончанием процедуры «ПриНачалеРаботыСистемы»
…
АЦРК_Привилегированный.ЗакрытиеПредыдущегоПериода(); //АЦРК
КонецПроцедуры // ПриНачалеРаботыСистемы()
Вот и все.
Как это работает
Если ничего с дополнительными правами не делать, то ни для каких пользователей не будет отменена установка запрета редактирования. Значит будет устанавливаться запрет редактирования на минимальную глубину, в нашем примере 1 день, то есть по вчерашний день включительно.
Чтобы увеличить эту глубину для некоторых пользователей, надо установить для них флажок у соответствующих прав. Сделать это может уполномоченный пользователь. При этом следует учитывать, что запрет будет установлен на наименьшую глубину из всех не отмененных. Например, если установить только один флажок «Автоматически НЕ закрывать предыдущий день: 5», а флажок «Автоматически НЕ закрывать предыдущий день: 0» оставить не установленным, то окажется, что запрет редактирования предыдущего дня не отменен, он и будет установлен при входе пользователя в базу. То есть, если надо открыть для редактирования 5 дней или месяц, надо прежде всего установить флажок «Автоматически НЕ закрывать предыдущий день: 0».
ВАЖНО! период с максимальной глубиной запрета будет установлен в любом случае, даже если установить все флажки «Автоматически НЕ закрывать предыдущий …». В нашем примере 10-го числа очередного месяца будет гарантировано закрыт предыдущий месяц для ЛЮБОГО пользователя, вошедшего в базу, даже для того, у кого установлен флажок «Автоматически НЕ закрывать предыдущий месяц: 10».
Итак, когда пользователи утром заходят в базу данных, для них автоматически устанавливается запрет редактирования, каждому на свою глубину. В этом можно убедиться, посмотрев в меню «Сервис / Настройка учета / Установка даты запрета изменения данных». На закладке «Основная дата» вы увидите записи по всем пользователям, работающим в базе данных.
Делать изменения в закрытом периоде смогут только пользователи с полными правами. Для этого такой пользователь должен выполнить следующие действия:
выбрать меню «Сервис / Настройка учета / Установка даты запрета изменения данных». На закладке «Основная дата» отображаются записи по пользователям. Для себя пользователь может отодвинуть дату запрета на нужную дату, нажать кнопку «Установить». Для него дата запрета редактирования отодвинется немедленно, в этом же сеансе работы. Можно производить изменения в закрытом периоде, с осознанием всех последствий.
Но как только такой пользователь выйдет из базы и снова в нее зайдет, для него снова установится дата запрета редактирования согласно настройкам дополнительных прав пользователя. И это хорошо.
Я делал более гибко, можно задавать формулу для вычисления даты запрета, использую метод Вычислить(). Тогда можно привязываться и к рабочему календарю и другим механизмам базы. Количество дней не сильно функционально.
Механизм Ваш тоже не плох, я с него тоже начинал. Понравилась реализации через Доп права, я для этого создавал отдельный РС для реализации этой задачи.
Меняет пользователь у себя дату, допустил на год назад и все дыра появляется ….
Нужно брать дату с сервера
(3) 1malder1, Все дыры не заткнешь.
Это уже проблемы системщиков, чтобы пользователь не мог так сделать.
Спасибо за статью. И ессно за проделанный труд и желание поделиться с другими. Может показаться, что все мы умные и чего тут делать? Да действительно так с одной стороны, с другой уж больно не хочется изобретать велосипед, тем более, что люди эту проблему уже «прокурили». Так что спасибо.
Здравствуйте.
В режиме файл-сервер возможна работа данного решения?
(6) kosas, ну а почему нет? Конечно возможно!
ВОТ ТАК ЗАРАБОТАЛО
л_ТаблицаДополнительныхПрав.Колонки.Добавить(«ДатаЗапрета»,Новый ОписаниеТипов(«Дата»));
л_ТаблицаДополнительныхПрав.Колонки.Добавить(«ГлубинаЗапрета»,Новый ОписаниеТипов(«Число»)); л_Сутки = 24*60*60;
Для Каждого л_СтрокаТЗ из л_ТаблицаДополнительныхПрав Цикл
л_НаименованиеДополнительногоПрава = л_СтрокаТЗ.НаименованиеДополнительногоПрава;
Если Найти(л_НаименованиеДополнительногоПрава,л_ПрефиксДополнительногоПрава1) > 0 Тогда
л_ПараметрДополнительногоПрава = СокрЛП(Сред(л_НаименованиеДополнительногоПрава,44));
л_СтрокаТЗ.ГлубинаЗапрета = Число(л_ПараметрДополнительногоПрава);
л_СтрокаТЗ.ДатаЗапрета = ТекущаяДата() — л_СтрокаТЗ.ГлубинаЗапрета*л_Сутки;
ИначеЕсли Найти(л_НаименованиеДополнительногоПрава,л_ПрефиксДополнительногоПрава2) > 0 Тогда
л_ПараметрДополнительногоПрава = СокрЛП(Сред(л_НаименованиеДополнительногоПрава,45));
л_СтрокаТЗ.ГлубинаЗапрета = Число(л_ПараметрДополнительногоПрава);
л_СтрокаТЗ.ДатаЗапрета = НачалоМесяца(ТекущаяДата() — л_СтрокаТЗ.ГлубинаЗапрета*л_Сутки) — 1;
КонецЕсли;
КонецЦикла;
л_ТаблицаДополнительныхПрав.Сортировать(«ЗначениеДополнительногоПрава Убыв, ДатаЗапрета Возр»);
// Для максимальной глубины запрет не может быть отменен
// то есть для ВСЕХ пользователей будет действовать установка запрета редактирования, хотя бы на максимальную глубину
л_ТаблицаДополнительныхПрав[0].ЗначениеДополнительногоПрава = Ложь;
л_ТаблицаДополнительныхПрав.Сортировать(«ЗначениеДополнительногоПрава Возр, ДатаЗапрета Убыв»);
Если л_ТаблицаДополнительныхПрав[0].ЗначениеДополнительногоПрава = Истина Тогда
// отменена установка запретов редактирования для всех глубин, то есть ничего для этого пользователя не делаем.
// такого не будет
л_УстановитьЗапрет = Ложь;
Иначе
л_УстановитьЗапрет = Истина;
л_ДатаЗапрета = КонецДня(л_ТаблицаДополнительныхПрав[0].ДатаЗапрета);
Если л_ДатаЗапрета >= КонецДня(ТекущаяДата()) Тогда
л_ДатаЗапрета = НачалоДня(НачалоДня(ТекущаяДата()) — 1);
КонецЕсли;
КонецЕсли;
Если л_УстановитьЗапрет Тогда
л_Запись = РегистрыСведений.ГраницыЗапретаИзмененияДанных.СоздатьМенеджерЗаписи();
л_Запись.Пользователь = л_ТекущийПользователь;
л_Запись.ГраницаЗапретаИзменений = л_ДатаЗапрета;
л_Запись.Записать();
//Сообщить(«Дата запрета = «+л_ДатаЗапрета);
КонецЕсли;
ПолныеПрава.УстановитьПараметрГраницыЗапретаИзмененияДанных();