Как подменить документ-основание в «Корректировке реализации» при обмене данными через КД 2.1

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

При настройке обмена данными между устаревшими конфигурациями (например, 1С:Торговля и Склад 7.7) и современными решениями на платформе 8.3 (например, Бухгалтерия предприятия 2.0) часто возникают ситуации, когда типовые правила переноса не соответствуют бизнес-логике. Одна из таких задач — подмена документа-основания. Рассмотрим ситуацию, когда при переносе исправлений счетов-фактур в качестве основания для документа КорректировкаРеализации должен выступать не сам счет-фактура, а исходная РеализацияТоваровУслуг.

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

Анализ проблемы: почему стандартный подход не работает

Разберем типичную ситуацию. Программист пытается изменить документ-основание в обработчике ПКО (Правила конвертации объектов) После загрузки. Часто код выглядит следующим образом:

Объект.ДокументРеализации = Объект.Ссылка.ДокументРеализации.ДокументОснование;

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

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

Решение проблемы через обработчик «При загрузке»

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

Нам необходимо напрямую переопределить реквизит ДокументРеализации. Вместо обращения к ссылке самого объекта, мы используем данные, которые уже попали в структуру объекта в памяти. Посмотрим на итоговый работающий код:


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

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

Разбор последовательности событий в КД 2.1

Чтобы лучше понимать, где именно писать код, проанализируем жизненный цикл загрузки объекта:

  1. При загрузке: Срабатывает в самом начале. Объект только создан программно, реквизиты еще пустые. Здесь удобно устанавливать значения по умолчанию.
  2. Заполнение реквизитов (ПКС): Система читает данные из файла и записывает их в Объект.ИмяРеквизита.
  3. После загрузки: Все данные из файла уже в объекте. Это идеальное место для подмены ссылок. Объект еще не записан в базу, но он «полный».
  4. Перед записью: Последний шанс изменить данные перед фиксацией в БД.
  5. После записи: Объект уже в базе. Здесь нельзя менять реквизиты без повторного вызова Записать(), что крайне не рекомендуется.

Следовательно, ошибка автора темы заключалась в лишнем посреднике Ссылка. Правильный доступ выглядит так: Объект.Реквизит.РеквизитДругогоОбъекта.

Дополнительные настройки для корректной работы «Корректировки реализации»

Просто подменить ссылку в поле ДокументРеализации часто недостаточно для корректного учета в 1С:Бухгалтерия. Документ корректировки имеет сложную структуру табличных частей. Разберем, что еще нужно сделать в обработчике После загрузки:

  1. Заполнение счетов учета: Обязательно вызывайте стандартные процедуры конфигурации-приемника, чтобы счета подставились корректно.
  2. Установка вида операции: Для корректировок важно явно указывать вид операции (например, «Согласованное изменение»).

Пример расширенного кода в После загрузки:


// Устанавливаем вид операции
Объект.ВидОперации = Перечисления.ВидыОперацийИсправленияПоступленияРеализации.СогласованноеИзменение;

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

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

// Устанавливаем флаги НДС
Объект.КорректироватьНДС = Истина;
Объект.СуммаВключаетНДС = Истина;

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

Почему не стоит использовать Объект.Записать() внутри ПКО

В сообщениях форума упоминалось принудительное проведение объекта: Объект.Записать(РежимЗаписиДокумента.Проведение). Проанализируем, почему это плохая практика в КД 2.1:

Альтернативный метод через ПКС (Правила конвертации свойств)

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

В этом случае вам не нужно писать код в общем обработчике документа. В ПКС для реквизита ДокументРеализации напишите:


// Значение - это то, что пришло из источника (например, ссылка на СФ)
Если ТипЗнч(Значение) = Тип("ДокументСсылка.СчетФактураВыданный") Тогда
    // Меняем значение ссылки на основание счета-фактуры
    Значение = Значение.ДокументОснование;
КонецЕсли;

Этот способ хорош тем, что подмена происходит еще на этапе сопоставления данных, и в объект Объект.ДокументРеализации сразу попадает нужная вам Реализация. Это избавляет от необходимости «перезаписывать» реквизит в обработчике После загрузки.

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

← На главную