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

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

При настройке правил обмена в 1С с помощью конфигурации «Конвертация данных 2.0 (2.1)» разработчики часто сталкиваются с необходимостью кастомизации выгрузки проводок. Одна из наиболее трудоемких задач здесь — это программное изменение видов субконто и их значений «на лету» в процессе выгрузки свойств СубконтоДт или СубконтоКт регистра бухгалтерии.

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

Почему стандартные методы удаления и добавления значений не работают?

Попытки решить задачу «в лоб» через прямое изменение коллекции Значение (которая в обработчиках КД представляет собой системный набор субконто) часто приводят к фиаско. Например, код вида:


Значение.Удалить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НайтиПоНаименованию("Регистрация в налоговом органе"));
Значение.Вставить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты, НайденныйКонтрагент);

не приносит желаемого результата: в XML-файле обмена все равно оказывается старое субконто. Выясним причину этого поведения.

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

Рассмотрим два проверенных и рабочих сценария решения этой задачи.

Решение 1. Элегантная подмена параметров в событии «При выгрузке» (Рекомендуемый способ)

Самый простой и красивый способ подменить субконто — использовать локальные переменные, которые платформа КД 2.0 предоставляет в обработчике ПКС «При выгрузке» для свойств субконто.

Когда КД обрабатывает очередное субконто в цикле, нам доступны следующие параметры:

  1. ВидСубконто — текущий вид характеристики (тип ПланВидовХарактеристикСсылка).
  2. Субконто — текущее значение субконто (ссылочный или простой тип данных).
  3. ИмяПКО — строковое имя правила конвертации объектов, по которому будет выгружаться значение субконто.

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


// Проверяем, что обрабатывается именно то субконто, которое мы хотим заменить
Если ВидСубконто = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НайтиПоНаименованию("Регистрация в налоговом органе") Тогда

    // 1. Подменяем Вид субконто на требуемый в приемнике
    ВидСубконто = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты;
    
    // 2. Ищем новое значение субконто в базе источника
    // Например, ищем контрагента по коду государственного органа, сохраненному в исходном субконто
    КодГосОргана = Субконто.Код;
    НайденныйКонтрагент = Справочники.Контрагенты.НайтиПоРеквизиту("КодГосударственногоОргана", КодГосОргана);
    
    Если ЗначениеЗаполнено(НайденныйКонтрагент) Тогда
        Субконто = НайденныйКонтрагент;
    Иначе
        // Если контрагент не найден, можно записать пустую ссылку, чтобы избежать ошибок при загрузке
        Субконто = Справочники.Контрагенты.ПустаяСсылка();
    КонецЕсли;
    
    // 3. Явно указываем Имя ПКО для выгрузки нового значения
    ИмяПКО = "Контрагенты";

КонецЕсли;

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

Решение 2. Полное переопределение коллекции через «Соответствие» в событии «Перед выгрузкой»

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

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

Проанализируем пример реализации такого алгоритма:


// Создаем новое соответствие для субконто
СубконтоДтНовое = Новый Соответствие();

// Получаем исходные субконто из выгружаемой строки движений (ОбъектКоллекции)
ИсходноеСубконтоРегистрация = ОбъектКоллекции.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НайтиПоНаименованию("Регистрация в налоговом органе")];
ИсходноеСубконтоПлатежи = ОбъектКоллекции.СубконтоДт.ВидыПлатежейВГосБюджет;

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

// Переносим второе субконто (если оно заполнено) без изменений
Если ЗначениеЗаполнено(ИсходноеСубконтоПлатежи) Тогда
    СубконтоДтНовое.Вставить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ВидыПлатежейВГосБюджет, ИсходноеСубконтоПлатежи);
КонецЕсли;

// Передаем сформированное соответствие в параметр Значение
Значение = СубконтоДтНовое;

При таком подходе движок КД 2.0 примет созданное нами соответствие СубконтоДтНовое за основу и выгрузит только те виды субконто, которые мы в него явно добавили.

Важный нюанс: Использование универсальной таблицы значений

Иногда возникает ситуация, когда база-источник является небухгалтерской (например, «Управление торговлей»), и в ее метаданных вообще нет планов счетов и планов видов характеристик ВидыСубконтоХозрасчетные. Написать код с обращением к ПланыВидовХарактеристик... в такой базе невозможно — конфигурация выдаст синтаксическую ошибку при компиляции обработчиков.

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


// Создаем таблицу значений с жестко определенной структурой колонок
ТаблицаСубконто = Новый ТаблицаЗначений;
ТаблицаСубконто.Колонки.Добавить("Ключ");
ТаблицаСубконто.Колонки.Добавить("Значение");

// Добавляем строку для субконто "Контрагенты"
НоваяСтрока = ТаблицаСубконто.Добавить();

// Передаем структуру с наименованием вида субконто для идентификации в приемнике
НоваяСтрока.Ключ = Новый Структура("Наименование", "Контрагенты");

// Находим и присваиваем значение
НайденныйКонтрагент = Справочники.Контрагенты.НайтиПоКоду("00001");
НоваяСтрока.Значение = НайденныйContragent;

// Передаем таблицу в Значение
Значение = ТаблицаСубконто;

// Явно указываем правило конвертации для видов субконто
ИмяПКОВидСубконто = "ВидыСубконтоХозрасчетные";

Этот способ гарантирует, что на стороне базы-приемника КД автоматически сопоставит переданную нами структуру с реальным планом видов характеристик по наименованию "Контрагенты".

Советы по предотвращению ошибок при загрузке

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

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


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

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

← На главную