Курс 2016 года “Разработка на UMI.CMS от 0 до готового сайта”
Синхронизация с 1С не меняя указанные поля

Автор tatfoxРаздел Настройка системы и модулей

Ответов: 11
Просмотров: 2853
Последний ответ 17 Июня 2016, 09:07:57
от tatfox

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

*

rauschen

  • *
  • 22
  • +1/-0
    • Просмотр профиля
Синхронизация с 1С
« : 17 Ноября 2011, 19:17:08 »
Доброго времени суток всем!

Я настроил синхронизацию с 1С. Выгрузил весь каталог на сайт.
Переименовал разделы и товары как нужно мне. Но при следующей синхронизации с 1С все названия разделов и товаров возвращаются к 1Совским.

Как сделать так, чтобы значение поля name у разделов каталога и товаров не менялось после выгрузки данных из 1С?
Спасибо.

*

admin

  • *****
  • 2444
  • +172/-1
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #1 : 17 Ноября 2011, 22:29:20 »
перезапись название товара происходит в виду алгоритма синхронизации, либо надо править xsl файл (/xsl/import/custom/commerceML.xsl), хотя не факт что можно пойти таким путем, либо дописывать event который будет пересохранять после синхронизации ваше кастомное название поля

*

rauschen

  • *
  • 22
  • +1/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #2 : 17 Ноября 2011, 22:51:15 »
А вам никогда не приходилось такого делать?

я сделал так сейчас

<xsl:param name="is_exist" select="document(concat('udata://system/getFilteredPages/72/1c_product_id/', Ид))/udata/items/item" />
...
<xsl:if test="not($is_exist)">
   <name>
      <xsl:value-of select="$name" />
   </name>
</xsl:if>

Но при большом кол-ве товаров скрипт валится. С чем связано - проследить не удается...

*

