Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions _build/elements/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
'msOnChangeOrderStatus',
'msOnBeforeCreateOrder',
'msOnCreateOrder',
'msOnBeforeCreateShipment',
'msOnCreateShipment',
'msOnBeforeChangeShipmentStatus',
'msOnChangeShipmentStatus',
'msOnBeforeUpdateShipmentTracking',
'msOnUpdateShipmentTracking',
'msOnBeforeMgrCreateOrder',
'msOnMgrCreateOrder',
'msOnBeforeUpdateOrder',
Expand Down
20 changes: 20 additions & 0 deletions _build/elements/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,26 @@
'xtype' => 'numberfield',
'area' => 'ms3_statuses',
],
'ms3_status_sent' => [
'value' => 4,
'xtype' => 'numberfield',
'area' => 'ms3_statuses',
],
'ms3_shipment_enabled' => [
'value' => false,
'xtype' => 'combo-boolean',
'area' => 'ms3_statuses',
],
'ms3_shipment_on_delivered_status' => [
'value' => 0,
'xtype' => 'numberfield',
'area' => 'ms3_statuses',
],
'ms3_shipment_on_in_transit_status' => [
'value' => 0,
'xtype' => 'numberfield',
'area' => 'ms3_statuses',
],
'ms3_customer_cancel_allowed_statuses' => [
'value' => '2,3',
'xtype' => 'textfield',
Expand Down
5 changes: 5 additions & 0 deletions core/components/minishop3/config/ms3.services.example.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@
'ms3_delivery_service' => [
'class' => \MyCompany\Delivery\CdekDeliveryService::class,
],

// External WMS / fulfillment:
// 'ms3_shipment_lifecycle' => [
// 'class' => \MyCompany\Fulfillment\WmsShipmentLifecycle::class,
// ],
*/

];
8 changes: 8 additions & 0 deletions core/components/minishop3/config/routes/manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,9 @@
$router->get('/{id}/logs', function ($params) use ($modx) {
return (new \MiniShop3\Controllers\Api\Manager\OrdersController($modx))->getLogs($params);
});
$router->get('/{id}/shipment', function ($params) use ($modx) {
return (new \MiniShop3\Controllers\Api\Manager\OrderShipmentController($modx))->get($params);
});
}, [
new PermissionMiddleware($modx, 'msorder_list')
]);
Expand Down Expand Up @@ -864,6 +867,11 @@
$router->delete('/{id}/products/{product_id}', function ($params) use ($modx) {
return (new \MiniShop3\Controllers\Api\Manager\OrdersController($modx))->deleteProduct($params);
});
$router->put('/{id}/shipment', function ($params) use ($modx) {
$data = json_decode(file_get_contents('php://input'), true) ?: [];
return (new \MiniShop3\Controllers\Api\Manager\OrderShipmentController($modx))
->save(array_merge($params, is_array($data) ? $data : []));
});
}, [
new PermissionMiddleware($modx, 'msorder_save')
]);
Expand Down
5 changes: 5 additions & 0 deletions core/components/minishop3/config/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@
$controller = new \MiniShop3\Controllers\Api\Web\DeliveryController($modx);
return $controller->getList($params);
});

$router->post('/webhook/{delivery_id}', function ($params) use ($modx) {
$controller = new \MiniShop3\Controllers\Api\Web\DeliveryWebhookController($modx);
return $controller->handle($params);
});
});

