При переносе данных между базами 1С часто возникает задача оптимизации объема передаваемой информации. Классический пример: перенос документов реализации из отраслевой или торговой базы в 1С:Бухгалтерию. Если документов много, они перегружают базу-приемник лишней аналитикой. Гораздо эффективнее сворачивать данные за день и переносить их в виде одной сводной проводки через документ ОперацияБух (Операция (бухгалтерский учет)).
В этой статье мы подробно рассмотрим, как реализовать такую свертку с помощью конфигурации «1С:Конвертация данных 2.1» (КД 2.1). Мы разберем логику настройки правил выгрузки данных (ПВД), создания правил конвертации объектов (ПКО) с пустым источником и правильной передачи субконто в проводках.
Стандартный обмен «один в один» (один документ источника преобразуется в один документ приемника) настраивается в КД 2.1 за несколько кликов. Однако для свертки нескольких документов в один такой подход не сработает. Нам необходимо:
ОперацияБух.Хозрасчетный.Для реализации этой схемы мы будем использовать ПВД с произвольным алгоритмом выгрузки.
Перед началом настройки правил в КД 2.1 важно правильно выгрузить метаданные базы-приемника (Бухгалтерии). При использовании обработки выгрузки метаданных MD82Exp.epf (или ее аналога для управляемых форм) обязательно убедитесь, что снят флаг «Не выгружать регистры бухгалтерии».
Если этот флаг будет установлен, КД 2.1 не увидит движений регистра Хозрасчетный у документа ОперацияБух, и вы не сможете настроить правила конвертации для табличной части проводок.
Создадим новое Правило выгрузки данных. Поскольку выборка объектов не будет привязана к конкретному документу напрямую, в ПВД мы указываем способ выборки — Произвольный алгоритм. В качестве ПКО (Правила конвертации объекта) выбираем наше будущее правило для ОперацияБух (о его создании поговорим в Шаге 3).
Основную работу выполняет обработчик «Перед обработкой» в ПВД. Напишем алгоритм, который собирает данные по исходным документам (например, Реализациям), группирует их по дням/организациям и передает в выгрузку.
Рассмотрим пример кода в обработчике «Перед обработкой»:
// 1. Создаем запрос для сбора и группировки данных из документов-источников
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ) КАК ПериодДень,
| Реализация.Организация КАК Организация,
| Реализация.ДоговорКонтрагента.ВидВзаиморасчетов КАК ВидВзаиморасчетов,
| СУММА(Реализация.СуммаДокумента) КАК Сумма,
| СУММА(Реализация.СуммаНДС) КАК СуммаНДС
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Реализация
|ГДЕ
| Реализация.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
| И Реализация.Проведен = ИСТИНА
|ГРУППИРОВАТЬ ПО
| НАЧАЛОПЕРИОДА(Реализация.Дата, ДЕНЬ),
| Реализация.Организация,
| Реализация.ДоговорКонтрагента.ВидВзаиморасчетов";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаКонца", ДатаКонца);
РезультатЗапроса = Запрос.Выполнить();
// 2. Обходим результаты по группировке "День + Организация" (это будут наши будущие документы)
ВыборкаПоДням = РезультатЗапроса.Выбрать();
Пока ВыборкаПоДням.Следующий() Цикл
// Формируем структуру входящих данных для шапки документа ОперацияБух
ВходящиеДанные = Новый Структура("Дата, Организация, Содержание, СпособЗаполнения, Хозрасчетный");
ВходящиеДанные.Дата = КонецДня(ВыборкаПоДням.ПериодДень);
ВходящиеДанные.Организация = ВыборкаПоДням.Организация;
ВходящиеДанные.Содержание = "Сводные проводки по продажам за " + Формат(ВыборкаПоДням.ПериодДень, "ДФ=dd.MM.yyyy");
ВходящиеДанные.СпособЗаполнения = "Вручную";
// Создаем таблицу значений для будущих проводок (коллекция Хозрасчетный)
ТаблицаПроводок = Новый ТаблицаЗначений;
ТаблицаПроводок.Колонки.Добавить("СчетДт");
ТаблицаПроводок.Колонки.Добавить("СчетКт");
ТаблицаПроводок.Колонки.Добавить("СубконтоДт"); // Будет содержать Соответствие
ТаблицаПроводок.Колонки.Добавить("СубконтоКт"); // Будет содержать Соответствие
ТаблицаПроводок.Колонки.Добавить("Сумма");
ТаблицаПроводок.Колонки.Добавить("Активность");
// Заполняем проводку по выручке (Дт 62.01 - Кт 90.01.1)
СтрокаПроводки = ТаблицаПроводок.Добавить();
СтрокаПроводки.СчетДт = "62.01"; // передаем код или ссылку на счет
СтрокаПроводки.СчетКт = "90.01.1";
СтрокаПроводки.Сумма = ВыборкаПоДням.Сумма;
СтрокаПроводки.Активность = Истина;
// Формируем субконто для Дт (Контрагенты, Договоры)
СубконтоДт = Новый Соответствие;
// Ключ соответствия - Структура с именем вида субконто в приемнике, значение - объект-ссылка
СубконтоДт.Вставить(Новый Структура("Наименование", "Контрагенты"), ВыборкаПоДням.Организация); // Пример заполнения
СтрокаПроводки.СубконтоДт = СубконтоДт;
// Привязываем таблицу проводок к входящим данным
ВходящиеДанные.Хозрасчетный = ТаблицаПроводок;
// Формируем уникальный КлючВыгружаемыхДанных, чтобы избежать дублирования документа при повторной выгрузке
КлючУникальности = "СводнаяОперация_" + Формат(ВыборкаПоДням.ПериодДень, "ДФ=yyyyMMdd") + "_" + СокрЛП(ВыборкаПоДням.Организация.УникальныйИдентификатор());
// Вызываем выгрузку по правилу конвертации
ВыгрузитьПоПравилу(,, ВходящиеДанные, КлючУникальности, "ОперацияБух");
КонецЦикла;
Обратите внимание на параметр КлючВыгружаемыхДанных (в коде это переменная КлючУникальности). Он критически важен. Без него система не сможет сопоставить повторные выгрузки за этот день, что приведет к созданию дублирующих документов при каждой последующей синхронизации.
Теперь создадим ПКО для документа ОперацияБух. Разберем по шагам ключевые настройки этого правила:
ДокументСсылка.ОперацияБух.Дата, Организация, Содержание, СпособЗаполнения) устанавливаем флаг «Получить из входящих данных». Это указывает системе, что значения нужно брать из структуры ВходящиеДанные, которую мы сформировали в ПВД.Хозрасчетный. Для этой группы также обязательно устанавливаем флаг «Получить из входящих данных».Хозрасчетный создаем подчиненные ПКС для полей проводки: СчетДт, СчетКт, Сумма, СубконтоДт, СубконтоКт. Для них также взводим флаг получения из входящих данных.Заполнение субконто в проводках — самая частая точка преткновения у разработчиков. Субконто в платформе 1С представляет собой не просто реквизит, а специальную коллекцию (набор записей), связывающую виды субконто со значениями. Выясним, как передать эти данные без ошибок.
Для свойств СубконтоДт и СубконтоКт в ПКС не нужно указывать конкретное ПКО в поле «Правило конвертации», так как типы субконто могут быть абсолютно любыми (справочники, документы и т.д.). Вместо этого мы будем определять ПКО динамически в момент выгрузки.
В ПКС для СубконтоДт (и аналогично для СубконтоКт) в обработчик «Перед выгрузкой» пишется следующий код:
// Динамически определяем ПКО в зависимости от типа переданного значения субконто
Если ЗначениеЗаполнено(Значение) Тогда
ТипЗначения = ТипЗнч(Значение);
Если ТипЗначения = Тип("СправочникСсылка.Контрагенты") Тогда
ИмяПКО = "Контрагенты";
ИначеЕсли ТипЗначения = Тип("СправочникСсылка.ДоговорыКонтрагентов") Тогда
ИмяПКО = "ДоговорыКонтрагентов";
ИначеЕсли ТипЗначения = Тип("СправочникСсылка.НоменклатурныеГруппы") Тогда
ИмяПКО = "НоменклатурныеГруппы";
КонецЕсли;
Иначе
Выражение = Неопределено;
КонецЕсли;
Такой подход позволяет гибко передавать любые типы справочников в субконто проводки. Главное — убедиться, что указанные имена ПКО (например, "Контрагенты", "ДоговорыКонтрагентов") реально существуют в ваших правилах обмена.
После того как данные выгружены и успешно прочитаны базой-приемником, могут возникнуть две проблемы:
ОперацияБух загружается, но движений в базе нет (вкладка проводок пустая).Решим обе проблемы с помощью обработчиков событий в ПКО ОперацияБух.
В обработчик ПКО «После загрузки» добавим код, который принудительно заставит платформу записать проводки при сохранении документа, а также очистит некорректные виды субконто, не принадлежащие выбранным счетам:
// 1. Указываем платформе, что движения по регистру Хозрасчетный нужно принудительно записать
Объект.Движения.Хозрасчетный.Записывать = Истина;
// 2. Очищаем лишние субконто, если они не соответствуют настройкам счета в приемнике
Для Каждого Движение Из Объект.Движения.Хозрасчетный Цикл
// Проверяем субконто Дт
Если ЗначениеЗаполнено(Движение.СчетДт) Тогда
Для Каждого КлючЗначение Из Движение.СубконтоДт Цикл
ВидСубконто = КлючЗначение.Ключ;
Если Не Движение.СчетДт.ВидыСубконто.Найти(ВидСубконто, "ВидСубконто") = Неопределено Тогда
// Вид субконто не подходит для этого счета, удаляем
Движение.СубконтоДт.Удалить(ВидСубконто);
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Проверяем субконто Кт
Если ЗначениеЗаполнено(Движение.СчетКт) Тогда
Для Каждого КлючЗначение Из Движение.СубконтоКт Цикл
ВидСубконто = КлючЗначение.Ключ;
Если Не Движение.СчетКт.ВидыСубконто.Найти(ВидСубконто, "ВидСубконто") = Неопределено Тогда
// Вид субконто не подходит для этого счета, удаляем
Движение.СубконтоКт.Удалить(ВидСубконто);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецДля;
Этот код гарантирует, что загруженная ОперацияБух сразу же отобразится в оборотно-сальдовой ведомости и не вызовет логических ошибок в структуре регистра бухгалтерии.
Мы подробно разобрали, как реализовать сложный перенос данных с группировкой нескольких документов в один в конфигурации «1С:Конвертация данных 2.1». Использование ПВД с произвольным запросом и ручной вызов ВыгрузитьПоПравилу открывают неограниченные возможности для трансформации данных в процессе обмена.
Описанный алгоритм является классическим шаблоном проектирования правил обмена и может быть адаптирован для любых схожих задач — например, для переноса отчетов о розничных продажах, начисления амортизации или сводных кассовых ордеров.