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

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

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

Механизм решения проблемы через параметры загрузки

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

Шаг 1: Инициализация хранилища в обработчике «Перед загрузкой данных»

Первым делом нам необходимо подготовить структуру, в которой будут храниться ссылки на документы. Для этого перейдем в глобальные обработчики конвертации и выберем событие «Перед загрузкой данных». Здесь мы создадим таблицу значений и поместим её в параметры обмена, чтобы она была доступна во всех последующих обработчиках.


ТаблицаДокументов = Новый ТаблицаЗначений;
ТаблицаДокументов.Колонки.Добавить("Документ");
ТаблицаДокументов.Колонки.Добавить("ДатаВремя");

Параметры.Вставить("ТаблицаДокументов", ТаблицаДокументов);

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

Шаг 2: Сбор ссылок в обработчике «После загрузки объекта»

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


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

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

Шаг 3: Сортировка и последовательное проведение

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


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

Тонкости и рекомендации по оптимизации

Рассмотрим несколько продвинутых советов, которые помогут сделать обмен более надежным:

  1. Сортировка по моменту времени: Если в вашей базе много документов, созданных в одну и ту же секунду, простой сортировки по ДатаВремя может быть недостаточно. Проанализируем ситуацию: два документа имеют время 12:00:00. В этом случае 1С определяет их порядок по ссылке. Для идеального результата в таблицу значений лучше сохранять Объект.МоментВремени() и сортировать по нему.
  2. Использование БСП: Если вы работаете в современной конфигурации на базе БСП (Библиотека стандартных подсистем), рекомендуем использовать механизм отложенного проведения. Вместо создания своей таблицы в параметрах, можно программно добавлять ссылки в типовой регистр сведений ОчередьДокументовДляПроведения. Это позволит системе провести документы в фоновом режиме, не блокируя работу пользователя.
  3. Контроль памяти: При очень больших объемах данных (десятки тысяч документов) хранение таблицы значений в оперативной памяти может привести к её переполнению. В таких случаях лучше записывать ссылки во временный файл или технический регистр сведений в самой базе 1С, а после загрузки считывать их оттуда порциями.
  4. Обработка ошибок: Обязательно используйте конструкцию Попытка ... Исключение. Если один документ не проведется (например, из-за нехватки товара), ваш цикл не должен прерываться. Все ошибки стоит записывать в лог, чтобы после обмена администратор мог оперативно их исправить.

Таким образом, разделение процесса загрузки и процесса проведения позволяет полностью контролировать последовательность действий и избежать логических ошибок, связанных с отсутствием данных в базе в момент записи объекта. Мы проанализировали самый эффективный способ реализации этого механизма через стандартные средства «Конвертации данных».

← На главную