Как изменить тип реквизита в 1С со строки на ссылочный объект и адаптировать конфигурацию?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Изменение типа реквизита в конфигурации 1С, особенно со строкового на ссылочный объект, является комплексной задачей, требующей внимательного планирования и поэтапного выполнения. Это связано не только с технической перестройкой структуры данных, но и с необходимостью сохранения уже существующих значений, а также адаптации всего кода, который с этим реквизитом взаимодействует. Рассмотрим подробнее основные подходы к решению этой задачи, а также ключевые аспекты, которые необходимо учитывать.

Прежде всего, давайте осознаем масштаб задачи. Мы не просто меняем тип в одном месте, но должны обеспечить бесшовную миграцию данных и корректную работу всей системы после изменений. Это может затронуть документы, регистры, отчеты, обработки, веб-сервисы и правила обмена данными. Поэтому перед началом любых работ критически важно создать резервную копию информационной базы и проводить все изменения на копии.

Подход 1: Использование составного типа данных для плавного перехода

Один из самых безопасных способов провести такую миграцию — это временное создание составного типа данных для изменяемого реквизита. Этот метод позволяет постепенно перевести данные со старого типа на новый, минимизируя риски и потенциальное время простоя системы.

  1. Добавление нового типа к существующему реквизиту:

    Начнем с того, что в конфигураторе откроем свойства реквизита (например, в документе или регистре), тип которого хотим изменить. Вместо того чтобы сразу удалять строковый тип, мы добавляем к нему новый тип — СправочникСсылка.МойСправочник. Таким образом, реквизит становится составным, способным хранить как строковые значения, так и ссылки на элементы вашего справочника.

    После сохранения изменений и обновления конфигурации базы данных, система будет готова принимать данные нового типа. Это позволяет избежать потери данных на первом этапе, так как старые строковые значения остаются в реквизите.

    Вы можете установить контроль в документах, чтобы пользователи выбирали только из справочника для новых записей, например, через свойства поля ввода или обработчик события при записи.

  2. Конвертация данных:

    На этом этапе нам потребуется специальная обработка или часть кода, которая будет конвертировать существующие строковые значения в ссылочные объекты. Алгоритм конвертации будет зависеть от того, как строковые значения соотносятся с элементами справочника:

    • Если в справочнике уже есть элементы, соответствующие вашим строковым значениям (например, по наименованию или коду), то обработка должна найти эти элементы и присвоить ссылки на них.
    • Если элементы справочника нужно создать на основе существующих строковых значений, то обработка должна создать новые элементы справочника и затем присвоить ссылки на них.

    Эту обработку можно запускать в несколько итераций, например, по частям данных, или как фоновое задание. Это особенно важно для больших объемов данных, чтобы не блокировать работу пользователей надолго.

    Пример концептуального кода для обработки конвертации:

    
    Процедура КонвертироватьДанныеРеквизита()
    
        Запрос = Новый Запрос;
        Запрос.Текст = 
        "ВЫБРАТЬ
        |    Документ.МойДокумент.Ссылка КАК Ссылка,
        |    Документ.МойДокумент.МойРеквизитСтрока КАК МойРеквизитСтрока
        |ИЗ
        |    Документ.МойДокумент
        |ГДЕ
        |    ТИПЗНАЧЕНИЯ(Документ.МойДокумент.МойРеквизитСтрока) = ТИП(Строка)";
    
        Выборка = Запрос.Выполнить().Выбрать();
    
        Пока Выборка.Следующий() Цикл
            ОбъектДокумента = Выборка.Ссылка.ПолучитьОбъект();
    
            // Поиск элемента справочника по строковому значению
            // Предполагаем, что строковое значение соответствует наименованию элемента
            ЭлементСправочника = Справочники.МойСправочник.НайтиПоНаименованию(Выборка.МойРеквизитСтрока);
    
            Если ЭлементСправочника = Неопределено Тогда
                // Если элемента нет, создаем новый
                НовыйЭлемент = Справочники.МойСправочник.СоздатьЭлемент();
                НовыйЭлемент.Наименование = Выборка.МойРеквизитСтрока;
                Попытка
                    НовыйЭлемент.Записать();
                    ЭлементСправочника = НовыйЭлемент.Ссылка;
                Исключение
                    Сообщить("Не удалось создать элемент справочника для строки: " + Выборка.МойРеквизитСтрока + ". Ошибка: " + ОписаниеОшибки());
                    Продолжить;
                КонецПопытки;
            КонецЕсли;
    
            ОбъектДокумента.МойРеквизитСтрока = ЭлементСправочника;
            Попытка
                ОбъектДокумента.Записать();
            Исключение
                Сообщить("Не удалось записать документ " + ОбъектДокумента + ". Ошибка: " + ОписаниеОшибки());
            КонецПопытки;
        КонецЦикла;
    
        Сообщить("Конвертация данных завершена.");
    
    КонецПроцедуры
    
  3. Удаление старого типа данных:

    После успешной конвертации всех необходимых данных и убедившись в корректности переноса, можно вернуться в конфигуратор и убрать строковый тип из составного типа реквизита. В результате реквизит будет иметь только тип СправочникСсылка.МойСправочник. Это завершит миграцию типа данных на уровне метаданных.

