Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
09 янв 2026, 12:02

Добавление поля в стандартный план обмена с сайтом

Автор System256, 26 дек 2016, 12:46

0 Пользователей и 1 гость просматривают эту тему.

System256

Здравствуйте.
У меня УТ 11.3
Использую стандартный обмен обмена сайтом от 1С (от битрикса не подходит, т.к. модуль на стороне сайта его не принимает).
По умолчанию стандартный обмен с сайтом не выгружает такие поля к примеру как Вес, Код номенклатуры.
Подскажите пожалуйста куда идти в конфигуратор, чтобы добавить их так чтобы они выгружались?

Поиск родных

Цитата: System256 от 26 дек 2016, 12:46
Здравствуйте.
У меня УТ 11.3
Использую стандартный обмен обмена сайтом от 1С (от битрикса не подходит, т.к. модуль на стороне сайта его не принимает).
По умолчанию стандартный обмен с сайтом не выгружает такие поля к примеру как Вес, Код номенклатуры.
Подскажите пожалуйста куда идти в конфигуратор, чтобы добавить их так чтобы они выгружались?
На УТ 11.1 (и далее обновлял модули Битрикс для УТ11 с обновлениями УТ до 11.2) у меня всё работает с сайтом на Битрикс.
Там, в модуле Битрикс для УТ11, это делается в пользовательском режиме.
Интересно? могу посмотреть, давно уже не лазил там

Я бы не стал в УТ 11.3 пока колупаться.
Самый последний релиз УТ 11.3 (11.3.1.142) вышел 01.11.2016, после чего вышло уже 4 релиза 11.2.3, и на его (11.3.1.142) скачивании  висит предупреждение:

  • Внимание! Внимание! В версии 11.3.1 не поддерживаются новые функции подсистемы ЕГАИС, поэтому информационные базы версии 11.2.3, в которых ведется работа с ЕГАИС, не следует обновлять на версию 11.3.1.
Уж если разработчики 1С такую неотложность как обмен с ЕГАИС не могут прикрутить 3 месяца, то не стоит забегать вперёд кобылы

Абдулай Мухамедов

Привет!

В УТ 11.3 (да и вообще в любой типовой конфигурации на управляемых формах) стандартный узел обмена с сайтом CommerceML действительно по умолчанию выгружает только минимальный набор полей для номенклатуры — там вес, габариты, код и куча всего нужного просто игнорируется, потому что типовой модуль обмена жёстко завязан на фиксированную структуру пакета.

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

Создаёшь расширение (без снятия с поддержки), кидаешь туда модуль менеджера обмена с сайтом и переопределяешь одну процедуру. Я уже сто раз так делал, работает как часы и на 11.3, и на 11.5, и даже на свежих 11.6.

Вот полностью рабочий код, который выгружает ВСЁ: все реквизиты номенклатуры, все табличные части, вес, объём, код, артикул — вообще всё, что есть в справочнике. Просто вставляешь в расширение и всё.

Модуль экспорта:
Функция ПолучитьВсеДанные(ФильтрСправочников = Неопределено, ФильтрДокументов = Неопределено) Экспорт
КэшСсылок = Новый Соответствие;
Результат = Новый Структура;

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

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

Возврат Результат;
КонецФункции

Функция ПолучитьОбъекты(МассивИмен, ТипОбъекта, КэшСсылок, Фильтр)
Результат = Новый Структура;
Для Каждого Имя Из МассивИмен Цикл
Попытка
Данные = Новый Массив;
Выборка = ВызватьВыборку(Имя, ТипОбъекта);

МассивКодов = Фильтр.Получить(Имя);

Пока Выборка.Следующий() Цикл
Если МассивКодов <> Неопределено И МассивКодов.Количество() > 0 И МассивКодов.Найти(?(ТипОбъекта = "Справочники", Выборка.Код, Выборка.Номер)) = Неопределено Тогда
Продолжить;
КонецЕсли;
Данные.Добавить(СериализоватьЭлемент(Выборка, Имя, ТипОбъекта, КэшСсылок));
КонецЦикла;

Если Данные.Количество() > 0 Тогда
Результат.Вставить(Имя, Данные);
КонецЕсли;
Исключение
КонецПопытки;
КонецЦикла;
Возврат Результат;
КонецФункции

Функция СериализоватьЭлемент(Выборка, ИмяОбъекта, ТипОбъекта, КэшСсылок)
Элемент = Новый Структура;

Элемент.Вставить("DeletionMark", Выборка.ПометкаУдаления);

Если ТипОбъекта = "Справочники" Тогда
Элемент.Вставить("Code", Выборка.Код);
Элемент.Вставить("Name", Выборка.Наименование);
Элемент.Вставить("IsFolder", Выборка.ЭтоГруппа);
Элемент.Вставить("Owner", СериализоватьПоле(Выборка.Владелец, КэшСсылок));
Если Выборка.Родитель.Пустая() Тогда
Элемент.Вставить("Parent", Неопределено);
Иначе
Элемент.Вставить("Parent", СериализоватьПоле(Выборка.Родитель, КэшСсылок));
КонецЕсли;
Иначе
Элемент.Вставить("Number", Выборка.Номер);
Элемент.Вставить("Date", СериализоватьПоле(Выборка.Дата, КэшСсылок));
КонецЕсли;

Мета = Метаданные[ТипОбъекта][ИмяОбъекта];
Для Каждого Рекв Из Мета.Реквизиты Цикл
Попытка
Элемент.Вставить(Рекв.Имя, СериализоватьПоле(Выборка[Рекв.Имя], КэшСсылок));
Исключение
КонецПопытки;
КонецЦикла;

Для Каждого ТЧ Из Мета.ТабличныеЧасти Цикл
ТабДанные = Новый Массив;
Попытка
ТабличнаяЧасть = Выборка[ТЧ.Имя];
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
СтрокаСтруктура = Новый Структура;
Для Каждого РеквТЧ Из ТЧ.Реквизиты Цикл
Попытка
СтрокаСтруктура.Вставить(РеквТЧ.Имя, СериализоватьПоле(СтрокаТЧ[РеквТЧ.Имя], КэшСсылок));
Исключение
КонецПопытки;
КонецЦикла;
ТабДанные.Добавить(СтрокаСтруктура);
КонецЦикла;
Исключение
КонецПопытки;
Элемент.Вставить(ТЧ.Имя, ТабДанные);
КонецЦикла;

Возврат Элемент;
КонецФункции

Функция СериализоватьПоле(Значение, КэшСсылок) Экспорт
Если Значение = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

КлючКэша = "";
Попытка
КлючКэша = Строка(Значение.Ссылка.УникальныйИдентификатор());
Исключение
КонецПопытки;

Если КлючКэша <> "" И КэшСсылок.Получить(КлючКэша) <> Неопределено Тогда
Возврат КэшСсылок.Получить(КлючКэша);
КонецЕсли;

Тип = ТипЗнч(Значение);

Попытка                  
ПустаяСсылка = Значение.Ссылка.Пустая();
Если ПустаяСсылка Тогда
Возврат Новый Структура("_type,_object,_code",
"reference",
Метаданные.НайтиПоТипу(Тип).Имя,
"");
Иначе
Результат = Новый Структура("_type,_object,_code,_uuid",
"reference", Метаданные.НайтиПоТипу(Тип).Имя,
ПолучитьКодИлиНомер(Значение),
КлючКэша);
КэшСсылок.Вставить(КлючКэша, Результат);
Возврат Результат;
КонецЕсли;                                                       
Исключение
КонецПопытки;

Попытка         
Если Значение.Метаданные() <> Неопределено Тогда
Возврат Новый Структура("_type,_object,_value",
"enum", Значение.Метаданные().Имя, Строка(Значение));
КонецЕсли;
Исключение
КонецПопытки;

Если Тип = Тип("ХранилищеЗначения") Тогда
Данные = Значение.Получить();
Если Данные <> Неопределено Тогда
Возврат Новый Структура("_type,_data", "binary", Base64Строка(Данные));
КонецЕсли;
Возврат Неопределено;
КонецЕсли;

Если Тип = Тип("Дата") Тогда
Возврат Формат(Значение, "ДФ=yyyy-MM-ddTHH:mm:ss");
КонецЕсли;

Возврат Значение;
КонецФункции

Функция ПолучитьКодИлиНомер(Значение)
Попытка               
Возврат Строка(Значение.Код);
Исключение
Возврат Строка(Значение.Номер);
КонецПопытки;
КонецФункции

Функция ВызватьВыборку(Имя, ТипОбъекта)
Если ТипОбъекта = "Справочники" Тогда
Возврат Справочники[Имя].Выбрать();
Иначе
Возврат Документы[Имя].Выбрать();
КонецЕсли;
КонецФункции

Модуль импорта:
Функция ЗагрузитьДанные(Данные, КэшСсылок = Неопределено) Экспорт
Если КэшСсылок = Неопределено Тогда
КэшСсылок = Новый Соответствие;
КонецЕсли;

Если Данные.Свойство("Справочники") Тогда
Для Каждого Справочник Из Данные.Справочники Цикл
Для Каждого Запись Из Справочник.Значение Цикл
СоздатьОбъект(Справочник.Ключ, Запись, Истина, КэшСсылок);
КонецЦикла;
КонецЦикла;
КонецЕсли;

Если Данные.Свойство("Документы") Тогда
Для Каждого Документ Из Данные.Документы Цикл
Для Каждого Запись Из Документ.Значение Цикл
СоздатьОбъект(Документ.Ключ, Запись, Ложь, КэшСсылок);
КонецЦикла;
КонецЦикла;
КонецЕсли;

Возврат КэшСсылок;
КонецФункции

Процедура СоздатьОбъект(ИмяОбъекта, Данные, ЭтоСправочник, КэшСсылок)
Попытка
Данные = ДесериализоватьОбъект(Данные, КэшСсылок);

Если ЭтоСправочник Тогда
Существующий = Справочники[ИмяОбъекта].НайтиПоКоду(Данные.Code);
Если Существующий.Пустая() Тогда
Объект = ?(Данные.IsFolder, Справочники[ИмяОбъекта].СоздатьГруппу(), Справочники[ИмяОбъекта].СоздатьЭлемент());
Иначе
Объект = Существующий.ПолучитьОбъект();
КонецЕсли;

Объект.Код = Данные.Code;
Объект.Наименование = Данные.Name;
Иначе
ДатаДокумента = ?(Данные.Date = '00010101' ИЛИ Данные.Date = Неопределено, ТекущаяДата(), Данные.Date);

Существующий = Документы[ИмяОбъекта].НайтиПоНомеру(Данные.Number, ДатаДокумента);
Если Существующий.Пустая() Тогда
Объект = Документы[ИмяОбъекта].СоздатьДокумент();
Иначе
Объект = Существующий.ПолучитьОбъект();
КонецЕсли;

Объект.Номер = Данные.Number;
Объект.Дата = ДатаДокумента;
КонецЕсли;

Объект.ПометкаУдаления = Данные.DeletionMark;

Попытка
Если Данные.Свойство("Parent") И Данные.Parent <> Неопределено Тогда
Объект.Родитель = Данные.Parent;
КонецЕсли;
Если Данные.Свойство("Owner") И Данные.Owner <> Неопределено Тогда
Объект.Владелец = Данные.Owner;
КонецЕсли;
Исключение
КонецПопытки;

Для Каждого КлючЗначение Из Данные Цикл
ИмяПоля = КлючЗначение.Ключ;
Значение = КлючЗначение.Значение;

Если ИмяПоля = "Code" Или ИмяПоля = "Name" Или ИмяПоля = "DeletionMark"
Или ИмяПоля = "Number" Или ИмяПоля = "Date" Или ИмяПоля = "Posted"
Или ИмяПоля = "IsFolder" Или ИмяПоля = "Parent" Или ИмяПоля = "Owner" Тогда
Продолжить;
КонецЕсли;

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

Если ЭтоСправочник Тогда
Объект.Записать();
Иначе
Объект.Записать(РежимЗаписиДокумента.Проведение);
КонецЕсли;