$router->group('/payment', function ($router) use ($modx) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
'payment' => ($payment = $msOrder->getOne('Payment'))
? $payment->toArray()
: [],
'shipments' => $ms3->shipmentPublicForOrder((int) $id),
'total' => [
'cost' => (float)$msOrder->get('cost'),
'cost_formatted' => $ms3->format->price($msOrder->get('cost'), true),
Expand Down
8 changes: 8 additions & 0 deletions core/components/minishop3/lexicon/en/default.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@
$_lang['ms3_err_status_nf'] = 'Status with this identifier not found.';
$_lang['ms3_err_delivery_nf'] = 'Delivery method with this identifier not found.';
$_lang['ms3_err_delivery_id_required'] = 'Delivery ID is required';
$_lang['ms3_err_shipment_nf'] = 'Shipment not found.';
$_lang['ms3_err_shipment_disabled'] = 'Shipment lifecycle is disabled.';
$_lang['ms3_err_shipment_cancelled'] = 'Shipment operation was cancelled.';
$_lang['ms3_err_shipment_tracking_invalid'] = 'Tracking number is empty.';
$_lang['ms3_err_shipment_event_conflict'] = 'This shipment event cannot be applied to the current shipment.';
$_lang['ms3_err_shipment_webhook_unsupported'] = 'This delivery method does not support the core webhook.';
$_lang['ms3_err_shipment_webhook_invalid'] = 'Delivery callback payload is invalid.';
$_lang['ms3_err_shipment_webhook_unauthorized'] = 'Delivery callback signature is invalid.';
$_lang['ms3_err_payment_nf'] = 'Payment method with this identifier not found.';
$_lang['ms3_err_payment_id_required'] = 'Payment ID is required';
$_lang['ms3_err_status_final'] = 'Final status is set. It cannot be changed.';
Expand Down
8 changes: 8 additions & 0 deletions core/components/minishop3/lexicon/en/setting.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@
$_lang['setting_ms3_status_paid_desc'] = 'What status to set after order payment';
$_lang['setting_ms3_status_canceled'] = 'Canceled order status ID';
$_lang['setting_ms3_status_canceled_desc'] = 'What status to set when canceling order';
$_lang['setting_ms3_status_sent'] = 'Sent order status ID';
$_lang['setting_ms3_status_sent_desc'] = 'Order status to set when a shipment becomes shipped (if the transition is allowed).';
$_lang['setting_ms3_shipment_enabled'] = 'Enable shipment lifecycle';
$_lang['setting_ms3_shipment_enabled_desc'] = 'Off (default): checkout and order statuses are unchanged. On: shipment shipped maps to ms3_status_sent via OrderStatusService, cancelled/failed maps to ms3_status_canceled. Create/setTracking still work when off. Webhook is 404 when off. Replace ms3_shipment_lifecycle to use an external WMS.';
$_lang['setting_ms3_shipment_on_delivered_status'] = 'Order status ID on delivered shipment';
$_lang['setting_ms3_shipment_on_delivered_status_desc'] = 'Optional. 0 (default) keeps order status unchanged when the shipment becomes delivered. Seed sent is final, so leave 0 unless you use a non-final sent status.';
$_lang['setting_ms3_shipment_on_in_transit_status'] = 'Order status ID on in-transit shipment';
$_lang['setting_ms3_shipment_on_in_transit_status_desc'] = 'Optional. 0 (default) keeps order status unchanged when the shipment becomes in_transit.';
$_lang['setting_ms3_customer_cancel_allowed_statuses'] = 'Statuses from which customer can cancel order';
$_lang['setting_ms3_customer_cancel_allowed_statuses_desc'] = 'Comma-separated status IDs. Default: New and Paid (2,3). Empty = use ms3_status_new and ms3_status_paid.';
$_lang['setting_ms3_status_for_stat'] = 'Status IDs for statistics';
Expand Down
16 changes: 16 additions & 0 deletions core/components/minishop3/lexicon/en/vue.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,23 @@
$_lang['order_dates'] = 'Dates';
$_lang['order_products'] = 'Products';
$_lang['order_address'] = 'Address';
$_lang['order_tracking'] = 'Tracking';
$_lang['order_history'] = 'History';
$_lang['shipment_empty'] = 'No shipment yet';
$_lang['shipment_create'] = 'Create shipment';
$_lang['shipment_saved'] = 'Shipment saved';
$_lang['shipment_status'] = 'Shipment status';
$_lang['shipment_tracking_number'] = 'Tracking number';
$_lang['shipment_carrier'] = 'Carrier';
$_lang['shipment_shipped_at'] = 'Shipped';
$_lang['shipment_delivered_at'] = 'Delivered';
$_lang['shipment_status_preparing'] = 'Preparing';
$_lang['shipment_status_shipped'] = 'Shipped';
$_lang['shipment_status_in_transit'] = 'In transit';
$_lang['shipment_status_delivered'] = 'Delivered';
$_lang['shipment_status_cancelled'] = 'Cancelled';
$_lang['shipment_status_returned'] = 'Returned';
$_lang['shipment_status_failed'] = 'Failed';
$_lang['order_comment'] = 'Comment';
$_lang['select_status'] = 'Select status';
$_lang['select_delivery'] = 'Select delivery';
Expand Down
8 changes: 8 additions & 0 deletions core/components/minishop3/lexicon/ru/default.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@
$_lang['ms3_err_status_nf'] = 'Статус с таким идентификатором не найден.';
$_lang['ms3_err_delivery_nf'] = 'Способ доставки с таким идентификатором не найден.';
$_lang['ms3_err_delivery_id_required'] = 'Не указан ID доставки';
$_lang['ms3_err_shipment_nf'] = 'Отгрузка не найдена.';
$_lang['ms3_err_shipment_disabled'] = 'Lifecycle отгрузки выключен.';
$_lang['ms3_err_shipment_cancelled'] = 'Операция с отгрузкой отменена.';
$_lang['ms3_err_shipment_tracking_invalid'] = 'Номер отслеживания пустой.';
$_lang['ms3_err_shipment_event_conflict'] = 'Это событие отгрузки нельзя применить к текущей отгрузке.';
$_lang['ms3_err_shipment_webhook_unsupported'] = 'Этот способ доставки не поддерживает системный webhook.';
$_lang['ms3_err_shipment_webhook_invalid'] = 'Тело callback доставки некорректно.';
$_lang['ms3_err_shipment_webhook_unauthorized'] = 'Подпись callback доставки недействительна.';
$_lang['ms3_err_payment_nf'] = 'Способ оплаты с таким идентификатором не найден.';
$_lang['ms3_err_payment_id_required'] = 'Не указан ID оплаты';
$_lang['ms3_err_status_final'] = 'Установлен финальный статус. Его нельзя менять.';
Expand Down
8 changes: 8 additions & 0 deletions core/components/minishop3/lexicon/ru/setting.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@
$_lang['setting_ms3_status_paid_desc'] = 'Какой статус нужно устанавливать после оплаты заказа';
$_lang['setting_ms3_status_canceled'] = 'ID статуса отмены заказа';
$_lang['setting_ms3_status_canceled_desc'] = 'Какой статус нужно устанавливать при отмене заказа';
$_lang['setting_ms3_status_sent'] = 'ID статуса «отправлен»';
$_lang['setting_ms3_status_sent_desc'] = 'Статус заказа при переходе отгрузки в shipped, если переход разрешён.';
$_lang['setting_ms3_shipment_enabled'] = 'Включить lifecycle отгрузки';
$_lang['setting_ms3_shipment_enabled_desc'] = 'Выкл. (по умолчанию): оформление и статусы заказа как сейчас. Вкл.: shipped ставит ms3_status_sent через OrderStatusService, cancelled/failed — ms3_status_canceled. create/setTracking работают и при выкл. Webhook при выкл. отвечает 404. Внешний WMS подменяется через ms3_shipment_lifecycle.';
$_lang['setting_ms3_shipment_on_delivered_status'] = 'ID статуса заказа при delivered';
$_lang['setting_ms3_shipment_on_delivered_status_desc'] = 'Необязательно. 0 (по умолчанию) не меняет статус заказа, когда отгрузка становится delivered. Сид sent финальный, поэтому оставьте 0, если не используете нефинальный sent.';
$_lang['setting_ms3_shipment_on_in_transit_status'] = 'ID статуса заказа при in_transit';
$_lang['setting_ms3_shipment_on_in_transit_status_desc'] = 'Необязательно. 0 (по умолчанию) не меняет статус заказа, когда отгрузка становится in_transit.';
$_lang['setting_ms3_customer_cancel_allowed_statuses'] = 'Статусы, из которых покупатель может отменить заказ';
$_lang['setting_ms3_customer_cancel_allowed_statuses_desc'] = 'ID статусов через запятую. По умолчанию: «Новый» и «Оплачен» (2,3). Пусто — использовать ms3_status_new и ms3_status_paid.';
$_lang['setting_ms3_status_for_stat'] = 'ID статусов для статистики';
Expand Down
16 changes: 16 additions & 0 deletions core/components/minishop3/lexicon/ru/vue.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,23 @@
$_lang['order_dates'] = 'Даты';
$_lang['order_products'] = 'Товары';
$_lang['order_address'] = 'Адрес';
$_lang['order_tracking'] = 'Отслеживание';
$_lang['order_history'] = 'История';
$_lang['shipment_empty'] = 'Отгрузка ещё не создана';
$_lang['shipment_create'] = 'Создать отгрузку';
$_lang['shipment_saved'] = 'Отгрузка сохранена';
$_lang['shipment_status'] = 'Статус отгрузки';
$_lang['shipment_tracking_number'] = 'Трек-номер';
$_lang['shipment_carrier'] = 'Перевозчик';
$_lang['shipment_shipped_at'] = 'Отправлено';
$_lang['shipment_delivered_at'] = 'Доставлено';
$_lang['shipment_status_preparing'] = 'Подготовка';
$_lang['shipment_status_shipped'] = 'Отправлено';
$_lang['shipment_status_in_transit'] = 'В пути';
$_lang['shipment_status_delivered'] = 'Доставлено';
$_lang['shipment_status_cancelled'] = 'Отменено';
$_lang['shipment_status_returned'] = 'Возврат';
$_lang['shipment_status_failed'] = 'Ошибка';
$_lang['order_comment'] = 'Комментарий';
$_lang['select_status'] = 'Выберите статус';
$_lang['select_delivery'] = 'Выберите способ доставки';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

/**
* Order shipments for fulfillment and tracking (#591).
*/
final class CreateShipments extends AbstractMigration
{
public function change(): void
{
if ($this->hasTable('ms3_shipments')) {
return;
}

$this->table('ms3_shipments', [
'id' => true,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
])
->addColumn('order_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('delivery_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('status', 'string', ['limit' => 32, 'null' => false, 'default' => 'preparing'])
->addColumn('tracking_number', 'string', ['limit' => 191, 'null' => true, 'default' => null])
->addColumn('external_id', 'string', ['limit' => 191, 'null' => true, 'default' => null])
->addColumn('provider', 'string', ['limit' => 191, 'null' => true, 'default' => null])
->addColumn('carrier', 'string', ['limit' => 191, 'null' => true, 'default' => null])
->addColumn('shipped_at', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addColumn('delivered_at', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addColumn('last_event_id', 'string', ['limit' => 191, 'null' => true, 'default' => null])
->addColumn('meta', 'text', ['null' => true])
->addColumn('createdon', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addColumn('updatedon', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addIndex(['order_id'], ['unique' => true, 'name' => 'uniq_shipment_order'])
->addIndex(['delivery_id', 'provider', 'external_id'], [
'unique' => true,
'name' => 'uniq_shipment_external',
])
->create();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

use Phinx\Migration\AbstractMigration;

/**
* Provider webhook event ids for shipment replay (#606).
*/
final class CreateShipmentEvents extends AbstractMigration
{
public function change(): void
{
if ($this->hasTable('ms3_shipment_events')) {
return;
}

$this->table('ms3_shipment_events', [
'id' => true,
'primary_key' => ['id'],
'engine' => 'InnoDB',
'encoding' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
])
->addColumn('shipment_id', 'integer', ['signed' => false, 'null' => false])
->addColumn('provider_event_id', 'string', ['limit' => 191, 'null' => false])
->addColumn('createdon', 'integer', ['signed' => false, 'null' => true, 'default' => null])
->addIndex(['shipment_id', 'provider_event_id'], [
'unique' => true,
'name' => 'uniq_shipment_provider_event',
])
->create();
}
}
Loading