При настройке обмена данными между конфигурациями 1С часто возникают ситуации, когда методология учета в базе-источнике отличается от методологии в базе-приемнике. Яркий пример — обмен между конфигурациями 1С:Розница и 1С:Управление торговлей (УТ). В «1С:Розница» документ ОтчетОРозничныхПродажах может одновременно содержать информацию как о продажах (табличная часть «Товары»), так и о возвратах в течение кассовой смены (табличная часть «Возвращенные товары»).
Однако руководство компании или методология ведения учета в «1С:Управление торговлей» могут требовать, чтобы эти операции разделялись на два самостоятельных документа: один документ должен фиксировать исключительно продажи, а второй — исключительно возвраты от розничного покупателя. В этой статье мы подробно разберем, как решить эту задачу с помощью правил обмена в Конвертации данных 2.1 (КД 2.1).
Первое решение, которое приходит в голову начинающему разработчику, — создать два отдельных Правила выгрузки данных (ПВД) и два Правила конвертации объектов (ПКО):
Выясним причину, почему этот подход не сработает в реальном обмене. Платформа 1С при выполнении выгрузки по правилам обмена использует внутренний механизм оптимизации и кэширования. Когда объект (ссылка на документ) выгружается через первое ПВД, его уникальный идентификатор (UUID) регистрируется в специальном соответствии выгруженных объектов. При попытке обработать тот же самый объект вторым ПВД система видит, что этот объект уже был выгружен в текущем сеансе обмена, и просто пропускает его. В итоге второй документ в базе-приемнике так и не создается.
Для обхода этого ограничения нам потребуется использовать **одно ПВД** и механизм программного вызова выгрузки по правилам с помощью функции ВыгрузитьПоПравилу.
Рассмотрим по шагам правильный алгоритм настройки правил конвертации в КД 2.1 для решения нашей задачи.
Нам понадобятся два ПКО для одного и того же типа документа источника ДокументСсылка.ОтчетОРозничныхПродажах:
ОтчетОРозничныхПродажах). Это правило будет переносить стандартные продажи. Табличную часть «Товары» сопоставляем стандартным образом.ОтчетОРозничныхПродажах). Это правило будет создавать документ возврата. Табличную часть «Товары» в приемнике мы будем заполнять данными из таблицы «Возвращенные товары» источника.Создаем одно общее ПВД для документа ОтчетОРозничныхПродажах. В настройках ПВД способ выгрузки выбираем «Произвольный алгоритм». Нам необходимо переопределить стандартную выгрузку и программно запустить обработку объекта по двум разным ПКО.
Переходим в обработчик ПВД «Перед выгрузкой объекта» и пишем следующий код:
// 1. Выгружаем первый документ (Продажи) по стандартному правилу
ВыгрузитьПоПравилу(Объект, , , , "ПКО_ОтчетОРозничныхПродажах_Продажи");
// Проверяем, есть ли возвраты в документе источника
Если Объект.ВозвращенныеТовары.Количество() > 0 Тогда
// Формируем структуру входящих данных для документа возврата
ВходящиеДанныеДляВозврата = Новый Структура;
// Генерируем уникальный номер для документа возврата, чтобы избежать совпадения номеров
НовыйНомер = СтрЗаменить(Объект.Номер, "-", "В");
ВходящиеДанныеДляВозврата.Вставить("Номер", НовыйНомер);
ВходящиеДанныеДляВозврата.Вставить("Комментарий", "Документ возврата создан автоматически на основании ООРП №" + Объект.Номер);
// Получаем таблицу возвращенных товаров запросом (или напрямую из ТЧ объекта)
ТаблицаВозвратов = Объект.ВозвращенныеТовары.Выгрузить();
ВходящиеДанныеДляВозврата.Вставить("Товары", ТаблицаВозвратов);
// Рассчитываем сумму возврата
СуммаВозврата = ТаблицаВозвратов.Итог("Сумма");
ВходящиеДанныеДляВозврата.Вставить("СуммаДокумента", СуммаВозврата);
// 2. Выгружаем второй документ (Возврат) по специальному правилу
ВыгрузитьПоПравилу(Объект, , ВходящиеДанныеДляВозврата, , "ПКО_ОтчетОРозничныхПродажах_Возврат");
КонецЕсли;
Теперь проанализируем, как правильно принять переданные нами из ПВД параметры во втором ПКО (ПКО_ОтчетОРозничныхПродажах_Возврат). В сообщениях темы на форуме была совершена частая ошибка: автор пытался заполнить структуру ВходящиеДанные непосредственно в обработчиках ПКО. Запомните: менять ВходящиеДанные внутри ПКО бессмысленно, так как ПКО их только получает от вызывающей процедуры выгрузки.
Для того чтобы ПКО приняло параметры из структуры ВходящиеДанныеДляВозврата, выполним следующие настройки:
Номер, СуммаДокумента, Комментарий и табличной части Товары установим флаг «Получить из входящих данных».Товары в событии «Перед выгрузкой» укажем соответствие колонок, если имена реквизитов ТЧ «Возвращенные товары» источника отличаются от ТЧ «Товары» приемника.Проанализируем крайне важный нюанс, который часто упускают из виду. При вызове функции ВыгрузитьПоПравилу для одного и того же объекта (в нашем случае переменная Объект), КД 2.1 по умолчанию выгружает оригинальный UUID (Уникальный идентификатор) ссылки источника в XML-файл.
Если оба правила запишут один и тот же UUID в файл выгрузки, то при загрузке в базу-приемник произойдет коллизия: второй документ (возврат) просто затрет первый документ (продажи) по ссылке, так как у них будет одинаковый GUID. Поиск по полям поиска (Номер + Дата) в данном случае не спасет, так как идентификация по UUID имеет наивысший приоритет.
Как решить эту проблему?
Необходимо переопределить ключевое свойство идентификации для второго документа. Для этого в ПКО возвратов (ПКО_ОтчетОРозничныхПродажах_Возврат) в обработчике «Перед выгрузкой» переопределим параметр КлючВыгружаемыхДанных:
// Генерируем уникальный ключ выгрузки на основании исходной ссылки
КлючВыгружаемыхДанных = "Return_" + Строка(Источник.Ссылка.УникальныйИдентификатор());
Благодаря этой строчке кода КД 2.1 сгенерирует для документа возврата новый, детерминированный UUID в базе-приемнике. Он будет постоянным при последующих обменах, что предотвратит появление дублей и затирание документов.
Посмотрим на ситуацию со стороны бизнес-логики. Документ ОтчетОРозничныхПродажах содержит не только информацию о товарах, но и информацию о способах оплаты (вкладка «Оплата» или «Оплата платежными картами»). Если мы просто разделим товары, но оставим все оплаты в первом документе:
Поэтому в ПВД при разделении документа обязательно нужно также пропорционально разделять и таблицу оплат (наличные, эквайринг), вычитая суммы возвратов из первого документа и перенося их (возможно, с отрицательным знаком или в специализированные реквизиты возврата оплат) во второй документ.
Также рекомендуется в ПКО для документа возврата в обработчике «После загрузки» установить режим записи документа. Возвраты — это операции, требующие повышенного контроля, и часто их безопаснее загружать непроведенными (в состоянии «Записан»), чтобы менеджеры в базе-приемнике перепроверяли их вручную:
РежимЗаписи = "Записать"; // или "Проводить", если уверены в автоматическом балансе партий и касс
Мы подробно разобрали, как с помощью одного ПВД и программного вызова функции ВыгрузитьПоПравилу реализовать разделение одной транзакции в источнике на несколько независимых документов в приемнике. Этот метод является стандартным и наиболее надежным инструментом при работе с Конвертацией данных 2.1, позволяя гибко управлять бизнес-логикой обмена любой сложности.