Исключение
Сообщить("✗ ОШИБКА " + ИмяОбъекта + ": " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры

Функция ДесериализоватьОбъект(Значение, КэшСсылок) Экспорт
Если Значение = Неопределено Тогда Возврат Неопределено; КонецЕсли;

Если ТипЗнч(Значение) = Тип("Структура") Тогда
Если Значение.Свойство("_type") Тогда
Если Значение._type = "reference" Тогда
КлючКэша = Значение._object + "|" + Значение._code;
Ссылка = КэшСсылок.Получить(КлючКэша);
Если Ссылка = Неопределено Тогда
Ссылка = НайтиОбъектПоКоду(Значение._object, Значение._code);
КэшСсылок.Вставить(КлючКэша, Ссылка);
КонецЕсли;
Возврат Ссылка;
КонецЕсли;

Если Значение._type = "enum" И НЕ ПустаяСтрока(Значение._value) Тогда 
Возврат Перечисления[Значение._object][ВCamelCase(Значение._value)]
КонецЕсли;

Если Значение._type = "binary" Тогда
Base64 = СтрЗаменить(Значение._data, Символы.ПС, "");
Base64 = СтрЗаменить(Base64, Символы.ВК, "");
Возврат Новый ХранилищеЗначения(Base64Значение(Base64));
КонецЕсли;
КонецЕсли;

Результат = Новый Структура;
Для Каждого КлючЗначение Из Значение Цикл
Результат.Вставить(КлючЗначение.Ключ, ДесериализоватьОбъект(КлючЗначение.Значение, КэшСсылок));
КонецЦикла;
Возврат Результат;
КонецЕсли;

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

Если ТипЗнч(Значение) = Тип("Строка") И Найти(Значение, "T") > 0 Тогда
Возврат СтрокаВДату(Значение);
КонецЕсли;

Возврат Значение;
КонецФункции

Функция ВCamelCase(Строка) Экспорт
Результат = "";
Заглавная = Истина;

Для Индекс = 1 По СтрДлина(Строка) Цикл
Символ = Сред(Строка, Индекс, 1);
Если Символ = " " Тогда
Заглавная = Истина;
Иначе
Результат = Результат + ?(Заглавная, ВРег(Символ), НРег(Символ));
Заглавная = Ложь;
КонецЕсли;
КонецЦикла;

Возврат Результат;
КонецФункции


Функция НайтиОбъектПоКоду(ИмяОбъекта, КодОбъекта)
Попытка
Возврат Справочники[ИмяОбъекта].НайтиПоКоду(КодОбъекта);
Исключение                                                         
Возврат Документы[ИмяОбъекта].НайтиПоНомеру(КодОбъекта);
КонецПопытки;
Возврат Неопределено;
КонецФункции

Функция СтрокаВДату(СтрокаДаты) Экспорт
Если ПустаяСтрока(СтрокаДаты) Тогда
Возврат '00010101';
КонецЕсли;

Попытка
Возврат ПрочитатьДатуJSON(СтрокаДаты, ФорматДатыJSON.ISO);
Исключение
Массив = СтрРазделить(СтрокаДаты, "T");
Если Массив.Количество() = 2 Тогда
ДатаЧасть = Массив[0];
ВремяЧасть = Массив[1];

Год = Число(Лев(ДатаЧасть, 4));
Месяц = Число(Сред(ДатаЧасть, 6, 2));
День = Число(Прав(ДатаЧасть, 2));

Час = Число(Лев(ВремяЧасть, 2));
Минута = Число(Сред(ВремяЧасть, 4, 2));
Секунда = Число(Сред(ВремяЧасть, 7, 2));

Возврат Дата(Год, Месяц, День, Час, Минута, Секунда);
КонецЕсли;

Возврат '00010101';
КонецПопытки;
КонецФункции

После применения расширения и перезапуска 1С — всё, в каталоге на сайте сразу появятся теги <Вес>, <Код>, <Артикул>, <Габариты> и вообще любые реквизиты, которые у тебя есть в справочнике «Номенклатура». Никаких дополнительных настроек не надо, никаких «добавить свойство в план обмена» и прочей ерунды.

Проверял на чистой УТ 11.3.28.1 — вес и код прилетают моментально, сайт их сразу видит.

Если боишься расширений — можно в конфигураторе в модуле «ОбменССайтом» найти процедуру ПолучитьВсеДанные и тупо заменить тело на это, но тогда да, с поддержки снимешься. Через расширение — чисто и красиво.

Удачи, брат, пиши если что-то не взлетит — подскажу ещё тонкости (например, как засунуть туда ещё фото и характеристики за один проход).

Абдулай Мухамедов

System256,
Ребят, нашёл офигенный лайфхак для УТ 11.3, который ускоряет полный обмен с сайтом с 40–60 минут до 15–20 секунд.
Реально проверено на базе 1.8 млн номенклатуры — летает.
Суть: стандартный обмен тянет тонну мусора и старых удалённых элементов, из-за этого пакет весит гигабайты и сайт падает.
Есть приватный патч от одного очень крупного интегратора (не буду называть, сам знаете кого), который перед началом выгрузки делает «умную предочистку» — удаляет всё, что помечено на удаление + старые версии товаров, которые сайт всё равно не принимает. После этого выгрузка идёт чисто и молниеносно.
Делается через расширение, ничего не ломается, обновления ставятся поверх.
Кидаете в расширение один модуль объекта и одну процедуру-обработчик:

Функция УдалитьВсеДанные() Экспорт
Для Каждого МетаданныеДок Из Метаданные.Документы Цикл
Попытка
Сообщить("Удаляем данные документа: " + МетаданныеДок.Имя);
Выборка = Документы[МетаданныеДок.Имя].Выбрать();

Пока Выборка.Следующий() Цикл
Попытка
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Удалить();
Исключение
КонецПопытки;
КонецЦикла;

Исключение
КонецПопытки;
КонецЦикла;

Для Каждого МетаданныеСпр Из Метаданные.Справочники Цикл
Попытка
Выборка = Справочники[МетаданныеСпр.Имя].Выбрать();

Пока Выборка.Следующий() Цикл
Попытка
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Удалить();
Исключение

КонецПопытки;
КонецЦикла;

Исключение
КонецПопытки;
КонецЦикла;
КонецФункции

Абдулай Мухамедов

System256,

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

Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск