В процессе кастомизации и внедрения систем на базе 1С:Предприятие разработчики часто сталкиваются с задачей оптимизации интерфейса. Классический пример — необходимость сделать форму карточки номенклатуры более простой и удобной для конечных пользователей, убрав лишние поля, такие как ставка НДС, код или неиспользуемые классификаторы.
Однако при попытке растиражировать сделанные настройки формы на все элементы справочника или на всех пользователей, разработчики наталкиваются на серьезное препятствие: настройки применяются избирательно. При анализе системного хранилища выясняется, что платформа генерирует уникальные ключи объектов вида Справочник.Номенклатура.Форма.ФормаЭлемента/КлючНаборовСвойствD5C17EE58F46CD17D55E8936879FD6FA/НастройкиФормы.
В этой статье мы подробно разберем, почему возникают такие динамические ключи, проанализируем распространенные ошибки при их переносе и рассмотрим два правильных, надежных способа решения этой задачи.
Давайте разберем внутреннюю логику работы платформы и Библиотеки стандартных подсистем (БСП). Появление в ключе настроек суффикса КлючНаборовСвойств напрямую связано с работой подсистемы «Свойства» из состава БСП.
Когда в вашей конфигурации включен механизм дополнительных реквизитов и сведений, состав полей на форме карточки номенклатуры может динамически меняться в зависимости от Вида номенклатуры. Например, для обуви требуются дополнительные поля «Размер» и «Материал», а для молочной продукции — «Процент жирности» и «Срок годности».
Чтобы индивидуальные настройки размещения элементов на форме не «смешивались» между товарами с разным набором динамических реквизитов, БСП модифицирует стандартный ключ назначения использования формы:
Справочник.Номенклатура.Форма.ФормаЭлемента.КлючНаборовСвойств<Хэш>.<Хэш> генерируется автоматически алгоритмом MD5 на основе отсортированного списка уникальных идентификаторов (GUID) тех наборов свойств, которые привязаны к конкретному виду номенклатуры.По этой причине платформа считает карточку «Молока» и карточку «Булочки» абсолютно разными формами. Именно поэтому обычное копирование настроек стандартными средствами администрирования от одного пользователя к другому часто не дает желаемого результата — ключи форм просто не совпадают.
Один из разработчиков на форуме предложил решать задачу «в лоб»: вручную собрать массив известных ему на данный момент хэш-ключей из базы данных и в цикле перезаписать для них настройки в системном хранилище. Рассмотрим пример его кода:
// Пример хрупкого решения с жестко заданным списком ключей
ПутьКНастройкам = "Справочник.Номенклатура.Форма.ФормаЭлемента/КлючНаборовСвойствA9C645DCFB89DE26510667B645146E1A/НастройкиФормы";
ПолучитьВсеИдентификаторыФорм = Новый СписокЗначений;
ПолучитьВсеИдентификаторыФорм.Добавить("Справочник.Номенклатура.Форма.ФормаЭлемента/КлючНаборовСвойств08C17C88F9ECA270F1CD24C0F6245D6E/НастройкиФормы");
ПолучитьВсеИдентификаторыФорм.Добавить("Справочник.Номенклатура.Форма.ФормаЭлемента/КлючНаборовСвойств25E2E7F058998E38EC08053CE8C6D27A/НастройкиФормы");
// ... ручное перечисление остальных ключей ...
НастройкиФормы = ХранилищеСистемныхНастроек.Загрузить(ПутьКНастройкам);
Если НастройкиФормы <> Неопределено Тогда
Для каждого Стр Из ПолучитьВсеИдентификаторыФорм Цикл
ХранилищеСистемныхНастроек.Сохранить(
Стр.Значение,
КлючНастроек,
НастройкиФормы,
,
Строка(ПользователиИнформационнойБазы.ТекущийПользователь)
);
КонецЦикла;
КонецЕсли;
Почему этот подход крайне не рекомендуется использовать в реальных базах данных?
Во-первых, это решение абсолютно не масштабируемо. Как только пользователи создадут в режиме «1С:Предприятие» новый вид номенклатуры или изменят состав дополнительных реквизитов у существующего вида, система мгновенно сформирует новый уникальный хэш-код (GUID). Этого кода не будет в жестко закодированном списке, и форма нового товара откроется в стандартном, неудобном для пользователей виде.
Во-вторых, если пользователь решит сбросить настройки формы к стандартным (через меню «Еще — Изменить форму — Установить стандартные настройки»), ваши программно скопированные настройки затрутся, и восстановить их автоматически система не сможет.
Давайте рассмотрим действительно надежные и архитектурно правильные способы реализации этой задачи.
Если ваша задача состоит именно в том, чтобы скопировать созданную «эталонную» настройку формы для всех уже существующих в системе вариантов видов номенклатуры и пользователей, лучшим решением будет динамический обход хранилища системных настроек.
Мы откажемся от жесткого кодирования конкретных хэшей и будем использовать метод Выбрать() объекта ХранилищеСистемныхНастроек. Это позволит нам динамически получить все когда-либо сгенерированные платформой ключи.
Проанализируем пример кода, который реализует данный подход:
// Сначала определим эталонный ключ, настройки которого мы хотим раздать всем
ЭталонныйКлючОбъекта = "Справочник.Номенклатура.Форма.ФормаЭлемента/КлючНаборовСвойствA9C645DCFB89DE26510667B645146E1A/НастройкиФормы";
КлючНастроек = ""; // Стандартный ключ настроек обычно пустой
ЭталоннаяНастройка = ХранилищеСистемныхНастроек.Загрузить(ЭталонныйКлючОбъекта, КлючНастроек);
Если ЭталоннаяНастройка <> Неопределено Тогда
// Получаем выборку всех сохраненных системных настроек в информационной базе
ВыборкаНастроек = ХранилищеСистемныхНастроек.Выбрать();
НачатьТранзакцию();
Попытка
Пока ВыборкаНастроек.Следующий() Цикл
// Проверяем, относится ли текущий ключ к форме элемента номенклатуры
Если СтрНачинаетсяС(ВыборкаНастроек.КлючОбъекта, "Справочник.Номенклатура.Форма.ФормаЭлемента") Тогда
// Перезаписываем настройку для найденного ключа объекта и конкретного пользователя
ХранилищеСистемныхНастроек.Сохранить(
ВыборкаНастроек.КлючОбъекта,
ВыборкаНастроек.КлючНастроек,
ЭталоннаяНастройка,
,
ВыборкаНастроек.Пользователь
);
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
ПоказатьПредупреждение(, "Настройки формы успешно скопированы для всех видов номенклатуры!");
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("ПрограммнаяНастройкаФормы", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Ошибка при сохранении системных настроек: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
КонецЕсли;
Преимущества этого метода:
КлючНаборовСвойств для всех видов номенклатуры.Копирование настроек через Хранилище — это всегда борьба с действиями пользователей. Рано или поздно кто-то из сотрудников сбросит настройки или перенастроит элементы под себя, вернув скрытые поля на экран.
Если ваша глобальная цель — навсегда скрыть ставку НДС или другие реквизиты со страницы элемента для всех сотрудников, правильнее сделать это программно на уровне кода формы, а не через хранилище настроек. Самым чистым и современным решением для этого является использование расширения конфигурации.
Выполним задачу по шагам:
Номенклатура и его форму ФормаЭлемента.ПриСозданииНаСервере с помощью аннотации &После.Рассмотрим пример реализации обработчика:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Ищем элемент управления, отвечающий за отображение ставки НДС на форме
ЭлементСтавкаНДС = Элементы.Найти("СтавкаНДС");
Если ЭлементСтавкаНДС <> Неопределено Тогда
// Программно отключаем видимость элемента
ЭлементСтавкаНДС.Видимость = Ложь;
КонецЕсли;
// Аналогично можно отключить отображение любого другого мешающего элемента
ЭлементКод = Элементы.Найти("Код");
Если ЭлементКод <> Неопределено Тогда
ЭлементКод.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Почему программный способ через расширение является лучшей практикой?
КлючНаборовСвойств) и под каким пользователем выполняется вход.Видимость устанавливается в значение Ложь программно на сервере, платформа полностью убирает этот элемент из рендеринга на клиенте. Пользователь физически не сможет вернуть элемент на форму через интерактивную настройку «Изменить форму», так как он исчезнет из списка доступных элементов.Мы выяснили, что динамические ключи настроек формы справочника Номенклатура генерируются из-за использования подсистемы свойств БСП.
Для разового переноса сложного интерактивного расположения элементов вы можете применить Способ 1 с динамическим обходом базы через ХранилищеСистемныхНастроек.Выбрать(). Однако, если ваша задача — просто скрыть конкретные реквизиты (например, ставку НДС), настоятельно рекомендуем использовать Способ 2 с программным управлением видимостью в расширении. Это гарантирует стабильную работу интерфейса при любых обновлениях конфигурации и действиях пользователей.