Однажды, читая тех. задание от аналитика, увидел пункт с замечанием: "Вот некоторые папки бы убрать из этой тематики, а то они засоряют взгляд, куда файлы и таблички закидывать". Потом ещё был случай, когда для определенной тематики нужно было добавить роль файла (папку) с очень узким направлением. То есть эта папка буквально нужна только для этой тематики, а более нигде. Посмотрев на это всё, я принялся пилить документооборот и делать "красиво" для пользователей программы.
В данной разработке добавлена возможность указывать тематику или список тематик по ролям файлов. Выполняется настройка через "Вид документа", если включена настройка "Вести учет по тематикам".


Хранение данных оформлено через регистр сведений. Он хранит данные о виде документа, роли файла и тематику. Для каждой тематики записывается отдельная строка регистра сведений.

Сама доработка затрагивает видимость папок для всех форм, где отображается обзорная часть документа: форма документа, форма списка документов, форма задач.



Программный код по модулям:
&Вместо("ПолучитьДанныеФайловДляСписка")
Функция ДБ_ПолучитьДанныеФайловДляСписка(Файлы, ВладелецФайла, ПоказыватьУдаленныеФайлы, ОтметитьЗахваченныеФайлы, МассивКомбинацийРолей, ЗаполнятьДанныеДляВизуализации, ВидДокумента)
Результат = ПродолжитьВызов(Файлы, ВладелецФайла, ПоказыватьУдаленныеФайлы, ОтметитьЗахваченныеФайлы, МассивКомбинацийРолей, ЗаполнятьДанныеДляВизуализации, ВидДокумента);
Если НЕ ДелопроизводствоКлиентСервер.ЭтоДокумент(ВладелецФайла) Тогда
Возврат Результат;
КонецЕсли;
Если МассивКомбинацийРолей = Неопределено Или МассивКомбинацийРолей.Количество() = 0 Тогда
Возврат Результат;
КонецЕсли;
Тематика = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВладелецФайла, "Тематика");
Если Не ЗначениеЗаполнено(Тематика) Тогда
Возврат Результат;
КонецЕсли;
ДополнитьРолиФайловТематиками(ВидДокумента, МассивКомбинацийРолей);
ОтфильтрованныеРоли = ОтфильтроватьРолиФайловПоТематике(МассивКомбинацийРолей, Тематика);
МассивКомбинацийРолей.Очистить();
Для Каждого ОписаниеРоли Из ОтфильтрованныеРоли Цикл
КомбинацияРоли = Новый Структура("Роль, Обязательная",
ОписаниеРоли.Роль, ОписаниеРоли.Обязательная);
МассивКомбинацийРолей.Добавить(КомбинацияРоли);
КонецЦикла;
Возврат Результат;
КонецФункции
&Вместо("ЗаполнитьКэшВидаДокументаНаФорме")
Процедура ДБ_ЗаполнитьКэшВидаДокументаНаФорме(Форма, ВидДокумента)
ПродолжитьВызов(Форма, ВидДокумента);
ДокументСсылка = Форма.Объект;
Если Не ЗначениеЗаполнено(ДокументСсылка.Тематика) Тогда
Возврат;
КонецЕсли;
Форма.ВидДокументаКэш.РолиФайлов = ОтфильтроватьРолиФайловПоТематике(
Форма.ВидДокументаКэш.РолиФайлов, ДокументСсылка.Тематика);
КонецПроцедуры
&ИзменениеИКонтроль("КэшВидаДокумента")
Функция ДБ_КэшВидаДокумента(ВидДокумента)
Если Не ЗначениеЗаполнено(ВидДокумента) Тогда
Возврат НовыйКэшВидаДокумента();
Иначе
ВидДокументаКэш = ОбщегоНазначенияДокументооборот.ЗначенияРеквизитовОбъектаВПривилегированномРежиме(
ВидДокумента, ИменаРеквизитовДляКешаВидаДокументов());
РолиФайлов = РолиФайловДляВидаДокументов(ВидДокумента, ВидДокументаКэш);
ВидДокументаКэш.Вставить("РолиФайлов", Новый Массив);
Для Каждого Стр Из РолиФайлов Цикл
#Удаление
ОписаниеРоли = Новый Структура(
"Роль, Обязательная, ТолькоОдинФайл");
#КонецУдаления
#Вставка
ОписаниеРоли = Новый Структура(
"Роль, Обязательная, ТолькоОдинФайл, Тематики");
#КонецВставки
ЗаполнитьЗначенияСвойств(ОписаниеРоли, Стр);
ВидДокументаКэш.РолиФайлов.Добавить(ОписаниеРоли);
КонецЦикла;
#Вставка
ДополнитьРолиФайловТематиками(ВидДокумента, ВидДокументаКэш.РолиФайлов);
#КонецВставки
ВидДокументаКэш.Вставить("ОбработкаЗадана",
Справочники.НастройкиОбработкиВидовОбъектов.НастройкиОбработкиЗаданы(
ВидДокумента, ТекущаяДатаСеанса()));
ВидДокументаКэш.Вставить("НастройкиДействийЗаданы",
НастройкиДействий.КоличествоНастроекПравилОбработки(ВидДокумента) > 0);
КонецЕсли;
Возврат ВидДокументаКэш; //@skip-check constructor-function-return-section
КонецФункции
// Отбирает роли файлов по тематике документа.
// Роль включается, если у неё нет ограничения по тематикам либо тематика документа есть в списке.
// При отсутствии тематики документа возвращается исходный набор ролей.
//
// Параметры:
// РолиФайлов - Массив из Структура - описания ролей (поля Роль, Обязательная, Тематики и др.).
// Тематика - СправочникСсылка.ТематикиДокументов - тематика документа.
//
// Возвращаемое значение:
// Массив из Структура - отфильтрованные роли без дублей по полю Роль.
//
Функция ОтфильтроватьРолиФайловПоТематике(РолиФайлов, Тематика) Экспорт
Если Не ЗначениеЗаполнено(Тематика) Или РолиФайлов = Неопределено Тогда
Возврат РолиФайлов;
КонецЕсли;
Результат = Новый Массив;
ИспользуемыеРоли = Новый Соответствие;
Для Каждого ОписаниеРоли Из РолиФайлов Цикл
Роль = ОписаниеРоли.Роль;
Если ИспользуемыеРоли[Роль] <> Неопределено Тогда
Продолжить;
КонецЕсли;
Если РольПодходитТематике(ОписаниеРоли, Тематика) Тогда
ИспользуемыеРоли.Вставить(Роль, Истина);
Результат.Добавить(ОписаниеРоли);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Дополняет описания ролей массивом тематик из регистра ДБ_ТематикиРолейФайлов.
//
// Параметры:
// ВидДокумента - СправочникСсылка.ВидыДокументов - вид документа.
// РолиФайлов - Массив из Структура - описания ролей кэша вида документа.
//
Процедура ДополнитьРолиФайловТематиками(ВидДокумента, РолиФайлов) Экспорт
ТематикиПоРолям = РегистрыСведений.ДБ_ТематикиРолейФайлов.ТематикиРолейФайловПоВидуДокумента(ВидДокумента);
Для Каждого ОписаниеРоли Из РолиФайлов Цикл
МассивТематик = ТематикиПоРолям.Получить(ОписаниеРоли.Роль);
Если МассивТематик = Неопределено Тогда
МассивТематик = Новый Массив;
КонецЕсли;
ОписаниеРоли.Вставить("Тематики", МассивТематик);
КонецЦикла;
КонецПроцедуры
// Проверяет, подходит ли описание роли файлов тематике документа.
//
// Параметры:
// ОписаниеРоли - Структура - описание роли с полем Тематики (Массив) или устаревшим ДБ_Тематика.
// Тематика - СправочникСсылка.ТематикиДокументов - тематика документа.
//
// Возвращаемое значение:
// Булево
//
Функция РольПодходитТематике(ОписаниеРоли, Тематика)
ТематикиРоли = ОписаниеРоли.Тематики;
Если ТематикиРоли.Количество() Тогда
Возврат ТематикиРоли.Найти(Тематика) <> Неопределено;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
&Вместо("ИнициализироватьДокументыПредприятияФормаЭлемента")
Функция ДБ_ИнициализироватьДокументыПредприятияФормаЭлемента(ДокументОбъект)
Результат = ПродолжитьВызов(ДокументОбъект);
Если ЗначениеЗаполнено(ДокументОбъект.Тематика) Тогда
Результат.КэшВидаДокумента.РолиФайлов = Делопроизводство.ОтфильтроватьРолиФайловПоТематике(
Результат.КэшВидаДокумента.РолиФайлов, ДокументОбъект.Тематика);
КонецЕсли;
Возврат Результат;
КонецФункции
&ИзменениеИКонтроль("ПроверитьРолиФайловПередЗапускомОбработки")
Процедура ДБ_ПроверитьРолиФайловПередЗапускомОбработки(Знач Предмет)
// Документы
Если ДелопроизводствоКлиентСервер.ЭтоДокументПредприятия(Предмет) Тогда
#Удаление
ВидДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Предмет, "ВидДокумента");
РолиФайлов = Делопроизводство.РолиФайловДляВидаДокументов(ВидДокумента);
#КонецУдаления
#Вставка
РеквизитыДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Предмет, "ВидДокумента, Тематика");
КэшВидаДокумента = Делопроизводство.КэшВидаДокумента(РеквизитыДокумента.ВидДокумента);
РолиФайлов = Делопроизводство.ОтфильтроватьРолиФайловПоТематике(
КэшВидаДокумента.РолиФайлов, РеквизитыДокумента.Тематика);
#КонецВставки
Если РолиФайлов.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Получим файлы
Файлы = РаботаСФайламиВызовСервера.ПолучитьВсеПодчиненныеФайлы(Предмет, Ложь);
КэшРолейФайлов = Новый Соответствие(); // ключ - файл, значение - роль
// Роли файлов
ЧислоРолейОбязательная = 0;
ЧислоРолейТолькоОдинФайл = 0;
ЧислоФайлов = 0;
ЧислоФайловБезРоли = 0;
ФайлСсылка = Неопределено; // ссылка на файл без роли
Для Каждого СтрРоль Из РолиФайлов Цикл
Если СтрРоль.Обязательная Тогда
ЧислоРолейОбязательная = ЧислоРолейОбязательная + 1;
КонецЕсли;
Если СтрРоль.ТолькоОдинФайл Тогда
ЧислоРолейТолькоОдинФайл = ЧислоРолейТолькоОдинФайл + 1;
КонецЕсли;
КонецЦикла;
Для Каждого Файл Из Файлы Цикл
ЧислоФайлов = ЧислоФайлов + 1;
РольФайла = Неопределено;
РолиФайлаМассив = РегистрыСведений.РолиФайловДокументов.ПолучитьРолиФайла(Файл);
Если РолиФайлаМассив.Количество() <> 0 Тогда
РольФайла = РолиФайлаМассив[0];
КонецЕсли;
КэшРолейФайлов[Файл] = РольФайла;
Если Не ЗначениеЗаполнено(РольФайла) Тогда
ЧислоФайловБезРоли = ЧислоФайловБезРоли + 1;
ФайлСсылка = Файл;
КонецЕсли;
КонецЦикла;
// Обязательная
Для Каждого СтрРоль Из РолиФайлов Цикл
Если СтрРоль.Обязательная Тогда
Если Не ЕстьФайлыСРолью(КэшРолейФайлов, СтрРоль.Роль) Тогда
Если ЧислоРолейОбязательная = 1 И ЧислоФайлов = 1 И ЧислоФайловБезРоли = 1 Тогда
// автоматом поставим роль файлу
ЗаписатьРольФайла(ФайлСсылка, СтрРоль.Роль);
Иначе
ТекстПредупреждения = СтрШаблон(
НСтр("ru = 'Для запуска в обработку требуется указать хотя бы один файл с ролью ""%1"".'"), СтрРоль.Роль);
ВызватьИсключение ТекстПредупреждения;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// ТолькоОдинФайл
Для Каждого СтрРоль Из РолиФайлов Цикл
Если СтрРоль.ТолькоОдинФайл Тогда
ЧислоФайловСРолью = ЧислоФайловСРолью(КэшРолейФайлов, СтрРоль.Роль);
Если ЧислоФайловСРолью <> 1 Тогда
Если ЧислоРолейТолькоОдинФайл = 1 И ЧислоФайлов = 1 И ЧислоФайловБезРоли = 1 Тогда
// автоматом поставим роль файлу
ОбработкиОбъектовВызовСервера.ЗаписатьРольФайла(ФайлСсылка, СтрРоль.Роль);
ИначеЕсли ЧислоФайловСРолью >= 2 Тогда
ТекстПредупреждения = СтрШаблон(
НСтр("ru = 'Для запуска в обработку должен быть указан только один файл с ролью ""%1"".'"), СтрРоль.Роль);
ВызватьИсключение ТекстПредупреждения;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&После("ПриЗаписи")
Процедура ДБ_ПриЗаписи(Отказ)
Если Отказ Тогда
Возврат;
КонецЕсли;
Если НЕ ЭтотОбъект.ВестиУчетПоТематикам Тогда
РанееУчетПоТематикамВелся = ОбщегоНазначенияДокументооборот.ИзменилосьЗначениеРеквизитов(
ЭтотОбъект, "ВестиУчетПоТематикам");
Если РанееУчетПоТематикамВелся Тогда
РегистрыСведений.ДБ_ТематикиРолейФайлов.УдалитьТематикиРолейПоВидуДокумента(Ссылка);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&Вместо("ОтслеживаемыеРеквизиты")
Функция ДБ_ОтслеживаемыеРеквизиты()
ОтслеживаемыеРеквизиты = ПродолжитьВызов();
ОбщегоНазначенияДокументооборот.ДополнитьОтслеживаемыеРеквизиты(
ОтслеживаемыеРеквизиты,
"ВестиУчетПоТематикам");
Возврат ОтслеживаемыеРеквизиты;
КонецФункции
#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ДБ_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
ОбновитьТематикиРолейФайлов();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ДБ_ПриЧтенииНаСервереПосле(ТекущийОбъект)
ОбновитьТематикиРолейФайлов();
КонецПроцедуры
&НаСервере
Процедура ДБ_ПослеЗаписиНаСервереПосле(ТекущийОбъект, ПараметрыЗаписи)
Если ТекущийОбъект.ВестиУчетПоТематикам Тогда
ЗаписатьТематикиРолейФайловВРегистр(ТекущийОбъект);
ЗаполнитьПредставленияТематикРолейФайлов();
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыРолиФайлов
&НаКлиенте
Процедура ДБ_РолиФайловВыборПосле(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Если Элемент.ТекущийЭлемент <> Элементы.ДБ_РолиФайловТематикиПредставление Тогда
Возврат;
КонецЕсли;
СтандартнаяОбработка = Ложь;
ТекущиеДанные = Элементы.РолиФайлов.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
Если Не ЗначениеЗаполнено(ТекущиеДанные.Роль) Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Сначала выберите роль файла.'"));
Возврат;
КонецЕсли;
ВыбранныеТематики = ТематикиРоли(ДБ_ТематикиРолейФайлов, ТекущиеДанные.Роль);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ВидДокумента", Объект.Ссылка);
ПараметрыФормы.Вставить("ВыбранныеТематики", ВыбранныеТематики);
ДополнительныеПараметры = Новый Структура("Роль", ТекущиеДанные.Роль);
ОбработкаОповещения = Новый ОписаниеОповещения("ДБ_РолиФайловТематикиНачалоВыбораЗавершение",
ЭтотОбъект,
ДополнительныеПараметры);
ОткрытьФорму("Справочник.ТематикиДокументов.Форма.ВыборИзСпискаСПометками",
ПараметрыФормы,
Элемент, , , ,
ОбработкаОповещения,
РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ДБ_РолиФайловПослеУдаленияПосле(Элемент)
ТекущиеДанные = Элементы.РолиФайлов.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ОчиститьТематикиРолиФайла(ТекущиеДанные.Роль);
Модифицированность = Истина;
КонецПроцедуры
&НаКлиенте
Процедура ДБ_РолиФайловРольПриИзмененииПосле(Элемент)
Если НЕ Объект.ВестиУчетПоТематикам Тогда
Возврат;
КонецЕсли;
ТекущиеДанные = Элементы.РолиФайлов.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
СписокТематик = ТематикиРоли(ДБ_ТематикиРолейФайлов, ТекущиеДанные.Роль);
ТекущиеДанные.ДБ_ТематикиПредставление = ПредставлениеТематикДляРолиФайлов(СписокТематик);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
&НаКлиентеНаСервереБезКонтекста
&После("ОбновитьВидимостьРеквизитов")
Процедура ДБ_ОбновитьВидимостьРеквизитов(Форма)
Объект = Форма.Объект;
Элементы = Форма.Элементы;
Элементы.ДБ_РолиФайловТематикиПредставление.Видимость = Объект.ВестиУчетПоТематикам;
КонецПроцедуры
&НаКлиенте
&ИзменениеИКонтроль("РолиФайловПередНачаломДобавленияПродолжение")
Процедура ДБ_РолиФайловПередНачаломДобавленияПродолжение(Результат, ПараметрыЗаписи)
Если ТипЗнч(Результат) <> Тип("СправочникСсылка.РолиФайлов") Тогда
Возврат;
КонецЕсли;
Роль = Результат;
Для Каждого Стр Из Объект.РолиФайлов Цикл
Если Стр.Роль = Роль Тогда
Сообщить(НСтр("ru = 'Эта роль уже выбрана ранее.'"));
Возврат;
КонецЕсли;
КонецЦикла;
НовСтр = Объект.РолиФайлов.Добавить();
НовСтр.Роль = Результат;
#Вставка
НовСтр.ДБ_ТематикиПредставление = ПредставлениеТематикДляРолиФайлов();
#КонецВставки
РолиКоличество = Объект.РолиФайлов.Количество();
Модифицированность = Истина;
КонецПроцедуры
// Загружает тематики ролей файлов из регистра в реквизит формы и обновляет представления в таблице.
// Для нового (незаписанного) вида документа только заполняет представления.
//
&НаСервере
Процедура ОбновитьТематикиРолейФайлов()
Если НЕ Объект.ВестиУчетПоТематикам Тогда
Возврат;
КонецЕсли;
ДБ_ТематикиРолейФайлов.Очистить();
Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
ЗаполнитьПредставленияТематикРолейФайлов();
Возврат;
КонецЕсли;
ТематикиПоРолям = РегистрыСведений.ДБ_ТематикиРолейФайлов.ТематикиРолейФайловПоВидуДокумента(Объект.Ссылка);
Для Каждого СтрокаРоли Из Объект.РолиФайлов Цикл
Если Не ЗначениеЗаполнено(СтрокаРоли.Роль) Тогда
СтрокаРоли.ДБ_ТематикиПредставление = "";
Продолжить;
КонецЕсли;
СписокТематик = Новый СписокЗначений;
МассивТематик = ТематикиПоРолям.Получить(СтрокаРоли.Роль);
Если ЗначениеЗаполнено(МассивТематик) Тогда
СписокТематик.ЗагрузитьЗначения(МассивТематик);
УстановитьТематикиРолиФайла(СтрокаРоли.Роль, СписокТематик);
КонецЕсли;
СтрокаРоли.ДБ_ТематикиПредставление = ПредставлениеТематикДляРолиФайлов(СписокТематик);
КонецЦикла;
КонецПроцедуры
// Сохраняет тематики ролей файлов из реквизита формы в регистр сведений.
//
// Параметры:
// ТекущийОбъект - СправочникОбъект.ВидыДокументов - записанный объект вида документа.
//
&НаСервере
Процедура ЗаписатьТематикиРолейФайловВРегистр(ТекущийОбъект)
ТематикиПоРолям = Новый Соответствие;
Для Каждого СтрокаРоли Из Объект.РолиФайлов Цикл
Если ТематикиПоРолям.Получить(СтрокаРоли.Роль) <> Неопределено Тогда
Продолжить;
КонецЕсли;
НайденныеСтроки = ДБ_ТематикиРолейФайлов.НайтиСтроки(Новый Структура("Роль", СтрокаРоли.Роль));
Если НайденныеСтроки.Количество() > 0 Тогда
ТематикиПоРолям.Вставить(СтрокаРоли.Роль, НайденныеСтроки[0].Тематики);
КонецЕсли;
КонецЦикла;
РегистрыСведений.ДБ_ТематикиРолейФайлов.ЗаписатьТематикиРолейВидаДокумента(
ТекущийОбъект.Ссылка, ТематикиПоРолям);
КонецПроцедуры
// Возвращает список тематик, назначенных роли файла, из реквизита формы.
//
// Параметры:
// Роль - СправочникСсылка.РолиФайлов - роль файла.
//
// Возвращаемое значение:
// СписокЗначений - тематики роли; пустой список, если тематики не заданы.
//
&НаКлиентеНаСервереБезКонтекста
Функция ТематикиРоли(ТематикиРолейФайлов, Роль)
ПараметрыОтбора = Новый Структура("Роль", Роль);
НайденныеСтроки = ТематикиРолейФайлов.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
Возврат НайденныеСтроки[0].Тематики;
КонецЕсли;
Возврат Новый СписокЗначений;
КонецФункции
// Обрабатывает результат выбора тематик из формы выбора с пометками.
// Сохраняет отмеченные тематики для роли или очищает их, если выбраны все либо ни одной.
//
// Параметры:
// ВыбранноеЗначение - СписокЗначений - результат выбора с пометками.
// ДополнительныеПараметры - Структура - дополнительные параметры оповещения:
// * Роль - СправочникСсылка.РолиФайлов - роль файла, для которой выбирались тематики.
//
&НаКлиенте
Процедура ДБ_РолиФайловТематикиНачалоВыбораЗавершение(ВыбранноеЗначение, ДополнительныеПараметры) Экспорт
Если ТипЗнч(ВыбранноеЗначение) <> Тип("СписокЗначений") Тогда
Возврат;
КонецЕсли;
Роль = ДополнительныеПараметры.Роль;
СписокТематик = Новый СписокЗначений;
ЕстьНеотмеченные = Ложь;
Для Каждого Элемент Из ВыбранноеЗначение Цикл
Если Элемент.Пометка Тогда
СписокТематик.Добавить(Элемент.Значение, Элемент.Представление);
Иначе
ЕстьНеотмеченные = Истина;
КонецЕсли;
КонецЦикла;
Если СписокТематик.Количество() И ЕстьНеотмеченные Тогда
УстановитьТематикиРолиФайла(Роль, СписокТематик);
Иначе
ОчиститьТематикиРолиФайла(Роль, СписокТематик);
КонецЕсли;
ТекущиеДанные = Элементы.РолиФайлов.ТекущиеДанные;
ТекущиеДанные.ДБ_ТематикиПредставление = ПредставлениеТематикДляРолиФайлов(СписокТематик);
Модифицированность = Истина;
КонецПроцедуры
// Устанавливает список тематик для роли файла в реквизите формы.
// При отсутствии строки по роли добавляет новую.
//
// Параметры:
// Роль - СправочникСсылка.РолиФайлов - роль файла.
// СписокТематик - СписокЗначений - тематики, назначаемые роли.
//
&НаСервере
Процедура УстановитьТематикиРолиФайла(Роль, СписокТематик)
ПараметрыОтбора = Новый Структура("Роль", Роль);
НайденныеСтроки = ДБ_ТематикиРолейФайлов.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
НайденныеСтроки[0].Тематики = СписокТематик;
Иначе
СтрокаТематикРолей = ДБ_ТематикиРолейФайлов.Добавить();
СтрокаТематикРолей.Роль = Роль;
СтрокаТематикРолей.Тематики = СписокТематик;
КонецЕсли;
КонецПроцедуры
// Удаляет тематики роли файла из реквизита формы.
// При передаче списка дополнительно очищает его.
//
// Параметры:
// Роль - СправочникСсылка.РолиФайлов - роль файла.
// СписокТематик - СписокЗначений - список для очистки.
// - Неопределено - очищать только реквизит формы.
//
&НаКлиенте
Процедура ОчиститьТематикиРолиФайла(Роль, СписокТематик = Неопределено)
Если СписокТематик <> Неопределено Тогда
СписокТематик.Очистить();
КонецЕсли;
ПараметрыОтбора = Новый Структура("Роль", Роль);
НайденныеСтроки = ДБ_ТематикиРолейФайлов.НайтиСтроки(ПараметрыОтбора);
Для Каждого Строка Из НайденныеСтроки Цикл
ДБ_ТематикиРолейФайлов.Удалить(Строка);
КонецЦикла;
КонецПроцедуры
// Формирует текстовое представление тематик роли файла для отображения в таблице.
// При пустом списке и включенном учете по тематикам возвращает "Все тематики".
//
// Параметры:
// СписокТематик - СписокЗначений - тематики роли.
// - Неопределено - считается пустым списком.
//
// Возвращаемое значение:
// Строка - представление тематик через "; " либо "Все тематики"/пустая строка.
//
&НаКлиентеНаСервереБезКонтекста
Функция ПредставлениеТематикДляРолиФайлов(СписокТематик = Неопределено)
Если СписокТематик = Неопределено Тогда
СписокТематик = Новый СписокЗначений;
КонецЕсли;
Если СписокТематик.Количество() = 0 Тогда
Возврат НСтр("ru = 'Все тематики'");
КонецЕсли;
ПредставленияТематик = Новый Массив;
Для Каждого ЭлементСписка Из СписокТематик Цикл
Представление = ?(ЗначениеЗаполнено(ЭлементСписка.Представление),
ЭлементСписка.Представление,
Строка(ЭлементСписка.Значение));
ПредставленияТематик.Добавить(Представление);
КонецЦикла;
Возврат СтрСоединить(ПредставленияТематик, "; ");
КонецФункции
// Заполняет колонку представления тематик во всех строках таблицы ролей файлов.
//
&НаСервере
Процедура ЗаполнитьПредставленияТематикРолейФайлов()
Для Каждого СтрокаРоли Из Объект.РолиФайлов Цикл
СписокТематик = ТематикиРоли(ДБ_ТематикиРолейФайлов, СтрокаРоли.Роль);
СтрокаРоли.ДБ_ТематикиПредставление = ПредставлениеТематикДляРолиФайлов(СписокТематик);
КонецЦикла;
КонецПроцедуры
#КонецОбласти
// Возвращает соответствие ролей файлов массивам тематик для вида документа.
// Пустой массив тематик означает, что роль доступна для всех тематик
//
// Параметры:
// ВидДокумента - СправочникСсылка.ВидыДокументов - вид документа.
//
// Возвращаемое значение:
// Соответствие из КлючИЗначение:
// * Ключ - СправочникСсылка.РолиФайлов - роль файла.
// * Значение - Массив из СправочникСсылка.ТематикиДокументов - тематики роли (без пустых).
//
Функция ТематикиРолейФайловПоВидуДокумента(ВидДокумента) Экспорт
Результат = Новый Соответствие;
Если Не ЗначениеЗаполнено(ВидДокумента) Тогда
Возврат Результат;
КонецЕсли;
Запрос = Новый Запрос(
"ВЫБРАТЬ
| ТематикиРолей.Роль КАК Роль,
| ТематикиРолей.Тематика КАК Тематика
|ИЗ
| РегистрСведений.ДБ_ТематикиРолейФайлов КАК ТематикиРолей
|ГДЕ
| ТематикиРолей.ВидДокумента = &ВидДокумента
| И НЕ ТематикиРолей.Роль.ПометкаУдаления
| И НЕ ЕСТЬNULL(ТематикиРолей.Тематика.ПометкаУдаления, ЛОЖЬ)
|
|УПОРЯДОЧИТЬ ПО
| Роль
|ИТОГИ ПО
| Роль");
Запрос.УстановитьПараметр("ВидДокумента", ВидДокумента);
ВыборкаРоль = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаРоль.Следующий() Цикл
Тематики = Новый Массив;
Роль = ВыборкаРоль.Роль;
Выборка = ВыборкаРоль.Выбрать();
Пока Выборка.Следующий() Цикл
Тематики.Добавить(Выборка.Тематика);
КонецЦикла;
Результат.Вставить(Роль, Тематики);
КонецЦикла;
Возврат Результат;
КонецФункции
// Записывает тематики ролей файлов вида документа.
// Пустой список тематик для роли означает доступность для всех тематик
// (записи по роли не создаются).
//
// Параметры:
// ВидДокумента - СправочникСсылка.ВидыДокументов - вид документа.
// ТематикиПоРолям - Соответствие из КлючИЗначение:
// * Ключ - СправочникСсылка.РолиФайлов - роль файла.
// * Значение - СписокЗначений, Массив из СправочникСсылка.ТематикиДокументов - тематики роли.
//
Процедура ЗаписатьТематикиРолейВидаДокумента(ВидДокумента, ТематикиПоРолям) Экспорт
УстановитьПривилегированныйРежим(Истина);
НаборЗаписей = СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ВидДокумента.Установить(ВидДокумента);
Для Каждого КлючИЗначение Из ТематикиПоРолям Цикл
Роль = КлючИЗначение.Ключ;
Если Не ЗначениеЗаполнено(Роль) Тогда
Продолжить;
КонецЕсли;
СписокТематик = КлючИЗначение.Значение;
Если ТипЗнч(СписокТематик) = Тип("СписокЗначений") Тогда
МассивТематик = СписокТематик.ВыгрузитьЗначения();
ИначеЕсли ТипЗнч(СписокТематик) = Тип("Массив") Тогда
МассивТематик = СписокТематик;
Иначе
Продолжить;
КонецЕсли;
Если МассивТематик.Количество() = 0 Тогда
Продолжить;
КонецЕсли;
Для Каждого Тематика Из МассивТематик Цикл
Запись = НаборЗаписей.Добавить();
Запись.ВидДокумента = ВидДокумента;
Запись.Роль = Роль;
Запись.Тематика = Тематика;
КонецЦикла;
КонецЦикла;
НаборЗаписей.Записать();
КонецПроцедуры
// Удаляет все тематики ролей файлов по виду документа.
//
// Параметры:
// ВидДокумента - СправочникСсылка.ВидыДокументов - вид документа.
//
Процедура УдалитьТематикиРолейПоВидуДокумента(ВидДокумента) Экспорт
Если Не ЗначениеЗаполнено(ВидДокумента) Тогда
Возврат;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
НаборЗаписей = СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ВидДокумента.Установить(ВидДокумента);
НаборЗаписей.Записать();
КонецПроцедуры
Проверено на следующих конфигурациях и релизах:
- Документооборот КОРП, редакция 3.0, релизы 3.0.21.3
Вступайте в нашу телеграмм-группу Инфостарт