Add "Feed"
86
Feed.md
Normal file
86
Feed.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Фид товаров
|
||||
|
||||
## Обзор
|
||||
|
||||
YML-фид каталога товаров загружается с URL из настроек (`feedUrl`). Данные используются для подстановки в Mindbox-теги при рендере превью.
|
||||
|
||||
## Загрузка фида
|
||||
|
||||
Функция `_fetchFeedProducts(feedUrl)`:
|
||||
|
||||
1. Проверка `isPublicUrl(feedUrl)` — блокирует localhost, private IP, IPv6, hex IP
|
||||
2. HTTP GET с таймаутом 90 сек, User-Agent: `AspekterVA-FeedReader/1.0`
|
||||
3. Автодетект кодировки windows-1251 из Content-Type или XML declaration
|
||||
4. Парсинг regex-ом (не DOM) — извлекает `<offer>` элементы
|
||||
|
||||
## Кэширование
|
||||
|
||||
### В памяти
|
||||
- `feedCache` — Map `{url: {ts, products: Map}}`
|
||||
- TTL: 3 часа (`FEED_CACHE_TTL = 3 * 60 * 60 * 1000`)
|
||||
|
||||
### На диске
|
||||
- `data/feed-cache.json` — `{url, ts, products: {id: {...}}}`
|
||||
- Восстанавливается при старте сервера
|
||||
|
||||
### Дедупликация запросов
|
||||
- `feedPending` — Map текущих in-flight запросов
|
||||
- Если запрос уже выполняется, новый подключается к Promise
|
||||
- Stale timeout: 2 минуты (если Promise завис)
|
||||
|
||||
## Поля товара из фида
|
||||
|
||||
```javascript
|
||||
{
|
||||
id, available, // идентификатор и наличие
|
||||
name, price, oldPrice, // название, цены
|
||||
image, url, // картинка и ссылка
|
||||
description, // описание
|
||||
categoryId, vendor, // категория и бренд
|
||||
typePrefix, model, // тип товара и модель
|
||||
gender, color, // гендер и цвет
|
||||
discountPercent, // процент скидки
|
||||
// Кастомные поля (из param):
|
||||
denomination, year, dia, material, country,
|
||||
condition, weight, assay, vendorCode,
|
||||
reverseImage, salePercent, series
|
||||
}
|
||||
```
|
||||
|
||||
## API эндпоинты фида
|
||||
|
||||
### POST /api/project/:name/feed-refresh
|
||||
Принудительная перезагрузка фида:
|
||||
- Очищает кэш
|
||||
- Загружает заново
|
||||
- Возвращает diff: `{added, removed, total}`
|
||||
|
||||
### POST /api/project/:name/feed-lookup
|
||||
Поиск товаров по ID:
|
||||
- Body: `{ids: ["123", "456"]}`
|
||||
- Возвращает: `{found: [{id, name, price, ...}], notFound: ["789"]}`
|
||||
|
||||
### POST /api/project/:name/feed-suggest
|
||||
Замена недоступного товара:
|
||||
- Body: `{productId: "123", limit: 10}`
|
||||
- Алгоритм скоринга:
|
||||
| Фактор | Баллы |
|
||||
|--------|-------|
|
||||
| Тот же бренд (vendor) | +25 |
|
||||
| Тот же тип (typePrefix) | +20 |
|
||||
| Та же категория (categoryId) | +15 |
|
||||
| Тот же гендер | +10 |
|
||||
| Близкая цена | 0-10 |
|
||||
| Тот же цвет | +5 |
|
||||
- Исключаются товары с ценой >3x от оригинала
|
||||
- Возвращает топ-N по скору
|
||||
|
||||
## "Нет в наличии"
|
||||
|
||||
При рендере:
|
||||
1. Mindbox-теги подставляются из фида
|
||||
2. Если товар `available === false` → на картинку накладывается CSS-оверлей
|
||||
3. Список `unavailableProducts[]` возвращается клиенту
|
||||
4. В UI показывается warning: "⚠ Нет в наличии (N) · фид DD.MM HH:MM"
|
||||
5. Клик раскрывает список с кнопками "Заменить" для каждого товара
|
||||
6. "Заменить" → показывает модал с рекомендациями из `feed-suggest`
|
||||
Reference in New Issue
Block a user