Перейти к содержимому

Данные на двух сайтах - каталог, цены, заказы, письма

Разбираем, что у двух сайтов одной копии общее, а что своё: каталог и цены, корзина и заказы, пользователи, письма, поиск и настройки модулей.

Механика

Пользователи в платформе общие для всей копии, и это не настраивается. Один человек с одной учётной записью ходит по обеим витринам, а разделяют его правами и группами, а не отдельными списками.

Инфоблоки привязываются к сайтам явным списком. Общий каталог привязывают к обоим сайтам, а новостную ленту второй витрины - только к ней, и от этой привязки зависит и вывод, и адреса элементов.

Типы цен общие для копии, но доступ к ним раздают группам покупателей. Разные цены на двух витринах делают разными типами цен и разными группами, а не дублированием товаров.

Корзина принадлежит сайту, а не только посетителю. Товар, положенный на одной витрине, на второй не появляется, и это правильное поведение: у витрин разные цены и разные условия доставки.

Заказ хранит сайт, на котором его оформили. По этому полю строят отчёты, письма и права менеджеров, поэтому фильтр по сайту в своих выборках заказов обязателен.

Почтовые шаблоны привязаны к сайту, а почтовые события - общие. На каждую витрину заводят свой шаблон письма, иначе покупатель второго сайта получает письмо с логотипом и адресами первого.

Поиск строит индекс по сайтам, и выдача ограничивается текущим. Отдельно проверяют, что при переиндексации в индекс попал контент обеих витрин, а не только основной.

Настройки модулей бывают общими и заданными по сайтам. Значение по умолчанию действует везде, а значение для сайта перекрывает его только на нём, и разбор странностей начинается с проверки обоих уровней сразу.

Файлы витрин чаще всего тоже раздельные, а ядро и загрузки общие. Из-за этого правка шаблона одной витрины не задевает вторую, а обновление платформы ставится один раз на обе.

Шаги

  1. Выписать, какие данные проекта общие, а какие обязаны различаться по витринам.
  2. Привязать инфоблоки к нужным сайтам и проверить адреса элементов на обеих витринах.
  3. Развести цены типами и группами покупателей, а не копиями товаров.
  4. Завести почтовые шаблоны отдельно для каждого сайта проекта.
  5. Добавить фильтр по сайту во все свои выборки заказов и отчёты.

Код

Смотрим привязку инфоблоков к сайтам:

SELECT s.IBLOCK_ID, i.NAME, s.SITE_ID FROM b_iblock_site s
JOIN b_iblock i ON i.ID = s.IBLOCK_ID ORDER BY s.IBLOCK_ID;
-- инфоблок без нужной привязки на этой витрине не покажет ничего

Привязка инфоблоков объясняет большинство жалоб «на втором сайте пусто». Проверять её быстрее всего запросом: интерфейс показывает привязку по одному инфоблоку, а запрос - сразу по всем.

Фильтруем заказы по сайту:

$rows = \Bitrix\Sale\Order::getList([
'select' => ['ID', 'ACCOUNT_NUMBER', 'PRICE', 'LID'],
'filter' => ['=LID' => 's2', '>=DATE_INSERT' => $from], // только вторая витрина
])->fetchAll();

Фильтр по сайту в отчётах обязателен с первого дня работы второй витрины. Без него суммы двух витрин складываются в одну, и разговор с бухгалтерией превращается в поиск потерянных заказов.

То же правило действует в письмах и уведомлениях менеджерам. Сообщение о новом заказе полезно помечать витриной, иначе смена путается, с какого сайта пришёл покупатель и по каким условиям его обслуживать.

Читаем настройку модуля для конкретного сайта:

printf("общая=%s для s2=%s\n",
\Bitrix\Main\Config\Option::get('sale', 'default_currency'),
\Bitrix\Main\Config\Option::get('sale', 'default_currency', '', 's2'));
// значение для сайта перекрывает общее, но только на этом сайте

Проверяем почтовые шаблоны по сайтам:

SELECT m.ID, m.EVENT_NAME, m.LID, m.SUBJECT FROM b_event_message m
WHERE m.EVENT_NAME = 'SALE_NEW_ORDER' ORDER BY m.LID;
-- у каждой витрины свой шаблон: иначе письма уходят с чужими реквизитами

Сверяем каталоги и папки витрин:

