Как свернуть табличную часть документа по ставке НДС при обмене через Конвертацию данных 2.1?

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

Рассмотрим частую и довольно интересную задачу при настройке обменов между конфигурациями (например, из УАС в Бухгалтерию Предприятия КОРП) с использованием правил обмена в Конвертации данных 2.1 (КД 2.1). Допустим, в базе-источнике в документах (приобретение, реализация) присутствует большая номенклатурная табличная часть. В базе-приемнике детальный учет по номенклатуре не требуется, и нам необходимо свернуть весь этот большой список до нескольких строк — обобщенных позиций номенклатуры с разделением только по ставкам НДС (например, «Медикаменты 0%», «Медикаменты 10%» и так далее).

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

Вариант 1: Использование параметров и сериализации (решение с форума)

Первый способ, который часто применяют разработчики, заключается в передаче свернутой таблицы в виде строки через параметры объекта. Посмотрим на пример реализации данного метода.

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


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   СУММА(ТЧ.Сумма) КАК Сумма,
|   ТЧ.Номенклатура.СтавкаНДС КАК НоменклатураСтавкаНДС
|ИЗ
|   Документ.ПриобретениеТоваровУслуг.Товары КАК ТЧ
|ГДЕ
|   ТЧ.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
|   ТЧ.Номенклатура.СтавкаНДС";

Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
ВходящиеДанные = Новый Структура("ТЧ", ЗначениеВСтрокуВнутр(Запрос.Выполнить().Выгрузить()));

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

Далее, в обработчике ПКО документа После загрузки мы перехватываем этот параметр в базе-приемнике, распаковываем таблицу значений с помощью ЗначениеИзСтрокиВнутр и программно заполняем табличную часть:


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

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

Вариант 2: Оптимальный (штатный) способ через КоллекциюОбъектов

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

  1. Переходим в ПКО нашего документа.
  2. Проваливаемся в ПКС табличной части (например, Товары).
  3. Открываем обработчик Перед выгрузкой именно для ПКС табличной части.
  4. Пишем запрос, который группирует строки документа-источника, и выгружаем результат в переменную КоллекцияОбъектов.

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   ТЧ.Номенклатура.СтавкаНДС КАК СтавкаНДС,
|   СУММА(ТЧ.Сумма) КАК Сумма,
|   СУММА(ТЧ.СуммаНДС) КАК СуммаНДС,
|   СУММА(ТЧ.Количество) КАК Количество
|ИЗ
|   Документ.ПриобретениеТоваровУслуг.Товары КАК ТЧ
|ГДЕ
|   ТЧ.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
|   ТЧ.Номенклатура.СтавкаНДС";

Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
КоллекцияОбъектов = Запрос.Выполнить().Выгрузить();

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

На этом всё! Механизм конвертации автоматически возьмет эту таблицу значений в качестве источника для табличной части приемника. Он сам пробежится по строкам КоллекцияОбъектов и сформирует узлы XML. Вам не нужно писать код После загрузки.

Важные нюансы при настройке выгрузки свернутых данных

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

1. Полнота данных в запросе

В первом варианте мы группировали только реквизит Сумма. Для Бухгалтерии этого недостаточно. Обязательно нужно суммировать СуммаНДС и Количество. Если учет по свернутой номенклатуре предполагается суммовой (количество не важно), можно принудительно ставить Количество равным единице, а всю сумму переносить в Цена.

2. Правильный поиск Номенклатуры

Искать номенклатуру конструкцией Справочники.Номенклатура.НайтиПоРеквизиту(...) в коде приемника небезопасно. Если пользователь переименует элемент или изменит реквизит, документ загрузится с пустой строкой. Рекомендуем сделать следующее:

  1. Создайте отдельное ПКО для справочника Номенклатура (назовем его, например, НоменклатураСводная).
  2. В ПКС реквизита Номенклатура (внутри ПКО табличной части) укажите это правило и передавайте ставку НДС через ИсходящиеДанные.
  3. В самом ПКО НоменклатураСводная настройте поиск элементов по Уникальному Идентификатору (УИД) или по точному коду, заранее создав 4 нужных элемента в БП КОРП. Это обеспечит надежное сопоставление 1 в 1.

3. Заполнение счетов учета в Бухгалтерии

В конфигурациях 1С:Бухгалтерия для проведения документов требуются заполненные счета учета номенклатуры, счета НДС и счета расчетов. Если мы подставляем искусственные сводные элементы номенклатуры, механизмы автоматической подстановки счетов в БП могут не сработать (особенно если документ просто записывается при обмене). Чтобы избежать ручного заполнения счетов бухгалтерами, добавьте вызов стандартной процедуры в ПКО документа в обработчике После загрузки:


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

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

← На главную