Как перенести добавленный реквизит из основной конфигурации в расширение без потери данных

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

При сопровождении нетиповых решений часто возникает ситуация, когда конфигурация была снята с поддержки (или поставлена на поддержку с возможностью изменения) ради добавления одного-двух реквизитов. Со временем это превращается в обузу при обновлении. Современный стандарт разработки в экосистеме 1С:Предприятие 8.3 диктует правило: «максимальная чистота основной конфигурации». Рассмотрим подробнее, как перенести уже накопленные данные из самописного реквизита основной конфигурации в расширение, чтобы вернуть базу на полную поддержку.

Зачем это нужно и какие есть риски

Основная цель — вернуть конфигурацию на «замок» (полную поддержку). Это позволяет обновлять систему в автоматическом режиме «далее-далее». Однако перенос данных в расширение таит в себе технические нюансы. Проанализируем ситуацию: в отличие от основной конфигурации, данные расширений хранятся в отдельных таблицах СУБД. Если расширение будет удалено из списка (через кнопку «Удалить»), платформа физически удалит и таблицу с данными. Поэтому, выбирая путь расширений, мы должны быть уверены в регламентах обслуживания базы.

Вариант 1. Перенос в реквизит расширения (Классический метод)

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

  1. Создание расширения. Добавим новое расширение (или используем существующее). Убедимся, что у него сняты флажки «Защита от опасных действий».
  2. Добавление объекта в расширение. Добавим нужный документ (например, ПоступлениеТоваровУслуг) в расширение, но не будем переносить туда старый реквизит.
  3. Создание нового реквизита в расширении. Создаем реквизит с тем же типом данных, но с временным именем, например, _ВероисповеданиеКонтрагента.
  4. Перенос данных. Напишем и запустим обработку, которая скопирует данные из старого поля в новое. Проанализируем пример кода для такой обработки:

Выборка = Документы.ПоступлениеТоваровУслуг.Выбрать();
Пока Выборка.Следующий() Цикл
    Если ЗначениеЗаполнено(Выборка.ВероисповеданиеКонтрагента) Тогда
        Объект = Выборка.ПолучитьОбъект();
        // Заполняем реквизит расширения
        Объект["_ВероисповеданиеКонтрагента"] = Выборка.ВероисповеданиеКонтрагента;
        Объект.ОбменДанными.Загрузка = Истина; // Чтобы не срабатывали лишние проверки
        Объект.Записать();
    КонецЕсли;
КонецЦикла;
  1. Удаление реквизита из основной конфигурации. После проверки данных удаляем старый реквизит ВероисповеданиеКонтрагента из основной конфигурации и принимаем изменения БД.
  2. Переименование. Теперь переименовываем реквизит в расширении из _ВероисповеданиеКонтрагента в ВероисповеданиеКонтрагента. Платформа сопоставит данные внутри таблиц расширения.

Вариант 2. Использование механизма дополнительных реквизитов (БСП)

Выясним причину, почему этот способ часто считается предпочтительным для типовых конфигураций, таких как 1С:Бухгалтерия или 1С:ERP. Эти программы построены на Библиотеке стандартных подсистем (БСП), которая уже содержит готовый механизм хранения любых свойств объектов без изменения метаданных.

Преимущества этого метода:

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

Вариант 3. Создание «Sidecar-таблицы» (Регистр сведений)

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

Разберем алгоритм:

  1. В расширении создаем новый Регистр сведений (назовем его ДанныеДокументовРасширение).
  2. В качестве Измерения устанавливаем ссылку на документ (тип ДокументСсылка.ПоступлениеТоваровУслуг).
  3. В качестве Ресурса создаем наше поле ВероисповеданиеКонтрагента.
  4. Переносим данные из документа в регистр:

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    |   ПоступлениеТоваровУслуг.ВероисповеданиеКонтрагента КАК Значение
    |ИЗ
    |   Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    |ГДЕ
    |   ПоступлениеТоваровУслуг.ВероисповеданиеКонтрагента <> ЗНАЧЕНИЕ(Справочник.Вероисповедания.ПустаяСсылка)";

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
    МенеджерЗаписи = РегистрыСведений.ДанныеДокументовРасширение.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Ссылка = Выборка.Ссылка;
    МенеджерЗаписи.ВероисповеданиеКонтрагента = Выборка.Значение;
    МенеджерЗаписи.Записать();
КонецЦикла;

Для того чтобы данные в регистре были актуальными, нам потребуется в расширении перехватить событие ПередЗаписью или ПриЗаписи документа и дописать код синхронизации. Это гарантирует, что при изменении данных в форме они попадут в нашу «sidecar-таблицу».

Методика «бесшовного» перехода для большой базы

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

  1. Подготовка: Создаем реквизит в расширении.
  2. Синхронизация «на лету»: В расширении модуля объекта документа пишем обработчик, который при записи документа копирует данные из старого реквизита в новый. Так новые и измененные документы начнут заполняться сами.
  3. Фоновое заполнение: Запускаем фоновое задание, которое порциями (по 100-500 документов) переносит исторические данные.
  4. Финальный аккорд: Когда все данные перенесены, удаляем реквизит из основной конфигурации и ставим ее на замок.

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

Посмотрим на ситуацию со стороны производительности: программное добавление реквизитов на форму (через ЭтаФорма.Элементы.Добавить) может незначительно замедлять открытие, если реквизитов десятки. Для одного-двух полей разница будет незаметна. Однако наиболее стабильным и «правильным» с точки зрения архитектуры 1С является путь интеграции с подсистемой Свойства из БСП.

← На главную