Создание панели модератора и доработка уведомлений

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-05-25 06:06:55 +10:00
parent 248f5470f9
commit 4f8a99d8e2
17 changed files with 494 additions and 72 deletions

View File

@ -36,10 +36,15 @@ class CartController extends Controller
// Инициализация // Инициализация
$model = new Order(); $model = new Order();
$model->save() or throw new Exception('Не удалось инициализировать заказ');
// Подключение if ($model->save()) {
$model->connect($account); // Удалось инициализировать заказ
// Подключение заказа к аккаунту
$model->connect($account);
} else {
throw new Exception('Не удалось инициализировать заказ');
}
} }
// Инициализация содержимого корзины // Инициализация содержимого корзины

View File

@ -12,6 +12,8 @@ use yii\web\Cookie;
use app\models\Order; use app\models\Order;
use app\models\AccountEdgeOrder; use app\models\AccountEdgeOrder;
use app\models\Notification;
use Codeception\PHPUnit\ResultPrinter\HTML;
use Exception; use Exception;
class OrderController extends Controller class OrderController extends Controller
@ -71,6 +73,7 @@ class OrderController extends Controller
{ {
// Инициализация // Инициализация
$orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}'); $orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}');
$moderator_orders = self::genOrdersForModeration();
if (yii::$app->request->isPost) { if (yii::$app->request->isPost) {
// POST-запрос // POST-запрос
@ -78,14 +81,14 @@ class OrderController extends Controller
yii::$app->response->format = Response::FORMAT_JSON; yii::$app->response->format = Response::FORMAT_JSON;
return [ return [
'main' => $this->renderPartial('/orders/index', compact('orders')), 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders')),
'title' => 'Заказы', 'title' => 'Заказы',
'redirect' => '/orders', 'redirect' => '/orders',
'_csrf' => yii::$app->request->getCsrfToken() '_csrf' => yii::$app->request->getCsrfToken()
]; ];
} }
return $this->render('/orders/index', compact('orders')); return $this->render('/orders/index', compact('orders', 'moderator_orders'));
} }
/** /**
@ -313,13 +316,21 @@ class OrderController extends Controller
$edge = $edge[0]; $edge = $edge[0];
// Запись // Запись
$edge->type = 'accepted'; $edge->type = 'requested';
// Отправка изменений if ($edge->update()) {
$edge->update(); // Удалось сохранить изменения
// Запись в журнал
$model->journal('requested');
// Отправка уведомлений модераторам
Notification::_write($this->renderPartial('/notification/system/newOrder', ['id' => $edge->_key]), true, '@auth', Notification::TYPE_MODERATOR_ORDER_NEW);
}
// Инициализация // Инициализация
$orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}'); $orders = Order::search(type: 'all', limit: 30, page: 1, select: '{account_edge_order, order}');
$moderator_orders = Order::search(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}');
if (yii::$app->request->isPost) { if (yii::$app->request->isPost) {
// POST-запрос // POST-запрос
@ -327,13 +338,32 @@ class OrderController extends Controller
yii::$app->response->format = Response::FORMAT_JSON; yii::$app->response->format = Response::FORMAT_JSON;
return [ return [
'main' => $this->renderPartial('/orders/index', compact('orders')), 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders')),
'title' => 'Заказы', 'title' => 'Заказы',
'redirect' => '/orders', 'redirect' => '/orders',
'_csrf' => yii::$app->request->getCsrfToken() '_csrf' => yii::$app->request->getCsrfToken()
]; ];
} }
return $this->render('/orders/index', compact('orders')); return $this->render('/orders/index', compact('orders', 'moderator_orders'));
}
/**
* Генерация данных заказов для модераторов
*
* Включает поиск запрошенных заказов и связанных с ними поставках
*
* @return array ['order' => array, 'order_edge_account' => array, 'supplies' => array]
*/
protected static function genOrdersForModeration(int $page = 1): array {
$orders = Order::search(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}');
foreach ($orders as &$order) {
// Перебор заказов
$order['supplies'] = Order::searchById($order['order']['_id'])->content(10, $page);
}
return $orders;
} }
} }

