====== Шаг9. Работа с заказами ====== Итак, наши пользователи могут отсылать заказы. Теперь наша задача - расширить панель управления так, чтобы администраторы могли просматривать список заказов, а пользователи - просматривать сделанные ими заказы. Администратор должен иметь возможность: * просмотреть все заказы, * просмотреть только заказы с определенным статусом (новый, в обработке, выполненный) * просмотреть информацию по заказу * сменить статус заказа ===== Просмотр и изменение статусов заказов администраторами ===== ==== Шаблон admin_order/display.html ==== При помощи этого шаблона мы будет выводить список заказов. Страница будет также содержать небольшую форму, которая позволит указать статус заказов, которые нужно отобразить. Для вывода списка заказов, мы будем использовать статический find()-метод Order :: findForAdmin(), который мы добавим чуть позже. В принпипе, аналогичную задачу мы решали при выводе списка товаров на фронтальной части для покупателей с возможностью поиска и фильтрации. Файл shop/template/admin_order/display.html:

Filter orders:

setChildDatasource('status_options_source', Order :: getStatusOptions()); ?> Filter :
Date Status Summ Actions
{$date|date:"F j, Y, G:i"} {$status_name} ${$summ|number:2, '.'} Delete
Обратите внимание вот на эти две строки: setChildDatasource('status_options_source', Order :: getStatusOptions()); ?> При помощи php-вставки мы передаем набор данных в тег [[limb3:ru:packages:wact:tags:form_tags:select_options_source_tag|]]. Этот тег используется для заполнения списка опций тега

Customer

Name : {$user.name}
Email : {$user.email}
Login : {$user.login}
Посмотрите, как мы вывели список позиций заказа. Мы использования атрибут **from** тега . Запись вида приводит к вызову метода get('lines') объекта Order, который вернет коллекцию (dataset) из связанных с заказом OrderLine. Шаблон содержит форму, которая позволит администраторам менять статус заказа. Обратите внимание на то, как мы заполнили список доступных статусов в данном случае - мы использовали атрибут from со значением "^status_options": Status : Почему именно так?
тег является контейнером данных, поэтому нам необходимо было использовать модификатор видимости на "1-уровень выше", а status_options приведет к вызову getStatusOptions() у объекта класса Order, который был загружен при помощи тега и передан в тег . ==== Контроллер AdminOrderController ==== setFormDatasource($this->request, 'filter_form'); } function doDelete() { try { lmbActiveRecord :: delete('Order', 'id = ' . $this->request->getInteger('id')); $this->redirect(); } catch(lmbARException $e) { $this->flashError('Wrond Order ID'); $this->redirect(array('controller' => 'admin')); return; } } function doDetails() { if(!$this->request->hasPost()) return; try { $order = new Order($this->request->getInteger('id')); } catch(lmbARException $e) { $this->flashError('Wrond Order ID'); $this->redirect(array('controller' => 'admin')); return; } $status = $this->request->get('status'); $this->flashMessage('Order status was changed'); $order->setStatus($status); $order->save(); } } ?> Надеемся, что все в данном классе для вас уже знакомо и пояснений не требует. ===== Предварительные итоги ===== Покажем внешний вид страницы списка заказов в панеле управления: {{{limb3:ru:tutorials:shop:orders.png|}}} и страницы конкретного заказа: {{{limb3:ru:tutorials:shop:single_order.png|}}} ===== Просмотр заказов покупателями ===== Последний небольшой шаг - добавление возможности покупателям просматривать свои заказы. Для этого мы добавим 2 шаблона profile/orders.html и profile/show_order.html и добавим метод doShowOrder(), где мы будем проверять, имеет ли пользователь право просматривать определенный заказ. ==== Шаблон profile/orders.html ==== Файл shop/template/profile/orders.html:
# Date Summ Status
{$id} {$date|date:"F j, Y, G:i"} ${$summ|number:2, '.'} {$status_name}
You made no orders in our shop yet.
Так как объект пользователя всегда доступен в корневом контейнере данных шаблона, мы можем получить список его заказов при помощи конструкции from='#user.orders'. Помните, мы добавили в класс User связь с заказами один-ко-многим под названием orders. Именно это и позволяет нам использовать подобную конструкцию прямо в шаблоне. ==== Шаблон profile/show_order.html ==== Мы решили реализовать получение данных в данном случае обычным для большинства разработчиков способом - передать их из контроллера. Было бы слишком небезопасно давать возможность пользователям иметь возможность просмотреть содержимого любого заказа, ведь идентификатор можно легко изменить. Файл shop/template/profile/show_order.html:
Title Price Quantity Summ
{$product.title} ${$price|number:2, '.'} {$quantity} ${$summ|number:2, '.'}
Конструкция заберет из корневого контейнера данных переменную order, которую мы поставим в шаблоне из контроллера чуть ниже, затем из order возьмет переменную lines. lines - это коллекция позиций заказа. ==== Изменения в контроллере ProfileController ==== Добавим в ProfileController метод doShowOrder(), который будет загружать указанный заказ и проверять право доступа текущего пользователя к заказу: request->getInteger('id')); if(!$order->belongsToUser($this->toolkit->getUser())) { $this->flashError('You can see only your orders!'); $this->redirect('/'); } $this->view->set('order', $order); } catch(lmbARException $e) { $this->flashError('Can\'t load order!'); $this->redirect('/'); } } [...] } ?> ==== Изменения в классе Order ==== Теперь необходимо только добавить метод Order :: belongsToUser(). class Order extends lmbActiveRecord { [...] function belongsToUser($user) { return ($this->getUserId() == $user->getId()); } [...] } ===== Далее ===== Пока это все, о чем мы хотели рассказать Вам о Limb3 в рамках данного примера. У нас есть для Ваc еще один шаг: [[step10|Шаг10. Рекомендации по дальнейшему изучению]].