Как в Конвертации данных очистить движения документа, если он загружается распроведенным?

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

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

Проанализируем ситуацию: в базе-приемнике (например, 1С:УПП) открываем загруженный документ — он не проведен. Но при нажатии на кнопку "Показать движения документа" мы видим записи в регистрах. Это прямое следствие того, что при загрузке объекта не был выполнен механизм очистки движений. Рассмотрим несколько способов, как это исправить.

Способ 1. Принудительная отмена проведения документа

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

Реализуется он в обработчике события После загрузки в правиле конвертации объекта (ПКО) для нужного документа. Логика проста: если мы нашли существующий объект в базе-приемнике, мы принудительно его записываем с режимом отмены проведения. Это гарантированно вызовет стандартный платформенный механизм, который очистит все движения.

Пример кода в обработчике "После загрузки":


Если ОбъектНайден и НЕ Отказ Тогда
    // Принудительно отменяем проведение документа.
    // Это очистит все его старые движения.
    Объект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
КонецЕсли;

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

Преимущества:

Недостатки:

Способ 2. Прямая очистка наборов записей (рекомендуемый)

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

Реализация также происходит в обработчике После загрузки. Мы проверяем, должен ли документ быть проведенным (этот признак нужно передавать из источника, например, через ПараметрыОбъекта). Если документ пришел непроведенным, мы перебираем все его наборы записей движений и очищаем их.

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

Пример кода в обработчике "После загрузки":


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

Преимущества:

Недостатки:

Способ 3. Отложенная обработка документов (для больших объемов)

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

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

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

  1. Инициализация в "Перед загрузкой данных"

    В глобальном обработчике события Перед загрузкой данных создаем коллекцию (например, ТаблицаЗначений), где будем хранить информацию о документах для обработки.

    
    // Глобальный обработчик "Перед загрузкой данных"
    ТаблицаДокументов = Новый ТаблицаЗначений;
    ТаблицаДокументов.Колонки.Добавить("СсылкаНаДокумент");
    ТаблицаДокументов.Колонки.Добавить("Действие"); // Например, "Провести" или "ОтменитьПроведение"
    Параметры.Вставить("ДокументыДляОбработки", ТаблицаДокументов);
    
  2. Сбор данных в "После загрузки"

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

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

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

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

Преимущества:

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

← На главную