Как заполнить составной реквизит договора ссылкой на документ при конвертации из 1С 7.7 в 1С 8.3

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

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

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

Вариант 1. Заполнение договора в обработчике «ПослеЗагрузки» документа

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

Рассмотрим порядок настройки:

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

Посмотрим на пример кода в обработчике ПослеЗагрузки ПКО документа:


Если ЗначениеЗаполнено(Объект.ДоговорКонтрагента) Тогда
    ДоговорОбъект = Объект.ДоговорКонтрагента.ПолучитьОбъект();
    Если ДоговорОбъект <> Неопределено Тогда
        // Заполняем составной реквизит ссылкой на текущий загруженный документ
        ДоговорОбъект.ДокументОснование = Объект.Ссылка;
        Попытка
            ДоговорОбъект.Записать();
        Исключение
            ЗаписьЖурналаРегистрации("Ошибка переноса договора", 
                УровеньЖурналаРегистрации.Ошибка, , , 
                ОписаниеОшибки());
        КонецПопытки;
    КонецЕсли;
КонецЕсли;

Ограничения данного подхода:

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

Вариант 2. Передача данных через ИсходящиеДанные и ВходящиеДанные

Рассмотрим более архитектурно чистый способ, исключающий ручной вызов метода Записать() в коде загрузки документа. Механизм КД 2.1 позволяет передавать произвольные структуры данных из источника в приемник.

Разберем по шагам:

  1. В ПКО документа находим ПКС для реквизита ДоговорКонтрагента.
  2. В обработчике ПередВыгрузкой свойства формируем структуру ИсходящиеДанные, куда помещаем ссылку на текущий выгружаемый документ: ИсходящиеДанные = Новый Структура("ДокументОснование", Источник);
  3. В ПКО ДоговорыКонтрагентов создаем ПКС для составного реквизита. Устанавливаем флаг Получить из входящих данных.
  4. В обработчике ПередВыгрузкой или ПриВыгрузке этого свойства считываем значение из структуры ВходящиеДанные.ДокументОснование.

Такой способ позволяет штатно передать информацию о документе непосредственно в момент формирования XML-узла договора.

Вариант 3. Отложенная пакетная обработка в «ПослеЗагрузкиВсехДанных»

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

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

  1. В обработчике ПослеЗагрузки ПКО документа не вызываем Записать() для договора, а накапливаем пары Договор - Документ во временной таблице в глобальной коллекции Параметры:
    
    Если Параметры.ТаблицаСвязейДоговоров = Неопределено Тогда
        Таблица = Новый ТаблицаЗначений;
        Таблица.Колонки.Добавить("Договор", Новый ОписаниеТипов("СправочникСсылка.ДоговорыКонтрагентов"));
        Таблица.Колонки.Добавить("Документ", Новый ОписаниеТипов("ДокументСсылка.Документ1", "ДокументСсылка.Документ2"));
        Параметры.ТаблицаСвязейДоговоров = Таблица;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(Объект.ДоговорКонтрагента) Тогда
        СтрокаТЗ = Параметры.ТаблицаСвязейДоговоров.Добавить();
        СтрокаТЗ.Договор = Объект.ДоговорКонтрагента;
        СтрокаТЗ.Документ = Объект.Ссылка;
    КонецЕсли;
    
  2. В глобальном обработчике правил ПослеЗагрузкиВсехДанных выполняем единую пакетную обработку:
    
    Если Параметры.ТаблицаСвязейДоговоров <> Неопределено Тогда
        Таблица = Параметры.ТаблицаСвязейДоговоров;
        Таблица.Свернуть("Договор", "Документ");
        
        Для Каждого Стр Из Таблица Цикл
            Если ЗначениеЗаполнено(Стр.Договор) Тогда
                ДоговорОбъект = Стр.Договор.ПолучитьОбъект();
                Если ДоговорОбъект <> Неопределено И ДоговорОбъект.ДокументОснование <> Стр.Документ Тогда
                    ДоговорОбъект.ДокументОснование = Стр.Документ;
                    Попытка
                        ДоговорОбъект.Записать();
                    Исключение
                        // Обработка ошибок записи
                    КонецПопытки;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    

Оптимизация выборки на стороне 1С 7.7

Выясним причину возможных зависаний при выгрузке из 1С 7.7. Попытка перебирать документы или искать соответствия прямо внутри ПКО каждого отдельного договора в коде 7.7 приводит к многократным сканированиям таблиц базы данных (особенно в DBF-формате).

Чтобы ускорить процесс:

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