foreach (\Bitrix\Main\SiteTable::getList(['select' => ['LID', 'DIR', 'SERVER_NAME', 'DEF']])->fetchAll() as $site) {
printf("%-4s dir=%-10s домен=%-24s основной=%s\n",
$site['LID'], $site['DIR'], $site['SERVER_NAME'], $site['DEF']);
}
// папка сайта участвует в адресах и в путях к шаблонам обеих витрин

Папка и домен витрины участвуют в сборке всех адресов проекта. Ошибка в них проявляется не сразу, а в письмах и в карте сайта, где ссылки собираются кодом, а не руками редактора.

Определяем текущий сайт в своём коде:

$siteId = \Bitrix\Main\Context::getCurrent()->getSite(); // в публичной части
$siteId = $siteId ?: \Bitrix\Main\Config\Option::get('main', 'default_site');
// в консольном скрипте и в агенте текущего сайта нет: его задают явно

Фоновые задания выполняются вне сайта, и это регулярная причина писем с чужими ссылками. Сайт в таких сценариях передают параметром задания, а не полагаются на окружение.

Проверяем права менеджеров по сайтам:

$groups = \CUser::GetUserGroup($managerId);
printf("группы менеджера: %s\n", implode(',', $groups));
// права на заказы выдаются группам, а разделение витрин делают фильтром по сайту

Разделение менеджеров по витринам платформа сама не делает. Ограничение «видит только свои заказы» пишут своим кодом поверх прав, опираясь на поле сайта у заказа.

Смотрим корзины по сайтам:

SELECT LID, COUNT(*) FROM b_sale_basket WHERE ORDER_ID IS NULL GROUP BY LID;
-- корзины разделены по витринам так же, как и заказы
SELECT LID, COUNT(*) FROM b_sale_order GROUP BY LID; -- заказы по витринам

Ограничения

Общие пользователи - это не только удобство, но и ограничение. Разные требования к профилю на двух витринах приходится решать полями и группами, а не двумя независимыми базами людей.

Складской учёт общий для копии. Разделить остатки между витринами можно только складами и своей логикой вывода, а не настройкой «этот склад для этого сайта».

Часть модулей не знает о сайтах вовсе. Их настройки общие для копии, и различия между витринами приходится закрывать своим кодом.

Две витрины удваивают работу по контенту и проверкам. Любая правка шаблона, письма или настройки проверяется дважды, и это стоит закладывать в оценку работ.

Обмен с учётной системой усложняется вместе с числом витрин. Товары, цены и заказы приходится размечать сайтом на стороне обмена, иначе данные растекаются между витринами непредсказуемо.

Резервная копия и восстановление тоже становятся общими. Откатить одну витрину отдельно от второй не получится: база у копии одна, и восстановление возвращает состояние обеих сразу.

Типичные проблемы

На второй витрине каталог пустой.

Инфоблок не привязан ко второму сайту в своих настройках. Привязку смотрят запросом по всем инфоблокам сразу.

Отчёт по заказам показывает больше, чем ожидали.

В выборку попали заказы обеих витрин без фильтра по сайту. Фильтр по сайту добавляют во все свои выборки заказов.

Покупатель второго сайта получил письмо первого.

Почтовый шаблон заведён только для основного сайта. Шаблоны создают отдельно для каждой витрины проекта.

Настройка изменилась на одном сайте, а работает везде.

Значение задано общим, а не для конкретного сайта. Настройку задают на нужном уровне и проверяют оба.

Письма из фонового задания уходят с чужими ссылками.

В агенте нет текущего сайта, и берётся сайт по умолчанию. Сайт передают параметром задания и подставляют явно.

Частые вопросы

Можно ли развести пользователей по сайтам?

Нет, учётные записи общие для всей копии платформы. Разделяют доступ группами и правами, а полностью независимые базы людей требуют двух установок.

Как сделать разные цены на витринах?

Разными типами цен и группами покупателей, привязанными к витринам. Дублировать товары ради цен не нужно и вредно для обмена с учётной системой.

Общая ли корзина у двух сайтов?

Нет, корзина принадлежит сайту, и это правильно: цены и условия различаются. Перенос корзины между витринами делают своим кодом, если он вообще нужен.

Что делать с поиском на второй витрине?

Проверить, что её контент попал в индекс, и ограничить выдачу текущим сайтом. Индексация настраивается для каждой витрины отдельно.

Когда две витрины лучше двух установок?

Когда общие товары, общие покупатели и общая команда: экономия на обновлениях и обмене велика. Разные бизнесы с разными правилами дешевле развести по установкам.

Смежное

Первоисточник