Почему не заполняются счета учета для новой номенклатуры при переносе документов из УТ 10.3 в БП 3.0 и как это исправить?

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

При настройке обмена данными между конфигурациями «Управление торговлей 10.3» и «Бухгалтерия предприятия 3.0» через «Конвертацию данных 2.1» часто возникает классическая проблема. При переносе документов (например, Перемещение товаров или Поступление товаров и услуг) счета учета для уже существовавшей в базе-приемнике номенклатуры заполняются правильно (например, 10.06), а для только что созданной номенклатуры подставляются счета по умолчанию (например, 41.01), игнорируя настройки папки (родителя) справочника.

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

Выясняем причину: почему счета не заполняются с первого раза?

Для того чтобы понять суть проблемы, проанализируем структуру выгружаемого XML-файла обмена и логику работы парсера КД 2.1 на стороне приемника (БП 3.0). Если открыть XML-файл выгрузки, мы увидим следующую последовательность объектов:

  1. Сначала в файле идет блок описания документа: <Объект Нпп="1" Тип="ДокументСсылка.ПеремещениеТоваров">.
  2. И только ниже располагается блок описания новой номенклатуры, которая содержится в табличной части этого документа: <Объект Нпп="12" Тип="СправочникСсылка.Номенклатура">.

Когда обработка загрузки читает этот XML-файл, она движется строго последовательно сверху вниз:

Шаг 1. Чтение документа. Парсер доходит до табличной части документа и видит ссылку на номенклатуру. Поскольку этой номенклатуры в базе-приемнике еще нет, платформа 1С временно создает пустую «битую» ссылку (placeholder) с нужным GUID (уникальным идентификатором). Физически элемента в базе данных еще не существует, у этой ссылки нет ни наименования, ни родителя (папки).

Шаг 2. Вызов обработчика «После загрузки». На этом этапе в ПКО документа срабатывает стандартный код заполнения счетов учета:


Документы.ПеремещениеТоваров.ЗаполнитьСчетаУчетаВТабличнойЧасти(Объект, "Товары");

Шаг 3. Обращение к базе данных. Метод заполнения счетов учета БП 3.0 делает запрос к регистру сведений СчетаУчетаНоменклатуры. Запрос пытается определить счета, настроенные для родителя (папки) данной номенклатуры. Но так как сам элемент справочника еще не записан в БД, связь с родителем отсутствует. Запрос возвращает пустой результат, и система вынужденно подставляет счета по умолчанию (41.01).

Шаг 4. Запись номенклатуры. Только после того, как документ полностью обработан, парсер КД доходит до блока номенклатуры, создает полноценный элемент справочника в БД, заполняет его реквизиты (включая родителя) и записывает его. Теперь номенклатура связана с папкой.

Шаг 5. Повторный проход. При повторном обмене номенклатура уже физически существует в БД со всеми связями. Метод заполнения счетов отрабатывает корректно и находит нужный счет (10.06).

Попытка просто вставить Объект.Записать() в обработчике «После загрузки» документа не решит проблему, так как в этот момент сам элемент номенклатуры в базе данных еще не создан.

Правильное решение: отложенное заполнение счетов учета

Наиболее правильным и архитектурно верным решением в рамках «Конвертации данных 2.1» является использование механизма **отложенного заполнения**. Мы не будем заполнять счета в момент чтения документа. Вместо этого мы соберем ссылки на все загруженные документы, а когда весь файл импорта будет полностью прочитан (и все новые элементы номенклатуры гарантированно запишутся в БД), мы в один проход заполним счета учета во всех этих документах.

Разберем по шагам, как это реализовать в правилах конвертации.

Шаг 1. Инициализация параметра в правилах конвертации

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

Параметры.Вставить("ДокументыСОпределениемДопРеквизитов", Новый Массив);

Шаг 2. Сбор документов в ПКО документа

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

Важно: для новых документов, у которых еще нет физической ссылки в базе данных, необходимо использовать метод ПолучитьСсылкуНового().


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

Шаг 3. Заполнение счетов в глобальном обработчике после завершения загрузки

Теперь переходим в глобальный обработчик правил конвертации «После загрузки данных». Этот обработчик выполняется платформой в самом конце, когда абсолютно все объекты из XML-файла уже прочитаны и физически записаны в базу данных приемника. Здесь мы обходим наш массив накопленных документов и вызываем штатные механизмы БП 3.0 для автоматического заполнения счетов учета:


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

Проанализируем этот код: мы используем штатную функцию СчетаУчетаВДокументах.ЗаполнитьПередЗаписью, предварительно передав в ДополнительныеСвойства специальный флаг "ЗаполнитьСчетаУчетаПередЗаписью". Это заставляет логику БП 3.0 принудительно рассчитать счета учета номенклатуры (которая к этому моменту уже записана в базу вместе со своим родителем) и обновить табличную часть документа.

Альтернативные варианты решения

Для полноты картины рассмотрим еще два альтернативных способа решения данной проблемы, которые также применяются в практике интеграции на платформе 1С:

  1. Принудительное изменение порядка выгрузки через функцию ВыгрузитьОбъект. Мы можем заставить «Конвертацию данных» выгружать номенклатуру в XML-файл до того, как выгрузится сам документ. Для этого в ПКС (Правила конвертации свойств) для свойства Номенклатура перед выгрузкой можно написать: ВыгрузитьОбъект(Источник.Номенклатура);. В таком случае номенклатура запишется в базу-приемник первой, и при загрузке документа счета определятся сразу. Однако у этого метода есть существенный минус — он может значительно замедлить процесс выгрузки и увеличить размер XML-файла из-за дублирования анализа ссылок.
  2. Передача счетов учета через ПараметрыОбъекта. Мы можем определить счета учета номенклатуры еще на стороне источника (УТ 10.3) в ПКО номенклатуры или документа и передать их в XML в виде параметров (например, через структуру ПараметрыОбъекта). При загрузке документа в БП 3.0 мы просто прочитаем эти параметры и подставим готовые счета в табличную часть без обращения к регистру сведений приемника. Этот способ эффективен, если учетная политика и структура счетов в обеих базах полностью идентичны.

Тем не менее, предложенный автором темы вариант с отложенным заполнением в «После загрузки данных» признан наиболее надежным, так как он полностью опирается на штатные и актуальные механизмы БУХ 3.0, гарантируя консистентность данных при любых последующих обновлениях конфигурации-приемника.

← На главную