Один дилер в Новосибирске случайно увидел в личном кабинете остатки и цены дилера из Екатеринбурга — просто изменив номер в адресной строке. Инцидент невелик по масштабу, но по сути — это провал всей идеи дилерской сети: каждый партнёр должен быть уверен, что его коммерческие условия и объёмы закупок видны только ему и головной компании, а не соседям по сети, с которыми он формально не конкурирует, но которым точно не обязан показывать свою экономику.
Ниже разбираем, как устроен B2B-портал для дилерской сети на 1С-Битрикс: общий каталог, управляемый централизованно, и строго изолированные данные каждого дилера — цены, остатки, заказы, статистика; иерархия дилеров и субдилеров; партнёрские бонусы и выплаты. Материал фокусируется именно на слое сети из многих дилеров — если нужен разбор функциональности одного кабинета, см. отдельную статью «Личный кабинет дилера на 1С-Битрикс: закрытый опт и повторные заказы». Материал обобщает практику по разработке B2B-порталов для дилерских сетей на 1С-Битрикс.
Коротко
- Портал дилерской сети — это общий каталог и контент, управляемые централизованно, поверх строго изолированных данных каждого дилера.
- Разграничение данных должно быть встроено в каждый запрос к базе, а не только скрывать элементы интерфейса — иначе прямой запрос по идентификатору вскроет чужие данные.
- Иерархия «дилер → субдилер» требует продумать, чьи данные и в каком объёме видны на каждом уровне.
- Партнёрские бонусы считаются по объёму закупок и должны опираться на данные из учётной системы, а не на ручной пересчёт.
- Разделяйте общий контент товара и коммерческие данные (цена, остаток) архитектурно с самого начала — это не мешает расти сети без переделки структуры.
Чем портал сети отличается от кабинета одного дилера
Личный кабинет одного дилера решает задачу «дилер видит свою цену, свою историю заказов, может оформить повторную закупку». Это важная, но локальная задача — она не решает вопрос, что происходит, когда таких дилеров становится пятьдесят, они работают из разных городов, часть из них имеет собственных субдилеров, а головная компания хочет централизованно управлять каталогом и контентом, при этом не давая ни одному дилеру доступа к коммерческим условиям другого.
Портал дилерской сети — это архитектурная надстройка над множеством личных кабинетов: общая база товаров и контента (одна карточка товара для всех), но данные, специфичные для конкретного дилера или его региона — цена, остаток на его складе, статус его заказов, — строго привязаны к нему и не пересекаются с данными других дилеров. Разница не в наборе фич кабинета, а в том, как устроены данные под капотом: один каталог, много изолированных срезов коммерческой информации поверх него.
Архитектура: общий каталог и изолированные данные дилера
На уровне данных портал дилерской сети строится на разделении двух сущностей, которые легко перепутать на старте проекта: контентный каталог и коммерческий слой. Контентный каталог — это инфоблок товаров с описанием, характеристиками, фото — общий для всей сети, редактируется централизованно сотрудниками головной компании, и любое изменение карточки товара видно сразу всем дилерам.
Коммерческий слой — это данные, которые различаются по дилерам: цена (обычно через тип цен, привязанный к группе дилера или конкретному контрагенту), остаток (привязан к складу дилера или региональному распределительному центру), статус заказов дилера, история его закупок. Технически коммерческий слой хранится отдельно от карточки товара — либо как отдельные свойства с привязкой к дилеру, либо, при большом числе дилеров, в отдельных таблицах или highload-блоках, где каждая запись явно содержит идентификатор дилера-владельца.
Такое разделение — не архитектурная прихоть, а прямое следствие требования безопасности: если цена и остаток хранятся прямо в карточке товара без привязки к дилеру, значит, они одни на всех, и персонализация становится невозможной в принципе. Разделение слоёв нужно закладывать на старте — переносить уже работающий каталог на новую модель данных, когда сеть выросла до полусотни дилеров, заметно дороже, чем спроектировать это с первого дня.
Разграничение прав: как один дилер не видит другого
Скрыть чужие данные в интерфейсе — недостаточная мера защиты. Если дилер А физически не может видеть ссылку на заказ дилера Б в меню, но при этом прямой запрос к странице заказа по известному или подобранному идентификатору отдаёт данные без проверки владельца, — это уязвимость, а не защита. Такие случаи (доступ к чужим данным по прямому URL с изменённым числовым идентификатором) — одна из самых частых практических утечек в самодельных B2B-порталах.
Правильная модель — проверка владельца записи на уровне каждого обращения к данным, а не только на уровне пунктов меню. Практически это означает: любой компонент или обработчик, который отдаёт заказ, остаток, историю или документ, должен сначала проверить, что текущий авторизованный пользователь имеет право на именно эту запись (по совпадению ID дилера в записи и в сессии пользователя), и только потом отдавать данные. Такую проверку стоит вынести в общий слой — единую точку, через которую проходит любой доступ к коммерческим данным дилера, — чтобы не дублировать логику проверки в каждом отдельном компоненте и не рисковать забыть её где-то одном месте.
Иерархия сети: дилеры и субдилеры второго уровня
У части дилерских сетей структура двухуровневая: дилер первого уровня закупает у головной компании и перепродаёт дальше своим субдилерам — более мелким партнёрам в своём регионе. Портал в такой структуре должен поддерживать не два, а фактически три роли одновременно: головная компания видит всю сеть, дилер первого уровня видит свои данные и данные своих субдилеров (но не других дилеров первого уровня и их субдилеров), а субдилер видит только свои данные в рамках витрины своего дилера.
| Уровень | Что видит | Чего не видит |
|---|---|---|
| Головная компания | Всю сеть: всех дилеров, всех субдилеров, все цены и объёмы | — |
| Дилер 1-го уровня | Свои данные, данные своих субдилеров | Данные других дилеров 1-го уровня и их субдилеров |
| Субдилер 2-го уровня | Только свои данные в рамках витрины своего дилера | Данные дилера 1-го уровня и других субдилеров |
Технически такая иерархия реализуется через явное поле «родительский дилер» у каждого субдилера и рекурсивную (или заранее развёрнутую) проверку принадлежности при выдаче данных. Важно решить заранее, видит ли дилер первого уровня закупочную цену, по которой субдилер берёт товар (обычно да, поскольку это его наценка), и видит ли субдилер цену, по которой дилер первого уровня закупает у головной компании (как правило нет — это уже не его уровень коммерческой информации).
Свои цены и остатки для каждого дилера
Цена для дилера в 1С-Битрикс реализуется через типы цен каталога, привязанные к группе пользователей дилера или конкретному контрагенту — тот же механизм, что применяется для персональных цен в обычном личном кабинете B2B. Особенность сети в том, что типов цен становится не один-два (розница/опт), а десятки — по числу групп дилеров с разными условиями, и управление этим множеством типов цен само по себе требует продуманной структуры, иначе список типов цен в админке превращается в нечитаемую простыню.
Остатки для сети дилеров — отдельная сложность, если у дилеров есть собственные региональные склады или распределительные центры, а не единый склад головной компании. В этом случае каталог должен показывать остаток не «вообще», а именно на складе, релевантном конкретному дилеру, — а это уже не просто тип цены, а привязка остатков к комбинации «товар + склад дилера», которая должна корректно приходить из учётной системы по каждому складу отдельно.
Централизованный контент и локальные витрины
Головная компания обычно хочет управлять контентом централизованно — единые описания товаров, актуальные фото, маркетинговые баннеры — чтобы не зависеть от того, насколько аккуратно каждый дилер ведёт свою часть каталога. При этом дилеру часто важно иметь узнаваемую витрину: свой логотип, контакты, иногда — свой поддомен вида dealer-name.company.ru.
Технически это разделяется на два независимых слоя: общий контент товаров (инфоблок, редактируется централизованно) и брендирование витрины конкретного дилера (шаблон, логотип, контакты, привязанные к его учётной записи или поддомену). Дилер, как правило, не должен иметь возможность редактировать сам контент товара — иначе один дилер сможет случайно или намеренно исказить описание, которое увидят клиенты другого дилера через общий каталог, если карточка действительно общая для всех.
Партнёрские выплаты и бонусная программа
Многие дилерские сети строят мотивацию не только на скидке от прайса, но и на бонусной программе — дополнительной выплате или начислении, зависящем от объёма закупок дилера за период. Формула обычно прогрессивная: чем больше объём за квартал, тем выше процент бонуса, иногда с разными ставками по категориям товаров.
Для портала это означает отдельный раздел личного кабинета дилера — «Бонусы» или «Партнёрская программа» — с текущим накопленным объёмом за период, прогнозом бонуса при сохранении текущего темпа закупок, и историей уже начисленных и выплаченных сумм. Данные для расчёта (фактический объём отгрузок и оплат) должны приходить из учётной системы обменом, а сам расчёт формулы бонуса может выполняться либо в 1С с последующей выгрузкой готовой суммы, либо на стороне портала по синхронизированным данным об объёме — оба варианта рабочие, но правило должно быть одно и применяться последовательно, без расхождений между тем, что видит дилер на портале, и тем, что реально начисляет бухгалтерия.
Как это выглядит в админке 1С-Битрикс
Структура дилерской сети настраивается через группы пользователей с иерархией «родитель — потомок» и привязкой типов цен и складов к каждой группе. Схематично карточка дилера в админке выглядит так:
Связь с 1С: откуда берутся цены и остатки по дилерам
Как и в обычном личном кабинете B2B, источником истины для цен, остатков и объёма закупок по каждому дилеру должна быть учётная система, а не ручной ввод на портале. Специфика сети в том, что обмен должен учитывать не один набор цен и остатков, а множество — по числу групп дилеров и, если есть, по числу региональных складов.
На практике это означает, что структура обмена (CommerceML или иной формат) должна явно передавать привязку «тип цены/склад → дилер», а не просто общий прайс. Если в 1С уже настроена работа с несколькими организациями, складами или сегментами клиентов, интеграция во многом опирается на эту существующую структуру; если в 1С такого разделения ещё нет, его придётся сначала выстроить там, прежде чем переносить на портал, — обмен не может передать данные, которых в учётной системе просто не существует в нужном разрезе.
Риски утечки данных между дилерами и как их закрыть
Стоит отдельно перечислить типичные векторы утечки данных между дилерами в портале сети — практический опыт показывает, что почти все инциденты укладываются в короткий список.
- Прямой перебор идентификаторов в URL. Номер заказа, счёта или документа в адресной строке без проверки владельца на сервере.
- Общие экспортные файлы. Выгрузка прайса или остатков в Excel/PDF, в которую по ошибке попали данные не только текущего дилера, если фильтрация применена не на уровне запроса к базе, а постфактум к уже собранным данным.
- Поиск по сайту без учёта прав. Полнотекстовый поиск, который индексирует и отдаёт в результатах данные заказов или документов без проверки, кому они принадлежат.
- API и REST-методы без авторизации на уровне записи. Метод API проверяет, что пользователь авторизован вообще, но не проверяет, что конкретная запись принадлежит именно ему.
- Кэш, общий для разных пользователей. Если кэшированный фрагмент с коммерческими данными одного дилера по ошибке не учитывает пользователя в ключе кэша, следующий посетитель может увидеть чужие закэшированные данные.
Единственный надёжный способ закрыть все эти векторы — не полагаться на разрозненные проверки в разных местах кода, а провести отдельный аудит безопасности перед запуском портала сети, целенаправленно проверяя каждый экран и каждый метод API негативными сценариями «а что если запросить чужие данные напрямую».
Частые ошибки при проектировании портала сети
- Скрывают чужие данные только в интерфейсе, не проверяя владельца записи на уровне запроса к базе, — прямой URL вскрывает утечку.
- Хранят цену и остаток прямо в карточке товара без привязки к дилеру — персонализация становится невозможной архитектурно.
- Не продумывают заранее, что видит дилер первого уровня в данных своих субдилеров, а что нет, — вопрос всплывает уже после запуска, когда переделка дороже.
- Дают дилеру право редактировать общий контент товара — искажения видят клиенты всех дилеров сети сразу.
- Считают партнёрские бонусы вручную вне системы — расхождения между тем, что видит дилер на портале, и фактическим начислением подрывают доверие к программе.
- Не тестируют разграничение прав негативными сценариями перед запуском — уязвимость обнаруживается только после реального инцидента с дилером.
- Забывают учесть кэш при мультидилерской архитектуре — общий кэш без пользователя в ключе отдаёт чужие данные следующему посетителю.
- Пытаются сразу поддержать многоуровневую иерархию с произвольной глубиной вложенности, хотя реальная структура сети — просто дилер и его субдилеры, без дальнейших уровней.
dealer.company.ru) — он проще в администрировании и не требует отдельного SSL-сертификата и DNS-настроек на стороне дилера. Отдельный домен имеет смысл только для крупных дилеров с собственным сильным брендом, которым важно полностью скрыть связь с головной компанией в адресной строке.
Чек-лист перед стартом проекта
- Структура сети описана. Число уровней иерархии (дилеры, субдилеры), число групп с разными коммерческими условиями.
- Разделение контента и коммерческих данных заложено. Ясно, что общее для всех (карточка товара), а что индивидуально по дилеру (цена, остаток).
- Модель прав спроектирована на уровне данных. Проверка владельца записи предусмотрена для каждого типа данных — заказы, документы, остатки, — а не только для экранов интерфейса.
- Источник цен и остатков по дилерам определён. Ясно, как 1С передаёт привязку «тип цены/склад → дилер» через обмен.
- Формула бонусной программы зафиксирована. Если бонусы есть — понятно, откуда берутся данные для расчёта и кто их проверяет.
- Запланирован аудит безопасности. Перед запуском предусмотрена проверка разграничения прав негативными сценариями.
Вывод
Портал для дилерской сети — это не масштабированный личный кабинет одного дилера, а отдельная архитектурная задача: общий каталог и контент под централизованным управлением, поверх которого строго изолированы коммерческие данные каждого партнёра. Разграничение прав должно быть встроено в каждый запрос к данным, а не только скрывать пункты меню — иначе рано или поздно найдётся дилер, который случайно или намеренно увидит чужие цены. Продумывайте иерархию, разделение слоёв данных и модель прав на старте проекта — переделка этой архитектуры, когда сеть уже выросла до десятков дилеров, обходится заметно дороже, чем правильное проектирование с первого дня.