feat(core): add shipment lifecycle and delivery webhook - #605
Conversation
Fulfillment packages need a first-class shipment row and tracking without overloading order status or msDelivery.properties. Keep checkout unchanged until ms3_shipment_enabled is on.
Keep webhook replay honest across event ids, expose shipment in Fenom and the order editor, and cover PdoShipmentStore on MySQL.
Conflict resolution: keep inventory (603) + payment (604) lifecycle additions, merge shipment events/settings/lexicons alongside them; ms3_get_order combines PaymentPublicFields (604) with shipments public payload; dedupe ms3_status_sent lexicon pair (kept from PR 596).
Conflict resolution: PR 640 supersedes merged modx-pro#621 rework (same author, same intent) — took PR side for 36 files; manually preserved modx-pro#631 useConfirm grids, modx-pro#623 datefield dialog styles, modx-pro#643 gallery bits, modx-pro#605 order entry; ProductData sections rebuilt on groupProductDataSections (keeps modx-pro#611/modx-pro#620 sort_order) under PR 640 Panel layout.
|
Этот PR включён в тестовую интеграционную сборку всех открытых PR MiniShop3: AgelxNash/MiniShop3, ветка Сборка нужна, чтобы проверить совместимость взаимозависимых серий PR до их мержа — при последовательном слиянии они конфликтуют друг с другом. Это не ревью и не конкурирующий PR: авторство сохранено (1 PR = 1 коммит с исходным автором), ветка пересобирается по мере обновления PR. Как вошёл в сборку: Конфликты с #603/#604 разрешены: события/настройки/лексиконы объединены (inventory + shipment + transitions); в |
|
Спасибо за PR! Пожелание: скорейшего ревью и мержа 👍 Удачи! |
Описание
Добавляет сущность отгрузки (
ms3_shipments) иShipmentLifecycleService, чтобы fulfillment-пакеты вели статус доставки и трек отдельно от справочникаmsDeliveryи от одного толькоorder.status_id.По умолчанию
ms3_shipment_enabled=false. Checkout, submit и ручная смена статуса заказа не меняются. Публичный webhook отвечает 404. Менеджер или пакет может создать shipment и записатьtracking_numberбез смены статуса заказа.При включённом флаге
shippedмапится наms3_status_sentчерезOrderStatusService(не прямойstatus_id).cancelled/failedидут вms3_status_canceled.in_transitиdeliveredпо умолчанию статус заказа не трогают (сидsentфинальный). Падениеchange()логируется, строка отгрузки уже сохранена.Публичный callback:
POST /api/v1/delivery/webhook/{delivery_id}(без customer token, подпись провайдера). Cost-onlyDefaultDeliverywebhook не принимает. ОпциональныйShipmentProviderInterface. HMAC:ShipmentWebhookHmac. Кабинет и Fenomms3_get_orderотдаютshipments[]черезShipmentPublicDtoбезmeta/provider/external_id/секретов.Повтор webhook ищется в
ms3_shipment_events(уникальная пара shipment + provider_event_id). Полеlast_event_idостаётся кэшем последнего id.Менеджер:
GET/PUT /api/mgr/orders/{id}/shipment(msorder_list/msorder_save) и вкладка «Отслеживание» в карточке заказа.v1: один shipment на заказ. Реализаций CDEK/Почты/DPD/Яндекса нет.
Тип изменений
Связанные Issues
Closes #591
Closes #606
Closes #607
Closes #608
Closes #609
Как это было протестировано?
Локальный CI-гейт (без полной установки MODX), PHP lint + vueManager jobs из
.github/workflows/ci.yml.composer ci:phpчерез Composer упёрся в process-timeout 300 с. Те же шаги (php -l, smoke, PHPUnit) прошли с exit 0.composer test:smoke/composer test,npm run lint:ci,composer stan)Конфигурация тестирования:
feat/issue-591-shipment-lifecycleотbeta.phpstan-depsСкриншоты (если применимо)
не приложено
Чеклист
composer stan/ CI jobPHPStan)npm run lint:ciдля Vue)Дополнительные заметки
ms3_shipment_events. Повтор старого id после нового не вызывает второйchange().MiniShop3::shipmentPublicForOrder(), без новых$modx->servicesв сниппете (phpstan ignore.count остаётся 5).@group mysqlдляPdoShipmentStoreпропускается безMS3_TEST_MYSQL_DSN.