Commit 63e1932e authored by Batyr Mackenov's avatar Batyr Mackenov

#33

parent 6bda769d
<?php
//##copyright##
class iaBackendController extends iaAbstractControllerModuleBackend
{
protected $_name = 'orders';
protected $_helperName = 'order';
protected $_gridFilters = ['buyer' => self::LIKE, 'status' => self::EQUAL];
protected $_gridQueryMainTableAlias = 'o';
protected $_processAdd = false;
protected $_processEdit = false;
protected $_systemFieldsEnabled = false;
protected function _indexPage(&$iaView)
{
$action = isset($this->_iaCore->requestPath[0]) ? $this->_iaCore->requestPath[0] : null;
switch ($action)
{
case 'view':
if (empty($this->_iaCore->requestPath[1]))
{
return iaView::errorPage(iaView::ERROR_NOT_FOUND);
}
$this->_viewDetails($iaView, $this->_iaCore->requestPath[1]);
break;
case 'email':
if (empty($this->_iaCore->requestPath[1]) || empty($this->_iaCore->requestPath[2]))
{
return iaView::errorPage(iaView::ERROR_NOT_FOUND);
}
$this->_sendNotificationEmail($iaView, $this->_iaCore->requestPath[1], $this->_iaCore->requestPath[2]);
break;
case 'remove':
if (empty($this->_iaCore->requestPath[1]))
{
return iaView::errorPage(iaView::ERROR_NOT_FOUND);
}
$this->_deleteOrder($iaView, $this->_iaCore->requestPath[1]);
break;
default:
parent::_indexPage($iaView);
}
}
private function _viewDetails(&$iaView, $orderId)
{
iaBreadcrumb::toEnd(iaLanguage::get('view'));
$order = $this->getHelper()->getById($orderId);
if (!$order) {
return iaView::errorPage(iaView::ERROR_NOT_FOUND);
}
iaBreadcrumb::replaceEnd($order['id']);
$iaUsers = $this->_iaCore->factory('users');
$statuses = [iaOrder::PENDING, iaOrder::CANCELED, iaOrder::SHIPPED, iaOrder::COMPLETED];
$iaView->assign('buyer', $iaUsers->getInfo($order['member_id']));
$iaView->assign('fields', $this->_iaField->get($this->getItemName()));
$iaView->assign('item', $order);
$iaView->assign('statuses', $statuses);
$iaView->assign('path', $this->getPath());
$iaView->title(iaLanguage::getf('order_details', ['id' => $orderId]));
$iaView->display('form-orders');
}
protected function _sendNotificationEmail(&$iaView, $emailType, $orderId)
{
$orderData = $this->getById($orderId);
if (!$orderData) {
return iaView::errorPage(iaView::ERROR_NOT_FOUND);
}
iaHelper::sendEmail($emailType, $orderData)
? $iaView->setMessages(iaLanguage::get('email_sent'), iaView::SUCCESS)
: $iaView->setMessages(iaLanguage::get('error_on_email_submission'));
iaUtil::go_to($_SERVER['HTTP_REFERER']);
}
protected function _deleteOrder(&$iaView, $id)
{
$result = $this->getHelper()->delete($id);
$iaView->setMessages(iaLanguage::get($result ? 'order_removed' : 'db_error'),
$result ? iaView::SUCCESS : iaView::ERROR);
iaUtil::go_to($this->getPath());
}
protected function _gridQuery($columns, $where, $order, $start, $limit)
{
$sql =
'SELECT SQL_CALC_FOUND_ROWS '
. 'o.`id`, o.`date_added`, o.`total`, o.`comment`, o.`status`, o.`buyer_name`, '
. 'SUM(i.`qty`) `items_num`, '
. '1 `view` '
. 'FROM `:prefix:table_orders` o '
. 'LEFT JOIN `:prefix:table_items` i ON (i.`order_id` = o.`id`) '
. "WHERE o.`status` != ':status' "
. ($where ? 'AND ' . $where . ' ' : '')
. 'GROUP BY o.`id` '
. $order . ' '
. 'LIMIT :start, :limit';
$sql = iaDb::printf($sql, [
'prefix' => $this->_iaDb->prefix,
'table_orders' => $this->getTable(),
'table_items' => $this->getHelper()->getTableItems(),
'status' => iaOrder::INCOMPLETE,
'start' => $start,
'limit' => $limit
]);
return $this->_iaDb->getAll($sql);
}
}
\ No newline at end of file
......@@ -27,38 +27,17 @@ if (iaView::REQUEST_HTML == $iaView->getRequestType()) {
list($orderData, , $messages, ) = $iaField->parsePost($iaOrder->getItemName(), $order);
$requiredFields = ['buyer_name', 'phone'];
foreach ($_POST['buyer'] as $key => $value) {
$orderData['buyer_' . $key] = $value;
if (empty($value) && in_array($key, $requiredFields))
{
$messages[] = iaLanguage::getf('field_is_empty', ['field' => iaLanguage::get($key)]);
}
}
$orderData['comment'] = iaSanitize::tags(trim($_POST['comment']));
$result = $iaOrder->save($orderData);
$order = $iaOrder->get();
if (empty($messages) && $result) {
$orderData = ['status' => iaOrder::PENDING];
if (isset($_POST['createaccount'])) {
$member = [
'email' => $order->buyer_email,
'fullname' => $order->buyer_first_name . ($order->buyer_last_name ? ' ' . $order->buyer_last_name : ''),
//'password' => $_POST['password']
'disable_fields' => true
];
$orderData['member_id'] = $iaCore->factory('users')->register($member);
}
$iaOrder->copyProductsFromCart();
$iaOrder->save($orderData);
iaHelper::sendEmail('order_placed', (array)$order);
$iaCore->factoryModule('notification', IA_CURRENT_MODULE, 'common')
->send('order_placed', (array)$order);
$iaCart->cleanup();
$iaOrder->cleanup();
......@@ -76,12 +55,16 @@ if (iaView::REQUEST_HTML == $iaView->getRequestType()) {
return;
} else {
$order = array_merge((array)$order, $orderData);
$iaView->setMessages($messages);
}
}
$order = (array)$order;
$iaView->assign('cartUrl', $iaPage->getUrlByName('cart'));
$iaView->assign('itemName', $iaProduct->getItemName());
$iaView->assign('order', (array)$order);
$iaView->assign('itemSections', $iaField->getGroupsFiltered($iaOrder->getItemName(), $order));
$iaView->assign('item', $order);
$iaView->assign('products', $cart->items);
}
\ No newline at end of file
<?php
//##copyright##
class iaOrder extends abstractModuleAdmin
{
const INCOMPLETE = 'incomplete';
const PENDING = 'pending';
const CANCELED = 'canceled';
const COMPLETED = 'completed';
const SHIPPED = 'shipped';
protected static $_table = 'orders';
protected $_tableItems = 'orders_items';
protected $_itemName = 'orders';
protected $_statuses = [self::INCOMPLETE, self::PENDING, self::CANCELED, self::COMPLETED];
public function getTableItems()
{
return $this->_tableItems;
}
public function getById($id, $decorate = true)
{
$result = parent::getById($id, $decorate);
if ($result) {
//$result['member'] =
$result['products'] = $this->getItemsByOrderId($id);
}
return $result;
}
public function getItemsByOrderId($orderId)
{
return $this->iaDb->all(iaDb::ALL_COLUMNS_SELECTION, iaDb::convertIds($orderId, 'order_id'), null, null, $this->getTableItems());
}
public function delete($itemId)
{
$result1 = parent::delete($itemId);
$result2 = $this->iaDb->delete(iaDb::convertIds($itemId, 'order_id'), $this->getTableItems());
return $result1 && $result2;
}
}
\ No newline at end of file
<?php
//##copyright##
class iaHelper extends abstractCore
{
public static function sendEmail($event, array $data, $data2 = null)
{
iaCore::instance()->loadClass('common', 'mailer', 'commerce');
return iaEmailHelper::send($event, $data, $data2);
}
}
\ No newline at end of file
<?php
//##copyright##
class iaEmailHelper
class iaNotification extends abstractCore
{
protected static $_moduleName = 'commerce';
public static function send($eventType, $data, $data2 = null)
public function send($eventType, $data, $data2 = null)
{
$emailsOptions = [
'order_placed' => true
];
$iaCore = iaCore::instance();
$params = [];
$addressee = [];
$result = true;
if (!$iaCore->get(self::$_moduleName . '_' . $eventType))
if (!$this->iaCore->get(self::$_moduleName . '_' . $eventType))
{
return $result;
}
$iaMailer = $iaCore->factory('mailer');
$iaMailer = $this->iaCore->factory('mailer');
switch ($eventType)
{
......@@ -31,7 +29,7 @@ class iaEmailHelper
$addressee[$data['buyer_email']] = $data['buyer_name'];
$params['order'] = $data;
$params['items'] = $iaCore->factoryModule('order', self::$_moduleName)->getItemsByOrderId($data['id']);
$params['items'] = $this->iaCore->factoryModule('order', self::$_moduleName)->getItemsByOrderId($data['id']);
}
if ($emailsOptions[$eventType]) {
......
......@@ -102,8 +102,7 @@ class iaOrder extends abstractModuleFront
'category_id' => $entry['category_id'],
'title' => $entry['title'],
'price' => $entry['price'],
'discount' => 0,
'quantity' => $entry['qty'],
'qty' => $entry['qty'],
'price_total' => $finalPrice
];
......@@ -121,8 +120,8 @@ class iaOrder extends abstractModuleFront
$sql =
'SELECT '
. 'i.*, '
. 'p.`alias`, p.`pictures`, '
. 'c.`url` `category_slug` '
. 'p.`slug`, p.`pictures`, '
. 'c.`slug` `category_slug` '
. 'FROM `:prefix:table_items` i '
. 'LEFT JOIN `:prefix:table_products` p ON (p.`id` = i.`product_id`) '
. 'LEFT JOIN `:prefix:table_categories` c ON (c.`id` = i.`category_id`) '
......
......@@ -80,6 +80,7 @@
<group item="categories" name="seo" title="SEO"><![CDATA[]]></group>
<group item="orders" name="buyer" title="Buyer"><![CDATA[]]></group>
<group item="orders" name="other" title="Other"><![CDATA[]]></group>
</fields_groups>
<fields>
......@@ -96,23 +97,28 @@
<field item="categories" group="seo" name="meta_description" type="textarea" length="255" adminonly="1" editable="0" multilingual="1">Meta-Description</field>
<field item="categories" group="seo" name="meta_keywords" type="text" length="255" adminonly="1" editable="0" multilingual="1">Meta-Keywords</field>
<field item="orders" group="buyer" name="buyer_name" type="text" required="1" length="92">Full Name</field>
<field item="orders" group="buyer" name="buyer_email" type="text" required="1" length="64">Email</field>
<field item="orders" group="buyer" name="buyer_phone" type="text" required="1" length="16">Phone</field>
<field item="orders" group="buyer" name="buyer_name" type="text" required="1" editable="0" length="92" page="checkout">Full Name</field>
<field item="orders" group="buyer" name="buyer_email" type="text" required="1" editable="0" length="64" page="checkout">Email</field>
<field item="orders" group="buyer" name="buyer_phone" type="text" required="1" editable="0" length="16" page="checkout">Phone</field>
<field item="orders" group="other" name="comment" type="textarea" editable="0" length="5000" page="checkout">Comment</field>
</fields>
<phrases>
<phrase category="admin" key="add_category">Add Category</phrase>
<phrase category="admin" key="add_product">Add Product</phrase>
<phrase category="admin" key="buyer">Buyer</phrase>
<phrase category="admin" key="commerce_package">&quot;Commerce&quot; Package</phrase>
<phrase category="admin" key="do_you_want_to_delete_selected_products">Do you really want to delete MULTIPLE products permanently?</phrase>
<phrase category="admin" key="do_you_want_to_delete_this_category">Do you really want to delete this category and all of its subcategories?</phrase>
<phrase category="admin" key="do_you_want_to_delete_this_product">Do you really want to delete this product permanently?</phrase>
<phrase category="admin" key="do_you_want_to_remove_order">Do you really want to permanently remove this order?</phrase>
<phrase category="admin" key="edit_category">Edit Category</phrase>
<phrase category="admin" key="edit_product">Edit Product</phrase>
<phrase category="admin" key="order_removed">Order removed.</phrase>
<phrase category="admin" key="priority">Priority</phrase>
<phrase category="admin" key="product_with_similar_slug_exists_in_category">Product with the same slug already exists in category.</phrase>
<phrase category="common" key="order_details">Order Details</phrase>
<phrase category="common" key="orders">Orders</phrase>
<phrase category="common" key="out_of_stock">Out of Stock</phrase>
<phrase category="common" key="price">Price</phrase>
......@@ -123,13 +129,14 @@
<phrase category="common" key="total">Total</phrase>
<phrase category="frontend" key="add_to_cart">Add to Cart</phrase>
<phrase category="frontend" key="buyer_info">Buyer Info</phrase>
<phrase category="frontend" key="cart_is_empty">Your cart is currently empty</phrase>
<phrase category="frontend" key="checkout">Checkout</phrase>
<phrase category="frontend" key="go_to_shopping_cart">Go to Cart</phrase>
<phrase category="frontend" key="no_products">No products.</phrase>
<phrase category="frontend" key="num_items_added_to_cart">:num items added to cart</phrase>
<phrase category="frontend" key="order_details">Order Details</phrase>
<phrase category="frontend" key="order_summary">Order Summary</phrase>
<phrase category="frontend" key="place_order">Place Order</phrase>
<phrase category="frontend" key="product_added_to_cart">Product added to your shopping cart</phrase>
<phrase category="frontend" key="products_count">:count Products</phrase>
<phrase category="frontend" key="qty">Qty</phrase>
......@@ -139,6 +146,7 @@
<phrase category="frontend" key="sorting_option_price">Price: low to high</phrase>
<phrase category="frontend" key="sorting_option_price-desc">Price: high to low</phrase>
<phrase category="frontend" key="sorting_option_title">Title</phrase>
<phrase category="frontend" key="thank_you_for_order">Thank you for your order!</phrase>
<phrase category="frontend" key="update_cart">Update Cart</phrase>
</phrases>
......
Ext.onReady(function()
{
var grid = new IntelliGrid({
columns:[
'selection',
'expander',
{name: 'buyer_name', title: _t('buyer'), width: 1},
{name: 'date_added', title: _t('added_date'), hidden: true},
{name: 'total', title: _t('amount'), width: 100},
{name: 'items_num', title: _t('products'), width: 70},
'status',
{name: 'view', title: _t('details'), icon: 'eye', href: intelli.config.admin_url + '/commerce/orders/view/{id}/'}
],
expanderTemplate: '{comment}',
fields: ['comment'],
sorters: [{property: 'date_added', direction: 'DESC'}],
statuses: ['pending', 'canceled', 'shipped', 'completed']
}, false);
grid.toolbar = new Ext.Toolbar({items:[
{
emptyText: _t('buyer'),
name: 'buyer_name',
listeners: intelli.gridHelper.listener.specialKey,
width: 200,
xtype: 'textfield'
},{
displayField: 'title',
editable: false,
emptyText: _t('status'),
id: 'fltStatus',
name: 'status',
store: grid.stores.statuses,
typeAhead: true,
valueField: 'value',
xtype: 'combo'
},{
handler: function(){intelli.gridHelper.search(grid);},
id: 'fltBtn',
text: '<i class="i-search"></i> ' + _t('search')
},{
handler: function(){intelli.gridHelper.search(grid, true);},
text: '<i class="i-close"></i> ' + _t('reset')
}]});
grid.init();
});
\ No newline at end of file
<form method="post" class="sap-form form-horizontal">
{preventCsrf}
<div class="wrap-list">
<div class="wrap-group">
<div class="wrap-group-heading">
<h4>{lang key='general'}</h4>
</div>
<div class="row">
<label class="col col-lg-2 control-label">{lang key='status'}</label>
<div class="col col-lg-4">
{lang key=$item.status}
</div>
</div>
<div class="row">
<label class="col col-lg-2 control-label">{lang key='date'}</label>
<div class="col col-lg-4">{$item.date_added|date_format:$core.config.date_format}</div>
</div>
<div class="row">
<label class="col col-lg-2 control-label">{lang key='buyer'}</label>
<div class="col col-lg-4">
<p><i class="i-address-book"></i>
{$item.buyer_name|escape}
</p>
<p><i class="i-newspaper"></i>
{$item.buyer_phone|escape}
</p>
{if $item.buyer_email}<p><i class="i-envelop"></i>
{$item.buyer_email}
</p>
{/if}
{if $buyer}
<p style="margin-top: 16px;"><small class="muted">Ordered under member</small>
<a href="{$smarty.const.ADMIN_URL}members/edit/{$item.member_id}/" target="_blank">{$buyer.fullname}</a> ({$buyer.username})</p>
{/if}
</div>
</div>
{if $item.comment}
<div class="row">
<label class="col col-lg-2 control-label">{lang key='comment'}</label>
<div class="col col-lg-4">{$item.comment|escape|nl2br}</div>
</div>
{/if}
</div>
<div class="wrap-group">
<div class="wrap-group-heading">
<h4><i class="i-coin"></i> {lang key='financial'}</h4>
</div>
<div class="row">
<label class="col col-lg-2 control-label">{lang key='total'}</label>
<div class="col col-lg-4">
{$item.total}
</div>
</div>
</div>
<div class="wrap-group">
<div class="wrap-group-heading">
<h4><i class="i-tags"></i> {lang key='products'}</h4>
</div>
<table class="table table-hover">
<thead>
<tr>
<th width="30"></th>
<th>{lang key='product'}</th>
<th width="100">{lang key='price'}</th>
<th width="80" class="text-right">{lang key='quantity'}</th>
</tr>
</thead>
<tbody>
{foreach $item.products as $i => $entry}
<tr>
<td>{$i + 1}</td>
<td>
<strong>{$entry.title|escape}</strong>
</td>
<td>{$entry.price}</td>
<td class="text-right">{$entry.qty}</td>
</tr>
{/foreach}
</tbody>
</table>
</div>
<div class="form-actions text-right">
<button class="btn btn-primary pull-left" type="submit">{lang key='save'}</button>
<a class="btn btn-danger js-cmd-delete" href="{$path}remove/{$item.id}/"><i class="i-remove"></i> {lang key='permanently_delete_order'}</a>
</div>
</div>
</form>
{ia_hooker name='smartyAdminSubmitItemBeforeFooter'}
{ia_add_js}
$(function()
{
$('.js-cmd-delete').on('click', function(e)
{
confirm(_t('do_you_want_to_remove_order')) || e.preventDefault();
});
});
{/ia_add_js}
\ No newline at end of file
......@@ -46,21 +46,17 @@
<table>
<tbody>
<tr>
<th>{lang key='buyer'}:</th>
<th>{lang key='field_orders_buyer_name'}:</th>
<td>{$order.buyer_name|escape}</td>
</tr>
<tr>
<th>{lang key='email'}:</th>
<th>{lang key='field_orders_buyer_email'}:</th>
<td>{$order.buyer_email|escape}</td>
</tr>
<tr>
<th>{lang key='phone'}:</th>
<th>{lang key='field_orders_buyer_phone'}:</th>
<td>{$order.buyer_phone|escape}</td>
</tr>
<tr>
<th>Адрес:</th>
<td>{$order.shipping_street|escape}{if $order.shipping_building}, {$order.shipping_building|escape}{/if}</td>
</tr>
</tbody>
</table>
</div>
\ No newline at end of file
<div class="tab-pane ia-form">
<div class="fieldset">
<h3 class="title">{lang key='buyer_info'}</h3>
<form method="post">
<div class="tab-pane ia-form">
<div class="fieldset">
<h3 class="title">{lang key='buyer_info'}</h3>
<form method="post">
<div class="form-group">
<label>{lang key='field_orders_buyer_name'}</label>
<input type="text" class="form-control" name="buyer_name">
</div>
<div class="form-group">
<label>{lang key='field_orders_buyer_email'}</label>
<input type="email" class="form-control" name="buyer_email">
</div>
<div class="form-group">
<label>{lang key='field_orders_buyer_phone'}</label>
<input type="tel" class="form-control" name="buyer_phone">
</div>
</form>
</div>
{include 'field-type-content-fieldset.tpl' item_sections=$itemSections}
</div>
<div class="fieldset">
<h3 class="title">{lang key='order_summary'}</h3>
<div class="fieldset-wrapper content">
<dl class="dl-horizontal">
<dt>{lang key='total'}</dt>
<dd>{$order.total|number_format} {$core.config.currency}</dd>
</dl>
<div class="fieldset">
<h3 class="title">{lang key='order_summary'}</h3>
<div class="fieldset-wrapper content">
<dl class="dl-horizontal">
<dt>{lang key='total'}</dt>
<dd>{$item.total|number_format} {$core.config.currency}</dd>
</dl>
</div>
</div>
</div>
<div class="fieldset">
<h3 class="title">{lang key='products'}</h3>
<div class="fieldset">
<h3 class="title">{lang key='products'}</h3>
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th width="80">{lang key='price'}</th>
<th width="50">{lang key='quantity'}</th>
<th width="90" class="text-right">{lang key='total'}</th>
</tr>
</thead>
<tbody>
{foreach $products as $item}
{include 'extra:commerce/list-checkout'}
{/foreach}
</tbody>
</table>
</div>
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th width="80">{lang key='price'}</th>
<th width="50">{lang key='quantity'}</th>
<th width="90" class="text-right">{lang key='total'}</th>
</tr>
</thead>
<tbody>
{foreach $products as $item}
{include 'extra:commerce/list-checkout'}
{/foreach}
</tbody>
</table>
</div>
<div class="form-actions">
<a class="btn btn-default" href="{$cartUrl}"><i class="icon-chevron-left"></i> {lang key='back_to_shopping_cart'}</a>
<button type="submit" class="btn btn-primary pull-right">{lang key='next'} <i class="icon-chevron-right"></i></button>
<div class="form-actions">
<a class="btn btn-default" href="{$cartUrl}"><i class="icon-chevron-left"></i> {lang key='back_to_shopping_cart'}</a>
<button type="submit" name="data-checkout" class="btn btn-primary pull-right">{lang key='place_order'} <i class="icon-chevron-right"></i></button>
</div>
</div>
</div>
\ No newline at end of file
</form>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment