Рано или поздно перед разработчиками и системными архитекторами крупных баз на платформе 1С встает задача ограничения прав доступа внутри бухгалтерии. Самый частый сценарий — скрыть данные по 70 счету (расчеты с персоналом по оплате труда), чтобы рядовые бухгалтеры не видели заработные платы коллег и руководства. Аналогичные требования могут возникать для валютных счетов, кассы или расчетов с учредителями. Для комплексной защиты таких сведений можно использовать готовое расширение для ограничения доступа к зарплатным отчетам и документам.
В этой статье мы подробно разберем, почему стандартный механизм RLS (ограничение доступа на уровне записей) не подходит для решения этой задачи «в лоб», проанализируем возможные последствия и рассмотрим наиболее эффективные программные и организационные методы обхода этого ограничения.
---
Попытка настроить RLS непосредственно на регистр бухгалтерии Хозрасчетный или План счетов сталкивается с фундаментальными ограничениями платформы «1С:Предприятие» и методологии двойной записи:
<Объект не найден>, что нарушит целостность отчетов.Поэтому решать задачу необходимо либо на уровне интерфейса и компоновки отчетов, либо организационными методами.
---
Прежде чем приступать к написанию кода, проанализируем самый простой и надежный методологический путь. Если задача состоит в сокрытии детализации по зарплате (70 счет), то правильным решением будет отказ от ведения персонального учета сотрудников непосредственно в базе 1С:ERP.
Выясним, как это реализовать:
При таком подходе рядовые бухгалтеры видят общие обороты по 70 счету (что не является тайной, так как затраты на оплату труда все равно распределяются по публичным затратным счетам 20, 25, 26, 44), но физически не могут сопоставить суммы с конкретными персоналиями. Никаких доработок кода при этом не требуется.
---
Если административный вариант не подходит, и аналитика на счете должна быть, нам придется программно запретить пользователям без определенной роли формировать отчеты, в параметрах или отборах которых фигурирует запрещенный счет. Для решения этой задачи можно использовать готовое решение для ограничения видимости 70 счета.
Для реализации этого метода создадим профиль безопасности или роль, например, ДоступКЗакрытымСчетам. Пользователям, у которых этой роли нет, мы запретим выполнять отчеты. Все стандартные бухгалтерские отчеты в современных конфигурациях (ERP, КА, БП) проходят проверку заполнения настроек в общем модуле.
Разберем по шагам, как вклиниться в этот процесс с помощью механизма расширений:
БухгалтерскиеОтчетыВызовСервера.ОбработкаПроверкиЗаполнения с аннотацией &После.Посмотрим на пример реализации кода в расширении:
&После("ОбработкаПроверкиЗаполнения")
Процедура Расш_ОбработкаПроверкиЗаполнения(ОтчетОбъект, Отказ, Проверки = Неопределено) Экспорт
// Если у пользователя есть полные права или специальная роль доступа — игнорируем проверку
Если РольДоступна("ПолныеПрава") Или РольДоступна("ДоступКЗакрытымСчетам") Тогда
Возврат;
КонецЕсли;
// Зададим код счета, который необходимо скрыть (например, счет 70)
КодЗапрещенногоСчета = "70";
// Проверим основной счет, выбранный в настройках отчета
Если Свойство(ОтчетОбъект, "Счет") И ЗначениеЗаполнено(ОтчетОбъект.Счет) Тогда
Если ОтчетОбъект.Счет.Код = КодЗапрещенногоСчета Тогда
Отказ = Истина;
ОбщегоНазначения.СообщитьПользователю("У вас нет прав на просмотр отчетов по счету " + КодЗапрещенногоСчета, , , , Отказ);
Возврат;
КонецЕсли;
КонецЕсли;
// Также необходимо проверить таблицу отборов (компоновщик настроек) на наличие запрещенного счета
КомпоновщикНастроек = ОтчетОбъект.КомпоновщикНастроек;
Для Каждого ЭлементОтбора Из КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если Строка(ЭлементОтбора.ЛевоеЗначение) = "Счет" Или Строка(ЭлементОтбора.ЛевоеЗначение) = "СчетДт" Или Строка(ЭлементОтбора.ЛевоеЗначение) = "СчетКт" Тогда
Если ЭлементОтбора.Использование И ЭлементОтбора.ПравоеЗначение = ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодЗапрещенногоСчета) Тогда
Отказ = Истина;
ОбщегоНазначения.СообщитьПользователю("Запрещено использовать счет " + КодЗапрещенногоСчета + " в отборах отчетов!", , , , Отказ);
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Вспомогательная функция для безопасного чтения свойств объекта
Функция Свойство(Объект, ИмяСвойства)
Попытка
Возврат Объект[ИмяСвойства] <> Неопределено;
Исключение
Возврат Ложь;
КонецПопытки;
КонецФункции
Этот способ надежно защищает от формирования специализированных отчетов (например, «Карточка счета 70» или «ОСВ по счету 70»). Однако остается лазейка: пользователь может сформировать общую ОСВ по всему плану счетов и увидеть там итоговую строку по 70 счету.
---
Чтобы закрыть лазейку с просмотром общих отчетов (где счет 70 выступает как один из многих или как корреспондирующий), нам потребуется вмешаться в процесс формирования выборки данных. Рассмотрим, как решить эту задачу в модуле менеджера отчета (например, ОСВ) перед компоновкой макета.
Проанализируем ситуацию: в запросах получения движений нам нужно полностью отсечь проводки, в которых задействован наш запрещенный счет. Сделать это нужно как для дебетовой, так и для кредитовой стороны проводки.
Важный логический нюанс: при написании условий исключения разработчики часто допускают ошибку в логических операторах И / ИЛИ. Если мы хотим убрать проводки, где хотя бы одна из сторон равна запрещенному счету, условие отбора в запросе должно выглядеть следующим образом:
ГДЕ Движения.СчетДт <> &ЗапрещенныйСчет И Движения.СчетКт <> &ЗапрещенныйСчет
Если написать через ИЛИ (СчетДт <> 70 ИЛИ СчетКт <> 70), то под отбор попадет проводка, где Дт равен 70, а Кт равен 51 (так как 51 действительно не равен 70, и условие ИЛИ вернет Истину). Использование оператора И гарантирует, что проводка будет выбрана только в том случае, если ни одна из ее сторон не содержит запрещенный счет.
Внедрить это условие можно через перехват компоновщика настроек в процедуре ПередКомпоновкойМакета менеджера отчета в расширении:
&Перед("ПередКомпоновкойМакета")
Процедура Расш_ПередКомпоновкойМакета(ПараметрыМакета, КомпоновщикНастроек, СхемаКомпоновкиДанных)
Если Не РольДоступна("ДоступКЗакрытымСчетам") Тогда
ЗапрещенныйСчет = ПланыСчетов.Хозрасчетный.НайтиПоКоду("10.06"); // Пример для теста
// Добавляем жесткий отбор в настройки компоновщика программно
ГруппаОтбора = КомпоновщикНастроек.Settings.Filter.Elements.Add(Type("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаОтбора.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИ;
ГруппаОтбора.Использование = Истина;
ЭлементОтбораДт = ГруппаОтбора.Elements.Add(Type("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораДт.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СчетДт");
ЭлементОтбораДт.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавен;
ЭлементОтбораДт.ПравоеЗначение = ЗапрещенныйСчет;
ЭлементОтбораДт.Использование = Истина;
ЭлементОтбораКт = ГруппаОтбора.Elements.Add(Type("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораКт.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СчетКт");
ЭлементОтбораКт.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавен;
ЭлементОтбораКт.ПравоеЗначение = ЗапрещенныйСчет;
ЭлементОтбораКт.Использование = Истина;
КонецЕсли;
КонецПроцедуры
При таком подходе любые формируемые пользователем отчёты будут выводить данные корректно для открытых счетов, но все проводки, корреспондирующие с закрытым счетом, будут просто отсекаться из результата компоновки данных. Итоговые суммы по открытым счетам будут уменьшены на суммы скрытых проводок. Бухгалтер должен быть предупрежден о том, что при отсутствии прав итоговый баланс в его отчетах может «не сходиться».
---
Полностью и бесшовно скрыть бухгалтерский счет в типовой конфигурации 1С без методологических последствий невозможно. Выбирая стратегию реализации, придерживайтесь следующих правил:
БухгалтерскиеОтчетыВызовСервера) и блокируйте вывод информации на уровне интерфейса.Начисление зарплаты, Отражение зарплаты в финучете или банковским выпискам. Доступ к этим документам должен быть параллельно ограничен на уровне обычных ролей профилей групп доступа.