Здравствуйте !
В этой статье я хотел бы поделиться одним из способов закрытия доступа к счетам в стандартных отчетах, таких как Оборотно-Сальдовая Ведомость, Анализ счета и др.
Данный способ не является чем-то новым - просто хотелось показать, что нужный результат можно получить без примнения RLS и все изменения не такие маштабные, как кажется на первый взгляд.
Итак, суть способа - изменить НастройкиКомпановкиДанных перед тем, как настройки будут проинициализированы, и инициализировать уже с новыми настройками. Для уменьшения изменений в основной конфигурации воспользуемся механизмом Расширение конфигураций.
Все настройки рассмотрим на примере Бухгалтерии БП 3.0 (релиз 3.0.44.140)
1. Для хранения данных о пользователях, у которых ограничены права на просмотр счетов, и самих счетов, доступ к которым ограничен, я добавил Справочник "ОграничениеПравПользователей" с реквизитом "Пользователь" - СправочникСсылка.Пользователи и две табличные части:. Длину наименования у спрвочника указываем 50 символов.
"СписокЗапрещенныхСчетов" - Колонки "Счет" - ПланыСчетов.Хозрасчетный, "Использование" - Тип Булево.
"СписокЗапрещенныхСубконто" - Колонки "ЗапрещенноеСубконто" - Тип ПланВидовХарактеристик.ВидыСубконтоХозрасчетный
Тут важное уточнение - полные права доступа на этот справочник должны быть только у администратора (или пользователя с полными правами), у других должен быть доступ только на чтение.
2. Добавление общего модуля «ОграничениеПравПользователей» (если кто использует платформу 8.3.9 модуль можно добавить в расширение)
Код Модуля (сразу оговорюсь, что данный код не оптимизировался , вполне возможно привести данный код в более красивый вид). Необходимые комментарии в коде
Функция ПроверитьУстановленныйОтбор (Отбор,ВидСравнения,Значение)
Если Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно Тогда
Если Значение.НайтиПоЗначению(Отбор.ПравоеЗначение)<> Неопределено Тогда
Отбор.ПравоеЗначение = Неопределено;
ОтборУстановлен = Истина;
КонецЕсли;
ИначеЕсли Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке
ИЛИ Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВИерархии
ИЛИ Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии Тогда
Для каждого СтрокаСписка Из Отбор.ПравоеЗначение Цикл
Если Значение.НайтиПоЗначению(СтрокаСписка.Значение)<>Неопределено тогда
Отбор.ПравоеЗначение.Удалить(СтрокаСписка);
КонецЕсли;
КонецЦикла;
ОтборУстановлен = Истина;
ИначеЕсли Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВИерархии
ИЛИ Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке
ИЛИ Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСпискеПоИерархии Тогда
Для каждого СтрокаСписка Из Значение Цикл
Если Отбор.ПравоеЗначение.НайтиПоЗначению(СтрокаСписка.Значение)=Неопределено тогда
Отбор.ПравоеЗначение.Добавить(СтрокаСписка.Значение);
КонецЕсли;
КонецЦикла;
ОтборУстановлен = Истина;
Иначе
ОтборУстановлен = Ложь;
КонецЕсли;
Возврат ОтборУстановлен;
КонецФункции
////ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ И ПРОЦЕДУРЫ///////////////////////
Функция ПоискиУстановкаОтбора (КомпоновщикНастроек,ПолеОтбора,ВидСравнения,ЗначениеОтбора)
ОтборНайден = Ложь;
Для каждого Отбор Из КомпоновщикНастроек.Отбор.Элементы Цикл
Если Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных (ПолеОтбора) Тогда
Если Отбор.Использование = Истина Тогда // Возможно пользователь сам установил какой-то отбор по заданному полю,
//поэтому мы должные проверить
ОтборНайден = ПроверитьУстановленныйОтбор(Отбор,ВидСравнения,ЗначениеОтбора);
Иначе
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравнения;
Отбор.ПравоеЗначение = ЗначениеОтбора;
ОтборНайден = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ОтборНайден;
КонецФункции
//Процедура Добавляет Отбор в НастройкуКомпановкиДанных
Процедура ДобавитьОтбор(НастройкаКомпоновкиДанных,ПолеОтбора,ВидСравнения,Значение,Использование)
Отбор = НастройкаКомпоновкиДанных.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ПолеОтбораСчет = Новый ПолеКомпоновкиДанных(ПолеОтбора);
Отбор.ЛевоеЗначение = ПолеОтбораСчет;
Отбор.Использование = Использование;
Отбор.ПравоеЗначение = Значение;
Отбор.ВидСравнения = ВидСравнения;
КонецПроцедуры
/////////////ОСНОВННЫЕ ФУНКЦИИ И ПРОЦЕДУРЫ /////////////////////////////////
Процедура УстановитьОграничениеНаПросмотрСчетов(ОтчетОбъект,НастройкаКомпоновкиДанных,Форма,СКД=неопределено) Экспорт;
// Получим список запрещенных Счетов для текущего пользователя
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВЫБОР
| КОГДА ОграничениеПравПользователейСписокРазрещенныхСчетов.Использование = ЛОЖЬ
| ТОГДА ОграничениеПравПользователейСписокРазрещенныхСчетов.Счет
| КОНЕЦ КАК ЗапрещенныеСчета
|ИЗ
| Справочник.ОграничениеПравПользователей.СписокРазрещенныхСчетов КАК ОграничениеПравПользователейСписокРазрещенныхСчетов
|ГДЕ
| ОграничениеПравПользователейСписокРазрещенныхСчетов.Ссылка.Пользователь = &Пользователь
| И ОграничениеПравПользователейСписокРазрещенныхСчетов.Использование = ЛОЖЬ";
Запрос.УстановитьПараметр("Пользователь",ПараметрыСеанса.ТекущийПользователь);
Результат = Запрос.Выполнить();
ТаблицаСчетов = Результат.Выгрузить(); // результат выгружаем в таблиц
ЗапрещенныеСчета = ТаблицаСчетов.ВыгрузитьКолонку("ЗапрещенныеСчета"); // Получаем массив запрещенных счетов
//Получим список запррещенных к просмотру субконто
Запрос.Текст ="ВЫБРАТЬ
| ОграничениеПравПользователейЗапрещенныеСубконто.ЗапрещенноеСубконто
|ИЗ
| Справочник.ОграничениеПравПользователей.ЗапрещенныеСубконто КАК ОграничениеПравПользователейЗапрещенныеСубконто
|ГДЕ
| ОграничениеПравПользователейЗапрещенныеСубконто.Ссылка.Пользователь = &Пользователь";
Запрос.УстановитьПараметр("Пользователь",ПараметрыСеанса.ТекущийПользователь);
ТаблицаЗапрещенныхСубконто = Запрос.Выполнить().Выгрузить();
Если ЗапрещенныеСчета.Количество()= 0 И ТаблицаЗапрещенныхСубконто.Количество() = 0 тогда // Если нет ограничений , то выходим
Возврат;
КонецЕсли;
МассивЗапрещенныхСубконто = ТаблицаЗапрещенныхСубконто.ВыгрузитьКолонку("ЗапрещенноеСубконто");
СписокЗапрещенныхСчетов = Новый СписокЗначений;
СписокЗапрещенныхСчетов.ЗагрузитьЗначения(ЗапрещенныеСчета); // из массива преобразуем в список значений
//Определим какой отчет запустил пользователь
ИдентификаторОбъекта = БухгалтерскиеОтчетыКлиентСервер.ПолучитьИдентификаторОбъекта(Форма); // получаем идентификатор отчета
// В зависимости от вида отчета переходим к обработке
Если ИдентификаторОбъекта = "ОборотноСальдоваяВедомостьПоСчету" // По иднентификатору определяем дальнейшее действие
ИЛИ ИдентификаторОбъекта = "АнализСчета"
ИЛИ ИдентификаторОбъекта = "КарточкаСчета" ИЛИ ИдентификаторОбъекта = "ОборотыСчета" Тогда
ОСВПоСчету_АнализСчета_КарточкаСчета(ОтчетОбъект,ИдентификаторОбъекта,НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов,СКД);
КонецЕсли;
Если ИдентификаторОбъекта = "ОборотноСальдоваяВедомость" тогда
ОСВ(НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов);
КонецЕсли;
Если ИдентификаторОбъекта = "АнализСубконто"
ИЛИ ИдентификаторОбъекта = "КарточкаСубконто" Тогда
АнализСубконто_КарточкаСубконто(НастройкаКомпоновкиДанных,МассивЗапрещенныхСубконто,СписокЗапрещенныхСчетов);
КонецЕсли;
Если (ИдентификаторОбъекта = "ОтчетПоПроводкам") ИЛИ (ИдентификаторОбъекта = "ОборотыМеждуСубконто") тогда
ОтчетПоПроводкам_ОборотыМеждуСубконто(НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов);
КонецЕсли;
Если ИдентификаторОбъекта = "СводныеПроводки" Тогда
СводныеПроводки(НастройкаКомпоновкиДанных, СписокЗапрещенныхСчетов);
КонецЕсли;
//Если ИдентификаторОбъекта = "ОборотыМеждуСубконто" Тогда
// ОборотыМеждуСубконто( НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов);
//КонецЕсли;
КонецПроцедуры
Процедура ОСВПоСчету_АнализСчета_КарточкаСчета(ОтчетОбъект,ИдентификаторОбъекта,НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов,СКД)
ОтборПоСчету = Ложь ; // установим флаг для поиска Отбора
ОтборПоСчету = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"Счет",ВидСравнения.НеВСписке,СписокЗапрещенныхСчетов);
Если Не ОтборПоСчету Тогда // Если отбор не найден - установим
ДобавитьОтбор(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
Если ИдентификаторОбъекта = "ОборотноСальдоваяВедомостьПоСчету" Тогда
// В стандартной настройке СКД на поле "Счет" установлено отграничение по условию , поэтому необходимо
// изменить запрос (только в части настроек для СКД , т.е. основной текст запроса не меняется) и отключить ограничение
// на поле "Счет"
Запрос = СКД.НаборыДанных.ОсновнойНаборДанных.Элементы.ОстаткиИОбороты.Запрос;
ЗапросБезСубконто = СКД.НаборыДанных.ОсновнойНаборДанных.Элементы.ОстаткиИОборотыБезСубконто.Запрос;
ПоляОсновногоНабораДанных = СКД.НаборыДанных.ОсновнойНаборДанных.Поля;
СтрокаЗамены = "{ГДЕ"+ Символы.ПС + "ХозрасчетныйОстаткиИОбороты.Счет.*,";
ЗаменяемаяСтрока = "{ГДЕ";
Запрос = СтрЗаменить(запрос,ЗаменяемаяСтрока,СтрокаЗамены);
ЗапросБезСубконто = СтрЗаменить(ЗапросБезСубконто,ЗаменяемаяСтрока,СтрокаЗамены);
//Ищем поле и отключаем ограничение
ПолеСчет = ПоляОсновногоНабораДанных.Найти("Счет");
Если ПолеСчет <> неопределено тогда
ПолеСчет.ОграничениеИспользования.Условие = Ложь;
ПолеСчет.ОграничениеИспользованияРеквизитов.Условие = Ложь;
КонецЕсли;
СКД.НаборыДанных.ОсновнойНаборДанных.Элементы.ОстаткиИОбороты.Запрос = Запрос;
СКД.НаборыДанных.ОсновнойНаборДанных.Элементы.ОстаткиИОборотыБезСубконто.Запрос= ЗапросБезСубконто;
// После данных действий - отбор который был установлен выше будет работать
КонецЕсли;
Если ИдентификаторОбъекта = "КарточкаСчета" тогда // Для карточки счета необходимо изменить Стандартный запрос для парметров СКД
ОтборДтНайден = Ложь; // Флаги для поиска ранее установленных отборов
ОтборКтНайден = Ложь;
//Для стандартного отчета Карточка счета нет возможности установить отбор по счетам. Для возможности добавления отбора необходимо
//поменять текст запроса для СКД (только в части настроек для СКД , т.е. основной текст запроса не меняется )
Запрос = СКД.НаборыДанных.Проводки.Запрос; // получим текст запроса
Запрос = СтрЗаменить(Запрос,"Проводки.ПериодГруппировки}", "Проводки.ПериодГруппировки,"+Символы.ПС
+ "Проводки.СчетДт.*,"+Символы.ПС+ "Проводки.СчетКт.*}"+Символы.ПС); // Изменяем текст для компоновщика добавляя поля СчетДт И СчетКТ
СКД.НаборыДанных.Проводки.Запрос = Запрос; // Устанавливаем новый текст Запроса
//Теперь в СКД нам доступны поля отбора СчетДт и СчетКт и по ним возможно устанавливать отбор. Попробуем найти ранее установленные отборы
ОтборДтНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"СчетДт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
ОтборДтНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"СчетКт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не ОтборДтНайден тогда // Если указанный отбор не найден, то установим его
ДобавитьОтбор(НастройкаКомпоновкиДанных,"СчетДт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
Если Не ОтборКтНайден тогда // Если указанный отбор не найден, то установим его
ДобавитьОтбор(НастройкаКомпоновкиДанных,"СчетКт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецЕсли;
Если ИдентификаторОбъекта = "АнализСчета" Тогда // Для Отчета Анализ Счета установим(проверим) отбор на КорСчет
КорСчетНайден = Ложь;
КоррСчетНайден=ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"КорСчет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не КорСчетНайден тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"КорСчет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ОСВ(НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов)
ПараметрыКомпоновки = НастройкаКомпоновкиДанных.ПараметрыДанных;
ПараметрСчет = ПараметрыКомпоновки.Элементы.Найти("СчетаИсключенныеИзЗапросаПоСчетам");
ПараметрСчетДетализации =ПараметрыКомпоновки.Элементы.Найти("Счетдетализации");
Если ПараметрСчет <> Неопределено Тогда
Если СписокЗапрещенныхСчетов.Количество()>0 Тогда
БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметр(ПараметрыКомпоновки.Элементы,"СчетаИсключенныеИзЗапросаПоСчетам",СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецЕсли;
СчетНайден = Ложь;
СчетНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не СчетНайден Тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецПроцедуры
Процедура АнализСубконто_КарточкаСубконто(НастройкаКомпоновкиДанных,МассивЗапрещенныхСубконто,СписокЗапрещенныхСчетов)
// В принципе можно обойтись только установкой отбора по счету. Но все таки решил оставить первоначальный вариант с двойной проверкой как по счету так и
// через удаление запрещенных субконто из списка параметров
Если СписокЗапрещенныхСчетов.Количество()> 0 Тогда
СчетНайден = Ложь;
СчетНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не СчетНайден Тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецЕсли;
Если МассивЗапрещенныхСубконто.Количество() > 0 Тогда
ПараметрыКомпоновки = НастройкаКомпоновкиДанных.ПараметрыДанных;
ПараметрСписокСубконто = ПараметрыКомпоновки.Элементы.Найти("СписокВидовСубконто");
Если ПараметрСписокСубконто<> неопределено Тогда
МассивУстановленныхСубконто = ПараметрыКомпоновки.Элементы.Найти("СписокВидовСубконто").Значение;
Для каждого Субконто из МассивЗапрещенныхСубконто Цикл
ИндексЭлемента = МассивУстановленныхСубконто.найти (Субконто) ;
Если ИндексЭлемента<> Неопределено Тогда
МассивУстановленныхСубконто.удалить(ИндексЭлемента) ;
КонецЕсли;
КонецЦикла;
Если МассивУстановленныхСубконто.Количество() = 0 Тогда
МассивУстановленныхСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка());
КонецЕсли;
БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметр(ПараметрыКомпоновки.Элементы,"СписокВидовСубконто",МассивУстановленныхСубконто,Истина);
КонецЕсли;
КонецЕСли;
КонецПроцедуры
Процедура ОтчетПоПроводкам_ОборотыМеждуСубконто(НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов)
ОтборКтНайден = Ложь;
ОтборДтНайден = Ложь;
ОтборКтНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
ОтборДтНайден = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"КорСчет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не ОтборДтНайден тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"Счет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
Если Не ОтборКтНайден тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"КорСчет",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецПроцедуры
Процедура СводныеПроводки (НастройкаКомпоновкиДанных,СписокЗапрещенныхСчетов)
СчетДт = Ложь;
СчетДт = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"СчетДт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не СчетДт Тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"СчетДт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
СчетКт = Ложь;
СчетКт = ПоискиУстановкаОтбора(НастройкаКомпоновкиДанных,"СчетКт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов);
Если Не СчетКт Тогда
ДобавитьОтбор(НастройкаКомпоновкиДанных,"СчетКт",ВидСравненияКомпоновкиДанных.НеВСписке,СписокЗапрещенныхСчетов,Истина);
КонецЕсли;
КонецПроцедуры
3. В конфигурацию добавляем расширение (имя заданное по умолчанию я менять не стал Расширение1 , префикс Расш1_
В расширение следует добавить формы отчетов, к которым настраивается ограничение. В моем случае это:
- Анализ счета
- Карточка счета
- Анализ субконто
- Карточка субконто
- Оборотно-сальдовая ведомость
- Оборотно-сальдовая ведомость по счету
- Обороты между субконто
- Сводные проводки
- Обороты счета
- Отчет по проводкам
В каждую расширенную форму следует добавить 2 функции и 1 процедуру (это в общем случае. отдельный случай будет описан ниже) из расширяемой формы основной конфигурации, а именно:
- Процедура "СформироватьОтчет"
- Функция "СформироватьОтчетНаСервере"
- Функция "ПодготовитьПараметрыОтчета"
К указанным функциям и процедуре необходимо добавить префикс расширения. А для команды "СформироватьОтчет" (кнопка "Сформировать" на форме) назначить новое действие "Расш1_СформирватьОтчет"
Вот пример для отчета КарточкаСчета
&НаСервере
Функция Расш1_ПодготовитьПараметрыОтчета()
// В этой функции происходит подмена настроек "НастройкиКомпоновкиДанных"
ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("Организация" , Отчет.Организация);
ПараметрыОтчета.Вставить("НачалоПериода" , Отчет.НачалоПериода);
ПараметрыОтчета.Вставить("КонецПериода" , Отчет.КонецПериода);
ПараметрыОтчета.Вставить("ВключатьОбособленныеПодразделения", Отчет.ВключатьОбособленныеПодразделения);
ПараметрыОтчета.Вставить("ПоказательБУ" , Отчет.ПоказательБУ);
ПараметрыОтчета.Вставить("ПоказательНУ" , Отчет.ПоказательНУ);
ПараметрыОтчета.Вставить("ПоказательПР" , Отчет.ПоказательПР);
ПараметрыОтчета.Вставить("ПоказательВР" , Отчет.ПоказательВР);
ПараметрыОтчета.Вставить("ПоказательВалютнаяСумма" , Мин(Отчет.ПоказательВалютнаяСумма, БухгалтерскийУчетПереопределяемый.ИспользоватьВалютныйУчет()));
ПараметрыОтчета.Вставить("ПоказательКоличество" , Отчет.ПоказательКоличество);
ПараметрыОтчета.Вставить("ПоказательКонтроль" , Отчет.ПоказательКонтроль);
ПараметрыОтчета.Вставить("РазвернутоеСальдо" , Отчет.РазвернутоеСальдо);
ПараметрыОтчета.Вставить("РазмещениеДополнительныхПолей" , Отчет.РазмещениеДополнительныхПолей);
ПараметрыОтчета.Вставить("Периодичность" , Отчет.Периодичность);
ПараметрыОтчета.Вставить("Счет" , Отчет.Счет);
ПараметрыОтчета.Вставить("ПоСубсчетам" , Отчет.ПоСубсчетам);
ПараметрыОтчета.Вставить("ПоСубсчетамКорСчетов" , Отчет.ПоСубсчетамКорСчетов);
ПараметрыОтчета.Вставить("Группировка" , Отчет.Группировка.Выгрузить());
ПараметрыОтчета.Вставить("ДополнительныеПоля" , Отчет.ДополнительныеПоля.Выгрузить());
ПараметрыОтчета.Вставить("ГруппировкаКор" , Отчет.ГруппировкаКор.Выгрузить());
ПараметрыОтчета.Вставить("РежимРасшифровки" , Отчет.РежимРасшифровки);
ПараметрыОтчета.Вставить("ВыводитьЗаголовок" , ВыводитьЗаголовок);
ПараметрыОтчета.Вставить("ВыводитьПодвал" , ВыводитьПодвал);
ПараметрыОтчета.Вставить("ДанныеРасшифровки" , ДанныеРасшифровки);
ПараметрыОтчета.Вставить("МакетОформления" , МакетОформления);
ПараметрыОтчета.Вставить("СхемаКомпоновкиДанных" , ПолучитьИзВременногоХранилища(СхемаКомпоновкиДанных));
ПараметрыОтчета.Вставить("ИдентификаторОтчета" , БухгалтерскиеОтчетыКлиентСервер.ПолучитьИдентификаторОбъекта(ЭтаФорма));
НастройкиКомпоновкиДанных = Отчет.КомпоновщикНастроек.ПолучитьНастройки();
ОграничениеПравПользователей.УстановитьОграничениеНаПросмотрСчетов(Отчет,НастройкиКомпоновкиДанных,ЭтаФорма,ПараметрыОтчета.СхемаКомпоновкиДанных);
ПараметрыОтчета.Вставить("НастройкиКомпоновкиДанных" , НастройкиКомпоновкиДанных);
ПараметрыОтчета.Вставить("НаборПоказателей" , Отчеты[ПараметрыОтчета.ИдентификаторОтчета].ПолучитьНаборПоказателей());
ПараметрыОтчета.Вставить("ОтветственноеЛицо" , Перечисления.ОтветственныеЛицаОрганизаций.ОтветственныйЗаБухгалтерскиеРегистры);
ПараметрыОтчета.Вставить("ВыводитьЕдиницуИзмерения" , ВыводитьЕдиницуИзмерения);
Возврат ПараметрыОтчета;
КонецФункции
&НаСервере
Функция Расш1_СформироватьОтчетНаСервере() Экспорт
Если Не КомпоновщикИнициализирован Тогда
ИнициализацияКомпоновщикаНастроек();
КонецЕсли;
Если Не ПроверитьЗаполнение() Тогда
Возврат Новый Структура("ЗаданиеВыполнено, ОтказПроверкиЗаполнения", Истина, Истина);
КонецЕсли;
ИБФайловая = ОбщегоНазначения.ИнформационнаяБазаФайловая();
ДлительныеОперации.ОтменитьВыполнениеЗадания(ИдентификаторЗадания);
ИдентификаторЗадания = Неопределено;
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "НеИспользовать");
Отчет.КомпоновщикНастроек.Настройки.ДополнительныеСвойства.Вставить("ВыводитьЗаголовок", ВыводитьЗаголовок);
Отчет.КомпоновщикНастроек.Настройки.ДополнительныеСвойства.Вставить("ВыводитьПодвал" , ВыводитьПодвал);
Отчет.КомпоновщикНастроек.Настройки.Отбор.ИдентификаторПользовательскойНастройки = "";
Отчет.КомпоновщикНастроек.Настройки.Порядок.ИдентификаторПользовательскойНастройки = "";
Отчет.КомпоновщикНастроек.Настройки.УсловноеОформление.ИдентификаторПользовательскойНастройки = "";
// Получаем параметры отчета из нашей функции
ПараметрыОтчета = Расш1_ПодготовитьПараметрыОтчета();
Если ИБФайловая Тогда
АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
БухгалтерскиеОтчетыВызовСервера.СформироватьОтчет(ПараметрыОтчета, АдресХранилища);
РезультатВыполнения = Новый Структура("ЗаданиеВыполнено", Истина);
Иначе
РезультатВыполнения = ДлительныеОперации.ЗапуститьВыполнениеВФоне(
УникальныйИдентификатор,
"БухгалтерскиеОтчетыВызовСервера.СформироватьОтчет",
ПараметрыОтчета,
БухгалтерскиеОтчетыКлиентСервер.ПолучитьНаименованиеЗаданияВыполненияОтчета(ЭтаФорма));
АдресХранилища = РезультатВыполнения.АдресХранилища;
ИдентификаторЗадания = РезультатВыполнения.ИдентификаторЗадания;
КонецЕсли;
Если РезультатВыполнения.ЗаданиеВыполнено Тогда
ЗагрузитьПодготовленныеДанные();
КонецЕсли;
Элементы.Сформировать.КнопкаПоУмолчанию = Истина;
Возврат РезультатВыполнения;
КонецФункции
&НаКлиенте
Процедура Расш1_СформироватьОтчет(Команда)
// СтандартныеПодсистемы.ОценкаПроизводительности
УИДЗамера = ОценкаПроизводительностиКлиент.НачатьЗамерВремени(Ложь, "ФормированиеОтчетаАнализСчета");
// СтандартныеПодсистемы.ОценкаПроизводительности
ОчиститьСообщения();
ОтключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания");
// Вызываем нашу функцию Расш1_сформироватьОтчетНаСервере
РезультатВыполнения = Расш1_СформироватьОтчетНаСервере();
Если Не РезультатВыполнения.ЗаданиеВыполнено Тогда
ДлительныеОперацииКлиент.ИнициализироватьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания);
ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания", 1, Истина);
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "ФормированиеОтчета");
Иначе
ЗафиксироватьДлительностьКлючевойОперации();
Если НЕ РезультатВыполнения.Свойство("ОтказПроверкиЗаполнения") Тогда
БухгалтерскийУчетКлиентПереопределяемый.ПодключитьПроверкуАктуальности(ЭтотОбъект);
КонецЕсли;
КонецЕсли;
Если РезультатВыполнения.Свойство("ОтказПроверкиЗаполнения") Тогда
ПоказатьНастройки("");
Иначе
СкрытьНастройки();
КонецЕсли;
//обработку из основной конфигурации отменяем
УстановитьВыполнениеОбработчиковСобытия(Ложь);
КонецПроцедуры
&НаСервере
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьВыполнениеПослеОбработчиковСобытия("Расш1_ПриСозданииНаСервереПосле", Неопределено);
КонецПроцедуры
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ,СтандартнаяОбработка,ДополнительныйПараметр)
Если Параметры.Свойство("ОткрытьРасшифровку") И Параметры.ОткрытьРасшифровку Тогда
Расш1_СформироватьОтчетНаСервере();
КонецЕсли;
КонецПроцедуры
Здесь следует обратить внимание на несколько моментов
1) Не забыть указать метод УстановитьВыполнениеОбработчиковСобытия(ложь) в самом конце процеду "СформироватьОтчет", что бы не вызывался обработчик из основной конфигурации
2) В перенесенных функциях и процедуре заменить обращение к стандарным функциям на наши
В процедуре Расш1_СформироватьОтчет - заменить строку
РезультатВыполнения = СформироватьОтчетНаСервер()
на
РезультатВыполнения = Расш1_СформироватьОтчетНаСервер()
И в функции "СформироватьОтчетНаСервере"
ПараметрыОтчета = ПодготовитьПараметрыОтчета();
на
ПараметрыОтчета = Расш1_ПодготовитьПараметрыОтчета();
3) в приведенном выше примере можно заметить, что в Расширении еще переопределяется процедура ПриСозданииНаСервере. Сделано это для правильной работы при открытии отчета по расшифровке из другого отчета, так как в этом случае, Расширение не перехватывает вызов СформирватьОтчетНаСервере (), вызванного из Общего модуля. Поэтому, сначала вызывается процедура из Расширения, которая устанавливает обработчик, который будет вызван после отработки процедуры основной конфигурации, и далее снова передаст управление Расширению. И уже здесь мы переформировываем отчет с установкой нужных отборов. Пока данной действие мне пригодилось только для отчета Карточка Счета (расшифровка вызывается из отчета Анализ счета), но если необходимо - такой же механизм можно включить и в другие отчеты.
Стоит сказать пару слов о недостатках данного подхода
- В заголовках отчета пользователь будет видеть установленный отбор (но в настройках его не будет, и снять отбор пользователь не сможет).
- Некорректные данные. Ну тут все стандартно. В принципе, как вариант, можно оставлять не закрывать ОСВ так как пользователь будет видеть общую сумму и полную картину, а вот расшифровки через другие отчеты придется закрывать.
- Требуется настройка прав на документы. В отчете суммы он может не увидеть, а вот если сможет открыть документ ...
- В данном решении не все отчеты прописаны, через которые можно получить данные (например отсутствует Шахматка) - пока не дошли руки . Думаю, реализовать в ближайшее время.
- Более сложная настройка по сравнению с RLS - Кода хоть и немного, но все же больше чем настройка через RLS
Выношу свое решение на публику. Буду рад обсудить данную тему, конструктивной критике или совету как можно улучшить данный механизм .
P.S. В прикрепленном файле содержится Расширение конфигурации + текстовый файл с кодом Общего модуля
Вам остается создать справочник.
Напомню - Эксперименты лучше проводить сначала на копии базы)))