Работа с заказом через админку OpenCart

2021.02.21
Детальный разбор процессов работы с заказом через адинку в OpenCart, интерактивный интерфейс, временная корзина, сохранение изменений заказа

С точки зрения покупателя, есть товары, которые нужно сложить в корзину, которую потом нужно оплатить. Но как все это выглядит внутри? Попробуем разобраться во внутреннем устройстве работы с заказами через админку Opencart.

Данные о товарах заказа хранятся в таблице order_product, где товары с заказами связаны по id (order_id, product_id). К слову информация о заказе хранится в нескольких таблицах order_.

Интерфейс

Перейдем в админке Продажи-Заказы и выберем любой заказ на редактирование.

Вкладка Товары на странице редактирования заказа в адинке

Страница редактирования заказа состоит из 5 вкладок, в каждую из которых можно попасть только из предыдущей нажимая кнопку Продолжить, при клике на которую на некоторых вкладках возникают ajax запросы, на основании ответов которых происходит заполнение вкладки.

Формирование заказа в админке OpenCart линейно и состоит из 5-ти последовательных этапов: Информация о покупателе - Товары - Детали оплаты - Адрес доставки - Итого.

Перейдем в admin/view/teplate/sale/order_form.tpl (OpenCart 2.3). Здесь можно увидеть что изначально весь интерфейс статичный, однако при переходе на вкладку Товары (клик по #button-customer внутри генерирует клик #button-refresh где и происходит изменение интерфейса) следует серия ajax запросов, в результате которых на вкладке меняется интерфейс.

Ajax запросы при переходе на вкладку Товары

Изменения заказа

Вернемся к вкладке редактирования заказа, а именно к Товары (скрин 2 раза выше).

При попытке изменить количество позиции посылается ajax запрос с route=api/cart/add. В файле catalog/controller/api/cart.php в методе add используется объект $this->cart класса Cart, а именно его метод add. Если взглянуть на код метода, то не трудно понять что новые данные о товарах записываются в таблицу cart, но нигде нет записи в таблицы order_.

В таблице cart есть столбец session_id, значение которого привязывается к текущему юзеру, и является ключом данных в массиве $_SESSION. То есть данные в таблице cart временные и существуют только на период существования сессии юзера.

Работа с заказом через админку осуществляется через корзину - данные сохраняются в корзину (таблица cart), но не сохраняются в данные заказа (таблицы order_).

Сохранение изменений заказа

На странице редактирования заказа перейдем в последнюю вкладку Итого, пролистаем вниз и нажмем кнопку Сохранить.

Просматривая консоль браузера можно увидеть запрос route=api/order/edit. Переходим в catalog/controller/api/order.php и смотрим немаленький метод edit, где заполняется массив order_data данными заказа ($this->cart->getProducts()).

Небольшой кусок кода, показывающий что данные о товарах заказа берутся из корзины:

// Products
$order_data['products'] = array();

foreach ($this->cart->getProducts() as $product) {
    $option_data = array();

    //...

    $order_data['products'][] = array(
        'product_id' => $product['product_id'],
        'name'       => $product['name'],
        'model'      => $product['model'],
        'option'     => $option_data,
        'download'   => $product['download'],
        'quantity'   => $product['quantity'],
        'subtract'   => $product['subtract'],
        'price'      => $product['price'],
        'total'      => $product['total'],
        'tax'        => $this->tax->getTax($product['price'], $product['tax_class_id']),
        'reward'     => $product['reward']
    );
}

Почти в конце метода есть сохранение изменений через модель checkout/order в таблицу order_product:

$this->model_checkout_order->editOrder($order_id, $order_data);

А еще ниже в этом методе есть добавление истории заказа:

$this->model_checkout_order->addOrderHistory($order_id, $order_status_id);

На этом можно было бы остановится ... но дальше будет интереснее :)

Посмотрим таблицу товаров заказа order_product:

Таблица товаров заказа order_product

А теперь взглянем на таблицу корзины cart где хранятся данные редактируемого заказа:

Таблица корзины cart редактируемого заказа через админку

Становится безумно интересно, как данные из корзины (cart), сопоставляются с данными в заказе (order)? Ведь просматривая таблицу корзины и товаров заказа между ними не видно никакой связи. Более того нет никакой связи между товарами этих двух таблиц!

На самом деле все просто, запрос сохранения заказа api/order/edit передает:

А теперь посмотрим внутрь модели checkout/order в метод editOrder и увидим там следующее:

$this->db->query("DELETE FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");
$this->db->query("DELETE FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "'");

Нет никакого сопоставления товаров из корзины с товарами из заказа: данные из заказа удаляются и записываются новые данные из корзины.

Не удобно ... но что является источником данных для заказа? Конечно корзина, а значит обновление данных корзины приводит к устареванию данных заказа.

Сохранение изменений заказа через админку осуществляется на основании данных корзины редактирования заказа, а корзина привязывается к сессии текущего администратора.

Итог

Схема не совсем очевидная, с первого взгляда может показаться запутанной. Однако, при детальном изучении становится понятна концепция, суть которой простота управления данными.

В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps