Как перенести регистры сведений с регистратором в КД2, заменив исходный регистратор на документ «ПереносДанных»?

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

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

Постановка задачи и основные сложности

Наша цель — перенести записи регистров сведений, таких как кадровые данные, данные для расчета среднего заработка и другие, из базы-источника в базу-приемник. Ключевая особенность заключается в том, что в базе-приемнике в поле Регистратор для всех этих записей должен быть указан не исходный документ, а специально созданный документ ПереносДанных. При этом мы можем захотеть создать как один общий документ ПереносДанных для всех записей, так и несколько, разделенных по смыслу (например, для кадровых данных, для расчетных данных и т.д.).

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

Причина в том, что движения регистра сведений жестко привязаны к регистратору. «Конвертация Данных 2» ожидает, что для поля Регистратор будет либо найден исходный документ, либо ссылка на новый документ будет однозначно определена в контексте переноса движений. Просто указать ПКО, которое находит или создает документ, может быть недостаточно, если сам механизм переноса регистра не понимает, как связать эти движения с новым регистратором.

Подход 1: Создание документа «ПереносДанных» заранее и прямое указание в ПКС регистра

Этот подход часто является первым, который мы пытаемся реализовать. Давайте рассмотрим его подробнее:

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

  2. Настраиваем ПКО для документа «ПереносДанных»: Мы создаем ПКО для объекта Документ.ПереносДанных. В этом ПКО мы должны настроить алгоритм поиска существующего документа в базе-приемнике. Например, мы можем искать документ по номеру и дате, или по значению в поле Комментарий.

    Пример настройки ПКО для поиска существующего документа:

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

Проблема данного подхода: Как мы уже упоминали, даже при такой, казалось бы, логичной настройке, КД2 может выдавать ошибку «не указан регистратор». Это происходит потому, что механизм переноса движений регистра сведений ожидает, что регистратор будет определен более явно, возможно, как часть документа, который является источником движений. Нам нужен более надежный способ "подсунуть" ссылку на наш документ ПереносДанных.

Подход 2: Основное рекомендуемое решение – выгрузка через документ-регистратор

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

Шаг 1: Подготовка документов «ПереносДанных» в базе-приемнике

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

  1. ПереносДанных с комментарием "Перенос кадровых данных".
  2. ПереносДанных с комментарием "Перенос данных для расчета среднего".

Шаг 2: Настройка ПКО для документа «ПереносДанных»

Мы создаем ПКО для объекта Документ.ПереносДанных. Главная задача этого ПКО — находить и возвращать ссылку на уже созданный нами документ в базе-приемнике, а не создавать новый. Это критически важно.

Например, в обработчике события «При загрузке» или «Перед записью» для ПКО документа ПереносДанных мы можем реализовать поиск по комментарию:


// В обработчике "При загрузке" ПКО для документа "ПереносДанных"
// ОбъектПриемника - это ссылка на документ, который КД2 пытается загрузить/создать

Если ОбъектПриемника = Неопределено Тогда // Если КД2 не нашла соответствие
    // Пробуем найти существующий документ по какому-либо уникальному признаку.
    // Например, по Комментарию, если мы договорились использовать его как идентификатор
    ИмяДляПоиска = Источник.ПолучитьИзИсточника("ИмяДокументаПереноса"); // Предположим, мы передаем это имя как свойство из источника

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

Обратите внимание, что мы можем передавать параметры в ПКО из правила конвертации свойства (ПКС), которое его вызывает, что дает нам гибкость в поиске нужного документа.

Шаг 3: Настройка ПВХ и ПКС для регистра сведений с использованием ПКО документа

Теперь мы переходим к самому главному — как мы связываем записи регистра сведений с нашим документом ПереносДанных.

  1. Создаем правило выгрузки данных (ПВХ) для каждого регистра сведений, который нам необходимо перенести. Например, для регистра сведений «КадроваяИсторияСотрудников».

  2. Внутри ПВХ регистра сведений, в правиле конвертации свойства (ПКС) для поля Регистратор, мы указываем ПКО, которое мы создали для документа ПереносДанных.

  3. Передача параметров в ПКО регистратора (опционально, но полезно): Если у нас несколько документов ПереносДанных (например, один для кадровых данных, другой для расчетных), мы должны указать, какой именно документ ПереносДанных должен быть использован. Это можно сделать, передавая параметр в ПКО регистратора.

    Например, в ПВХ для регистра «КадроваяИсторияСотрудников» в ПКС для поля Регистратор, мы можем добавить параметр, который будет указывать на имя нужного документа ПереносДанных:

    
    // В ПКС поля "Регистратор" регистра сведений, в обработчике "Перед выгрузкой"
    // (или при создании параметров через выражение)
    
    Параметры.Вставить("ИмяДокументаПереноса", "Перенос кадровых данных");
    // Или, если это передается из другого источника:
    // Параметры.Вставить("ИмяДокументаПереноса", Источник.ПолучитьИзИсточника("ВидПереносаДанных"));
    

    Это позволит ПКО для документа ПереносДанных, которое мы настроили на Шаге 2, получить нужный идентификатор и найти правильный документ в базе-приемнике.

