Создание фида ценообразования по шаблону

Фид для интеграции можно создать с помощью экспорта каталога по шаблону. Для этого небходимо создать профиль экспорта:

  • Перейдите на страницу "Настройки"
  • Перейдите на вкладку "Экспорт"
  • Нажмите на кнопку "+"
  • Укажите название профиля экспорта, выберите профиль ценообразования, по которому будет подготовлен фид, и выберите формат "Каталог по шаблону"
  • Нажмите "Сохранить"

После сохранения профиля экспорта станет доступна настройка шаблона интеграции.

Редактирование существующего профиля:

  • Нажмите напротив этого профиля на значок карандашика.
  • Отредактируйте название или добавьте/удалите профиль ценообразования.
  • Нажмите кнопку "Сохранить".

Удаление существующего профиля:

  • Нажмите напротив этого профиля на значок корзинки.
  • Подтвердите удаление.

Настройка шаблона интеграции:

  • Перейдите на вкладку "Настройка шаблона".
  • Выберите тип выгрузки параметров.
  • Выберите тип валидации (при необходимости).
  • Выберите шаблон (нажамите кнопку "Шаблоны") или напишите свой.
  • Нажмите кнопку "Сохранить".

Для написания шаблона мы используем язык Scriban. Scriban - это быстрый, мощный, безопасный и легкий язык сценариев. Подробнее с языком можно ознакимиться здесь. Проверить корректность работы шаблона можно нажав на кнопку "Тест". После этого появится окно "Результаты", в котором, при корректнонаписаном шаблоне, появится результат (как будет выглядеть фид).

Пример модели данных:

{
  "Categories": [
    {
      "Id": 5548,
      "SingularName": null,
      "Name": "Сад и дача",
      "ParentId": null
    },
    {
      "Id": 5549,
      "SingularName": null,
      "Name": "Отдых/досуг на даче",
      "ParentId": 5548
    },
    {
      "Id": 5550,
      "SingularName": null,
      "Name": "Бассейны",
      "ParentId": 5549
    },
    {
      "Id": 2312,
      "SingularName": "Надувной бассейн",
      "Name": "Надувные бассейны",
      "ParentId": 5550
    }
  ],
  "MaxDeliveryCost": "0.00",
  "MaxDeliveryTime": "2",
  "Currency": "BYN",
  "Offers": [
    {
      "ModelId": 21942,
      "OfferId": "0021942",
      "Model": "Easy Set 183x51",
      "Category": "Надувные бассейны",
      "CategorySingularName": "Надувной бассейн",
      "Vendor": "Intex",
      "Price": 1866.1,
      "SupplierPrice": 1166.31,
      "Article": "54402/28101",
      "OzonSku": 765430756,
      "OzonFboSku": 1000123456,
      "OzonFbsSku": 1000123457,
      "OzonProductId": 440761234,
      "OzonOfferId": "NV-TK1234",
      "WbImtId": 189510123,
      "WbNmId": 209690123,
      "WbSku": "4640001123456",
      "WbVendorCode": "HB-CE000A",
      "DeliveryTime": 0,
      "DeliveryTownPrice": 0.0,
      "DeliveryCountryPrice": 0.0,
      "MinHighCompetitorPrice": null,
      "MinLowCompetitorPrice": null,
      "Color": "",
      "InStockAmount": 1.0,
      "BarCodes": [
        "6941057400006"
      ],
      "ExternalId": "8e6558a5-c330-11e4-80c0-3085a918de0b",
      "MinRetailPrice": null,
      "CategoryId": 2312,
      "Description": "Конструкция: надувной, Назначение: детский, Объём: 886 л, Форма: круглый",
      "Profit": 37.5,
      "Pictures": [
        "https://catalogapp.b-cdn.net/production/images/12/72/89/09/55f7d8a5-df3f-4997-9937-a02a036db361.jpg",
        "https://catalogapp.b-cdn.net/production/images/03/50/17/16/7d2519d9-8851-40f0-86c2-342f7c80c554.jpg",
        "https://catalogapp.b-cdn.net/production/images/04/03/83/53/a9c7ff05-81f6-4a06-b4b9-f873d9cf99ba.jpg"
      ],
      "Parameters": [
        {
          "Name": "Производитель",
          "Value": "Intex"
        },
        {
          "Name": "Конструкция",
          "Value": "надувной"
        },
        {
          "Name": "Джакузи",
          "Value": "Нет"
        },
        {
          "Name": "Форма",
          "Value": "круглый"
        },
        {
          "Name": "Объём",
          "Value": "886.00",
          "Unit": "л"
        },
        {
          "Name": "Длина",
          "Value": "183.00",
          "Unit": "см"
        },
        {
          "Name": "Высота",
          "Value": "51.00",
          "Unit": "см"
        },
        {
          "Name": "Распылитель (фонтан)",
          "Value": "нет"
        },
        {
          "Name": "Генератор пузырьков",
          "Value": "Нет"
        },
        {
          "Name": "Скиммер (устройство сбора мусора)",
          "Value": "нет"
        },
        {
          "Name": "Подстилка",
          "Value": "Нет"
        },
        {
          "Name": "Тент-чехол",
          "Value": "Нет"
        },
        {
          "Name": "Ширина",
          "Value": "183.00",
          "Unit": "см"
        },
        {
          "Name": "Изготовитель",
          "Value": "Intex Dervelopment Co Ltd 9/F., Dah Sing Financial Centre,108 Glouceste Road, Wanchai, China."
        },
        {
          "Name": "Импортер",
          "Value": "АзияИнвест ЧТПУП, 220073, Минск, ул. Ольшевского, оф. 604А, Сандэйз точка бай ЧТПУП 220073, г. Минск, ул. Ольшевского, 22, комната 604 ><*\"'/\\&$?"
        },
        {
          "Name": "Прозрачные стенки",
          "Value": "Нет"
        },
        {
          "Name": "Комплект для чистки бассейна",
          "Value": "Нет"
        },
        {
          "Name": "Сетка для волейбола",
          "Value": "Нет"
        },
        {
          "Name": "Возраст детей",
          "Value": "3+"
        },
        {
          "Name": "Время установки",
          "Value": "0.17",
          "Unit": "ч"
        },
        {
          "Name": "Цвет",
          "Value": "синий"
        },
        {
          "Name": "Вес",
          "Value": "183"
        },
        {
          "Name": "Фильтр-насос",
          "Value": "нет"
        },
        {
          "Name": "Назначение",
          "Value": "детский"
        },
        {
          "Name": "Дополнительные опции",
          "Value": "сетка для волейбола"
        }
      ]
    },
    {
      "ModelId": 612923,
      "OfferId": "0612923",
      "Model": "Fast Set 10' x 30\"/305х76см",
      "Category": "Надувные бассейны",
      "CategorySingularName": "Надувной бассейн",
      "Vendor": "Bestway",
      "Price": 6313.31,
      "SupplierPrice": 1978.92,
      "Article": "57266",
      "DeliveryTime": 0,
      "DeliveryTownPrice": 0.0,
      "DeliveryCountryPrice": 0.0,
      "MinHighCompetitorPrice": null,
      "MinLowCompetitorPrice": null,
      "Color": "",
      "InStockAmount": 277.0,
      "BarCodes": [
        "6942138949933"
      ],
      "ExternalId": "6f25f580-0af8-4470-82b5-7cd11f12537c",
      "MinRetailPrice": null,
      "CategoryId": 2312,
      "Description": "Конструкция: надувной, Назначение: семейный, Объём: 3638 л, Форма: круглый",
      "Profit": 68.65,
      "Pictures": [
        "https://catalogapp.b-cdn.net/production/images/04/85/35/62/553709fa-5605-40a3-9b69-4c71b02600d8.jpg",
        "https://catalogapp.b-cdn.net/production/images/04/85/35/62/71789081-f5ed-4f3a-8d10-916b718717ea.jpg",
        "https://catalogapp.b-cdn.net/production/images/04/03/81/62/b136633b-f70b-408f-80c7-2c812e766377.jpg",
        "https://catalogapp.b-cdn.net/production/images/04/03/81/62/a5e8665f-2d12-4dbc-a9b0-94c720913d82.jpg"
      ],
      "Parameters": [
        {
          "Name": "Конструкция",
          "Value": "надувной"
        },
        {
          "Name": "Джакузи",
          "Value": "Нет"
        },
        {
          "Name": "Форма",
          "Value": "круглый"
        },
        {
          "Name": "Объём",
          "Value": "3638.00",
          "Unit": "л"
        },
        {
          "Name": "Длина",
          "Value": "305.00",
          "Unit": "см"
        },
        {
          "Name": "Высота",
          "Value": "76.00",
          "Unit": "см"
        },
        {
          "Name": "Распылитель (фонтан)",
          "Value": "нет"
        },
        {
          "Name": "Генератор пузырьков",
          "Value": "Нет"
        },
        {
          "Name": "Скиммер (устройство сбора мусора)",
          "Value": "нет"
        },
        {
          "Name": "Подстилка",
          "Value": "Нет"
        },
        {
          "Name": "Тент-чехол",
          "Value": "Нет"
        },
        {
          "Name": "Ширина",
          "Value": "305.00",
          "Unit": "см"
        },
        {
          "Name": "Сливной клапан",
          "Value": "Да"
        },
        {
          "Name": "Прозрачные стенки",
          "Value": "Нет"
        },
        {
          "Name": "Комплект для чистки бассейна",
          "Value": "Нет"
        },
        {
          "Name": "Сетка для волейбола",
          "Value": "Нет"
        },
        {
          "Name": "Тип фильтр-насоса",
          "Value": "картриджный"
        },
        {
          "Name": "Цвет",
          "Value": "синий"
        },
        {
          "Name": "Фильтр-насос",
          "Value": "нет"
        },
        {
          "Name": "Возраст детей",
          "Value": "3+"
        },
        {
          "Name": "Назначение",
          "Value": "семейный"
        }
      ]
    }
  ]
}

