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

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

При развитии прикладных решений на платформе 1С нередко возникает необходимость изменить структуру регистра сведений: например, поле, изначально созданное как ресурс или реквизит, требуется сделать измерением. Типичный пример — ценообразование, где единица измерения изначально хранилась в ресурсах, но с появлением цен на разные упаковки или единицы одного и того же товара её потребовалось перенести в состав ключевых полей (измерений).

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

Особенности изменения состава измерений регистра

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

  1. Изменение уникальности ключа записи. Измерения формируют уникальный индекс таблицы. Если ранее для одного товара могла существовать строго одна запись (на дату среза), то после добавления единицы измерения записей станет несколько — по каждой единице.
  2. Поведение виртуальных таблиц. Запросы к таблицам СрезПоследних и СрезПервых изменят свое поведение. Если ранее срез возвращал одну актуальную цену на номенклатуру, то теперь он вернет последнюю цену для каждой комбинации товара и единицы измерения. Все запросы конфигурации, обращающиеся к регистру, потребуют обязательной ревизии.
  3. Пустые значения в ключе. Если в старых данных ресурс не был заполнен, при его переносе в измерение сформируется пустая ссылка. Для корректности бизнес-логики необходимо заранее предусмотреть заполнение пустых значений (например, базовой единицей измерения из карточки номенклатуры).
  4. Режим записи регистра. Если регистр независимый, миграция данных выполняется напрямую через наборы записей. Если же регистр подчинен регистратору (РежимЗаписи = РежимЗаписиРегистраСведений.ПодчинениеРегистратору), прямая перезапись наборов опасна: при первой же перепроводке первичного документа движения перезапишутся по старому алгоритму. В таком случае потребуется также модернизировать табличные части и модули проведения самих документов-регистраторов.

Этап 1. Подготовка метаданных и поддержка совместимости

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

  1. В дереве метаданных добавляем новое измерение (например, ЕдиницаИзмерения). Старый ресурс переименовываем в УдалитьЕдиницаИзмерения (или сохраняем прежнее имя, если новое измерение названо иначе).
  2. Переписываем алгоритмы записи в регистр в документах и подсистемах так, чтобы при формировании новых движений заполнялись сразу оба поля — и новое измерение, и старый ресурс. Это гарантирует корректную работу конфигурации в переходный период.
  3. Адаптируем алгоритмы чтения данных (запросы, функции получения цен): переводим их на работу с новым измерением.

Этап 2. Миграция исторических данных

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

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


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

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

Этап 3. Окончательная очистка устаревших метаданных

После того как переходный релиз успешно установлен клиентам, данные перенесены, а работа всех алгоритмов проверена, выпускается следующий плановый релиз:

  1. Из метаданных окончательно удаляется устаревший ресурс УдалитьЕдиницаИзмерения.
  2. Удаляются вспомогательные процедуры миграции данных из модуля обновления.
  3. Удаляются все рудиментарные строки кода, где выполнялось дублирование записи в устаревший ресурс.

Архитектурная альтернатива для конфигураций класса УТ

Проанализируем альтернативный вариант решения исходной задачи. В типовой архитектуре «1С:Управление торговлей 11» редко хранят прямую цену на каждую потребительскую единицу измерения в основном регистре. Вместо этого применяется один из двух подходов:

  1. Хранение цены строго за базовую единицу: цена всегда регистрируется за базовую единицу номенклатуры, а стоимость упаковки или другой единицы рассчитывается динамически («на лету») через коэффициент пересчета. Это исключает дублирование записей и избавляет от необходимости менять состав измерений регистра сведений.
  2. Использование справочника упаковок: в типовых механизмах ценообразования измерением выступает не просто единица измерения, а справочник упаковок (индивидуальных или общих). Если функционал упаковок уже задействован в базе, привязка цены к упаковке является более естественным и типовым решением.
← На главную