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