Search for a command to run...
Обмен с 1С выполняется в воркфлоу Medusa, и в нескольких из них плагин предоставляет хуки. Обработчик хука получает то, что обмен собирается записать в Medusa или отправить в 1С, и возвращает исправленную версию. Так вы переносите реквизиты 1С в поля товара, дописываете в заказ данные, которых нет в Medusa, или включаете прайс-лист для группы покупателей, не меняя код плагина.
Хук воркфлоу позволяет встроить свою функцию в воркфлоу Medusa. Medusa вызывает её по ходу воркфлоу и передаёт ей данные, а то, что функция вернёт, воркфлоу использует дальше. Подробнее читайте в документации Medusa.
Импортируйте воркфлоу из , а типы входных данных и результата хуков и функции чтения реквизитов и свойств 1С из .
В бете имена хуков и форма элементов ещё могут измениться по отзывам участников. После релиза они меняются только с мажорной версией плагина.
Зарегистрируйте обработчик в файле внутри вашего проекта Medusa. Medusa загрузит его при запуске сервера. Например, этот обработчик не пускает в магазин услуги из 1С:
src/workflows/hooks/onec-catalog.ts1import { StepResponse } from "@medusajs/framework/workflows-sdk"2import { importOnecProductsWorkflow } from "@gorgo-store/medusa-erp-1c/workflows"3import { readRequisite } from "@gorgo-store/medusa-erp-1c/hooks"45importOnecProductsWorkflow.hooks.setProducts(async ({ products }) => {6 return new StepResponse({7 products: products.filter(({ source }) => readRequisite(source, "ВидНоменклатуры") !== "Услуга"),8 })9})
Обработчик получает товары пачки и возвращает их в , оставив только те, у которых реквизит «ВидНоменклатуры» не «Услуга». читает реквизит товара 1С по его наименованию, так что разбирать CommerceML самому не нужно.
Каждый хук, кроме , получает массив элементов. Элемент сводит в одно место всё, что нужно для решения:
Обработчик правит поле цели и возвращает элементы. устроен иначе. Он получает готовый XML строкой и нужен для того, чего нет в модели товара или документа, например для версии схемы, которую ждёт ваша конфигурация 1С.
Обработчик, который вернул обычный объект или ничего не вернул, останавливает обмен с ошибкой вида . Плагин получает от Medusa только содержимое .
Medusa разрешает только один обработчик на хук во всём приложении. Второй, зарегистрированный на тот же хук, остановит запуск сервера с ошибкой . Соберите все правки проекта для одного хука в одном обработчике и вызывайте их внутри него по очереди.
Обработчик выполняется внутри шага воркфлоу, и пока он работает, 1С ждёт ответа. и вызываются на каждую пачку, так что каталог в 10 000 товаров вызовет каждый из них сто раз. Вход и результат хука движок воркфлоу копирует, и всё, что вы допишете в элемент, копируется вместе с ним.
Вот что стоят три вида обработчика :
| Обработчик | Запросов к базе за импорт каталога | Время повторного импорта |
|---|---|---|
| Только поля из входных данных | столько же, сколько без обработчика | в пределах разброса прогонов |
| Один запрос на пачку | +10 | в пределах разброса прогонов |
| Запрос на каждый товар | +990 | +12 % |
Замер сделан на каталоге из 1 000 товаров и 4 000 предложений, то есть на 10 пачках, с локальной PostgreSQL, где запрос стоит около миллисекунды. В таблице медианы трёх прогонов, у запроса на каждый товар один прогон. Повторный импорт почти ничего не пишет, поэтому цена обработчика в нём заметнее всего. На удалённой базе каждый запрос дороже на сетевую задержку, и разница растёт.
Чтобы обработчик не замедлял обмен:
Запрос на каждый товар выглядит так. На пачку из 100 товаров это 100 запросов:
1for (const item of products) {2 const [brand] = readProperty(item.source, properties, "Бренд")3 const { data } = await query.graph({4 entity: "product_collection",5 fields: ["id"],6 filters: { title: brand },7 })8 // ...9}
Один запрос на пачку получает то же самое для всех товаров сразу:
1const titles = products.flatMap(({ source }) => readProperty(source, properties, "Бренд"))2const { data } = await query.graph({3 entity: "product_collection",4 fields: ["id", "title"],5 filters: { title: titles },6})7const collectionIdByTitle = new Map(data.map((collection) => [collection.title, collection.id]))
Полный пример с таким запросом есть на странице Примеры хуков.
На тестовом каталоге из нескольких товаров запрос на каждый товар не заметен. Он проявляется на полном каталоге, когда обмен уже идёт в продакшене.
Запустите сервер с . Плагин пишет в журнал длительность каждого шага импорта каталога, и шаг хука называется так же, как хук:
выполняется внутри дочернего воркфлоу импорта предложений, поэтому его время входит в общую строку . Выгрузки по шагам в журнал не пишутся.