Подход 2: Переименование старого реквизита и создание нового с требуемым типом

Этот подход также широко используется, особенно когда требуется более четкое разделение старых и новых данных, или если объем данных относительно небольшой. Он также позволяет временно сохранить старые данные для сверки или отката.

  1. Переименование существующего реквизита:

    В конфигураторе переименуйте существующий реквизит. Хорошей практикой является добавление префикса Удалить_ или суффикса _Старый, например, МойРеквизит станет Удалить_МойРеквизит. При переименовании платформа 1С обычно предлагает список мест, где этот реквизит используется в коде, что уже дает начальную точку для адаптации алгоритмов.

  2. Создание нового реквизита:

    Создайте новый реквизит с тем же именем, что было у старого реквизита (например, МойРеквизит), но уже с желаемым типом данных — СправочникСсылка.МойСправочник.

  3. Разработка обработчика обновления данных:

    Для переноса данных из старого (переименованного) реквизита в новый вам потребуется обработчик обновления информационной базы. В типовых конфигурациях 1С для таких задач часто используется механизм подсистемы "Обновление конфигурации базы данных", который позволяет создать обработчики, выполняемые при каждом обновлении ИБ. Это обеспечивает контролируемый и безопасный процесс миграции.

    В этом обработчике вы пишете код, который итерируется по всем объектам (документам, регистрам и т.д.), где был изменен реквизит, и переносит данные из Удалить_МойРеквизит в МойРеквизит, выполняя необходимую конвертацию строки в ссылку, аналогично Подходу 1.

    Пример концептуального кода для обработчика обновления (размещается в общем модуле, который вызывается при обновлении, например, в МодулиОбновленияИБ):

    
    Процедура ОбновитьДанныеМоегоРеквизита() Экспорт
    
        Сообщить("Начало обновления реквизита МойРеквизит.");
    
        Запрос = Новый Запрос;
        Запрос.Текст = 
        "ВЫБРАТЬ
        |    Документ.МойДокумент.Ссылка КАК Ссылка,
        |    Документ.МойДокумент.Удалить_МойРеквизит КАК СтароеЗначение
        |ИЗ
        |    Документ.МойДокумент
        |ГДЕ
        |    НЕ Документ.МойДокумент.Удалить_МойРеквизит ЕСТЬ NULL
        |    И Документ.МойДокумент.МойРеквизит ЕСТЬ NULL"; // Переносим только те, что еще не перенесены
    
        Выборка = Запрос.Выполнить().Выбрать();
    
        Пока Выборка.Следующий() Цикл
            ОбъектДокумента = Выборка.Ссылка.ПолучитьОбъект();
    
            Если ТипЗнч(ОбъектДокумента.Удалить_МойРеквизит) = Тип("Строка") Тогда
                // Ищем или создаем элемент справочника
                ЭлементСправочника = Справочники.МойСправочник.НайтиПоНаименованию(ОбъектДокумента.Удалить_МойРеквизит);
    
                Если ЭлементСправочника = Неопределено Тогда
                    НовыйЭлемент = Справочники.МойСправочник.СоздатьЭлемент();
                    НовыйЭлемент.Наименование = ОбъектДокумента.Удалить_МойРеквизит;
                    Попытка
                        НовыйЭлемент.Записать();
                        ЭлементСправочника = НовыйЭлемент.Ссылка;
                    Исключение
                        Сообщить("Ошибка создания элемента справочника для строки " + ОбъектДокумента.Удалить_МойРеквизит + " в документе " + ОбъектДокумента + ": " + ОписаниеОшибки());
                        Продолжить; // Пропускаем текущий документ
                    КонецПопытки;
                КонецЕсли;
    
                ОбъектДокумента.МойРеквизит = ЭлементСправочника; // Присваиваем ссылку новому реквизиту
                        
                Попытка
                    ОбъектДокумента.Записать();
                Исключение
                    Сообщить("Ошибка записи документа " + ОбъектДокумента + " при обновлении реквизита: " + ОписаниеОшибки());
                КонецПопытки;
            КонецЕсли;
        КонецЦикла;
    
        Сообщить("Обновление реквизита МойРеквизит завершено.");
    
    КонецПроцедуры
    

    После успешной миграции данных и проверки корректности, старый реквизит Удалить_МойРеквизит может быть удален из конфигурации.

Адаптация кода и поиск ссылок

