Задача
Оптовая торговля не сводится к обычному checkout. Цена зависит от конкретного клиента и его условий и не показывается до квалификации, товар заказывается упаковками и минимальными партиями, часть ассортимента физически в пути, а окончательная стоимость перевозки становится известна только после того, как склад соберёт заказ. При этом заказ может прийти с сайта, из Click2Buy, от торгового представителя, по email и по телефону — и все они должны попасть в один жизненный цикл, а не в пять разных.
Решение
Квалификация до цены. Регистрационная форма собирает не пару полей, а бизнес-профиль: имя, компанию, телефоны, адрес, тип бизнеса, сайт или соцсети, источник знакомства и комментарий. Тип бизнеса отличает retailer от design studio, furniture store, florist, garden centre или restaurant. Дальше заявка проходит review: проверка полноты и валидности данных, исключение дублей компании и контактов, определение обслуживаемой территории и ответственного представителя, назначение прайс-листа и доступных коллекций, при необходимости — кредитная заявка, и только затем approved, rejected или needs information. Статус компании отделён от статуса пользователя: увольнение одного сотрудника retailer не закрывает весь business account.
Остаток, который можно обещать. В Click2Buy видно не одно число, а четыре связанных: товар на складе, уже проданное и зарезервированное количество, позиции в закупке и доступный остаток. При добавлении в корзину проверяются минимальное количество и упаковочная кратность, доступность в выбранном канале, текущий резерв, ожидаемая поставка для preorder, снятие товара с продажи и конфликт с заказом, который параллельно собирает другой пользователь или сейлз. Корзина при этом не бесконечный складской резерв: окончательное allocation выполняется по настроенному событию — подтверждению заказа, оплате или credit approval, — а при дефиците заказ делится на доступную часть и backorder с явным согласованием клиента.
Цена считается на сервере. После квалификации система определяет прайс-лист компании, доступные скидки и специальные цены, налоговый статус, правила минимального заказа, допустимые способы оплаты, кредитные условия и возможность заказывать в долг, валюту и полномочия конкретного пользователя компании. Правило пересчитывается заново перед подтверждением заказа. POS не позволяет представителю просто вписать другую цену: допустимое отклонение, ручная скидка и override требуют права или согласования и попадают в audit log.
POS для выездных продаж. Order pad рассчитан на быстрый набор большого числа строк — сканирование штрихкода, поиск по SKU, шаг количества и проверка case pack, повторы из истории заказов, избранное и сохранённые списки клиента, замена снятой или отсутствующей позиции, preorder и backorder, автосохранение черновика, предпросмотр quote и отдельная сводка для клиента без внутренних полей. На выставке связь нестабильна, поэтому черновики и очередь операций хранятся локально и синхронизируются при восстановлении сети, а повторная отправка использует idempotency key, чтобы один заказ не появился дважды. Если за время офлайна изменились остаток или цена, POS не подтверждает старые данные молча: он показывает расхождение, предлагает обновлённый вариант и требует повторного решения ответственного.
Quote → order. Черновик и коммерческое предложение живут до согласования, но при превращении quote в заказ цены и наличие валидируются заново, а исходная версия предложения сохраняется для аудита. Строка заказа хранит версию цены и описание товара, поэтому заказ остаётся исторически достоверным даже после обновления каталога.
Доставка и рекламации. Поддерживаются самовывоз со склада, посылочная отправка, паллетная перевозка для мебели и крупных заказов и собственный перевозчик клиента. Финальный фрахт часто неизвестен до упаковки: склад фиксирует фактические коробки, паллеты, вес и объём, после чего стоимость перевозки рассчитывается и согласуется внутри workflow заказа. Рекламация связывается с компанией и заказом, принимает фотографии и проходит состояния submitted, needs information, under review, approved или rejected, replacement, credit или refund, closed; сотрудник видит связанные строки заказа, отгруженное количество, отправление и предыдущие обращения.
Кто чем владеет. Роли систем разделены явно: PIM или ERP отвечает за SKU, штрихкоды и атрибуты, ERP и бухгалтерия — за клиентские условия, счета и кредитное состояние, WMS — за остатки, комплектацию и отгрузку, закупки — за ожидаемые поступления, CRM — за лиды, компании, территории и активность продаж. Витрины не становятся независимой мастер-копией цены или остатка. Ошибка синхронизации попадает в retry queue и операционный мониторинг, а не маскируется успешным статусом на клиентском экране.
Результат
Retailer проходит весь путь сам: знакомится с ассортиментом, подаёт заявку, получает свои цены и условия и заказывает в Click2Buy. Торговый представитель собирает тот же заказ рядом с клиентом — с теми же ценами, остатками и правилами компании, а не в блокноте, который потом кто-то перенабирает. Заказы из всех каналов попадают в общий жизненный цикл и уходят на складскую обработку, оплату, отгрузку и бухгалтерский учёт без повторного ручного ввода. Отчётность при этом перестаёт считать web, POS и заказ по телефону разными клиентами только из-за источника: продажи видны по категории, коллекции, территории, представителю и каналу одновременно.