Создание фида ценообразования по шаблону
Фид для интеграции можно создать с помощью экспорта каталога по шаблону. Для этого небходимо создать профиль экспорта:
- Перейдите на страницу "Настройки"
- Перейдите на вкладку "Экспорт"
- Нажмите на кнопку "+"
- Укажите название профиля экспорта, выберите профиль ценообразования, по которому будет подготовлен фид, и выберите формат "Каталог по шаблону"
- Нажмите "Сохранить"
После сохранения профиля экспорта станет доступна настройка шаблона интеграции.
Редактирование существующего профиля:
- Нажмите напротив этого профиля на значок карандашика.
- Отредактируйте название или добавьте/удалите профиль ценообразования.
- Нажмите кнопку "Сохранить".
Удаление существующего профиля:
- Нажмите напротив этого профиля на значок корзинки.
- Подтвердите удаление.
Настройка шаблона интеграции:
- Перейдите на вкладку "Настройка шаблона".
- Выберите тип выгрузки параметров.
- Выберите тип валидации (при необходимости).
- Выберите шаблон (нажамите кнопку "Шаблоны") или напишите свой.
- Нажмите кнопку "Сохранить".
Для написания шаблона мы используем язык 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, который можно скачать нажав напротив нужного экспорта "Скачать". В настройках шаблона можно посмотеть ссылку на этот файл.