Данный метод подходит для 1С:Управление торговлей 11, Комплексная автоматизация 2 и ERP.
По задаче необходимо перенести номенклатуру вместе с характеристикой из документов товароучетной системы.
Чтобы в бухгалтерской базе в названии номенклатуры содержалось название характеристики в круглых скобках
В бухгалтерской базе справочник номенклатуры должен содержать элементы номенклатуры соответствующие каждой используемой паре номенклатура и характеристика
Для решения этой задачи потребуется создать расширения в базе источника, которой может являться Управление торговлей или Комплексная автоматизация, и в базе Бухгалтерия.
В базе источник заимствуем в расширение модуль МенеджерОбменаЧерезУниверсальныйФормат и Процедуру ПОД_Справочник_ХарактеристикиНоменклатуры_Отправка_ПриОбработке.
&После("ПОД_Справочник_ХарактеристикиНоменклатуры_Отправка_ПриОбработке")
Процедура уфх_ПОД_Справочник_ХарактеристикиНоменклатуры_Отправка_ПриОбработке(ДанныеИБ, ИспользованиеПКО, КомпонентыОбмена)
Если ЗначениеЗаполнено(ДанныеИБ.Владелец) И ТипЗнч(ДанныеИБ.Владелец) = Тип("СправочникСсылка.Номенклатура") Тогда
ПравилоОбработки = КомпонентыОбмена.ПравилаОбработкиДанных.Найти("Справочник_Номенклатура_Отправка");
ДанныеИБВладелец = ДанныеИБ.Владелец;
Наименование = ДанныеИБВладелец.Наименование + "(" + ДанныеИБ.Наименование + ")";
Характеристика = Новый Структура;
Для каждого ТекРеквизит Из Метаданные.Справочники.Номенклатура.Реквизиты Цикл
Характеристика.Вставить(ТекРеквизит.Имя);
КонецЦикла;
Для каждого ТекРеквизит Из Метаданные.Справочники.Номенклатура.ТабличныеЧасти Цикл
Характеристика.Вставить(ТекРеквизит.Имя);
КонецЦикла;
ЗаполнитьЗначенияСвойств(Характеристика, ДанныеИБВладелец);
Характеристика.Вставить("Наименование", Наименование);
Характеристика.Вставить("НаименованиеПолное", Наименование);
Характеристика.Вставить("Ссылка", ДанныеИБВладелец);
Характеристика.Вставить("ЭтоГруппа", ДанныеИБВладелец.ЭтоГруппа);
Характеристика.Вставить("Код", ДанныеИБВладелец.Код);
Характеристика.Вставить("Родитель", ДанныеИБВладелец.Родитель);
ОбменДаннымиXDTOСервер.ВыгрузкаОбъектаВыборки(КомпонентыОбмена, Характеристика, ПравилоОбработки);
ИначеЕсли ЗначениеЗаполнено(ДанныеИБ.Владелец) И ТипЗнч(ДанныеИБ.Владелец) = Тип("СправочникСсылка.ВидыНоменклатуры") Тогда
ПравилоОбработки = КомпонентыОбмена.ПравилаОбработкиДанных.Найти("Справочник_Номенклатура_Отправка");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| СвободныеОстатки.Номенклатура КАК Номенклатура,
| СвободныеОстатки.Характеристика КАК Характеристика
|ИЗ
| РегистрНакопления.СвободныеОстатки КАК СвободныеОстатки
|ГДЕ
| СвободныеОстатки.Характеристика = &Характеристика";
Запрос.УстановитьПараметр("Характеристика", ДанныеИБ.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДанныеИБВладелец = Выборка.Номенклатура;
Наименование = ДанныеИБВладелец.Наименование + "(" + ДанныеИБ.Наименование + ")";
Характеристика = Новый Структура;
Для каждого ТекРеквизит Из Метаданные.Справочники.Номенклатура.Реквизиты Цикл
Характеристика.Вставить(ТекРеквизит.Имя);
КонецЦикла;
Для каждого ТекРеквизит Из Метаданные.Справочники.Номенклатура.ТабличныеЧасти Цикл
Характеристика.Вставить(ТекРеквизит.Имя);
КонецЦикла;
ЗаполнитьЗначенияСвойств(Характеристика, ДанныеИБВладелец);
Характеристика.Вставить("Наименование", Наименование);
Характеристика.Вставить("НаименованиеПолное", Наименование);
Характеристика.Вставить("Ссылка", ДанныеИБВладелец);
Характеристика.Вставить("ЭтоГруппа", ДанныеИБВладелец.ЭтоГруппа);
Характеристика.Вставить("Код", ДанныеИБВладелец.Код);
Характеристика.Вставить("Родитель", ДанныеИБВладелец.Родитель);
ОбменДаннымиXDTOСервер.ВыгрузкаОбъектаВыборки(КомпонентыОбмена, Характеристика, ПравилоОбработки);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
В процедуре рассмотрено только два варианта использования характеристик как наиболее часто применяемые. Для варианта характеристик индивидуальные для номенклатуры создадим структуру, которая полностью повторяет объект номенклатуры с добавлением в наименование характеристики. Если характеристики общие для вида, то из процедуры мы не можем непосредственно получить выгружаемую номенклатуру. Поэтому решил выбирать все возможные комбинации номенклатура + характеристика из регистра остатков.
Теперь нужно сделать, чтобы в выгружаемых документах мы передавали номенклатуру с названием характеристики. Для этого заимствуем процедуру ДанныеXDTOИзДанныхИБ из модуля ОбменДаннымиXDTOСервер
&ИзменениеИКонтроль("ДанныеXDTOИзДанныхИБ")
Функция уфх_ДанныеXDTOИзДанныхИБ(КомпонентыОбмена, Источник, Знач ПравилоКонвертации, СтекВыгрузки)
Приемник = Новый Структура;
Если СтекВыгрузки = Неопределено Тогда
СтекВыгрузки = Новый Массив;
КонецЕсли;
Если ПравилоКонвертации.ЭтоСсылочныйТип Тогда
ПозицияВСтеке = СтекВыгрузки.Найти(Источник.Ссылка);
// Проверяем, выгружался ли объект по ссылке, чтобы не допустить зацикливания.
Если ПозицияВСтеке <> Неопределено Тогда
Если ПозицияВСтеке > 0 Тогда
Возврат Неопределено;
ИначеЕсли СтекВыгрузки.Количество() > 1 Тогда
// Необходимо искать перебором.
ПерваяИтерация = Истина;
Для Каждого ЭлементСтека Из СтекВыгрузки Цикл
Если ПерваяИтерация Тогда
ПерваяИтерация = Ложь;
Продолжить;
КонецЕсли;
Если ЭлементСтека = Источник.Ссылка Тогда
Возврат Неопределено;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
СтекВыгрузки.Добавить(Источник.Ссылка);
Если Не ОбщегоНазначения.СсылкаСуществует(Источник.Ссылка) Тогда
Возврат Неопределено;
КонецЕсли;
Иначе
СтекВыгрузки.Добавить(Источник);
КонецЕсли;
Если ПравилоКонвертации.ЭтоКонстанта Тогда
ТипОбъекта = ПравилоКонвертации.ТипXDTO; // ТипОбъектаXDTO
Если ТипОбъекта.Свойства.Количество() = 1 Тогда
Приемник.Вставить(ТипОбъекта.Свойства[0].Имя, Источник.Значение);
Иначе
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка XML-схемы. Для приемника должно быть задано одно свойство.
|Тип источника: %1
|Тип приемника: %2'"),
Строка(ТипЗнч(Источник)),
ПравилоКонвертации.ТипXDTO);
КонецЕсли;
Иначе
// Выполнение ПКС, 1-й этап
Для Каждого ПКС Из ПравилоКонвертации.Свойства Цикл
Если ПравилоКонвертации.ОбъектДанных <> Неопределено
И ПКС.СвойствоКонфигурации = ""
И ПКС.ИспользуетсяАлгоритмКонвертации Тогда
Продолжить;
КонецЕсли;
Если СтекВыгрузки.Количество() > 1 И Не ПКС.ОбработкаКлючевогоСвойства Тогда
Продолжить;
КонецЕсли;
ВыгрузитьСвойство(
КомпонентыОбмена,
Источник,
Приемник,
ПКС,
СтекВыгрузки,
1);
КонецЦикла;
// Выполнение ПКС для ТЧ (прямая конвертация).
Если СтекВыгрузки.Количество() = 1 Тогда
Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
Если НЕ (ЗначениеЗаполнено(ТЧИСвойства.ТЧКонфигурации) И ЗначениеЗаполнено(ТЧИСвойства.ТЧФормата)) Тогда
Продолжить;
КонецЕсли;
// ТЧ пустая.
Если Источник[ТЧИСвойства.ТЧКонфигурации].Количество() = 0 Тогда
Продолжить;
КонецЕсли;
НоваяТЧПриемника = СоздатьТЧПриемникаПоПКС(ТЧИСвойства.Свойства);
Для Каждого СтрокаТЧКонфигурации Из Источник[ТЧИСвойства.ТЧКонфигурации] Цикл
СтрокаТЧПриемник = НоваяТЧПриемника.Добавить();
Для Каждого ПКС Из ТЧИСвойства.Свойства Цикл
Если ПКС.ИспользуетсяАлгоритмКонвертации Тогда
Продолжить;
КонецЕсли;
ВыгрузитьСвойство(
КомпонентыОбмена,
СтрокаТЧКонфигурации,
СтрокаТЧПриемник,
ПКС,
СтекВыгрузки,
1);
КонецЦикла;
КонецЦикла;
Приемник.Вставить(ТЧИСвойства.ТЧФормата, НоваяТЧПриемника);
КонецЦикла;
КонецЕсли;
// {Обработчик: ПриОтправкеДанных} Начало
Если ПравилоКонвертации.ЕстьОбработчикПриОтправкеДанных Тогда
Если Не Приемник.Свойство("КлючевыеСвойства") Тогда
Приемник.Вставить("КлючевыеСвойства", Новый Структура);
КонецЕсли;
ПриОтправкеДанных(Источник, Приемник, ПравилоКонвертации.ПриОтправкеДанных, КомпонентыОбмена, СтекВыгрузки);
Если Приемник = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если СтекВыгрузки.Количество() > 1 Тогда
Для Каждого КлючевоеСвойство Из Приемник.КлючевыеСвойства Цикл
Приемник.Вставить(КлючевоеСвойство.Ключ, КлючевоеСвойство.Значение);
КонецЦикла;
Приемник.Удалить("КлючевыеСвойства");
КонецЕсли;
// Выполнение ПКС, 2-й этап
Для Каждого ПКС Из ПравилоКонвертации.Свойства Цикл
Если ПКС.СвойствоФормата = ""
Или (СтекВыгрузки.Количество() > 1 И Не ПКС.ОбработкаКлючевогоСвойства) Тогда
Продолжить;
КонецЕсли;
// Выполняем конвертацию, если в свойство помещена инструкция.
ЗначениеСвойства = Неопределено;
Если СтекВыгрузки.Количество() = 1 И ПКС.ОбработкаКлючевогоСвойства Тогда
Приемник.КлючевыеСвойства.Свойство(ПКС.СвойствоФормата, ЗначениеСвойства);
Иначе
СвойствоФормата_Имя = СокрЛП(ПКС.СвойствоФормата);
ВложенныеСвойства = СтрРазделить(СвойствоФормата_Имя,".",Ложь);
// Указано полное имя свойства, входящего в группу общих свойств.
Если ВложенныеСвойства.Количество() > 1 Тогда
ПолучитьЗначениеВложенныхСвойств(Приемник, ВложенныеСвойства, ЗначениеСвойства);
Иначе
Приемник.Свойство(СвойствоФормата_Имя, ЗначениеСвойства);
КонецЕсли;
КонецЕсли;
Если ЗначениеСвойства = Неопределено Тогда
Продолжить;
КонецЕсли;
Если ПКС.ИспользуетсяАлгоритмКонвертации Тогда
Если ТипЗнч(ЗначениеСвойства) = Тип("Структура")
И ЗначениеСвойства.Свойство("Значение")
И ЗначениеСвойства.Свойство("ИмяПКО")
Или ПКС.ПравилоКонвертацииСвойства <> ""
И ТипЗнч(ЗначениеСвойства) <> Тип("Структура") Тогда
ВыгрузитьСвойство(
КомпонентыОбмена,
Источник,
Приемник,
ПКС,
СтекВыгрузки,
2);
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Выполнение ПКС для ТЧ
Если СтекВыгрузки.Количество() = 1 Тогда
// Формируем структуру новых табличных частей по ПКС.
СвойстваТЧПриемника = Новый Структура;
Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
ИмяТЧПриемника = ТЧИСвойства.ТЧФормата;
Если ПустаяСтрока(ИмяТЧПриемника) Тогда
Продолжить;
КонецЕсли;
Если Не СвойстваТЧПриемника.Свойство(ИмяТЧПриемника) Тогда
ТаблицаПКС = Новый ТаблицаЗначений;
ТаблицаПКС.Колонки.Добавить("СвойствоФормата", Новый ОписаниеТипов("Строка"));
СвойстваТЧПриемника.Вставить(ИмяТЧПриемника, ТаблицаПКС);
КонецЕсли;
ТаблицаПКС = СвойстваТЧПриемника[ИмяТЧПриемника];
Для Каждого ПКС Из ТЧИСвойства.Свойства Цикл
СтрокаСвойство = ТаблицаПКС.Добавить();
СтрокаСвойство.СвойствоФормата = ПКС.СвойствоФормата;
КонецЦикла;
КонецЦикла;
Для Каждого ТЧИСвойства Из ПравилоКонвертации.СвойстваТабличныхЧастей Цикл
Если Не ТЧИСвойства.ИспользуетсяАлгоритмКонвертации Тогда
Продолжить;
КонецЕсли;
ПКСДляТЧ = ТЧИСвойства.Свойства;
ИмяТЧПриемника = ТЧИСвойства.ТЧФормата;
ТЧПриемника = Неопределено; // ТаблицаЗначений
Если Не ЗначениеЗаполнено(ИмяТЧПриемника)
Или Не Приемник.Свойство(ИмяТЧПриемника, ТЧПриемника) Тогда
Продолжить;
КонецЕсли;
// Создаем новую ТЗ, в которой нет ограничений типа для колонок.
НоваяТЧПриемника = СоздатьТЧПриемникаПоПКС(СвойстваТЧПриемника[ИмяТЧПриемника]);
// Убираем лишние колонки, которые могли добавить в приемнике.
УдаляемыеКолонки = Новый Массив;
Для Каждого Колонка Из ТЧПриемника.Колонки Цикл
Если НоваяТЧПриемника.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
УдаляемыеКолонки.Добавить(Колонка);
КонецЕсли;
КонецЦикла;
Для Каждого Колонка Из УдаляемыеКолонки Цикл
ТЧПриемника.Колонки.Удалить(Колонка);
КонецЦикла;
// Копируем данные в новую таблицу приемника.
Для Каждого СтрокаТЧПриемника Из ТЧПриемника Цикл
СтрокаНовойТЧПриемника = НоваяТЧПриемника.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаНовойТЧПриемника, СтрокаТЧПриемника);
КонецЦикла;
Приемник[ИмяТЧПриемника] = НоваяТЧПриемника;
Для Каждого Строка Из НоваяТЧПриемника Цикл
Для Каждого ПКС Из ПКСДляТЧ Цикл
Если НЕ ПКС.ИспользуетсяАлгоритмКонвертации Тогда
Продолжить;
КонецЕсли;
ВыгрузитьСвойство(
КомпонентыОбмена,
Источник,
Строка,
ПКС,
СтекВыгрузки,
2);
#Вставка
Если ПКС.ПравилоКонвертацииСвойства = "Справочник_Номенклатура_Отправка" тогда
Если ЗначениеЗаполнено(Строка.Характеристика) Тогда
Строка.Номенклатура.Наименование = Строка.Номенклатура.Наименование+"("+Строка.Характеристика.Наименование+")";
Строка.Номенклатура.НаименованиеПолное = Строка.Номенклатура.Наименование;
КонецЕсли;
КонецЕсли;
#КонецВставки
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЕсли;
// {Обработчик: ПриОтправкеДанных} Окончание
Если СтекВыгрузки.Количество() > 1 Тогда
Приемник.Вставить("ТипСоставногоСвойства", ПравилоКонвертации.ТипКлючевыхСвойствОбъектаXDTO);
Если ЭтоБазоваяСхема(КомпонентыОбмена, ПравилоКонвертации.ПространствоИмен) И ПравилоКонвертации.Расширения.Количество() Тогда
Для Каждого Расширение Из ПравилоКонвертации.Расширения Цикл
Если Расширение.Значение.ТипКлючевыхСвойствОбъектаXDTO <> Неопределено Тогда
ДанныеРасширения(Приемник, Расширение.Ключ).Вставить("ТипСоставногоСвойства",
Расширение.Значение.ТипКлючевыхСвойствОбъектаXDTO);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Приемник;
КонецФункции
В базе бухгалтерии в расширение заимствовать из модуля МенеджерОбменаЧерезУниверсальныйФормат процедуру ДобавитьПКО_Справочник_Номенклатура_Получение. В этой процедуре изменим поля поиска номенклатуры и отключим поиск по уникальному идентификатору.
&ИзменениеИКонтроль("ДобавитьПКО_Справочник_Номенклатура_Получение")
Процедура Расш1_ДобавитьПКО_Справочник_Номенклатура_Получение(ПравилаКонвертации)
ПравилоКонвертации = ОбменДаннымиXDTOСервер.ИнициализироватьПравилоКонвертацииОбъекта(ПравилаКонвертации);
ПравилоКонвертации.ИмяПКО = "Справочник_Номенклатура_Получение";
ПравилоКонвертации.ОбъектДанных = Метаданные.Справочники.Номенклатура;
ПравилоКонвертации.ОбъектФормата = "Справочник.Номенклатура";
ПравилоКонвертации.ПриКонвертацииДанныхXDTO = "ПКО_Справочник_Номенклатура_Получение_ПриКонвертацииДанныхXDTO";
ПравилоКонвертации.ПередЗаписьюПолученныхДанных = "ПКО_Справочник_Номенклатура_Получение_ПередЗаписьюПолученныхДанных";
ПравилоКонвертации.ПослеЗагрузкиВсехДанных = "ОтложеннаяОбработка_Номенклатура";
#Удаление
ПравилоКонвертации.ВариантИдентификации = "СначалаПоУникальномуИдентификаторуПотомПоПолямПоиска";
#КонецУдаления
#Вставка
ПравилоКонвертации.ВариантИдентификации = "ПоПолямПоиска";
#КонецВставки
СвойстваШапки = ПравилоКонвертации.Свойства;
ДобавитьПКС(СвойстваШапки, "Артикул", "Артикул");
ДобавитьПКС(СвойстваШапки, "ВидНоменклатуры", "ВидНоменклатуры", , "Справочник_ВидыНоменклатуры_Получение");
ДобавитьПКС(СвойстваШапки, "ВидСтавкиНДС", "", 1);
ДобавитьПКС(СвойстваШапки, "ЕдиницаИзмерения", "ЕдиницаИзмерения", , "Справочник_ЕдиницыИзмерения");
ДобавитьПКС(СвойстваШапки, "Импортер", "", 1, "Справочник_Контрагенты_Получение");
ДобавитьПКС(СвойстваШапки, "Код", "КодВПрограмме");
ДобавитьПКС(СвойстваШапки, "КодНоменклатурнойКлассификацииККТ", "", 1);
ДобавитьПКС(СвойстваШапки, "КодОКВЭД", "КодОКВЭД", , "Справочник_ОКВЭД");
ДобавитьПКС(СвойстваШапки, "КодОКП", "КодОКП", , "Справочник_ОКП");
ДобавитьПКС(СвойстваШапки, "КодТНВЭД", "", 1);
ДобавитьПКС(СвойстваШапки, "Комментарий", "Описание");
ДобавитьПКС(СвойстваШапки, "Наименование", "Наименование");
ДобавитьПКС(СвойстваШапки, "НаименованиеПолное", "НаименованиеПолное");
ДобавитьПКС(СвойстваШапки, "НоменклатурнаяГруппа", "ГруппаАналитическогоУчета", , "Справочник_НоменклатурнаяГруппа_Получение");
ДобавитьПКС(СвойстваШапки, "ОсновнаяСпецификацияНоменклатуры", "ОсновнаяСпецификацияНоменклатуры", , "Справочник_СпецификацииНоменклатуры_Получение");
ДобавитьПКС(СвойстваШапки, "Производитель", "", 1, "Справочник_Контрагенты_Получение");
ДобавитьПКС(СвойстваШапки, "ПрослеживаемыйТовар", "ПрослеживаемыйТовар");
ДобавитьПКС(СвойстваШапки, "Родитель", "Группа", , "Справочник_НоменклатураГруппа_Получение");
ДобавитьПКС(СвойстваШапки, "СтранаПроисхождения", "СтранаПроисхождения", , "Справочник_СтраныМира");
ДобавитьПКС(СвойстваШапки, "Услуга", "", 1);
СвойстваТЧ = ДобавитьПКТЧ(ПравилоКонвертации, "ДополнительныеРеквизиты", "");
ДобавитьПКС(СвойстваТЧ, "Значение", "", 1);
ДобавитьПКС(СвойстваТЧ, "Свойство", "", 1,"Справочник_ДополнительныеРеквизиты");
ПравилоКонвертации.ПоляПоиска.Добавить("НаименованиеПолное,ЭтоГруппа,Родитель");
#Удаление
ПравилоКонвертации.ПоляПоиска.Добавить("Артикул,ЭтоГруппа,Родитель");
#КонецУдаления
ПравилоКонвертации.ПоляПоиска.Добавить("Наименование,ЭтоГруппа,Родитель");
КонецПроцедуры
п.с. в некоторых случаях может не выгружаться элемент номенклатура+характеристика, в этом случае нужно удалить из регистра сведений ДанныеОбъектовДляРегистрацииВОбменах элементы с нужной номенклатурой и характеристикой для выбранного узла. В этом регистре система запоминает, какие объекты уже были выгружены в базу приемник.