admin

  • *****
  • 2444
  • +172/-1
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #3 : 18 Ноября 2011, 06:25:02 »
скорее всего время выполнение скрипта сильно возрастает, попробуй в config.ini уменьшить кол-во элементов импортируемых за раз (параметр exchange.splitter.limit подробнее http://help-dev.umi-cms.ru/part.Config.modules.html)

*

rauschen

  • *
  • 22
  • +1/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #4 : 18 Ноября 2011, 10:55:48 »
Сделал через эвент - exchangeOnUpdateElement. В режиме before беру имя элемента из базы (если он есть) и присваиваю его суперглобальной переменной. А затем в режиме after присваиваю имени элемента значение этой суперглобальной переменной.
Решение конечно кривое, т.к. скорее всего при всех типах импорта будет оставаться прежнее имя элементов и разделов.
Но если кому будет интересно выложу сюда листинг кода.

з.ы. надо писать в саппорт чтобы подсказали грамотное решение. имхо все должно делаться на уровне commerceML2.xsl

*

Alexey

  • *
  • 42
  • +3/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #5 : 21 Ноября 2011, 14:11:25 »
Здравствуйте всем!

Столкнулся с некоторыми проблемами при обмене данными с 1C.

1. Такая же проблема, как у rauschen. При обмене данными с 1C названия уже существующих объектов и разделов приобретают первоначальный вид (как в 1C). Как этого избежать? Пробовал добавлять строку exchange.commerceML.renameFiles = "0" в config.ini, как указано здесь (по умолчанию в файле ее вообще не было), переопределять присвоение названий в /xsl/import/custom/commerceML.xsl, однако это не принесло никаких результатов. Каким образом лучше разграничить процесс полной выгрузки и процесс выгрузки изменений? rauschen, как ты в конечном итоге вышел из данной ситуации? Если через event, выложи, пожалуйста, листинг кода.
Т.к. h1 остается прежним, то на крайний случай, как вариант можно добавить присвоение названия из h1 (что, конечно, не рационально).

2. Мне нужно, чтобы разделам и объектам каталога при полной выгрузке и обмене ставились в соответствие определенные tpl шаблоны, отличные от заданного по умолчанию.

В config.ini указал следующее:

exchange.translator.catalog_item_template = "catalogitem.tpl"
exchange.translator.catalog_rubric_template = "catalogrubric.tpl"

В таком случае и разделам, и объектам каталога по-прежнему ставится в соответствие шаблон по умолчанию (даже для новых добавляемых страниц).
Помимо этого, при каждом обмене в корне сайта создается страница Основной каталог товаров, которая не содержит в себе никаких объектов.
Воспользовался данным решением.
Теперь для всех разделов каталога используется шаблон catalogrubric.tpl (который мне и нужен), однако для объектов каталога по-прежнему применяется шаблон по умолчанию, и также создаются пустые страницы osnovnoi_katalog_tovarov, osnovnoi_katalog_tovarov1, osnovnoi_katalog_tovarov2 и т.д. в корне сайта. Как быть? И возможно ли задать исключения для ряда разделов каталога, для которых применяется другой шаблон, скажем catalogrubric_1.tpl?
Есть еще один альтернативный вариант - переопределить действия при выгрузке изменений таким образом, чтобы шаблоны страниц не менялись вообще (как и в ситуации 1). Тогда, на крайний случай, нужные шаблоны можно переопределить вручную (все равно каждый объект будет редактироваться отдельно). Понимаю, что это не рационально, но все же рассматриваю это, как один из вариантов.

3. Мне нужно применить данный шаблон с учетом ситуаций 1 и 2. Отдельно он работает нормально.

Очень надеюсь на вашу помощь!
« Последнее редактирование: 21 Ноября 2011, 14:39:06 от Alexey »

*

admin

  • *****
  • 2444
  • +172/-1
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #6 : 21 Ноября 2011, 14:51:37 »
Alexey

1. Эту задачу можно решить написанием своего варианта экспорта, который будет проверять импортируется ли товар в первый раз (и ему надо прописать имя), либо товар уже существует в системе и его имя менять не надо.
Можно написать код, который при преобразовании cml документа от 1с в umidump xml документ, будет проверять есть ли уже в системе товар и соответсвенно проставлять или нет узел "name" (этот вариант описывал rauschen выше) и можно написать свой обработчик события "exchangeOnUpdateElement".
Пример обработчика который вешаем на событие "exchangeOnUpdateElement"
public function RenameAllItems($e) {
if($e->getMode() == "after") {
$element = $e->getRef('element');
if (!$element instanceof umiHierarchyElement || $element->getMethod() != 'object') return false; // ести объект не страница и не объект каталога, то выходим

/*у типа данных "объект каталога добавил поле "резервное имя" (reserv_name) куда я сохраняю нужное мне имя товара*/
$element_reserv_name=$element->reserv_name;
if(strlen(trim($element_reserv_name))>0)$element->setName($element_reserv_name); //переименовываем имортированный товар обратно к "своему" варианту названия
$element->setTplId(4); //назначаем странице шаблон с id =4 (смотрел id в коде страницы в админке "настройки модуля структура")
$element->commit(); // сохраняем изменения
}
}

2.
Насчет создания пустого раздела
Цитировать
Помимо этого, при каждом обмене в корне сайта создается страница Основной каталог товаров, которая не содержит в себе никаких объектов.
не встречал такого, если вы пользовались модифицированным /xsl/import/custom/commerceML2.xsl то может ошибка в нем.

Насчет назначения шаблона страницам.
Действительно можно отключить назначение шаблона. Для этого просто проследите чтобы в /xsl/import/commerceML2.xsl  и /xsl/import/custom/commerceML2.xsl  файлах не формировался тег  <default-template>. А еще, шаблон можно назначать через event, так же как и в коде выше
$element->setTplId(4); 

*

Alexey

  • *
  • 42
  • +3/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #7 : 21 Ноября 2011, 15:22:14 »
admin, спасибо за оперативный ответ!

Насчет назначения шаблона страницам.
Действительно можно отключить назначение шаблона. Для этого просто проследите чтобы в /xsl/import/commerceML2.xsl  и /xsl/import/custom/commerceML2.xsl  файлах не формировался тег  <default-template>.

Заменил все вхождения default-template на template в файле /xsl/import/commerceML2.xsl, из файла /xsl/import/custom/commerceML2.xsl данные блоки удалил вообще, т.к. фактически получается дублирование данных. Результат - всем страницам каталога (и разделам, и объектам) по-прежнему присваивается дефолтный шаблон и создается пустая страница "Основной каталог товаров" в корне сайта.

Насчет создания пустого раздела
не встречал такого, если вы пользовались модифицированным /xsl/import/custom/commerceML2.xsl то может ошибка в нем.

Небольшое пояснение. Единственная модификация файла /xsl/import/commerceML2.xsl - замена всех вхождений default-template на template;
В файл /xsl/import/custom/commerceML2.xsl добавлено только это.

Можно поподробнее насчет события "exchangeOnUpdateElement", где применить эту функцию?

*

admin

  • *****
  • 2444
  • +172/-1
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #8 : 21 Ноября 2011, 15:28:57 »
Цитировать
Можно поподробнее насчет события "exchangeOnUpdateElement", где применить эту функцию?

в папке /classes/module/exchange 

добавляете custom_events.php:
<?php
new umiEventListener('exchangeOnUpdateElement', 'exchange  ', 'RenameAllItems');
?>

в __custom.php вкладываем мою функцию
public function RenameAllItems($e) {
if($e->getMode() == "after") {
$element = $e->getRef('element');
if (!$element instanceof umiHierarchyElement || $element->getMethod() != 'object') return false; // ести объект не страница и не объект каталога, то выходим

/*у типа данных "объект каталога добавил поле "резервное имя" (reserv_name) куда я сохраняю нужное мне имя товара*/
$element_reserv_name=$element->reserv_name;
if(strlen(trim($element_reserv_name))>0)$element->setName($element_reserv_name); //переименовываем имортированный товар обратно к "своему" варианту названия
$element->setTplId(4); //назначаем странице шаблон с id =4 (смотрел id в коде страницы в админке "настройки модуля структура")
$element->commit(); // сохраняем изменения
}
}

event подключен

*

rauschen

  • *
  • 22
  • +1/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #9 : 21 Ноября 2011, 22:14:08 »
Парни, я сделал через событие, как писал Даниил.
Вот метод, который вызывается по эвенту exchangeOnUpdateElement:

public function setCustomName($e) {
if($e->getMode() == "before") {
$hierarchy = umiHierarchy::getInstance();
$element = $e->getRef('element');
if (!$element instanceof umiHierarchyElement || $element->getMethod() != 'object') return false;
$source_id = $e->getParam('source_id');

$GLOBALS["custom_name"] = $element->getName();
}

if($e->getMode() == "after") {
$hierarchy = umiHierarchy::getInstance();
$element = $e->getRef('element');
if (!$element instanceof umiHierarchyElement || $element->getMethod() != 'object') return false;
$source_id = $e->getParam('source_id');

$element->setName($GLOBALS["custom_name"]);
}
}

Не уверен что хорошо использовать глобальные переменные для этого, но работает исправно и я не стал терять время на поиск другого решения.

А еще есть такой метод:

public function getNewIdRelation($old_id){
//if(!$old_id) return;
$relation = umiImportRelations::getInstance();
$source_id = $relation->getSourceId('commerceML2');
$old_id = htmlspecialchars($old_id);       
if($old_id && $source_id){                 
return $element_id = $relation->getNewIdRelation($source_id, $old_id);

}

Он возвращает id элемента каталога или раздела, если такой есть в системе. Методу передаем id товара или раздела из 1С.
Использовать этот метод можно прямо в /xsl/import/custom/commerceML2.xsl Но с этим методом у меня при импорте товаров (3600шт) сервер возвращает ошибку после 1200 импортированных объектов. Не знаю в чем соль - забил.

Если кто разберется, буду признателен за ответный листинг кода :)

*

Alexey

  • *
  • 42
  • +3/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #10 : 22 Ноября 2011, 09:49:18 »
admin, rauschen, спасибо за ответы! Я немного изменил и доработал функцию, которую предложил admin. Аналогично добавил переопределение имени и шаблона для разделов каталога (было только для объектов каталога). Все работает нормально. Таким образом, названия остаются прежними, и страницам назначаются нужные шаблоны в зависимости от их типа (раздел или объект каталога).

Попытки реализовать это путем редактирования файла /xsl/import/commerceML2.xsl результата не дают.

Загвоздка в том, что у меня для разных разделов каталога заданы разные шаблоны. В связи с этим возникает вопрос - можно ли как-то получить ID шаблона, который был у страницы изначально в if($e->getMode() == "before") {} и потом в if($e->getMode() == "after") {} присвоить этот шаблон уже известным способом $element->setTplId(ID шаблона). Или, может быть, есть еще какие-нибудь варианты? В любом случае, нужно, чтобы после ручной смены шаблона страницы раздела каталога при обмене шаблон оставался таким же.

И, раз уж все делается через event, можно ли  в данной функции назначить всем объектам каталога тип данных "Объект каталога"?
« Последнее редактирование: 22 Ноября 2011, 10:17:37 от Alexey »

*

Alexey

  • *
  • 42
  • +3/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #11 : 22 Ноября 2011, 11:08:49 »
Нашел ответ на свой вопрос:

getTplId() — Получить id шаблона дизайна (класс template), по которому отображается страница.

С получением нужных данных проблем нет, установить шаблон дизайна можно посредством setTplId(). А вот как быть с получением и установкой типа данных, пока не совсем понятно.

Более подробно можно ознакомиться здесь.

Попробую доделать функцию с учетом этого и протестировать, о результатах отпишу позже.
« Последнее редактирование: 22 Ноября 2011, 11:30:10 от Alexey »

*

rauschen

  • *
  • 22
  • +1/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #12 : 23 Ноября 2011, 00:49:27 »
Alexey, а получилось у тебя избавится от пустого раздела в корне сайта? Теперь для меня это актуально)

Я тут еще один сайт подключаю и в 1С дебильная структура у номенклатуры - большая вложенность :)
Соответственно все разделы которые выше нужного мне тоже выгружаются, а они мне не нужны - в них нет товаров.

*

Alexey

  • *
  • 42
  • +3/-0
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #13 : 23 Ноября 2011, 07:06:55 »
rauschen, пока нет. У меня тоже большая вложенность. Разбираюсь с этим.

P.S. Проверь ЛС.

*

admin

  • *****
  • 2444
  • +172/-1
    • Просмотр профиля
Re:Синхронизация с 1С
« Ответ #14 : 23 Ноября 2011, 07:53:43 »
при выгрузке пробовали указать фильтр какие разделы номенклатуры выгружать? или это не поможет?