Skip to content

feat(customer): add order cancel by customer in personal account#119

Merged
biz87 merged 2 commits intobetafrom
feat/customer-order-cancel
Feb 27, 2026
Merged

feat(customer): add order cancel by customer in personal account#119
biz87 merged 2 commits intobetafrom
feat/customer-order-cancel

Conversation

@Ibochkarev
Copy link
Copy Markdown
Member

Описание

Добавлена возможность отмены заказа покупателем в личном кабинете. Покупатель может отменить заказ в статусах, разрешённых настройкой ms3_customer_cancel_allowed_statuses (по умолчанию: новый, оплаченный).

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

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

Связанные Issues

Closes #117

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

  • Ручное тестирование
  • Автоматические тесты (ESLint, php -l)
  • Тестирование на разных версиях PHP/MODX

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

  • MiniShop3: текущая
  • MODX: 3.x
  • PHP: 8.2+

Чеклист

  • Код соответствует стилю проекта
  • Добавлены/обновлены комментарии в сложных местах
  • Изменения не ломают существующую функциональность
  • Лексиконы добавлены на двух языках (ru/en)
  • PHPStan проходит без новых ошибок (не установлен в проекте)
  • ESLint проходит без ошибок (для JS/Vue изменений)

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

  • API: POST /api/v1/customer/orders/{id}/cancel с авторизацией (session или ms3_token)
  • Кнопка «Отменить заказ» отображается в списке заказов и на странице деталей при can_cancel
  • Clean Code: const/let, intention-revealing имена в JS; isOrderCancellableByCustomer() в сервисе

- Add system setting ms3_customer_cancel_allowed_statuses (default: 2,3)
- Add CustomerOrderController with cancel() API endpoint
- Add POST /api/v1/customer/orders/{id}/cancel route
- OrdersPageService: add can_cancel and api_url to order data
- Add cancel button in order list and details templates
- Add isOrderCancellableByCustomer() helper, api_url in getOrderDetailsData
- Lexicons ru/en for cancel UI and errors
- Clean Code: const/let, intention-revealing names in JS
@Ibochkarev Ibochkarev requested a review from biz87 February 23, 2026 17:46
Copy link
Copy Markdown
Member

@biz87 biz87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ревью PR #119: feat(customer): add order cancel

Функциональность полезная, реализация в целом рабочая. Есть ряд замечаний.


1. Критическое: дублирование getAllowedCancelStatusIds()

Метод идентично скопирован в два класса:

  • CustomerOrderController::getAllowedCancelStatusIds() (строки 90–104)
  • OrdersPageService::getAllowedCancelStatusIds() (строки 460–474)

Это нарушает DRY. Если логика изменится, придётся менять в двух местах — и кто-то забудет. Нужно вынести в общее место — например, в OrderStatusService (который уже инжектится в контроллер), или в отдельный статический хелпер.


2. Дублирование getAuthorizedCustomer()

Метод скопирован из CustomerAddressController. Теперь одинаковый код авторизации живёт минимум в двух контроллерах. Стоит вынести в базовый класс (например, BaseWebController) или trait. Иначе каждый новый Web-контроллер будет копировать этот блок.


3. Дублирование JS в двух шаблонах

JavaScript для кнопки отмены практически идентичен в:

  • ms3_customer_orders.tpl (строки 104–126)
  • ms3_customer_order_details.tpl (строки 197–219)

~20 строк одинакового кода. Лучше вынести в отдельный JS-файл или хотя бы в один общий блок/чанк.


4. Хардкод пути к api.php

'api_url' => rtrim($this->modx->getOption('site_url'), '/') . '/assets/components/minishop3/api.php',

Путь к api.php зашит в строку. Если у пользователя кастомный assets_url или маппинг ассетов, URL будет неправильным. Лучше использовать конфиг MS3:

'api_url' => $this->ms3->config['assetsUrl'] . 'api.php',

Дублируется в трёх местах сервиса (renderOrdersList, renderOrderDetails, getOrderDetailsData).


5. Маршрут: размещение внутри группы /customer

Маршрут добавлен внутри группы /customer с $tokenMiddleware:

$router->post('/orders/{id}/cancel', function($params) use ($modx) {
    $controller = new \MiniShop3\Controllers\Api\Web\CustomerOrderController($modx);
    return $controller->cancel($params);
}, [$tokenMiddleware]);

TokenMiddleware уже валидирует токен и записывает $_SESSION['ms3']['customer_id']. После этого getAuthorizedCustomer() в контроллере всегда найдёт customer через сессию — двойная проверка избыточна (хотя и не вредна). Это ещё один аргумент за вынос авторизации в базовый класс.


6. Мелочь: избыточный fallback

$cancelledStatusId = (int) $this->modx->getOption('ms3_status_canceled', null, 5) ?: 5;

getOption уже возвращает 5 по умолчанию. ?: 5 дублирует это. Достаточно:

$cancelledStatusId = (int) $this->modx->getOption('ms3_status_canceled', null, 5);

Что сделано хорошо

  • IDOR защищён: 'customer_id' => $customer->get('id') при загрузке заказа
  • Проверка допустимых статусов через настройку с fallback
  • Лексиконы на двух языках
  • Кнопка отмены условно показывается через can_cancel
  • Используется OrderStatusService::change() вместо прямого изменения — сохраняются события и логи
  • Кнопка блокируется после клика (cancelButton.disabled = true)

Итог

Статус
Функциональность Корректная
Безопасность OK (IDOR защищён, авторизация есть)
Дублирование кода Требует рефакторинга (3 места)
Рекомендация Вынести общий код, убрать хардкод api_url

@Ibochkarev Ibochkarev self-assigned this Feb 25, 2026
…tion

- Moved order cancellation JavaScript to a separate file for better organization.
- Updated templates to reference the new JavaScript file for order cancellation functionality.
- Refactored CustomerOrderController and OrdersPageService to utilize the OrderStatusService for determining cancellable order statuses.
- Introduced a new method in OrderStatusService to retrieve allowed cancel status IDs based on configuration settings.
- Enhanced API URL handling in OrdersPageService to respect custom configurations for assets and actions.
@Ibochkarev Ibochkarev requested a review from biz87 February 25, 2026 02:12
@biz87 biz87 marked this pull request as ready for review February 27, 2026 18:46
@biz87 biz87 merged commit 10599c9 into beta Feb 27, 2026
@Ibochkarev Ibochkarev deleted the feat/customer-order-cancel branch March 16, 2026 07:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] В личном кабинете покупателя, дать возможность отменить заказ

2 participants