При настройке правил обмена в конфигурации Конвертация данных 2.1 (КД 2) часто возникает необходимость перенести настройки системы и значения констант из одной базы в другую. Если создать стандартное Правило Конвертации Объектов (ПКО) для объекта КонстантыНабор, выгрузка данных проходит без замечаний. Однако на этапе загрузки в приемник платформа выдает ошибку вида:
Ошибка при загрузке данных: Ошибка записи объекта. ОписаниеОшибки = Ошибка при вызове метода контекста (Записать): Нарушение прав доступа! - 'Запрещено изменение значение условного разделения по разделителю ОбластьДанныхВспомогательныеДанные'
Рассмотрим причинно-следственные связи этой ошибки и разберем практические способы корректного переноса констант.
Проанализируем особенности работы платформы «1С:Предприятие» и Библиотеки Стандартных Подсистем (БСП). При вызове метода Записать() у объекта КонстантыНабор платформа осуществляет запись и проверку прав доступа не только для тех констант, которые были переданы в файле обмена, а для всех констант, входящих в состав набора конфигурации по умолчанию.
В современных конфигурациях (таких как ЗУП, ERP, КА, УТ), где используются механизмы разделения данных БСП, в состав метаданных входят служебные константы-разделители (например, ОбластьДанныхОсновныеДанные, ОбластьДанныхВспомогательныеДанные, ИспользоватьРазделениеПоОбластямДанных). Изменение или даже сам факт попытки записи этих разделителей в стандартном сеансе пользователя жестко блокируется платформой на уровне прав доступа. Попытка записать объект КонстантыНабор стандартным механизмом обработки УниверсальныйОбменДаннымиXML приводит к фатальной ошибке.
Наиболее популярный и быстрый способ решения задачи — отмена стандартной записи набора констант и поэлементная установка нужных значений с перехватом возможных исключений.
В правилах обмена для ПКО объекта КонстантыНабор перейдем в обработчик события «После загрузки» и добавим следующий алгоритм:
Если Объект <> Неопределено Тогда
// Формируем массив констант, которые необходимо пропустить
мСписокИсключений = Новый Массив();
мСписокИсключений.Добавить("ИспользоватьРазделениеПоОбластямДанных");
мСписокИсключений.Добавить("ОбластьДанныхОсновныеДанные");
мСписокИсключений.Добавить("ОбластьДанныхВспомогательныеДанные");
// Перебираем все константы конфигурации-приемника
Для каждого эл Из Метаданные.Константы Цикл
Попытка
Если мСписокИсключений.Найти(эл.Имя) = Неопределено Тогда
// Записываем значение константы индивидуально через ее менеджер
Константы[эл.Имя].Установить(Объект[эл.Имя]);
КонецЕсли;
Исключение
Сообщить("Не удалось установить значение константы: " + эл.Имя);
КонецПопытки;
КонецЦикла;
// Отменяем стандартную запись всего объекта КонстантыНабор
Отказ = Истина;
КонецЕсли;
Посмотрим, как работает этот код: мы формируем список служебных констант-разделителей, после чего в цикле обходим метаданные и устанавливаем значения каждой константы по отдельности с помощью метода Установить() менеджера конкретной константы. В самом конце устанавливаем флаг Отказ = Истина, благодаря чему обработка обмена пропускает стандартный вызов метода Записать() для всего набора, предотвращая ошибку прав доступа.
Если требуется перенести не абсолютно все константы, а лишь небольшой список конкретных настроек (например, учетную политику или флаги функциональных опций), рекомендуется отказаться от ПКО для КонстантыНабор и использовать механизм параметров обмена.
Разберем данный подход по шагам:
Параметр_ИспользоватьШтатноеРасписание).
Параметры.Вставить("Параметр_ИспользоватьШтатноеРасписание", Константы.ИспользоватьШтатноеРасписание.Получить());
Если Параметры.Свойство("Параметр_ИспользоватьШтатноеРасписание") Тогда
Константы.ИспользоватьШтатноеРасписание.Установить(Параметры.Параметр_ИспользоватьШтатноеРасписание);
КонецЕсли;
Этот подход гарантирует отсутствие каких-либо коллизий с БСП и правами доступа, так как объект КонстантыНабор вообще не участвует в переносе.
Платформа 1С позволяет создавать набор не для всех констант метаданных, а для строго ограниченного перечня. Для этого используется метод СоздатьНабор() с передачей имен констант через запятую:
ИменаКонстант = "ЗаголовокСистемы, ИспользоватьПроверкуКонтрагентов";
НаборКонстант = Константы.СоздатьНабор(ИменаКонстант);
// Заполняем значения
НаборКонстант.ЗаголовокСистемы = "Моя база";
НаборКонстант.Записать();
При вызове метода Записать() у такого точечного набора платформа проверяет права доступа исключительно на константы, указанные в строке параметров, и игнорирует разделители БСП.
При работе с константами необходимо учитывать следующие особенности платформы:
Установить() не всегда сразу обновляет интерфейс открытых сеансов пользователей. Для корректного применения настроек может потребоваться перезапуск сеанса или вызов метода повторного считывания параметров функциональных опций БСП.УстановитьПривилегированныйРежим(Истина)) не снимает платформенный запрет на изменение констант-разделителей в сеансе, где разделение включено. Поэтому использование `Отказ = Истина` и выборочная запись остаются единственным надежным решением.