MiniShop3 1.14.0 и vueTools 1.2.1
Вышел MiniShop3 1.14.0-beta1 — 105 влитых PR и больше двухсот часов работы с середины августа. Это второй релиз подряд за сотню, и по содержанию самый весомый: заказ получил полноценный коммерческий жизненный цикл. Одновременно обновился VueTools до 1.2.1-pl — с ним Vue-экраны в админке наконец перестали отличаться от родных.
Начну с неё, потому что это видно сразу при первом же входе.
Тема Modx появилась в VueTools 1.2.0, а в 1.2.1 доведена до состояния, когда страницы на Vue не отличить от родных. Кнопки действия стали зелёными, как «Сохранить» в MODX, а тёмно-синий остался на вкладках, ссылках и выделении. Переключатели, ползунки, полосы загрузки, флажки, календарь, диалоги, таблицы, постраничная навигация и всплывающие подсказки перерисованы по живому интерфейсу, а не на глаз. Заодно починили тёмную тему.
Включается настройкой vuetools.theme со значением modx. По умолчанию остаётся Aura — пока не переключите, ничего не изменится.
Со стороны MiniShop3 кнопки приведены к единому размеру на всех экранах, а кнопки действий в таблицах оставлены компактными, чтобы списки не раздувались. Небольшое расхождение в высоте полей на трёх экранах уже исправлено и выйдет ближайшим обновлением.
Самое крупное в релизе. Настройка ms3_inventory_enabled выключена по умолчанию: пока не включите, корзина и оформление работают как раньше.
Дальше коротко, потому что тема тянет на отдельный разговор. Остаток резервируется, когда заказ создан, списывается после оплаты и возвращается при отмене. Доступность проверяется до того, как заказ получит номер, — покупатель не уйдёт с подтверждением на товар, которого нет. Два одновременных заказа на последнюю единицу не спишут её дважды, это проверяли отдельно и на живой базе.
Для внешней складской системы есть точки подключения: и на каждое движение остатка, и на замену всего расчёта своим. Перед включением заполните остатки — пустое значение считается нулём, иначе магазин разом окажется без товара.
Подробный разбор с настройками и сценариями выйдет отдельной статьёй.
Две части жизни заказа, которые MiniShop3 раньше не отслеживал.
Оплата. Покупатель уходил на страницу платёжного сервиса, и дальше начиналась слепая зона. Журнал заказа фиксировал смену статуса, но не сам разговор с сервисом: ни попытки, ни отказа, ни его причины. А когда сервис присылал подтверждение дважды — при сбоях связи они это делают, — заказ мог обработаться повторно, и защиту от этого каждое платёжное дополнение писало по-своему.
Теперь обращения к сервису записываются: когда началось, чем кончилось, что он ответил. У магазина появился собственный адрес для его уведомлений, и одно и то же событие второй раз не применяется. Вопрос «деньги списались, а заказ не оплачен» разбирается по журналу, а не по переписке с поддержкой.
Доставка. После оплаты заказ пропадал из виду: трек-номер жил в комментарии, статус двигали руками. Теперь у заказа есть отгрузка со своим номером и состоянием, служба доставки может сообщать о её движении, и статус заказа идёт следом. В карточке заказа появилась вкладка отгрузки, на витрине эти данные доступны покупателю. Выключено по умолчанию, настройка ms3_shipment_enabled.
Порядок в статусах. Запрет уйти из конечного статуса и откатиться на шаг назад работал и раньше: эта модель досталась ещё от miniShop2. Новое — возможность прописать маршрут заказа целиком. В настройке ms3_order_status_transitions перечисляются разрешённые переходы парами: запись 2:3,3:4,2:5 означает, что из второго статуса можно уйти в третий или в пятый, а из третьего только в четвёртый. Чего в списке нет, то запрещено. Пока настройка пуста, всё работает как прежде.
И повторная смена на тот же статус больше не срабатывает дважды. Это важно как раз здесь: уведомления от платёжных служб и служб доставки приходят по два раза.
О чём речь. Магазин живёт не в одиночестве: рядом CRM, складская программа, бухгалтерия, чат в мессенджере. Всем им нужно вовремя узнавать, что у заказа сменился статус. Обычно это решают так: внешняя система раз в минуту стучится на сайт и спрашивает, нет ли новостей. Лишняя нагрузка и всё равно с опозданием.
Что сделано. Теперь магазин сам сообщает наружу: у заказа номер такой-то статус сменился с одного на другой, сумма такая. Сообщение подписано, чтобы получатель мог убедиться, что оно и правда от вашего магазина, и снабжено собственным номером, чтобы одно и то же не обработали дважды.
Делать это через плагин на msOnChangeOrderStatus можно было и раньше, он никуда не делся. Разница в том, что плагин — это код на вашем же сайте, который каждый интегратор писал заново и обычно без подписи. Теперь отправка наружу устроена одинаково для всех, кто подключается.
Что уходит. Только цифры: номер заказа, прежний и новый статус, суммы. Ни имени, ни почты, ни телефона, ни адреса. Если чужую систему однажды вскроют, данные ваших покупателей там взять неоткуда.
Само по себе наружу не отправит. В ядре вместо отправки стоит заглушка: событие собирается, подписывается, доходит до точки отправки — и там останавливается. Пока так готовится одно событие, смена статуса заказа. Ещё тринадцать описаны в справочнике на будущее, но не выпускаются, так что рассчитывать на них рано.
Тогда зачем оно, если не работает? Работает — не хватает только последнего шага, и он оставлен снаружи намеренно. Событие выпускается в том же запросе, где покупатель оформляет заказ. Полези ядро в чужой сервер само, покупатель ждал бы ответа этого сервера, а лежащая CRM растягивала бы оформление на минуту. Такое отправляют в фоне, а чем именно — зависит от площадки: где-то cron, где-то очередь. Поэтому ядро берёт на себя формат, подпись и защиту от повторов, а способ доставки выбирает тот, кто знает своё окружение.
Обработчики на PHP при этом подключаются уже сегодня и никакой сети не требуют: дополнение подписывается на событие и делает с ним что нужно прямо на сайте. Так что для авторов дополнений это готовый инструмент, а не заготовка.
Масштаб работы для автора дополнения — одна функция, вот весь контракт:
Что было не так. В MODX есть штатный способ закрыть часть сайта от посторонних — группы ресурсов. Положили категорию в закрытую группу, и открыть её сможет только тот, кому разрешено. Вот только каталог MiniShop3 этого не замечал: сама страница категории закрывалась, а товары с неё продолжали спокойно показываться в списках и попадать в корзину. Сделать раздел для оптовиков или закрытую витрину для дилеров штатными средствами MODX не получалось.
Как сейчас. Каталог сверяется с правами. Товары и категории из закрытой группы посторонний не увидит нигде: ни в сниппетах на витрине, ни в публичном API, ни в корзине.
А дальше появилось то, ради чего всё затевалось. Теперь есть группы покупателей: создаёте группу, привязываете её к группе пользователей MODX, добавляете клиентов. Вошедший покупатель из такой группы видит расширенный каталог — тот самый закрытый раздел. Оптовику показываются оптовые позиции, случайному посетителю их просто нет.
Тонкость, которая стоит нервов. На кэшируемой странице MODX отдаёт готовый HTML раньше, чем успеют отработать сниппеты. Первый же заглянувший аноним застолбит страницу своим урезанным списком, и вошедший оптовик увидит ровно его. Лечится восклицательным знаком: [[!ms3_products]]. Без него закрытый каталог на кэшируемой странице работать не будет — имейте в виду сразу, иначе будете искать причину в правах.
Проверка включена по умолчанию. Если каталог у вас открыт всем и закрытых разделов нет, её можно выключить настройкой ms3_web_catalog_respect_resource_groups.
Раздел для тех, кто делает витрину не на шаблонах MODX, а отдельным приложением. Такой витрине каталог нужно получать по сети, и в этом релизе доступного стало заметно больше: публичные категории со списком, карточкой и деревом, больше фильтров у списка товаров, галерея товара и поиск каталога по обычному адресу страницы, а не по внутреннему номеру.
Что такое фасеты. Это фильтры с числами — те самые, что слева в каталоге: «Красный (12)», «Синий (3)», ползунок цены от и до, список производителей с количеством. Отдельный запрос отдаёт их готовыми под текущую выборку: какие значения вообще встречаются и сколько товаров за каждым.
Считаются они с одной хитростью, без которой фильтры бесполезны. Когда покупатель уже выбрал красный, счётчики цветов показываются так, будто цвет не выбран — иначе рядом с синим всегда стоял бы ноль и переключиться было бы некуда. Остальные выбранные фильтры при этом учитываются. То же самое с ценой: границы ползунка считаются без оглядки на сам ползунок.
SEO-блок. Когда страницу рисует внешнее приложение, а не MODX, метатеги брать неоткуда. Теперь API отдаёт их вместе с данными: заголовок, описание, canonical, robots и Open Graph.
Касается это двух сущностей каталога — товара и категории, больше ничего. В карточке товара и в карточке категории блок приходит сам, в списках и в дереве — по запросу, параметром include_seo=1, чтобы не раздувать выдачу там, где метатеги не нужны.
Значение robots берётся из галочки «Доступен для поиска» у ресурса. Если готовые значения не подходят, любое из них подменяется своей TV — настройкой ms3_public_seo_tv_map, это JSON вида {«title»:«tv.seo_title»,«robots»:«tv.robots»}. А если нужно вмешаться уже перед самой выдачей, есть событие msOnGetPublicSeo.
Четыре вещи, которые стоит проверить на своём магазине.
Честно скажу: документация отстала. Разделы по складскому учёту, отгрузкам и попыткам оплаты ещё не написаны, часть страниц по API описывает прежнее поведение. Сверку провели, список расхождений собран, обновление выйдет отдельно — раньше, чем следующий релиз.
Отдельно и по существу: Иван Бочкарев — автор 96 из 105 PR этого релиза. Складской учёт, попытки оплаты, отгрузки, доменные события, ACL групп ресурсов, Web API, оформление интерфейса — всё это его работа. Называть такой вклад «помощью в разработке» было бы нечестно: Иван сегодня ведущий разработчик MiniShop3, и дальше мы движемся именно в этой конфигурации. Мне иногда кажется что он безработный. Иначе откуда столько времени?
Моя часть — архитектурные решения, ревью и приёмка: каждый PR проходил проверку на живом MODX, а не только по диффу. За цикл из этой проверки родилось 48 issues — почти по одному на каждые два принятых PR.
Ставьте на тестовых площадках, пробуйте складской учёт и вебхуки — и пишите, что отвалилось.
Тема Modx и VueTools 1.2.1
Начну с неё, потому что это видно сразу при первом же входе.
Тема Modx появилась в VueTools 1.2.0, а в 1.2.1 доведена до состояния, когда страницы на Vue не отличить от родных. Кнопки действия стали зелёными, как «Сохранить» в MODX, а тёмно-синий остался на вкладках, ссылках и выделении. Переключатели, ползунки, полосы загрузки, флажки, календарь, диалоги, таблицы, постраничная навигация и всплывающие подсказки перерисованы по живому интерфейсу, а не на глаз. Заодно починили тёмную тему.
Включается настройкой vuetools.theme со значением modx. По умолчанию остаётся Aura — пока не переключите, ничего не изменится.
Со стороны MiniShop3 кнопки приведены к единому размеру на всех экранах, а кнопки действий в таблицах оставлены компактными, чтобы списки не раздувались. Небольшое расхождение в высоте полей на трёх экранах уже исправлено и выйдет ближайшим обновлением.
Складской учёт
Самое крупное в релизе. Настройка ms3_inventory_enabled выключена по умолчанию: пока не включите, корзина и оформление работают как раньше.
Дальше коротко, потому что тема тянет на отдельный разговор. Остаток резервируется, когда заказ создан, списывается после оплаты и возвращается при отмене. Доступность проверяется до того, как заказ получит номер, — покупатель не уйдёт с подтверждением на товар, которого нет. Два одновременных заказа на последнюю единицу не спишут её дважды, это проверяли отдельно и на живой базе.
Для внешней складской системы есть точки подключения: и на каждое движение остатка, и на замену всего расчёта своим. Перед включением заполните остатки — пустое значение считается нулём, иначе магазин разом окажется без товара.
Подробный разбор с настройками и сценариями выйдет отдельной статьёй.
Попытки оплаты и отгрузки
Две части жизни заказа, которые MiniShop3 раньше не отслеживал.
Оплата. Покупатель уходил на страницу платёжного сервиса, и дальше начиналась слепая зона. Журнал заказа фиксировал смену статуса, но не сам разговор с сервисом: ни попытки, ни отказа, ни его причины. А когда сервис присылал подтверждение дважды — при сбоях связи они это делают, — заказ мог обработаться повторно, и защиту от этого каждое платёжное дополнение писало по-своему.
Теперь обращения к сервису записываются: когда началось, чем кончилось, что он ответил. У магазина появился собственный адрес для его уведомлений, и одно и то же событие второй раз не применяется. Вопрос «деньги списались, а заказ не оплачен» разбирается по журналу, а не по переписке с поддержкой.
Доставка. После оплаты заказ пропадал из виду: трек-номер жил в комментарии, статус двигали руками. Теперь у заказа есть отгрузка со своим номером и состоянием, служба доставки может сообщать о её движении, и статус заказа идёт следом. В карточке заказа появилась вкладка отгрузки, на витрине эти данные доступны покупателю. Выключено по умолчанию, настройка ms3_shipment_enabled.
Порядок в статусах. Запрет уйти из конечного статуса и откатиться на шаг назад работал и раньше: эта модель досталась ещё от miniShop2. Новое — возможность прописать маршрут заказа целиком. В настройке ms3_order_status_transitions перечисляются разрешённые переходы парами: запись 2:3,3:4,2:5 означает, что из второго статуса можно уйти в третий или в пятый, а из третьего только в четвёртый. Чего в списке нет, то запрещено. Пока настройка пуста, всё работает как прежде.
И повторная смена на тот же статус больше не срабатывает дважды. Это важно как раз здесь: уведомления от платёжных служб и служб доставки приходят по два раза.
Доменные события и исходящие вебхуки
О чём речь. Магазин живёт не в одиночестве: рядом CRM, складская программа, бухгалтерия, чат в мессенджере. Всем им нужно вовремя узнавать, что у заказа сменился статус. Обычно это решают так: внешняя система раз в минуту стучится на сайт и спрашивает, нет ли новостей. Лишняя нагрузка и всё равно с опозданием.
Что сделано. Теперь магазин сам сообщает наружу: у заказа номер такой-то статус сменился с одного на другой, сумма такая. Сообщение подписано, чтобы получатель мог убедиться, что оно и правда от вашего магазина, и снабжено собственным номером, чтобы одно и то же не обработали дважды.
Делать это через плагин на msOnChangeOrderStatus можно было и раньше, он никуда не делся. Разница в том, что плагин — это код на вашем же сайте, который каждый интегратор писал заново и обычно без подписи. Теперь отправка наружу устроена одинаково для всех, кто подключается.
Что уходит. Только цифры: номер заказа, прежний и новый статус, суммы. Ни имени, ни почты, ни телефона, ни адреса. Если чужую систему однажды вскроют, данные ваших покупателей там взять неоткуда.
Само по себе наружу не отправит. В ядре вместо отправки стоит заглушка: событие собирается, подписывается, доходит до точки отправки — и там останавливается. Пока так готовится одно событие, смена статуса заказа. Ещё тринадцать описаны в справочнике на будущее, но не выпускаются, так что рассчитывать на них рано.
Тогда зачем оно, если не работает? Работает — не хватает только последнего шага, и он оставлен снаружи намеренно. Событие выпускается в том же запросе, где покупатель оформляет заказ. Полези ядро в чужой сервер само, покупатель ждал бы ответа этого сервера, а лежащая CRM растягивала бы оформление на минуту. Такое отправляют в фоне, а чем именно — зависит от площадки: где-то cron, где-то очередь. Поэтому ядро берёт на себя формат, подпись и защиту от повторов, а способ доставки выбирает тот, кто знает своё окружение.
Обработчики на PHP при этом подключаются уже сегодня и никакой сети не требуют: дополнение подписывается на событие и делает с ним что нужно прямо на сайте. Так что для авторов дополнений это готовый инструмент, а не заготовка.
Масштаб работы для автора дополнения — одна функция, вот весь контракт:
interface WebhookDispatcherInterface
{
public function dispatch(DomainEvent $event): void;
}Внутри остаётся отправить $event->toArray() по HTTP, подписав тело готовым хелпером WebhookHmacSigner::sign(). Плюс одна запись в core/config/ms3.services.php, чтобы ядро взяло ваш класс вместо заглушки:'ms3_webhook_dispatcher' => [
'class' => \MyCompany\Integration\HttpWebhookDispatcher::class,
'interface' => \MiniShop3\Services\Events\WebhookDispatcherInterface::class,
],Группы ресурсов на витрине
Что было не так. В MODX есть штатный способ закрыть часть сайта от посторонних — группы ресурсов. Положили категорию в закрытую группу, и открыть её сможет только тот, кому разрешено. Вот только каталог MiniShop3 этого не замечал: сама страница категории закрывалась, а товары с неё продолжали спокойно показываться в списках и попадать в корзину. Сделать раздел для оптовиков или закрытую витрину для дилеров штатными средствами MODX не получалось.
Как сейчас. Каталог сверяется с правами. Товары и категории из закрытой группы посторонний не увидит нигде: ни в сниппетах на витрине, ни в публичном API, ни в корзине.
А дальше появилось то, ради чего всё затевалось. Теперь есть группы покупателей: создаёте группу, привязываете её к группе пользователей MODX, добавляете клиентов. Вошедший покупатель из такой группы видит расширенный каталог — тот самый закрытый раздел. Оптовику показываются оптовые позиции, случайному посетителю их просто нет.
Тонкость, которая стоит нервов. На кэшируемой странице MODX отдаёт готовый HTML раньше, чем успеют отработать сниппеты. Первый же заглянувший аноним застолбит страницу своим урезанным списком, и вошедший оптовик увидит ровно его. Лечится восклицательным знаком: [[!ms3_products]]. Без него закрытый каталог на кэшируемой странице работать не будет — имейте в виду сразу, иначе будете искать причину в правах.
Проверка включена по умолчанию. Если каталог у вас открыт всем и закрытых разделов нет, её можно выключить настройкой ms3_web_catalog_respect_resource_groups.
Web API и SEO
Раздел для тех, кто делает витрину не на шаблонах MODX, а отдельным приложением. Такой витрине каталог нужно получать по сети, и в этом релизе доступного стало заметно больше: публичные категории со списком, карточкой и деревом, больше фильтров у списка товаров, галерея товара и поиск каталога по обычному адресу страницы, а не по внутреннему номеру.
Что такое фасеты. Это фильтры с числами — те самые, что слева в каталоге: «Красный (12)», «Синий (3)», ползунок цены от и до, список производителей с количеством. Отдельный запрос отдаёт их готовыми под текущую выборку: какие значения вообще встречаются и сколько товаров за каждым.
Считаются они с одной хитростью, без которой фильтры бесполезны. Когда покупатель уже выбрал красный, счётчики цветов показываются так, будто цвет не выбран — иначе рядом с синим всегда стоял бы ноль и переключиться было бы некуда. Остальные выбранные фильтры при этом учитываются. То же самое с ценой: границы ползунка считаются без оглядки на сам ползунок.
SEO-блок. Когда страницу рисует внешнее приложение, а не MODX, метатеги брать неоткуда. Теперь API отдаёт их вместе с данными: заголовок, описание, canonical, robots и Open Graph.
Касается это двух сущностей каталога — товара и категории, больше ничего. В карточке товара и в карточке категории блок приходит сам, в списках и в дереве — по запросу, параметром include_seo=1, чтобы не раздувать выдачу там, где метатеги не нужны.
Значение robots берётся из галочки «Доступен для поиска» у ресурса. Если готовые значения не подходят, любое из них подменяется своей TV — настройкой ms3_public_seo_tv_map, это JSON вида {«title»:«tv.seo_title»,«robots»:«tv.robots»}. А если нужно вмешаться уже перед самой выдачей, есть событие msOnGetPublicSeo.
Что изменится в поведении после обновления
Четыре вещи, которые стоит проверить на своём магазине.
- Неуспешная оплата больше не отменяет заказ. Настройка ms3_payment_on_failed_status теперь по умолчанию 0, и покупатель может повторить оплату, не упираясь в ошибку. Если у вас включён складской учёт, помните: резерв остаётся за заказом до отмены. Чтобы остаток освобождался автоматически, укажите в настройке статус отмены. Для нетронутых установок дефолт правит миграция, ваше значение не тронут.
- Уведомления уходят даже при ошибке плагина. Если плагин на msOnChangeOrderStatus вернул ошибку уже после сохранения статуса, письмо всё равно отправится — заказ оплачен, и покупатель не должен оставаться в неведении из-за сбоя интеграции.
- Данные способа оплаты в msGetOrder урезаны. В чанк приходят только идентификатор, название, описание, цена и логотип. Класс и свойства больше не отдаются, чтобы учётные данные шлюза не попадали в HTML. Если ваш чанк использовал свойства платёжного метода, его придётся переписать.
- Параметр sortby у msProducts проверяется по белому списку. Проходят поля товара и ресурса, объявленные TV, поля производителя, ключи sortbyOptions и функции RAND, FIELD, IFNULL, COALESCE и CAST с проверенными аргументами. Всё остальное отбрасывается и пишется в журнал. Произвольный SQL в ORDER BY через параметр сниппета больше не пройдёт. Сортировка по вашим «Своим полям» работает как работала: они настоящие колонки таблицы и попадают в список сами, никуда их дописывать не нужно — это касается и полей товара, и полей производителя.
Исправления
- Временная блокировка покупателя по числу неудачных попыток больше не мешает восстановить пароль.
- Ошибки записи попыток оплаты перестали теряться: на соединении MODX они молча возвращали false.
- Повторный вебхук службы доставки долечивает статус заказа, если он разошёлся с отгрузкой.
- Коннектор админки больше не отдаёт повреждённый UTF-8 и пустое тело ответа.
- Сортировка галереи и товаров проверяет права, ACL полей заказа следует политике miniShopManagerPolicy.
- Кэш фасетов и страниц сбрасывается при изменении ACL и членства в группах.
- Английские вкладки товара при русском интерфейсе лечатся один раз после установки.
- Вернулась сортировка по опциям, имя которых совпадает с колонкой товара, и по полям производителя.
Документация
Честно скажу: документация отстала. Разделы по складскому учёту, отгрузкам и попыткам оплаты ещё не написаны, часть страниц по API описывает прежнее поведение. Сверку провели, список расхождений собран, обновление выйдет отдельно — раньше, чем следующий релиз.
Кто это сделал
Отдельно и по существу: Иван Бочкарев — автор 96 из 105 PR этого релиза. Складской учёт, попытки оплаты, отгрузки, доменные события, ACL групп ресурсов, Web API, оформление интерфейса — всё это его работа. Называть такой вклад «помощью в разработке» было бы нечестно: Иван сегодня ведущий разработчик MiniShop3, и дальше мы движемся именно в этой конфигурации. Мне иногда кажется что он безработный. Иначе откуда столько времени?
Моя часть — архитектурные решения, ревью и приёмка: каждый PR проходил проверку на живом MODX, а не только по диффу. За цикл из этой проверки родилось 48 issues — почти по одному на каждые два принятых PR.
Ссылки
Ставьте на тестовых площадках, пробуйте складской учёт и вебхуки — и пишите, что отвалилось.
Техническая поддержка MODX
Сайт лежит, тормозит или остался без разработчика?
Переезд с MODX 2 на 3, PHP 7 на 8, скорость и безопасность. Поддержка со сроками и ответственностью, а не совет в чате.
Подробнее
Реклама
0
Комментарии: 0