Магазину сантехники на CS-Cart (~58 000 товаров) на старте нужен блок сопутствующих «С этим товаром покупают»: к ванне — смеситель, сифон, экран. Это кросс-сейл, поднимает средний чек. Коробочные механизмы не подходили: поведенческий блок CS-Cart строится по истории заказов, а на старте заказов нет — он пустой; стандартные «связанные товары» задаются кликами в каждой карточке и не масштабируются на 58k. Нужен был ручной, но массовый контроль: связи уже известны (в прайсе), их надо залить пачкой по артикулам.
Написал аддон CS-Cart, который управляет блоком через загрузку CSV. Менеджер готовит файл: строка = артикул главного товара + артикулы сопутствующих через «;», грузит в админке (Товары → Рекомендации → «Обновить связи»).
— Сопоставление по артикулу (product_code), не по внутреннему ID: менеджер оперирует артикулами из прайса/1С, скрипт сам резолвит их в product_id.
— Идемпотентность: связи в отдельной таблице (составной ключ); для каждого главного товара старые связи удаляются, новые пишутся через REPLACE. Повторная загрузка не плодит дубли, связи товаров не из файла не трогаются — можно обновлять частями.
— Устойчивость: trim кодов, пропуск битых строк и несуществующих артикулов, защита от петли. Кривая строка не роняет прогон.
— Вывод через движок ядра: блок на карточке рисуется штатным механизмом вывода товаров CS-Cart, поэтому рекомендации наследуют цены, фото, скидки и показывают только активные товары.
Блок «С этим товаром покупают» работает с первого дня, не дожидаясь накопления статистики заказов. Связи задаются и обновляются массово — одной загрузкой CSV по артикулам. Прогон идемпотентен, рекомендации наследуют цены/фото/скидки каталога. Честно про ограничение: импорт синхронный, по строке (без батчей/транзакции) — достаточно для разовой/периодической загрузки менеджером; под частые массовые обновления переписывается на батч-вставку.