Изменение типа реквизита в конфигурации 1С, особенно со строкового на ссылочный объект, является комплексной задачей, требующей внимательного планирования и поэтапного выполнения. Это связано не только с технической перестройкой структуры данных, но и с необходимостью сохранения уже существующих значений, а также адаптации всего кода, который с этим реквизитом взаимодействует. Рассмотрим подробнее основные подходы к решению этой задачи, а также ключевые аспекты, которые необходимо учитывать.
Прежде всего, давайте осознаем масштаб задачи. Мы не просто меняем тип в одном месте, но должны обеспечить бесшовную миграцию данных и корректную работу всей системы после изменений. Это может затронуть документы, регистры, отчеты, обработки, веб-сервисы и правила обмена данными. Поэтому перед началом любых работ критически важно создать резервную копию информационной базы и проводить все изменения на копии.
Один из самых безопасных способов провести такую миграцию — это временное создание составного типа данных для изменяемого реквизита. Этот метод позволяет постепенно перевести данные со старого типа на новый, минимизируя риски и потенциальное время простоя системы.
Начнем с того, что в конфигураторе откроем свойства реквизита (например, в документе или регистре), тип которого хотим изменить. Вместо того чтобы сразу удалять строковый тип, мы добавляем к нему новый тип — СправочникСсылка.МойСправочник. Таким образом, реквизит становится составным, способным хранить как строковые значения, так и ссылки на элементы вашего справочника.
После сохранения изменений и обновления конфигурации базы данных, система будет готова принимать данные нового типа. Это позволяет избежать потери данных на первом этапе, так как старые строковые значения остаются в реквизите.
Вы можете установить контроль в документах, чтобы пользователи выбирали только из справочника для новых записей, например, через свойства поля ввода или обработчик события при записи.
На этом этапе нам потребуется специальная обработка или часть кода, которая будет конвертировать существующие строковые значения в ссылочные объекты. Алгоритм конвертации будет зависеть от того, как строковые значения соотносятся с элементами справочника:
Эту обработку можно запускать в несколько итераций, например, по частям данных, или как фоновое задание. Это особенно важно для больших объемов данных, чтобы не блокировать работу пользователей надолго.
Пример концептуального кода для обработки конвертации:
Процедура КонвертироватьДанныеРеквизита()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Документ.МойДокумент.Ссылка КАК Ссылка,
| Документ.МойДокумент.МойРеквизитСтрока КАК МойРеквизитСтрока
|ИЗ
| Документ.МойДокумент
|ГДЕ
| ТИПЗНАЧЕНИЯ(Документ.МойДокумент.МойРеквизитСтрока) = ТИП(Строка)";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектДокумента = Выборка.Ссылка.ПолучитьОбъект();
// Поиск элемента справочника по строковому значению
// Предполагаем, что строковое значение соответствует наименованию элемента
ЭлементСправочника = Справочники.МойСправочник.НайтиПоНаименованию(Выборка.МойРеквизитСтрока);
Если ЭлементСправочника = Неопределено Тогда
// Если элемента нет, создаем новый
НовыйЭлемент = Справочники.МойСправочник.СоздатьЭлемент();
НовыйЭлемент.Наименование = Выборка.МойРеквизитСтрока;
Попытка
НовыйЭлемент.Записать();
ЭлементСправочника = НовыйЭлемент.Ссылка;
Исключение
Сообщить("Не удалось создать элемент справочника для строки: " + Выборка.МойРеквизитСтрока + ". Ошибка: " + ОписаниеОшибки());
Продолжить;
КонецПопытки;
КонецЕсли;
ОбъектДокумента.МойРеквизитСтрока = ЭлементСправочника;
Попытка
ОбъектДокумента.Записать();
Исключение
Сообщить("Не удалось записать документ " + ОбъектДокумента + ". Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Сообщить("Конвертация данных завершена.");
КонецПроцедуры
После успешной конвертации всех необходимых данных и убедившись в корректности переноса, можно вернуться в конфигуратор и убрать строковый тип из составного типа реквизита. В результате реквизит будет иметь только тип СправочникСсылка.МойСправочник. Это завершит миграцию типа данных на уровне метаданных.
Этот подход также широко используется, особенно когда требуется более четкое разделение старых и новых данных, или если объем данных относительно небольшой. Он также позволяет временно сохранить старые данные для сверки или отката.
В конфигураторе переименуйте существующий реквизит. Хорошей практикой является добавление префикса Удалить_ или суффикса _Старый, например, МойРеквизит станет Удалить_МойРеквизит. При переименовании платформа 1С обычно предлагает список мест, где этот реквизит используется в коде, что уже дает начальную точку для адаптации алгоритмов.
Создайте новый реквизит с тем же именем, что было у старого реквизита (например, МойРеквизит), но уже с желаемым типом данных — СправочникСсылка.МойСправочник.
Для переноса данных из старого (переименованного) реквизита в новый вам потребуется обработчик обновления информационной базы. В типовых конфигурациях 1С для таких задач часто используется механизм подсистемы "Обновление конфигурации базы данных", который позволяет создать обработчики, выполняемые при каждом обновлении ИБ. Это обеспечивает контролируемый и безопасный процесс миграции.
В этом обработчике вы пишете код, который итерируется по всем объектам (документам, регистрам и т.д.), где был изменен реквизит, и переносит данные из Удалить_МойРеквизит в МойРеквизит, выполняя необходимую конвертацию строки в ссылку, аналогично Подходу 1.
Пример концептуального кода для обработчика обновления (размещается в общем модуле, который вызывается при обновлении, например, в МодулиОбновленияИБ):
Процедура ОбновитьДанныеМоегоРеквизита() Экспорт
Сообщить("Начало обновления реквизита МойРеквизит.");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Документ.МойДокумент.Ссылка КАК Ссылка,
| Документ.МойДокумент.Удалить_МойРеквизит КАК СтароеЗначение
|ИЗ
| Документ.МойДокумент
|ГДЕ
| НЕ Документ.МойДокумент.Удалить_МойРеквизит ЕСТЬ NULL
| И Документ.МойДокумент.МойРеквизит ЕСТЬ NULL"; // Переносим только те, что еще не перенесены
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектДокумента = Выборка.Ссылка.ПолучитьОбъект();
Если ТипЗнч(ОбъектДокумента.Удалить_МойРеквизит) = Тип("Строка") Тогда
// Ищем или создаем элемент справочника
ЭлементСправочника = Справочники.МойСправочник.НайтиПоНаименованию(ОбъектДокумента.Удалить_МойРеквизит);
Если ЭлементСправочника = Неопределено Тогда
НовыйЭлемент = Справочники.МойСправочник.СоздатьЭлемент();
НовыйЭлемент.Наименование = ОбъектДокумента.Удалить_МойРеквизит;
Попытка
НовыйЭлемент.Записать();
ЭлементСправочника = НовыйЭлемент.Ссылка;
Исключение
Сообщить("Ошибка создания элемента справочника для строки " + ОбъектДокумента.Удалить_МойРеквизит + " в документе " + ОбъектДокумента + ": " + ОписаниеОшибки());
Продолжить; // Пропускаем текущий документ
КонецПопытки;
КонецЕсли;
ОбъектДокумента.МойРеквизит = ЭлементСправочника; // Присваиваем ссылку новому реквизиту
Попытка
ОбъектДокумента.Записать();
Исключение
Сообщить("Ошибка записи документа " + ОбъектДокумента + " при обновлении реквизита: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Сообщить("Обновление реквизита МойРеквизит завершено.");
КонецПроцедуры
После успешной миграции данных и проверки корректности, старый реквизит Удалить_МойРеквизит может быть удален из конфигурации.
Независимо от выбранного подхода к миграции данных, самая трудоемкая часть работы — это адаптация кода. Вам необходимо найти все места в конфигурации, где использовался старый реквизит, и модифицировать их для работы с новым типом данных.
В конфигураторе, выделив реквизит в дереве метаданных (или даже сам справочник), можно вызвать команду "Найти ссылки на объект в конфигурации" (F7). Этот инструмент покажет использования реквизита в модулях, формах, макетах и других объектах. Это отличная отправная точка для поиска, но не является исчерпывающим.
После использования "Найти ссылки на объект", обязательно выполните глобальный поиск по всей конфигурации (Ctrl+Shift+F). Ищите имя старого реквизита, а также его имя в запросах (например, &Реквизит, &Реквизит). Проверьте:
Особое внимание уделите динамически формируемым запросам и универсальным обработкам, где имя реквизита может передаваться строкой. В таких случаях автоматический поиск может не сработать, и потребуется более глубокий анализ кода.
В найденных местах измените логику работы с реквизитом. Если раньше вы работали со строкой, теперь вам потребуется работать со ссылкой на объект справочника. Например, вместо сравнения строк: Если МойДокумент.МойРеквизитСтрока = "Значение" Тогда теперь будет: Если МойДокумент.МойРеквизит = Справочники.МойСправочник.НайтиПоНаименованию("Значение") Тогда (или сравнение по ссылке, если она уже есть).
Чтобы минимизировать риски и обеспечить успешное внедрение изменений, рассмотрим дополнительные рекомендации.
Если конфигурация очень большая и затронуто много объектов, рассмотрите возможность поэтапного изменения. Выберите один документ или регистр, внесите в него изменения, адаптируйте связанный код, протестируйте. После успешного завершения переходите к следующему объекту. Этот подход позволяет уменьшить объем изменений на каждом шаге, упрощает отладку и быстрее выявляет ошибки.
Создание резервной копии — это первый и самый важный шаг. Далее, разработайте подробный план миграции, который включает последовательность действий, ожидаемые результаты и возможные точки отката. Всегда тестируйте изменения на копии рабочей базы данных с реальными данными. Это поможет выявить потенциальные ошибки в коде, связанные с изменением типа, а также проблемы с производительностью при миграции больших объемов данных.
После изменения типа и миграции данных необходимо проверить работоспособность всех связанных отчетов, обработок и обменов данными. Убедитесь, что все операции, которые ранее работали со строковым реквизитом, теперь корректно функционируют со ссылочным.
При переходе от строкового значения к ссылочному необходимо предусмотреть логику для сопоставления существующих строковых значений с элементами справочника. Если справочник уже содержит элементы, соответствующие строковым значениям, то можно использовать программный поиск по наименованию или коду. Если же элементы справочника должны быть созданы на основе существующих строк, потребуется соответствующая логика создания новых элементов и их последующая привязка.
Изменение типа реквизита с последующей конвертацией данных может быть ресурсоемкой операцией, особенно для таблиц с большим количеством записей. Это может занять значительное время и потребовать блокировки доступа пользователей к системе. Рекомендуется проводить такие операции в нерабочее время или использовать механизмы фонового обновления, если это возможно.
После изменения типа реквизита на ссылочный объект, если этот реквизит часто используется в запросах или для сортировки, стоит убедиться, что он проиндексирован. Правильная индексация может значительно улучшить производительность запросов. Платформа 1С обычно автоматически создает индексы для ссылочных полей, но для важных полей можно проверить и при необходимости добавить их вручную.
Если конфигурация используется в режиме РИБ, то изменение типа реквизита и миграция данных должны быть тщательно спланированы и выполнены таким образом, чтобы не нарушить обмен данными между узлами. Все изменения должны быть применены на всех узлах, а правила обмена могут потребовать адаптации.
Если измененный реквизит используется в параметрах или возвращаемых значениях web-сервисов или HTTP-сервисов, потребуется обновить их определения (XDTO-пакеты, структуры JSON/XML) и протестировать взаимодействие с внешними системами. Это важно, так как внешние системы ожидают строковое значение, а после изменения типа начнут получать ссылку или ее представление.
Изменение типа реквизита в 1С — это нетривиальная задача, требующая глубокого понимания структуры конфигурации и тщательного подхода. Выбирайте наиболее подходящий для вашей ситуации метод, всегда помните о необходимости резервного копирования и всестороннего тестирования. Только так можно обеспечить успешное и безопасное внедрение изменений без потери данных и нарушения работоспособности системы.