Skip to content

feat(core): add shipment lifecycle and delivery webhook - #605

Open
Ibochkarev wants to merge 2 commits into
betafrom
feat/issue-591-shipment-lifecycle
Open

feat(core): add shipment lifecycle and delivery webhook#605
Ibochkarev wants to merge 2 commits into
betafrom
feat/issue-591-shipment-lifecycle

Conversation

@Ibochkarev

@Ibochkarev Ibochkarev commented Aug 19, 2026

Copy link
Copy Markdown
Member

Описание

Добавляет сущность отгрузки (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-only DefaultDelivery webhook не принимает. Опциональный ShipmentProviderInterface. HMAC: ShipmentWebhookHmac. Кабинет и Fenom ms3_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/Яндекса нет.

Тип изменений

  • Исправление бага (non-breaking change)
  • Новая функциональность (non-breaking change)
  • Breaking change (изменение, ломающее обратную совместимость)
  • Рефакторинг (без изменения функциональности)
  • Документация
  • Другое (опишите):

Связанные Issues

Closes #591
Closes #606
Closes #607
Closes #608
Closes #609

Как это было протестировано?

Локальный CI-гейт (без полной установки MODX), PHP lint + vueManager jobs из .github/workflows/ci.yml.

cd core/components/minishop3
php -l  # 647 files, exit 0
composer test:smoke  # 90, exit 0
./vendor/bin/phpunit
# 291 tests, 712 assertions, 12 skipped (@group mysql без DSN), 2 deprecations, exit 0

composer stan:prepare && composer stan
# [OK] No errors, exit 0

cd ../../../vueManager
npm run lint:ci  # exit 0
npx vitest run src/utils/orderPluginTab.test.js  # 1 test, exit 0

composer ci:php через Composer упёрся в process-timeout 300 с. Те же шаги (php -l, smoke, PHPUnit) прошли с exit 0.

  • Ручное тестирование
  • Автоматические тесты (composer test:smoke / composer test, npm run lint:ci, composer stan)
  • Тестирование на разных версиях PHP/MODX

Конфигурация тестирования:

  • MiniShop3: ветка feat/issue-591-shipment-lifecycle от beta
  • MODX: PHPStan deps в .phpstan-deps
  • PHP: 8.4.17

Скриншоты (если применимо)

не приложено

Чеклист

  • Код соответствует стилю проекта
  • Добавлены/обновлены комментарии в сложных местах
  • Изменения не ломают существующую функциональность
  • Лексиконы добавлены на двух языках (ru/en)
  • PHPStan проходит без новых ошибок (composer stan / CI job PHPStan)
  • ESLint проходит без ошибок (npm run lint:ci для Vue)
  • Обновлён CHANGELOG.md (для значимых изменений)

Дополнительные заметки

  • Replay webhook: история ms3_shipment_events. Повтор старого id после нового не вызывает второй change().
  • Fenom: MiniShop3::shipmentPublicForOrder(), без новых $modx->services в сниппете (phpstan ignore.count остаётся 5).
  • @group mysql для PdoShipmentStore пропускается без MS3_TEST_MYSQL_DSN.

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.
@AgelxNash AgelxNash mentioned this pull request Sep 6, 2026
16 tasks
AgelxNash pushed a commit to AgelxNash/MiniShop3 that referenced this pull request Sep 6, 2026
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).
AgelxNash pushed a commit to AgelxNash/MiniShop3 that referenced this pull request Sep 6, 2026
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.
@AgelxNash

Copy link
Copy Markdown

Этот PR включён в тестовую интеграционную сборку всех открытых PR MiniShop3: AgelxNash/MiniShop3, ветка integration/open-prs-20260906 (28/28 открытых).

Сборка нужна, чтобы проверить совместимость взаимозависимых серий PR до их мержа — при последовательном слиянии они конфликтуют друг с другом. Это не ревью и не конкурирующий PR: авторство сохранено (1 PR = 1 коммит с исходным автором), ветка пересобирается по мере обновления PR.

Как вошёл в сборку: Конфликты с #603/#604 разрешены: события/настройки/лексиконы объединены (inventory + shipment + transitions); в ms3_get_order payment отдаётся через PaymentPublicFields (#604) + добавлен shipments; дубликат лексикон-пары setting_ms3_status_sent устранён (оставлена формулировка #596, shipment-поведение описано в дескрипторах shipment-настроек).

@AgelxNash

Copy link
Copy Markdown

Спасибо за PR! Пожелание: скорейшего ревью и мержа 👍 Удачи!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

2 participants