Заказчик - Raschini, интернет-магазин одежды, обуви и аксессуаров с розничными магазинами. Сайт на WordPress и WooCommerce делали другие подрядчики: витрина и тема магазина, каталог и цены из 1С, заказы уходят в retailCRM официальным модулем. Программа лояльности Raschini Club со скидочными уровнями живёт в retailCRM, в магазинах карту считывает касса.
Личного кабинета у покупателей не было: регистрация и вход на сайте были выключены, все заказы оформлялись гостем. Покупатель не видел ни истории заказов, ни своей карты лояльности, карта существовала только в CRM и на кассе. Статусы заказов из CRM на сайт не возвращались, часть способов оплаты и доставки попадала в CRM не теми. Сайт и 1С присылали телефон в разных форматах, и один и тот же покупатель мог оказаться в CRM двумя карточками.
Что нужно было сделать:
- личный кабинет покупателя на базе стандартного кабинета WooCommerce: заказы, карта лояльности, вишлист, подписки, личные данные, вёрстка по макету дизайнера заказчика;
- вход и регистрацию по коду из SMS: почта есть у малой части покупателей, а телефон знают все;
- обмен сайта с retailCRM и 1С: сайт не должен перезаписывать то, что ведут CRM и 1С, а покупатель должен попадать в CRM одной карточкой.
Ограничения: магазин живой и принимает деньги, поэтому всё сначала делается на изолированной тестовой копии, а на боевом сайте - окнами, с резервной копией и откатом. Тему магазина, модуль retailCRM и обмен с 1С не правим, работаем только через их фильтры и настройки. Общий хостинг без root.
Я был единственным разработчиком: тестовая копия и выкладки, плагин, интеграции, тесты. Кабинет собрал на стандартном кабинете WooCommerce, а не с нуля: свои разделы зарегистрированы как эндпоинты WooCommerce, логика - в отдельном плагине на PHP. Статичную вёрстку по макету сделал отдельный верстальщик, я перенёс её в 9 переопределённых шаблонов WooCommerce в дочерней теме. Тема магазина не тронута.
Личный кабинет:
- вход в кабинет из шапки сайта и из меню на телефоне, шаблоны темы при этом не тронуты;
- разделы «Главная», «Заказы», «Карта лояльности», «Вишлист», «Подписки», «Личные данные», на телефоне - выпадающее меню;
- на главной плитки разделов и баннер программы лояльности: уровень, что он даёт и сколько осталось до следующего;
- заказы карточками с фото товаров, на странице заказа цена до скидки, со скидкой и процент. Цена до скидки пишется в заказ при оформлении, а для старых заказов берётся с товара, только если акция та же: иначе старый заказ показал бы скидку, которой не было;
- офлайн-покупки, которые приходят на сайт из CRM пустыми заказами, в кабинете скрыты;
- личные данные с размерами одежды, обуви и сорочки по размерным сеткам магазина, адрес сам подставляется при оформлении заказа;
- карта лояльности: уровень, скидка, владелец и номер карты читаются из retailCRM через его REST API. Штрихкод Code 128 рисует свой генератор в SVG, без библиотек; на телефоне он открывается на весь экран, касса в магазине по нему находит клиента;
- вишлист на готовом плагине TI WooCommerce Wishlist со своим шаблоном раздела, сам плагин не правился;
- кабинет закрыт от индексации, вёрстка проверена на ширинах 1440, 1024, 768, 430, 390, 375 и в Safari.
Вход по коду из SMS:
- один экран «Вход или регистрация»: номер, код из SMS, кабинет. Первый вход и есть регистрация, без пароля и без почты;
- SMS уходят через МТС, на тестовой копии работает тестовый режим и наружу ничего не уходит;
- защита от подбора кода и от рассылки SMS по чужим номерам, коды не хранятся в открытом виде;
- WooCommerce не создаёт учётку без почты, поэтому у неё техническая почта, которую покупатель нигде не видит и которая не уходит в CRM;
- карточка клиента в retailCRM создаётся сразу с телефоном и именем;
- старые гостевые заказы привязываются к учётке только после подтверждения номера кодом и мимо сохранения заказа: иначе модуль CRM перенёс бы историю к новой пустой карточке, и у покупателя упал бы уровень лояльности.
Синхронизация с retailCRM и 1С:
- включил обратную синхронизацию: продажа, отмена и возврат приходят из CRM и 1С на сайт, а с сайта в CRM уходит только стартовый статус нового заказа;
- модуль шлёт статус в обе стороны одной таблицей и ставит «оплачен» по статусу заказа на сайте. Двумя фильтрами самого модуля сделал так, что в CRM уходит только согласованный статус, а «оплачен» - только при настоящей онлайн-оплате с номером транзакции. Файлы модуля не тронуты, правка переживает его обновления, на неё 19 юнит-тестов;
- исправил сопоставление способов оплаты и доставки в CRM;
- телефон во всех точках записи на сайте теперь в том формате, в котором его присылает 1С, и покупатель не приходит в CRM второй карточкой.
Работа рядом с живым магазином: изолированная тестовая копия с обезличенной базой, письма и запросы во внешние системы с неё перехватываются, боевая CRM с копии не меняется. Выкладка скриптами из исходников, перед каждой - резервная копия базы и файлов, откат одной командой. Юнит-тесты на заглушках WordPress в Docker: 9 наборов, 244 проверки.
Кабинет работает на сайте Raschini с 26.08.2026, примерно через месяц после старта работ 24.07.2026, заказчик принял его 28.08.2026. Вход по коду из SMS разработан за три дня, 20-22.09, и работает на боевом с 23.09.2026.
Что изменилось для покупателей и магазина:
- покупатель видит свои заказы и карту лояльности, на кассе показывает штрихкод с телефона;
- вход по номеру телефона, без пароля и без почты;
- карточка клиента в CRM с первого входа - с телефоном и именем;
- продажа, отмена и возврат приходят из CRM на сайт: при приёмке статус, сменённый в CRM, появился на сайте через 12 секунд;
- сайт больше не перезаписывает в CRM статус заказа и оплату, которые ведут CRM и 1С;
- телефон с сайта приходит в CRM в том же формате, что и из 1С.
В цифрах: 6 разделов кабинета, 9 переопределённых шаблонов WooCommerce, плагин около 5 000 строк PHP, 4 интеграции, 9 наборов юнит-тестов и 244 проверки.
Дальше на стороне заказчика: почта сайта, склейка старых дублей в CRM и обмен заказами сайта с 1С.