Независимо от выбранного подхода к миграции данных, самая трудоемкая часть работы — это адаптация кода. Вам необходимо найти все места в конфигурации, где использовался старый реквизит, и модифицировать их для работы с новым типом данных.

  1. Инструмент "Найти ссылки на объект":

    В конфигураторе, выделив реквизит в дереве метаданных (или даже сам справочник), можно вызвать команду "Найти ссылки на объект в конфигурации" (F7). Этот инструмент покажет использования реквизита в модулях, формах, макетах и других объектах. Это отличная отправная точка для поиска, но не является исчерпывающим.

  2. Глобальный поиск по конфигурации:

    После использования "Найти ссылки на объект", обязательно выполните глобальный поиск по всей конфигурации (Ctrl+Shift+F). Ищите имя старого реквизита, а также его имя в запросах (например, &Реквизит, &Реквизит). Проверьте:

    • Модули (формы, объекты, менеджеры, общие модули).
    • Макеты (могут содержать ссылки на реквизиты).
    • Запросы в конструкторах запросов.
    • Схемы компоновки данных (СКД).
    • Параметры выбора в формах.
    • Расширения конфигурации, если они используются.

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

  3. Изменение кода:

    В найденных местах измените логику работы с реквизитом. Если раньше вы работали со строкой, теперь вам потребуется работать со ссылкой на объект справочника. Например, вместо сравнения строк: Если МойДокумент.МойРеквизитСтрока = "Значение" Тогда теперь будет: Если МойДокумент.МойРеквизит = Справочники.МойСправочник.НайтиПоНаименованию("Значение") Тогда (или сравнение по ссылке, если она уже есть).

Стратегии миграции и безопасного внедрения

Чтобы минимизировать риски и обеспечить успешное внедрение изменений, рассмотрим дополнительные рекомендации.

  1. Поэтапный подход:

    Если конфигурация очень большая и затронуто много объектов, рассмотрите возможность поэтапного изменения. Выберите один документ или регистр, внесите в него изменения, адаптируйте связанный код, протестируйте. После успешного завершения переходите к следующему объекту. Этот подход позволяет уменьшить объем изменений на каждом шаге, упрощает отладку и быстрее выявляет ошибки.

  2. Планирование и тестирование:

    Создание резервной копии — это первый и самый важный шаг. Далее, разработайте подробный план миграции, который включает последовательность действий, ожидаемые результаты и возможные точки отката. Всегда тестируйте изменения на копии рабочей базы данных с реальными данными. Это поможет выявить потенциальные ошибки в коде, связанные с изменением типа, а также проблемы с производительностью при миграции больших объемов данных.

    После изменения типа и миграции данных необходимо проверить работоспособность всех связанных отчетов, обработок и обменов данными. Убедитесь, что все операции, которые ранее работали со строковым реквизитом, теперь корректно функционируют со ссылочным.

  3. Обработка существующих данных:

    При переходе от строкового значения к ссылочному необходимо предусмотреть логику для сопоставления существующих строковых значений с элементами справочника. Если справочник уже содержит элементы, соответствующие строковым значениям, то можно использовать программный поиск по наименованию или коду. Если же элементы справочника должны быть созданы на основе существующих строк, потребуется соответствующая логика создания новых элементов и их последующая привязка.

  4. Влияние на производительность при миграции:

    Изменение типа реквизита с последующей конвертацией данных может быть ресурсоемкой операцией, особенно для таблиц с большим количеством записей. Это может занять значительное время и потребовать блокировки доступа пользователей к системе. Рекомендуется проводить такие операции в нерабочее время или использовать механизмы фонового обновления, если это возможно.

  5. Индексация:

    После изменения типа реквизита на ссылочный объект, если этот реквизит часто используется в запросах или для сортировки, стоит убедиться, что он проиндексирован. Правильная индексация может значительно улучшить производительность запросов. Платформа 1С обычно автоматически создает индексы для ссылочных полей, но для важных полей можно проверить и при необходимости добавить их вручную.

  6. Особенности распределенных информационных баз (РИБ):

    Если конфигурация используется в режиме РИБ, то изменение типа реквизита и миграция данных должны быть тщательно спланированы и выполнены таким образом, чтобы не нарушить обмен данными между узлами. Все изменения должны быть применены на всех узлах, а правила обмена могут потребовать адаптации.

  7. Влияние на web-сервисы и HTTP-сервисы:

    Если измененный реквизит используется в параметрах или возвращаемых значениях web-сервисов или HTTP-сервисов, потребуется обновить их определения (XDTO-пакеты, структуры JSON/XML) и протестировать взаимодействие с внешними системами. Это важно, так как внешние системы ожидают строковое значение, а после изменения типа начнут получать ссылку или ее представление.

Изменение типа реквизита в 1С — это нетривиальная задача, требующая глубокого понимания структуры конфигурации и тщательного подхода. Выбирайте наиболее подходящий для вашей ситуации метод, всегда помните о необходимости резервного копирования и всестороннего тестирования. Только так можно обеспечить успешное и безопасное внедрение изменений без потери данных и нарушения работоспособности системы.

← На главную