View File

@ -215,6 +215,30 @@ class Account extends Document implements IdentityInterface, PartnerInterface
return static::searchById($_id); return static::searchById($_id);
} }
/**
* Чтение всех модераторов
*/
public static function readAllModerators(): array
{
return static::find()->where(['type' => 'moderator'])->all();
}
/**
* Чтение всех администраторов
*/
public static function readAllAdministrators(): array
{
return static::find()->where(['type' => 'administrator'])->all();
}
/**
* Чтение всех уполномоченных аккаунтов
*/
public static function readAllAuthorizeds(): array
{
return static::find()->where(['type' => 'moderator'])->orWhere(['type' => 'administrator'])->all();
}
/** /**
* Проверка почты * Проверка почты
*/ */

View File

@ -29,20 +29,25 @@ class Notification extends Document
const SCENARIO_TRUSTED_CREATE = 'create'; const SCENARIO_TRUSTED_CREATE = 'create';
/** /**
* Тип уведомления: памятка * Уведомление: "памятка"
*/ */
const TYPE_NOTICE = 'notice'; const TYPE_NOTICE = 'notice';
/** /**
* Тип уведомления: предупреждение * Уведомление: "предупреждение"
*/ */
const TYPE_WARNING = 'warning'; const TYPE_WARNING = 'warning';
/** /**
* Тип уведомления: ошибка * Уведомление: "ошибка"
*/ */
const TYPE_ERROR = 'error'; const TYPE_ERROR = 'error';
/**
* Уведомление для модераторов: "новый заказ"
*/
const TYPE_MODERATOR_ORDER_NEW = 'new order';
/** /**
* Цель для отправки уведомления * Цель для отправки уведомления
* *
@ -192,7 +197,7 @@ class Notification extends Document
foreach ($accounts as $account) { foreach ($accounts as $account) {
if (in_array('@all', $accounts, true)) { if (in_array('@all', $accounts, true)) {
// Найден флаг обозначающий отправку всем пользователям // Всем пользователям
// Инициализация // Инициализация
$return = []; $return = [];
@ -200,11 +205,64 @@ class Notification extends Document
foreach (Account::readAll() as $account) { foreach (Account::readAll() as $account) {
// Перебор всех аккаунтов // Перебор всех аккаунтов
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
$return[] = AccountEdgeNotification::writeSafe($model->readId(), $account->readId(), $type);
}
} else if (
in_array('@authorized', $accounts, true)
|| in_array('@authorizeds', $accounts, true)
|| in_array('@authorised', $accounts, true)
|| in_array('@authoriseds', $accounts, true)
|| in_array('@auth', $accounts, true)
|| in_array('@autheds', $accounts, true)
) {
// Всем авторизованным
// Инициализация
$return = [];
foreach (Account::readAllAuthorizeds() as $account) {
// Перебор всех аккаунтов
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
$return[] = AccountEdgeNotification::writeSafe($model->readId(), $account->readId(), $type);
}
} else if (
in_array('@administrator', $accounts, true)
|| in_array('@administrators', $accounts, true)
|| in_array('@admin', $accounts, true)
|| in_array('@admins', $accounts, true)
) {
// Администраторам
// Инициализация
$return = [];
foreach (Account::readAllAdministrators() as $account) {
// Перебор всех аккаунтов
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
$return[] = AccountEdgeNotification::writeSafe($model->readId(), $account->readId(), $type);
}
} else if (
in_array('@moderator', $accounts, true)
|| in_array('@moderators', $accounts, true)
|| in_array('@moder', $accounts, true)
|| in_array('@moders', $accounts, true)
) {
// Модераторам
// Инициализация
$return = [];
foreach (Account::readAllModerators() as $account) {
// Перебор всех аккаунтов
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ // Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
$return[] = AccountEdgeNotification::writeSafe($model->readId(), $account->readId(), $type); $return[] = AccountEdgeNotification::writeSafe($model->readId(), $account->readId(), $type);
} }
} else if (in_array('@test', $accounts, true)) { } else if (in_array('@test', $accounts, true)) {
// Найден флаг обозначающий тестирование (отправка самому себе) // Тестирование (отправка самому себе)
$return[] = AccountEdgeNotification::writeSafe($model->readId(), yii::$app->user->id, $type); $return[] = AccountEdgeNotification::writeSafe($model->readId(), yii::$app->user->id, $type);
} else { } else {

View File

@ -236,33 +236,51 @@ class Order extends Document implements DocumentInterface
/** /**
* Поиск заказа * Поиск заказа
*/ */
public static function search(Account $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null): self|array|null public static function search(Account|string $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null): self|array|null
{ {
// Инициализация // Инициализация аккаунта
$account or $account = yii::$app->user->identity ?? throw new Exception('Не удалось инициализировать пользователя'); if (empty($account) && isset(yii::$app->user->identity)) {
// Данные не переданы
// Генерация сдвига по запрашиваемым данным (пагинация) $subquery_where = [
$offset = $limit * ($page - 1); [
'account._id' => yii::$app->user->identity->readId()
if (strcasecmp($type, 'all') !== 0) { ]
// Если не указан параметр поиска всех заказов
$where_type = [
'account_edge_order.type' => $type
]; ];
} else if ($account instanceof Account) {
// Передан аккаунт
$subquery_where = [
[
'account._id' => $account->readId()
]
];
} else if (str_contains($account, '@all')) {
// Запрос на обработку всех аккаунтов
$subquery_where = [];
} else { } else {
$where_type = []; throw new Exception('Не удалось инициализировать пользователя');
} }
// Инициализация типа заказа
if (strcasecmp($type, 'all') !== 0) {
// Если не указан поиск всех заказов
$subquery_where[] = [
'account_edge_order.type' => $type
];
}
// Инициализация сдвига по запрашиваемым данным (пагинация)
$offset = $limit * ($page - 1);
// Запрос
$return = self::searchByEdge( $return = self::searchByEdge(
from: 'account', from: 'account',
to: 'order', to: 'order',
subquery_where: [ subquery_where: $subquery_where,
[
'account._id' => $account->readId()
],
$where_type
],
foreach: ['edge' => 'account_edge_order'], foreach: ['edge' => 'account_edge_order'],
where: 'edge._to == order._id', where: 'edge._to == order._id',
limit: $limit, limit: $limit,
@ -366,8 +384,7 @@ class Order extends Document implements DocumentInterface
// Поиск привязанного товара // Поиск привязанного товара
$connection['product'] = Product::searchBySupplyId($connection['supply']['_id']); $connection['product'] = Product::searchBySupplyId($connection['supply']['_id']);
try try {
{
// Инициализация доставки Dellin (автоматическая) // Инициализация доставки Dellin (автоматическая)
$connection['delivery']['auto'] = Dellin::calcDeliveryAdvanced( $connection['delivery']['auto'] = Dellin::calcDeliveryAdvanced(
explode('_', $connection['account']['opts']['delivery_from_terminal'])[1], explode('_', $connection['account']['opts']['delivery_from_terminal'])[1],
@ -385,10 +402,9 @@ class Order extends Document implements DocumentInterface
} }
// Запись цены (цена поставки + цена доставки + наша наценка) // Запись цены (цена поставки + цена доставки + наша наценка)
$connection['cost']['auto'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['auto']['price']['all'] ?? $connection['delivery']['auto']['price']['one'] ?? 0) + ($settings['increase'] ?? 0); $connection['cost']['auto'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['auto']['price']['all'] ?? $connection['delivery']['auto']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
try try {
{
// Инициализация доставки Dellin (автоматическая) // Инициализация доставки Dellin (автоматическая)
$connection['delivery']['avia'] = Dellin::calcDeliveryAdvanced( $connection['delivery']['avia'] = Dellin::calcDeliveryAdvanced(
explode('_', $connection['account']['opts']['delivery_from_terminal'])[1], explode('_', $connection['account']['opts']['delivery_from_terminal'])[1],
@ -403,11 +419,11 @@ class Order extends Document implements DocumentInterface
} catch (Exception $e) { } catch (Exception $e) {
$connection['delivery']['avia']['error'] = true; $connection['delivery']['avia']['error'] = true;
var_dump(json_decode($e->getMessage(), true)['errors']); die; // var_dump(json_decode($e->getMessage(), true)['errors']); die;
} }
// Запись цены (цена поставки + цена доставки + наша наценка) // Запись цены (цена поставки + цена доставки + наша наценка)
$connection['cost']['avia'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['avia']['price']['all'] ?? $connection['delivery']['avia']['price']['one'] ?? 0) + ($settings['increase'] ?? 0); $connection['cost']['avia'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['avia']['price']['all'] ?? $connection['delivery']['avia']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
// Запись валюты // Запись валюты
$connection['currency'] = $cost['Валюта']; $connection['currency'] = $cost['Валюта'];

View File

@ -118,6 +118,9 @@ class Dellin extends Model
$length = $z; $length = $z;
} }
// Инициализация
$query = [];
// Рассчёт типа доставки // Рассчёт типа доставки
if ( if (
$weight <= 30 $weight <= 30
@ -126,43 +129,46 @@ class Dellin extends Model
) { ) {
// Доставка категории "small" // Доставка категории "small"
$type = 'small'; $query['delivery']['deliveryType']['type'] = 'small';
$variant = 'address'; $query['delivery']['derival']['variant'] = 'address';
$query['delivery']['derival']['address']['search'] = $from;
$query['delivery']['derival']['time']['worktimeStart'] = '08:00';
$query['delivery']['derival']['time']['worktimeEnd'] = '20:00';
$query['delivery']['arrival']['variant'] = 'address';
$query['delivery']['arrival']['address']['search'] = $to;
$query['delivery']['arrival']['time']['worktimeStart'] = '08:00';
$query['delivery']['arrival']['time']['worktimeEnd'] = '20:00';
} else { } else {
// Доставка категории "auto" // Доставка категории "auto"
if ($avia) { if ($avia) {
// Рассчет для доставки по воздуху // Рассчет для доставки по воздуху
// Ограничение на минимальный вес
$weight <= 0.5 and $weight = 0.5; $weight <= 0.5 and $weight = 0.5;
$type = 'avia';
$query['delivery']['deliveryType']['type'] = 'avia';
} else { } else {
// Рассчет для доставки по земле // Рассчет для доставки по земле
$type = 'auto'; $query['delivery']['deliveryType']['type'] = 'auto';
} }
$variant = 'terminal'; $query['delivery']['derival']['variant'] = 'terminal';
$query['delivery']['derival']['terminalID'] = $from;
$query['delivery']['arrival']['variant'] = 'terminal';
$query['delivery']['arrival']['terminalID'] = $to;
} }
// Запрос // Инициализация
$request = self::$browser->post('/v2/calculator.json', [ $query = array_merge_recursive(
'json' => [ $query,
[
'appkey' => yii::$app->params['dellin']['key'], 'appkey' => yii::$app->params['dellin']['key'],
'sessionID' => self::$session, 'sessionID' => self::$session,
'delivery' => [ 'delivery' => [
'deliveryType' => [
'type' => $type
],
'derival' => [ 'derival' => [
'produceDate' => date('Y-m-d', time() + ($settings['delivery_handle_time'] ?? 86400)), 'produceDate' => date('Y-m-d', time() + ($settings['delivery_handle_time'] ?? 86400))
'variant' => $variant,
'terminalID' => $from,
],
'arrival' => [
'variant' => $variant,
'terminalID' => $to
] ]
], ],
'members' => [ 'members' => [
@ -182,6 +188,11 @@ class Dellin extends Model
'oversizedVolume' => $x * $y * $z 'oversizedVolume' => $x * $y * $z
] ]
] ]
);
// Запрос
$request = self::$browser->post('/v2/calculator.json', [
'json' => $query
]); ]);
if ($request->getStatusCode() === 200) { if ($request->getStatusCode() === 200) {

View File

@ -43,11 +43,15 @@ use DateTime;
if (isset($connection['delivery']['auto']['error'])) { if (isset($connection['delivery']['auto']['error'])) {
// Не удалось рассчитать доставку // Не удалось рассчитать доставку
// Инициализация времени
$delivery_auto = '?'; $delivery_auto = '?';
// Инициализация цены
$cost_auto = '?';
} else { } else {
// Удалось рассчитать доставку // Удалось рассчитать доставку
// Инициализация // Инициализация времени
$delivery_auto = ceil((DateTime::createFromFormat('Y-m-d', $connection['delivery']['auto']['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24) + 1; $delivery_auto = ceil((DateTime::createFromFormat('Y-m-d', $connection['delivery']['auto']['orderDates']['arrivalToOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24) + 1;
// Инициализация цены // Инициализация цены
@ -58,10 +62,15 @@ use DateTime;
if (isset($connection['delivery']['avia']['error'])) { if (isset($connection['delivery']['avia']['error'])) {
// Не удалось рассчитать доставку // Не удалось рассчитать доставку
// Инициализация времени
$delivery_avia = '?'; $delivery_avia = '?';
// Инициализация цены
$cost_avia = '?';
} else { } else {
// Удалось рассчитать доставку // Удалось рассчитать доставку
// Инициализация времени
$delivery_avia = ceil((DateTime::createFromFormat('Y-m-d H:i:s', $connection['delivery']['avia']['orderDates']['giveoutFromOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24) + 1; $delivery_avia = ceil((DateTime::createFromFormat('Y-m-d H:i:s', $connection['delivery']['avia']['orderDates']['giveoutFromOspReceiver'])->getTimestamp() - time()) / 60 / 60 / 24) + 1;
// Инициализация цены // Инициализация цены

View File

@ -1,2 +1 @@
<p>Импортированы товары из 1C <span>(<?= $date ?>)</span></p>
<p>Импортированы товары из 1C <span>(<?= $date ?>)</span></p>

View File

@ -0,0 +1 @@
<a href="orders#<?= $id ?>">Новый заказ</a>

View File

@ -33,7 +33,7 @@
<p><b class="mr-1">4</b> Гарантия, условия возврата</p> <p><b class="mr-1">4</b> Гарантия, условия возврата</p>
</h5> </h5>
<p class="ml-3"><b>4.1</b> Комплектность товара проверяется торговой площадкой при получении на складе торговой площадкой</p> <p class="ml-3"><b>4.1</b> Комплектность товара проверяется торговой площадкой при получении на складе торговой площадкой</p>
<p class="ml-3"><b>4.2</b> Поставщик гарантирует приём возврата некачественного, <u>а так же</u> некомплектного товара в течение 60 дней</p> <p class="ml-3"><b>4.2</b> Поставщик гарантирует приём возврата некачественного, а так же некомплектного товара в течение 60 дней</p>
<p class="ml-3"><b>4.3</b> Выявленные расхождения в поставке, возврат товара отражаются сообщаются поставщику на адрес электронной почты указанную при регистрации</p> <p class="ml-3"><b>4.3</b> Выявленные расхождения в поставке, возврат товара отражаются сообщаются поставщику на адрес электронной почты указанную при регистрации</p>
<p class="ml-3"><b>4.4</b> Поставщик даёт согласие и гарантирует законность сбора/обработки/хранения и передачи сведений, в т. ч. персональных данных, которые поставщик указывает в системе сайта</p> <p class="ml-3"><b>4.4</b> Поставщик даёт согласие и гарантирует законность сбора/обработки/хранения и передачи сведений, в т. ч. персональных данных, которые поставщик указывает в системе сайта</p>
</br> </br>
@ -41,7 +41,7 @@
<p><b class="mr-1">5</b> Иные условия</p> <p><b class="mr-1">5</b> Иные условия</p>
</h5> </h5>
<p class="ml-3"><b>5.1</b> Все споры решаются путём переговоров, в ином случае в Арбитражном суде города Хабаровск</p> <p class="ml-3"><b>5.1</b> Все споры решаются путём переговоров, в ином случае в Арбитражном суде города Хабаровск</p>
<p class="ml-3"><b>5.2</b> Настоящий договор-оферта может быть расторгнут: - по инициативе поставщика путём направления соответствующего сообщения в систему сайта либо на <u>электронный адрес</u> указанный ниже в теле текста настоящего договора-оферты; - по инициативе торговой площадки путём направления соответствующего сообщения через систему сайта, либо на адрес электронной почты указанной поставщиком при регистрации</p> <p class="ml-3"><b>5.2</b> Настоящий договор-оферта может быть расторгнут: - по инициативе поставщика путём направления соответствующего сообщения в систему сайта либо на электронный адрес указанный ниже в теле текста настоящего договора-оферты; - по инициативе торговой площадки путём направления соответствующего сообщения через систему сайта, либо на адрес электронной почты указанной поставщиком при регистрации</p>
<p class="ml-3"><b>5.3</b> Изменения оферты вступают в силу с момента их публикации</p> <p class="ml-3"><b>5.3</b> Изменения оферты вступают в силу с момента их публикации</p>
<p class="ml-3"><b>5.4</b> Стороны информированы о ранее действующих версиях оферт</p> <p class="ml-3"><b>5.4</b> Стороны информированы о ранее действующих версиях оферт</p>
</br> </br>

View File

@ -1,7 +1,174 @@
<?php
declare(strict_types=1);
use yii;
use yii\bootstrap\ActiveForm;
// Инициализация
if (
!yii::$app->user->isGuest
&& yii::$app->user->identity->type === 'administrator'
|| yii::$app->user->identity->type === 'moderator'
) {
$panel ?? $panel = 'orders_panel_moderation';
} else {
$panel ?? $panel = 'orders_panel_orders';
}
?>
<link href="/css/pages/orders.css" rel="stylesheet"> <link href="/css/pages/orders.css" rel="stylesheet">
<div id="page_orders" class="container mb-auto py-3"> <div id="page_orders" class="container mb-auto py-3">
<article class="py-3 px-4 rounded"> <?php if (
!yii::$app->user->isGuest
&& yii::$app->user->identity->type === 'administrator'
|| yii::$app->user->identity->type === 'moderator'
) : ?>
<div class="orders_panel_menu mb-2">
<label class="btn button_white mb-0 mr-2" for="orders_panel_moderation">Модерация</label>
<label class="btn button_white mb-0" for="orders_panel_orders">Мои заказы</label>
</div>
<input type="radio" id="orders_panel_moderation" name="main_panel" <?= $panel === 'orders_panel_moderation' ? 'checked' : null ?> />
<article>
<div class="orders_panel_moderation_menu mb-3">
<label class="btn btn-sm button_white mb-0 mr-2" for="orders_panel_moderation_all">Все</label>
<label class="btn btn-sm button_white mb-0 mr-2" for="orders_panel_moderation_requested">Запрошены</label>
<label class="btn btn-sm button_white mb-0 mr-2" for="orders_panel_moderation_handled">Обрабатываются</label>
<label class="btn btn-sm button_white mb-0" for="orders_panel_moderation_completed">Завершены</label>
</div>
<?php if (!empty($moderator_orders)) : ?>
<?php
// Инициализация счетчика заказов
$order_number = 1;
?>
<?php foreach ($moderator_orders as $order) : ?>
<div class="page_order_panel mb-3 py-3 px-4 rounded">
<h5 class="row mt-1 mb-3">
<?php
// Инициализация времени отправки заказа
$date = null;
foreach ($order['order']['jrnl'] as $entry) {
// Перебор записей в журнал
if ($entry['action'] === 'requested') {
if (empty($date) || $date <= $entry['date']) {
// Буфер не инициализирован или в него записано более старое событие
// Запись
$date = $entry['date'];
}
}
}
$date = [
'H:i' => date('H:i', $date),
'm.d.Y' => date('m.d.Y', $date)
];
?>
<p class="col-auto ml-1">#<?= $order['order']['_key'] ?></p>
<p class="col-auto mr-1">
<span class="mr-2"><?= $date['H:i'] ?? 'Неизвестно' ?></span>
<span><?= $date['m.d.Y'] ?? 'Неизвестно' ?></span>
</p>
</h5>
<div class="dropdown-divider mb-3"></div>
<div id="orders_panel_supplies_<?= $order_number ?>" class="row px-2 unselectable">
<div class="col-3">
<?php if (!empty($order['supplies'])) : ?>
<?php
// Инициализация счетчика поставок для отрисовки горизонтального разделителя
$count = 1;
?>
<?php foreach ($order['supplies'] as $supply) : ?>
<?php
// Инициализация обложки
$covr = null;
foreach ($imgs ?? [] as $img) {
// Перебор изображений для обложки
if ($img['covr'] ?? false) {
// Обложка найдена
$covr = $img['h150'];
break;
}
}
if (is_null($covr)) {
// Обложка не инициализирована
if (!$covr = $imgs[0]['h150'] ?? false) {
// Не удалось использовать первое изображение как обложку
// Запись обложки по умолчанию
$covr = '/img/covers/h150/product.png';
}
}
?>
<?php foreach ($supply['order_edge_supply'] as $part) : ?>
<a id="<?= $part['_id'] ?>" class="row p-2 px-0 rounded row_supply" type="button" onclick="return orders_supply_edit(this, <?= $order_number ?>);">
<img class="col-auto px-0 h-100 img-fluid rounded" src="<?= $covr ?>" />
<p class="col text-dark"><?= $supply['product']['catn'] ?></p>
</a>
<?php endforeach ?>
<?php if ($count++ < count($order['supplies'])) : ?>
<div class="dropdown-divider mb-2"></div>
<?php endif ?>
<?php endforeach ?>
<?php else : ?>
<div class="row">
<p>Поставки не найдены</p>
</div>
<?php endif ?>
</div>
<div id="orders_panel_edit_<?= $order_number ?>" class="col-6 d-flex">
<p class="my-auto">Выберите поставку</p>
</div>
<div id="orders_panel_info_<?= $order_number ?>" class="col-3 d-flex flex-column">
<?php
// Конвертация статуса заказа
$status = match ($order['account_edge_order'][0]['type']) {
'requested' => 'Запрошен',
'handled' => 'Обрабатывается',
'completed' => 'Завершен',
}
?>
<p class="row mt-0 mb-3 px-2"><b>Статус:</b> <span class="ml-auto"><?= $status ?></span></p>
<small class="row mt-auto mb-3 px-2">Здесь будет информация об общей цене и о максимальном сроке доставки которые будут меняться по мере настройки и подтверждения наличия поставок</small>
<a class="row mb-0 text-center text-white btn button_blue button_clean" type="button" onclick="return false;">Подтвердить</a>
</div>
</div>
</div>
<?php
// Обновление счетчика заказов
++$order_number;
?>
<?php endforeach ?>
<?php else : ?>
<div class="page_order_panel py-3 px-4 rounded">
<p class="text-center">Заказов нет</p>
</div>
<?php endif ?>
</article>
<input type="radio" id="orders_panel_orders" name="main_panel" <?= $panel === 'orders_panel_orders' ? 'checked' : null ?> />
<?php endif ?>
<article class="page_order_panel mt-3 py-3 px-4 rounded">
<h4 class="ml-4 mt-2 mb-4"><i class="fas fa-list mr-2"></i>Заказы</h4> <h4 class="ml-4 mt-2 mb-4"><i class="fas fa-list mr-2"></i>Заказы</h4>
<div class="col mb-4 list rounded overflow-hidden"> <div class="col mb-4 list rounded overflow-hidden">
<div class="row py-2"> <div class="row py-2">
@ -61,4 +228,11 @@
</article> </article>
</div> </div>
<script src="/js/orders.js" defer></script> <script src="/js/orders.js" defer></script>
<?php if (
!yii::$app->user->isGuest
&& (yii::$app->user->identity->type === 'administrator'
|| yii::$app->user->identity->type === 'moderator')
) : ?>
<script src="/js/orders_panel.js" defer></script>
<?php endif ?>

View File

@ -37,6 +37,7 @@
$catg ?? $catg = 'Категория'; $catg ?? $catg = 'Категория';
$covr = null; $covr = null;
// Инициализация обложки
foreach ($imgs ?? [] as $img) { foreach ($imgs ?? [] as $img) {
// Перебор изображений для обложки // Перебор изображений для обложки
@ -53,6 +54,9 @@
// Обложка не инициализирована // Обложка не инициализирована
if (!$covr = $imgs[0]['h150'] ?? false) { if (!$covr = $imgs[0]['h150'] ?? false) {
// Не удалось использовать первое изображение как обложку
// Запись обложки по умолчанию
$covr = '/img/covers/h150/product.png'; $covr = '/img/covers/h150/product.png';
} }
} }

View File

@ -95,7 +95,7 @@ AppAsset::register($this);
</div> </div>
<div class="row"> <div class="row">
<?= Html::submitButton('Отправить', ['name' => 'submitRequest', 'id' => 'request-button-send', 'class' => 'col-auto mx-auto btn button_white button_clean']) ?> <?= Html::submitButton('Отправить', ['name' => 'submitRequest', 'id' => 'request-button-send', 'class' => 'col-auto mx-auto btn button_blue button_clean']) ?>
</div> </div>
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>

View File

@ -1,16 +1,36 @@
#page_orders article { #page_orders .page_order_panel {
background-color: #fff; background-color: #fff;
} }
#page_orders article .list .row:nth-child(2n+1) { #page_orders .page_order_panel .list .row:nth-child(2n+1) {
background-color: #f7f6f9; background-color: #f7f6f9;
} }
#page_orders article .list .row:first-child { #page_orders .page_order_panel .list .row:first-child {
background-color: #dbdde3; background-color: #dbdde3;
} }
#page_orders .cart_field_cost span { #page_orders .cart_field_cost span {
font-weight: bold; font-weight: bold;
font-size: larger; font-size: larger;
} }
#page_orders>article, #page_orders>input {
display: none;
}
#page_orders>input:checked+article {
display: block;
}
#page_orders article .row_supply {
height: 60px;
}
#page_orders article .row_supply:hover {
background-color: #e9e7ee;
}
#page_orders article .row_supply:active, #page_orders article .row_supply_active {
background-color: #e4e2ea;
}

View File

@ -315,6 +315,12 @@ function cart_response(data, status) {
reinitialization(main); reinitialization(main);
} }
// Перенаправление
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
// CSRF-токен // CSRF-токен
if (data._csrf !== undefined) { if (data._csrf !== undefined) {
// Обновление документа // Обновление документа

View File

@ -0,0 +1,42 @@
function orders_response(data, status) {
// Обработка ответов
// Основной блок
if (data.main !== undefined) {
main = document.getElementsByTagName('main')[0];
// Обновление документа
main.innerHTML = data.main;
// Реинициализация
reinitialization(main);
}
// Перенаправление
if (data.redirect !== undefined) {
// Перенаправление
history.pushState({}, document.title, data.redirect);
}
// CSRF-токен
if (data._csrf !== undefined) {
// Обновление документа
$('meta[name=csrf-token]').prop("content", data._csrf);
}
}
function orders_response_success(data, status) {
// Обработка ответов от удавшихся запросов
orders_response(data, status);
}
function orders_response_error(data, status) {
// Обработка ответов от неудавшихся запросов
// Инициализвация
data = data.responseJSON;
orders_response(data, status);
}

View File

@ -0,0 +1,23 @@
function orders_supply_edit(target, order_number) {
// Поиск панели для вывода информации
let panel = document.getElementById('orders_panel_edit_' + order_number);
// Поиск всех кнопок с поставками
let rows = document.getElementsByClassName('row_supply');
// Деактивация остальных кнопок
for (let i = 0; i < rows.length; i++) {
if (rows[i].parentElement.parentElement.getAttribute('id') === 'orders_panel_supplies_' + order_number) {
// Если это кнопка конкретно с этого заказа
rows[i].classList.remove('row_supply_active');
}
}
// Активация выбранной кнопки
target.classList.add('row_supply_active');
panel.innerHTML = target.getAttribute('id');
return false
}