Таким образом, мы используем ПКС поля Регистратор, чтобы явно вызвать наше ПКО для документа ПереносДанных, которое, в свою очередь, найдет и вернет ссылку на заранее подготовленный нами документ в базе-приемнике. Это обеспечивает корректное заполнение поля Регистратор для всех переносимых записей регистра сведений.

Подход 3: Программное создание движений в базе-приемнике

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

  1. Выгружаем исходные данные регистра: На первом этапе мы выгружаем «сырые» данные из регистра сведений базы-источника. Это могут быть все измерения и ресурсы регистра, а также, возможно, период. Мы можем выгрузить их в таблицу значений (если используем обработку для выгрузки), или в простой текстовый файл (CSV, XML), который затем будет прочитан в базе-приемнике.

  2. Программное создание записей в базе-приемнике: В базе-приемнике мы создаем внешнюю обработку или дорабатываем существующую. Эта обработка будет выполнять следующие действия:

    1. Чтение данных: Считывает данные, выгруженные на первом этапе.
    2. Поиск или создание регистратора: Находит или, при необходимости, создает документы ПереносДанных, которые будут выступать в качестве регистраторов.
    3. Создание записей регистра: Для каждой строки выгруженных данных программно создает новую запись регистра сведений, заполняя все измерения, ресурсы и, самое главное, указывая в качестве Регистратора ссылку на наш документ ПереносДанных.

Пример программного создания записи регистра сведений в базе-приемнике:


// Этот код выполняется в базе-приемнике, например, во внешней обработке

// Ссылка на документ "ПереносДанных", который будет регистратором
// Предположим, мы уже получили эту ссылку (например, нашли по комментарию или создали)
ПереносДанныхРегистратор = Документы.ПереносДанных.НайтиПоНомеру("000000001", Дата("20240101")); 
// Или
// ПереносДанныхРегистратор = СсылкаНаРанееСозданныйДокументПереносДанных;

Если ПереносДанныхРегистратор = Неопределено Тогда
    Сообщить("Документ 'ПереносДанных' не найден!");
    Возврат;
КонецЕсли;

// Пример данных, которые мы выгрузили из базы-источника
// В реальном сценарии это могла бы быть ТаблицаЗначений, загруженная из файла
ДанныеДляЗаписи = Новый Структура;
ДанныеДляЗаписи.Вставить("Период", Дата("20240115"));
ДанныеДляЗаписи.Вставить("Сотрудник", Справочники.Сотрудники.НайтиПоКоду("000000001"));
ДанныеДляЗаписи.Вставить("ВидСобытия", "ПриемНаРаботу");
ДанныеДляЗаписи.Вставить("Должность", Справочники.Должности.НайтиПоНаименованию("Менеджер"));
// ... и другие измерения и ресурсы регистра

// Получаем менеджер записи регистра сведений
МенеджерЗаписи = РегистрыСведений.КадроваяИсторияСотрудников.СоздатьМенеджерЗаписи();

// Устанавливаем регистратор - это наша главная цель!
МенеджерЗаписи.Регистратор = ПереносДанныхРегистратор;

// Заполняем остальные поля записи
МенеджерЗаписи.Период = ДанныеДляЗаписи.Период; // Если регистр периодический
МенеджерЗаписи.Сотрудник = ДанныеДляЗаписи.Сотрудник;
МенеджерЗаписи.ВидСобытия = ДанныеДляЗаписи.ВидСобытия;
МенеджерЗаписи.Должность = ДанныеДляЗаписи.Должность;
// ... заполняем все измерения и ресурсы

Попытка
    // Записываем запись. Истина в Записать() означает, что запись будет произведена
    // в режиме движений регистратора, удаляя предыдущие движения этого регистратора (если они были)
    МенеджерЗаписи.Записать(Истина); 
    Сообщить("Запись регистра успешно создана.");
Исключение Э
    Сообщить("Ошибка при создании записи регистра: " + Э.Описание);
КонецПопытки;

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

Отладка и тестирование – ключ к успеху

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

  1. Используем режим отладки КД2: «Конвертация Данных 2» предоставляет мощные средства отладки. Мы можем пошагово проходить выполнение правил конвертации, проверять значения передаваемых параметров и формируемых объектов. Это позволит нам увидеть, какая именно ссылка присваивается полю Регистратор перед записью.

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

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

  4. Анализируем результат в базе-приемнике: После каждой тестовой загрузки мы проверяем, корректно ли создались записи регистра сведений, и, самое главное, правильно ли заполнилось поле Регистратор ссылкой на наш документ ПереносДанных.

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

← На главную