Добавление условий в шаблон

Условия помогают в выборе товаров, соответствующих определенным критериям. Для добавления условий удобно пользоваться функциями. Функции небходимо определить до шаблона и вызвать внутри шаблона. Пример:

{{-func condition(offer)
    if (offer.MinHighCompetitorPrice == null && offer.MinLowCompetitorPrice == null)
        ret true
    else
        ret false
    end
end-}}
<?xml version="1.0" encoding="utf-8"?>
<yml_catalog date="{{ date.now | date.to_string '%F %R' }}">
  <shop>
    <categories>
      {{- for category in model.Categories}}
      <category id="{{category.Id}}" parentId="{{category.ParentId}}">{{category.Name}}</category>
      {{- end }}
    </categories>
    <company>ООО "Компания"</company>
    <currencies>
      <currency id="{{model.Currency}}" />
    </currencies>
    <delivery-options>
      <option cost="{{model.MaxDeliveryCost}}" days="{{model.MaxDeliveryTime}}" />
    </delivery-options>
    <name>Название магазина</name>
    <url>https://example.ru/</url>
    <offers>
      {{- for offer in model.Offers}}
      {{- if condition offer }}
      <offer id="{{offer.OfferId}}" type="vendor.model" available="true">
        <barcode>{{offer.BarCodes | array.join ", "}}</barcode>
        <categoryId>{{offer.CategoryId}}</categoryId>
        <currencyId>{{model.Currency}}</currencyId>
        <outlets>
          <outlet id="0" instock="{{offer.InStockAmount}}" />
        </outlets>
        <model>{{offer.Model}} {{offer.Color}}</model>
        <name>{{offer.CategorySingularName}} {{offer.Vendor}} {{offer.Model}} {{offer.Color}} {{offer.Article}}</name>
        {{- for parameter in offer.Parameters}}
        <param name="{{parameter.Name}}" unit="{{parameter.Unit}}">{{parameter.Value}}</param>
        {{- if parameter.Name == "Страна-производитель" -}}
        {{- capture country_of_origin -}}
        {{parameter.Value}}
        {{- end -}}
        {{- end -}}
        {{- if parameter.Name == "Длина в упаковке" -}}
        {{- capture length -}}
        {{parameter.Value}}
        {{- end -}}
        {{- end -}}
        {{- if parameter.Name == "Ширина в упаковке" -}}
        {{- capture width -}}
        {{parameter.Value}}
        {{- end -}}
        {{- end -}}
        {{- if parameter.Name == "Высота в упаковке" -}}
        {{- capture height -}}
        {{parameter.Value}}
        {{- end -}}
        {{- end -}}
        {{- if parameter.Name == "Вес" -}}
        {{- capture weight -}}
        {{parameter.Value}}
        {{- end -}}
        {{- end -}}
        {{- end -}}
        {{- for picture in offer.Pictures}}
        <picture>{{picture}}</picture>
        {{- end }}
        <country_of_origin>{{country_of_origin}}</country_of_origin>
        <dimensions>{{length}}/{{width}}/{{height}}</dimensions>
        <weight>{{weight}}</weight>
        <description>{{offer.Description}}</description>
        <price>{{offer.Price}}</price>
        <typePrefix>{{offer.CategorySingularName}}</typePrefix>
        <url>https://techshop.ru/product/?XML_ID={{offer.ExternalId}}</url>
        <vendor>{{offer.Vendor}}</vendor>
        <vendorCode>{{offer.Article}}</vendorCode>
        <shop-sku>{{offer.OfferId}}</shop-sku>
      </offer>
      {{- end }}
      {{- end }}
    </offers>
  </shop>
</yml_catalog>

