Контроль записи/проведения документов в заданном интервале дней

Данное решение позволяет гибко настраивать правила записи и проведения документов для пользователей, групп пользователей.

Решение не претендует на оригинальность, но, возможно, поможет кому-нибудь.

Была поставлена задача разрешить определенным пользователям работать с одними документами в пределах текущего дня, с другими в пределах трех. Для универсальности сделал регистр сведений, где можно как для группы пользователей, так и для конкретного пользователя указывать временной интервал, в течение которого он может работать с выбранным видом документа.

Настройка правил

Кроме регистра добавлена подписка на событие записи документа.

Количество дней записи/проведения документа определяется следующим образом: ищутся правила, заданные именно для пользователя, если их нет, то ищем правила, заданные для группы, в которой состоит пользователь, из них выбирается минимальное количество дней. Если нет заданных правил для документа — то запись/проведение разрешается. Если правила есть, то дата документа проверяется на вхождение в заданный временной интервал, при прохождении проверки запись разрешается, в противном случае пользователю выдается сообщение, и запись прерывается.

 

Функция ПроверитьВозможностьЗаписиДокумента(СсылкаДок, Пользователь, РежимЗаписи)
КолДней = Неопределено;

//проверим есть ли в регистре правила контроля по данному документу для переданного
//пользователя, либо группы в которую он входит
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПравилаКонтроляДокументов.КолДнейПроведение КАК КолДнейПроведение,
| ПравилаКонтроляДокументов.КолДнейЗапись КАК КолДнейЗапись
|ИЗ
| РегистрСведений.ПравилаКонтроляДокументов КАК ПравилаКонтроляДокументов
|ГДЕ
| ПравилаКонтроляДокументов.Пользователь = &Пользователь
| И ТИПЗНАЧЕНИЯ(ПравилаКонтроляДокументов.Документ) = ТИПЗНАЧЕНИЯ(&Документ)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ГруппыДоступа.Ссылка КАК ГруппаДоступа,
| ПравилаКонтроля.КолДнейПроведение КАК КолДнейПроведение,
| ПравилаКонтроля.КолДнейЗапись КАК КолДнейЗапись
|ИЗ
| Справочник.ГруппыДоступа.Пользователи КАК ГруппыДоступа
|  ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПравилаКонтроляДокументов КАК ПравилаКонтроля
|  ПО (ПравилаКонтроля.Пользователь = ГруппыДоступа.Ссылка)
|ГДЕ
| ГруппыДоступа.Пользователь = &Пользователь
| И ТИПЗНАЧЕНИЯ(ПравилаКонтроля.Документ) = ТИПЗНАЧЕНИЯ(&Документ)
|";

Запрос.УстановитьПараметр("Документ", СсылкаДок.Ссылка);
Запрос.УстановитьПараметр("Пользователь", Пользователь);

РезультатЗапроса = Запрос.ВыполнитьПакет();

//сначала проверим есть ли правило для пользователя
Выборка = РезультатЗапроса[0].Выбрать();
Если Выборка.Следующий() Тогда
КолДней = ?(РежимЗаписи = РежимЗаписиДокумента.Запись, Выборка.КолДнейЗапись, Выборка.КолДнейПроведение);
КонецЕсли;

//для пользователя правил нету, возможно есть правило для групп в которых находится пользователь
Если КолДней = Неопределено Тогда
ПравилаПоГруппам = РезультатЗапроса[1].Выгрузить();
Если ПравилаПоГруппам.Количество() Тогда
КолДнейПроведение = Неопределено;
КолДнейЗапись = Неопределено;
//выбираем наименьшее количество дней из выбранных правил
Для каждого ТекПравило Из ПравилаПоГруппам Цикл
КолДнейПроведение = ?((КолДнейПроведение = Неопределено)
ИЛИ (ТекПравило.КолДнейПроведение < КолДнейПроведение И ТекПравило.КолДнейПроведение <> -1),
ТекПравило.КолДнейПроведение, КолДнейПроведение);
КолДнейЗапись = ?((КолДнейЗапись = Неопределено)
ИЛИ (ТекПравило.КолДнейЗапись < КолДнейЗапись И ТекПравило.КолДнейЗапись <> -1),
ТекПравило.КолДнейЗапись, КолДнейЗапись);
КонецЦикла;

КолДней = ?(РежимЗаписи = РежимЗаписиДокумента.Запись, КолДнейЗапись, КолДнейПроведение);
КонецЕсли;
КонецЕсли;

Если КолДней <> Неопределено И КолДней <> -1 Тогда
//ищем разницу в днях между текущей датой и датой документа,
//проверяем чтобы она не превышала заданое в правилах количество
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|   РАЗНОСТЬДАТ(&ДатаДокумента, &ТекущаяДата, ДЕНЬ) КАК РазностьДат
|";

Запрос.УстановитьПараметр("ДатаДокумента", СсылкаДок.Дата);
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Если Выборка.РазностьДат > КолДней Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;

//по данному документу для пользователя не заданно явных правил, контроль пройден
Возврат Истина;
КонецФункции

Процедура ПодпискаНаСобытиеЗаписиДокументаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
//Проверяем есть ли заданное количество дней для данного документа
КонтрольПройден = ПроверитьВозможностьЗаписиДокумента(Источник, ПараметрыСеанса.ТекущийПользователь, РежимЗаписи);
Если НЕ КонтрольПройден Тогда
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Согласно правилам контроля документов, вам отказано в "
+ ?(РежимЗаписи = РежимЗаписиДокумента.Запись, "записи",
?(РежимЗаписи = РежимЗаписиДокумента.Проведение, "проведении", "отмене проведения"))
+ " документа! Обратитесь к системному администратору!";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры


Данное решение в минимальное объеме использует функционал типовых решений 1С. Достаточно просто встраивается в типовые решения, для самописных придется немного поработать напильником. Для этого вам потребуется перенести в свою конфигурацию: регистр сведений «ПравилаКонтроляДокументов», общий модуль «МодульКонтроляДокументов» и подписку на событие «ПодпискаНаСобытиеЗаписиДокумента». Используются управляемые формы.

Решение прошло обкатку на УТ 11.

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *