Разберем классическую и крайне неприятную проблему, с которой часто сталкиваются специалисты при переносе данных с помощью конфигурации «1С:Конвертация данных 2.1» (КД 2.1). Представим ситуацию: вы успешно перенесли начальные остатки на определенную дату (например, на 1 июля) и теперь начинаете переносить документы за последующий период (с 1 по 31 июля). Все идет хорошо, но при выгрузке июльских документов программа начинает автоматически «подтягивать» по ссылкам связанные документы из структуры подчиненности, даты которых относятся к июню или более ранним периодам.
В результате в базе-приемнике появляются проведенные документы прошлых периодов (например, «Выдача наличных» за июнь, прикрепленная к июльскому «Авансовому отчету»). Эти документы делают движения по регистрам, удваивают обороты и безнадежно портят уже выверенное и введенное на 1 июля начальное сальдо. Рассмотрим подробнее, почему так происходит, почему простые попытки решить проблему в коде загрузки часто терпят неудачу, и как решить этот вопрос красиво и профессионально.
Посмотрим на ситуацию, описанную автором темы. Он попытался решить проблему на стороне загрузки: в обработчике ПослеЗагрузкиДокумента отбирал документы по дате и добавлял их в таблицу значений для последующего проведения, а для «старых» документов пытался установить режим записи без проведения. Однако документы прошлых периодов все равно оказались проведенными в базе-приемнике. Выясним причину этой ошибки. Здесь сработали сразу два важных механизма платформы 1С и загрузчика КД 2.1:
РежимЗаписи. В КД 2.1 параметры РежимЗаписи и РежимПроведения инициализируются и обрабатываются платформой строго в обработчике «Перед загрузкой». Попытка изменить значение РежимЗаписи = "Запись" в обработчике «После загрузки» (или в алгоритме, который из него вызывается) игнорируется загрузчиком, так как решение о режиме записи к этому моменту уже принято и передано платформе.<Проведен>true</Проведен>. При чтении файла загрузчик КД автоматически устанавливает свойству создаваемого объекта значение Объект.Проведен = Истина. Когда дело доходит до записи объекта в базу данных (а это происходит сразу после выполнения кода «После загрузки»), платформа видит, что у документа стоит признак проведенности, и автоматически проводит его, игнорируя ваши ожидания.Давайте разберем три наиболее эффективных и правильных способа решения этой проблемы, ранжированных по степени их изящества и соответствия стандартам разработки на КД 2.1.
Самый правильный архитектурный подход — не бороться с ненужными документами при загрузке, а вообще не выгружать их данные (табличные части, движения, реквизиты) из базы-источника, если они находятся за пределами выбранного периода переноса. Для этого мы можем использовать предопределенный параметр конвертации ТолькоПолучитьУзелСсылки.
Рассмотрим по шагам, как это реализовать:
Если Источник.Дата < Параметры.ДатаНачала Тогда
ТолькоПолучитьУзелСсылки = Истина;
КонецЕсли;
Как это работает: Если дата выгружаемого по ссылке документа меньше, чем дата начала периода переноса (которую мы предварительно передаем в параметрах настройки выгрузки), КД 2.1 не будет выгружать сам объект целиком. В XML-файл запишется только ссылка на него (УИД, код/номер и дата для поиска). Сам документ, его табличные части и движения выгружены не будут, что существенно сократит размер файла обмена и ускорит процесс.
Если мы применили Способ 1, то при загрузке ссылок на старые документы в базе-приемнике могут создаться «пустые» документы-фантомы (в которых заполнены только дата, номер и уникальный идентификатор, но нет никаких данных в табличных частях). Чтобы избежать появления таких «битых» документов, необходимо использовать специальную настройку КД 2.1.
Выполним следующую настройку:
Проанализируем результат совместной работы первого и второго способов. Теперь, если документ «Авансовый отчет» за июль ссылается на июньскую «Выдачу наличных», то благодаря первому способу в файл выгрузится только ссылка. А благодаря второму способу, при загрузке в базу-приемник, эта ссылка запишется в реквизит авансового отчета, но сам документ «Выдача наличных» создан не будет. В интерфейсе базы-приемника реквизит будет отображаться как «Объект не найден», либо останется пустым, что абсолютно корректно, ведь данные за июнь у нас уже занесены документами ввода начальных остатков!
Если по каким-то причинам вам все же необходимо загрузить документы старого периода в базу-приемник (например, для сохранения истории или последующего ручного сопоставления), но вы хотите гарантировать, что они запишутся исключительно в непроведенном состоянии, мы можем исправить исходный алгоритм автора двумя путями.
Вариант А. Через обработчик «После загрузки» (сброс признака проведения)
В ПКО нужного документа в обработчике событий «После загрузки» мы можем принудительно снять признак проведенности у объекта и очистить его движения еще до того, как загрузчик запишет его в базу данных:
Если Объект.Дата < Параметры.ДатаНачала Тогда
Объект.Проведен = Ложь;
// Обязательно очищаем движения, если они переносились напрямую
Для Каждого НаборДвижений Из Объект.Движения Цикл
НаборДвижений.Очистить();
КонецЦикла;
КонецЕсли;
Поскольку этот код выполняется непосредственно перед физической записью объекта в базу-приемник, документ гарантированно запишется как непроведенный, не создавая движений по регистрам и не ломая ОСВ.
Вариант Б. Через обработчик «Перед загрузкой» (переопределение режима записи)
Если мы хотим пойти более красивым путем и переопределить поведение самого загрузчика КД, используем обработчик «Перед загрузкой». Поскольку сам Объект на этом этапе еще не создан и не прочитан из файла, проверку даты документа мы делаем через структуру полученных из XML свойств:
ДатаДокумента = Неопределено;
Если ПолученныеСвойства.Свойство("Дата", ДатаДокумента) Тогда
Если ДатаДокумента < Параметры.ДатаНачала Тогда
РежимЗаписи = "Запись";
КонецЕсли;
КонецЕсли;
Этот способ работает максимально корректно на уровне ядра КД 2.1, принудительно переводя запись объекта в режим обычного сохранения без проведения.
Для достижения наилучшего результата и сохранения чистоты базы данных приемника мы рекомендуем использовать связку Способа 1 (выгрузка только ссылок через ТолькоПолучитьУзелСсылки = Истина в обработчике «Перед выгрузкой») и Способа 2 (установка флага «НЕ создавать новый объект» в ПКО). Это позволит вам избежать раздувания XML-файла выгрузки миллионами ненужных строк и гарантирует, что старые документы не появятся в базе-приемнике в виде «пустышек» или проведенных документов, искажающих ваш бухгалтерский и управленческий учет.