Вызов функции:

 <offers>
      {{- for offer in model.Offers}}
      {{- if condition offer }}
      <offer id="{{offer.OfferId}}" type="vendor.model" available="true">
        <barcode>{{offer.BarCodes | array.join ", "}}</barcode>
       ...
        <shop-sku>{{offer.OfferId}}</shop-sku>
      </offer>
      {{- end }}
      {{- end }}
</offers>

Примеры условий:

  • Цены выше до n % от цен конкурентов 1-го уровня
{{-func condition(offer, ConditionVal)
 if (offer.MinHighCompetitorPrice != null && ConditionVal != null)
     if (offer.Price > offer.MinHighCompetitorPrice && (offer.Price - offer.MinHighCompetitorPrice) * 100 / offer.MinHighCompetitorPrice < ConditionVal)
             ret true
     else
             ret false
     end
 end
end-}}
  • Цены = ценам конкурентов 1-го уровня
{{-func condition(offer)
 if (offer.MinHighCompetitorPrice != null)
     if (offer.MinHighCompetitorPrice == Price)
             ret true
     else
             ret false
     end
 end
end-}}
  • Цена ниже, чем у 1-го, но выше более n %, чем у 2-го
{{-func condition(offer, ConditionVal)
 if (offer.MinHighCompetitorPrice != null && offer.MinLowCompetitorPrice != null)
     if (offer.Price < offer.MinHighCompetitorPrice && offer.Price > offer.MinLowCompetitorPrice && (offer.Price - offer.MinLowCompetitorPrice) * 100 / offer.MinLowCompetitorPrice > ConditionVal)
             ret true
     else
             ret false
     end
 end
end-}}
  • Цена ниже, чем у 1-го, но выше не более n %, чем у 2-го
{{-func condition(offer, ConditionVal)
 if (offer.MinHighCompetitorPrice != null && offer.MinLowCompetitorPrice != null)
     if (offer.Price < offer.MinHighCompetitorPrice && offer.Price > offer.MinLowCompetitorPrice && (offer.Price - offer.MinLowCompetitorPrice) * 100 / offer.MinLowCompetitorPrice <= ConditionVal)
             ret true
     else
             ret false
     end
 end
end-}}
  • Цена ниже, чем у 1-го и 2-го
{{-func condition(offer)
 if (offer.MinHighCompetitorPrice != null && offer.MinLowCompetitorPrice != null)
     if (offer.Price < offer.MinHighCompetitorPrice && offer.Price < offer.MinLowCompetitorPrice)
             ret true
     else
             ret false
     end
 end
end-}}
  • Нет товара у конкурентов, но есть у нас
{{-func condition(offer)
 if (offer.MinHighCompetitorPrice == null && offer.MinLowCompetitorPrice == null)
             ret true
     else
             ret false
 end
end-}}
  • Минимальное время доставки в диапазоне MinDeliveryTime-MaxDeliveryTime дня и маржа в диапазоне MinProfit-MaxProfit %
{{-func condition(offer, MinProfit, MaxProfit, MinDeliveryTime, MaxDeliveryTime)
 if (offer.Profit >= MinProfit && offer.Profit <= MaxProfit && offer.DeliveryTime >= MinDeliveryTime && offer.DeliveryTime <= MaxDeliveryTime)
             ret true
     else
             ret false
 end
end-}}
  • Функция для получения родительской категории любого уровня (положительный level для подсчета уровня с корня дерева, отрицательный - для подсчета с категории товара):
categories = {}
for category in model.Categories
    categories[category.Id] = category
end

# use positive level to iterate categories from root
# use negative level to iterate categories from leaf
func getCategory(offer, level)
    i = 0
    path = []
    current = categories[offer.CategoryId]
    while current
        path[i] = current
        i = i + 1
        current = categories[current?.ParentId ?? 0]
    end
    if level < 0 && path.size > -level
        ret path[-level]
    end
    if path.size >= level
    begin
        ret path[path.size - level - 1]
    end
    ret null
end

Условий может быть несколько (при этом они должны называться по разному), несколько условий можно скомбинировать в одно, a также добавлять свои условия. Проверить корректность условий можно здесь.

Для выполнения экспорта:

  • Перейдите на страницу "Задачи".
  • Перейдите на вкладку "Экспорт".
  • Выберите необходимый профиль экспорта.
  • Нажмите кнопку "Запустить".

Статус задачи, а также историю последних выполненых экспортов можно посмотреть в списке "Последние экспорты".Результатом выполнения задачи является файл в формате .xml, который можно скачать нажав напротив нужного экспорта "Скачать". В настройках шаблона можно посмотеть ссылку на этот файл.