From dc30b8c6bb6297f342288fda408c817bd22b2558 Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Mon, 16 Aug 2021 03:53:25 +1000 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=20=D1=81=D0=B0=D0=B9=D1=82=D0=BE=D0=BC=2019?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../skillparts/system/config/web.php.example | 2 +- .../controllers/AuthenticationController.php | 4 +- .../system/controllers/CartController.php | 18 +- .../controllers/IdentificationController.php | 8 +- .../system/controllers/OrderController.php | 197 +++++++++++++----- .../controllers/RegistrationController.php | 4 +- mirzaev/skillparts/system/models/Order.php | 68 +++++- mirzaev/skillparts/system/models/Search.php | 6 +- .../system/models/traits/SearchByEdge.php | 21 +- .../views/account/panel/authenticated.php | 4 +- .../skillparts/system/views/cart/button.php | 18 ++ .../skillparts/system/views/layouts/main.php | 2 +- .../system/views/notification/button.php | 10 +- .../skillparts/system/views/orders/index.php | 55 +++-- .../system/views/orders/search/panel.php | 53 +++++ .../skillparts/system/views/search/panel.php | 3 +- mirzaev/skillparts/system/web/css/header.css | 6 + .../system/web/css/notification.css | 5 - .../system/web/css/pages/orders.css | 8 + mirzaev/skillparts/system/web/js/cart.js | 15 ++ mirzaev/skillparts/system/web/js/main.js | 2 + mirzaev/skillparts/system/web/js/menu.js | 61 +++++- .../skillparts/system/web/js/notification.js | 4 +- mirzaev/skillparts/system/web/js/orders.js | 44 ++-- 24 files changed, 475 insertions(+), 143 deletions(-) create mode 100644 mirzaev/skillparts/system/views/cart/button.php create mode 100644 mirzaev/skillparts/system/views/orders/search/panel.php diff --git a/mirzaev/skillparts/system/config/web.php.example b/mirzaev/skillparts/system/config/web.php.example index 17cc014..dc4eccc 100644 --- a/mirzaev/skillparts/system/config/web.php.example +++ b/mirzaev/skillparts/system/config/web.php.example @@ -98,7 +98,7 @@ $config = [ '///' => '
/-', 'profile/geolocation/' => 'profile/geolocation-', 'orders' => 'order/index', - 'orders/' => 'order/index', + 'orders/' => 'order/index', 'orders//' => 'order/', 'orders/supply//' => 'order/supply-', 'orders/supply///' => 'order/supply--', diff --git a/mirzaev/skillparts/system/controllers/AuthenticationController.php b/mirzaev/skillparts/system/controllers/AuthenticationController.php index 0db15ef..42f288f 100644 --- a/mirzaev/skillparts/system/controllers/AuthenticationController.php +++ b/mirzaev/skillparts/system/controllers/AuthenticationController.php @@ -76,12 +76,14 @@ class AuthenticationController extends Controller // Инициализация $notifications_button = $this->renderPartial('/notification/button'); $notifications_panel = $this->renderPartial('/notification/panel', ['notifications_panel_full' => true]); + $cart_button = $this->renderPartial('/cart/button', ['cart_amount' => Order::count(supplies: true)]); // Запись ответа $return = [ 'menu' => $this->renderPartial('/account/panel/authenticated', compact( 'notifications_button', - 'notifications_panel' + 'notifications_panel', + 'cart_button' )), '_csrf' => yii::$app->request->getCsrfToken() ]; diff --git a/mirzaev/skillparts/system/controllers/CartController.php b/mirzaev/skillparts/system/controllers/CartController.php index 1850ecc..ee6aeb6 100644 --- a/mirzaev/skillparts/system/controllers/CartController.php +++ b/mirzaev/skillparts/system/controllers/CartController.php @@ -30,7 +30,8 @@ class CartController extends Controller 'roles' => ['@'], 'actions' => [ 'index', - 'edit-comm' + 'edit-comm', + 'count' ] ], [ @@ -195,4 +196,19 @@ class CartController extends Controller return $this->redirect('/'); } } + + public function actionCount(): array|string|null + { + if (yii::$app->request->isPost) { + // POST-запрос + + // Настройка типа ответа + yii::$app->response->format = Response::FORMAT_JSON; + + return [ + 'button' => $this->renderPartial('/cart/button', ['cart_amount' => Order::count(supplies: true)]), + '_csrf' => yii::$app->request->getCsrfToken() + ]; + } + } } diff --git a/mirzaev/skillparts/system/controllers/IdentificationController.php b/mirzaev/skillparts/system/controllers/IdentificationController.php index fa27578..1edd825 100644 --- a/mirzaev/skillparts/system/controllers/IdentificationController.php +++ b/mirzaev/skillparts/system/controllers/IdentificationController.php @@ -9,6 +9,7 @@ use yii\web\Controller; use yii\web\Response; use app\models\AccountForm; +use app\models\Order; class IdentificationController extends Controller { @@ -38,14 +39,15 @@ class IdentificationController extends Controller // Инициализация $notifications_button = $this->renderPartial('/notification/button'); - $notifications_panel_full = true; - $notifications_panel = $this->renderPartial('/notification/panel', compact('notifications_panel_full')); + $notifications_panel = $this->renderPartial('/notification/panel', ['notifications_panel_full' => true]); + $cart_button = $this->renderPartial('/cart/button', ['cart_amount' => Order::count(supplies: true)]); // Запись ответа $return = [ 'menu' => $this->renderPartial('/account/panel/authenticated', compact( 'notifications_button', - 'notifications_panel' + 'notifications_panel', + 'cart_button' )), '_csrf' => yii::$app->request->getCsrfToken() ]; diff --git a/mirzaev/skillparts/system/controllers/OrderController.php b/mirzaev/skillparts/system/controllers/OrderController.php index 671c35c..eefce7a 100644 --- a/mirzaev/skillparts/system/controllers/OrderController.php +++ b/mirzaev/skillparts/system/controllers/OrderController.php @@ -18,6 +18,7 @@ use app\models\AccountEdgeOrder; use app\models\connection\Dellin; use app\models\Invoice; use app\models\Notification; +use app\models\Search; use app\models\Settings; use app\models\Supply; use app\models\SupplyEdgeProduct; @@ -112,88 +113,171 @@ class OrderController extends Controller } } - public function actionIndex(string $filter = 'all') + public function actionIndex(string $type = 'all') { // Инициализация cookie $cookies = yii::$app->response->cookies; // Инициализация открытой панели ("Модерация", "Мои заказы") - $panel = yii::$app->request->post('panel') ?? yii::$app->request->get('panel') ?? 'orders_panel_orders'; + $window = yii::$app->request->post('window') ?? yii::$app->request->get('window') ?? 'orders_panel_orders'; - // Инициализация фильтра по типу - if ($filter === 'last') { - // Запрошено использование прошлых данных о фильтрации по типу + // Инициализация данных поиска + try { + if ('@last' === $search = yii::$app->request->post('search') ?? yii::$app->request->get('search')) { + // Запрошено использование прошлых данных - // Чтение сохраненных cookie с данными прошлой фильтрации по типу - $filter = $cookies->get('filter'); - } else { - // Запрошена сортировка + // Чтение сохраненных данных в cookie + $search = $cookies->get('search'); - // Запись cookie с данными текущей фильтрации по типу - $cookies->add(new Cookie([ - 'name' => 'filter', - 'value' => $filter - ])); + if (empty($search)) { + // Переданы неверные данные + + throw new Exception("Переданы неверные данные \$search: $search", 500); + } + } else { + // Запрошен поиск + + if (empty($search)) { + // Переданы неверные данные + + throw new Exception("Переданы неверные данные \$search: $search", 500); + } + + // Запись данных в cookie + $cookies->add(new Cookie([ + 'name' => 'search', + 'value' => $search + ])); + } + } catch (Exception $e) { + // Деинициализация (не удалять, отправляется в представление через compact) + $search = null; + } finally { + if (isset($search)) { + // Запись в историю + Search::write($search, 'order'); + } } - // Инициализация входных данных - $from = yii::$app->request->post('from') ?? yii::$app->request->get('from'); - $to = yii::$app->request->post('to') ?? yii::$app->request->get('to'); + // Инициализация открытого окна + try { + if ('@last' === $type) { + // Запрошено использование прошлых данных - // Инициализация фильтра по периоду - if (!empty($from) && !empty($to) && filter_var($from, FILTER_VALIDATE_INT) && filter_var($to, FILTER_VALIDATE_INT)) { - // Данные фильтра по периоду переданы и представляют собой целые числа (подразумевается unixtime) + // Чтение сохраненных данных в cookie + $type = $cookies->get('type'); - // Конвертация типов - $from = (int) $from; - $to = (int) $to; + if (empty($type)) { + // Переданы неверные данные - // Запись cookie с данными начала периода - $cookies->add(new Cookie([ - 'name' => 'from', - 'value' => $from - ])); - - // Запись cookie с данными окончания периода - $cookies->add(new Cookie([ - 'name' => 'to', - 'value' => $to - ])); - } else { - // Некоректные данные или их отсутствие - - // Чтение сохраненных cookie с данными прошлой фильтрации по периоду (начало) - $from = $cookies->get('from'); - - // Чтение сохраненных cookie с данными прошлой фильтрации по периоду (конец) - $to = $cookies->get('to'); - - if (empty($from) || empty($to) || filter_var($from, FILTER_VALIDATE_INT) || filter_var($to, FILTER_VALIDATE_INT)) { - // Каких-то cookie не оказалось, либо данные в них не подходящие, либо это первый запрос, но без фильтрации по периоду - - // Реинициализация на стандартные параметры (неделя) - $from = time() - 604800; - $to = time(); + throw new Exception("Переданы неверные данные \$type: $type", 500); + } } else { - // Данные в cookie найдены и подходят для выполнения + // Запрошена сортировка - // Конвертация типов - $from = (int) $from; - $to = (int) $to; + if (empty($type)) { + // Переданы неверные данные + + throw new Exception("Переданы неверные данные \$type: $type", 500); + } + + // Запись данных в cookie + $cookies->add(new Cookie([ + 'name' => 'type', + 'value' => $type + ])); } + } catch (Exception $e) { + // Реинициализация + $type = 'all'; + } + + // Инициализация данных периода (от) + try { + if ('@last' === $from = yii::$app->request->post('from') ?? yii::$app->request->get('from')) { + // Запрошено использование прошлых данных + + // Чтение сохраненных данных в cookie + $from = $cookies->get('from'); + + if (empty($from) || !filter_var($from, FILTER_VALIDATE_INT)) { + // Переданы неверные данные (необходим unixtime) + + throw new Exception("Переданы неверные данные \$from: $from", 500); + } + } else { + // Запрошен поиск + + if (empty($from) || !filter_var($from, FILTER_VALIDATE_INT)) { + // Переданы неверные данные (необходим unixtime) + + throw new Exception("Переданы неверные данные \$from: $from", 500); + } + + // Запись данных в cookie + $cookies->add(new Cookie([ + 'name' => 'from', + 'value' => $from + ])); + } + } catch (Exception $e) { + // Реинициализация + $from = time() - 604800; + } finally { + // Конвертация типа + $from = (int) $from; + } + + // Инициализация данных периода (до) + try { + if ('@last' === $to = yii::$app->request->post('to') ?? yii::$app->request->get('to')) { + // Запрошено использование прошлых данных + + // Чтение данных в cookie + $to = $cookies->get('to'); + + if (empty($to) || !filter_var($to, FILTER_VALIDATE_INT)) { + // Переданы неверные данные (необходим unixtime) + + throw new Exception("Переданы неверные данные \$to: $to", 500); + } + } else { + // Запрошен поиск + + if (empty($to) || !filter_var($to, FILTER_VALIDATE_INT)) { + // Переданы неверные данные (необходим unixtime) + + throw new Exception("Переданы неверные данные \$to: $to", 500); + } + + // Запись данных в cookie + $cookies->add(new Cookie([ + 'name' => 'to', + 'value' => $to + ])); + } + } catch (Exception $e) { + // Реинициализация + $to = time(); + } finally { + // Конвертация типа + $to = (int) $to; } // Инициализация заказов $orders = Order::search( - type: $filter, + type: $type, limit: 10, page: 1, select: '{account_edge_order, order}', supplies: true, from: $from, - to: $to + to: $to, + search: $search ); + // Фильтрация + if ( !yii::$app->user->isGuest && yii::$app->user->identity->type === 'administrator' @@ -221,7 +305,8 @@ class OrderController extends Controller $to = DateTime::createFromFormat('U', (string) $to)->format('Y-m-d'); return [ - 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders', 'from', 'to', 'panel')), + 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders', 'search', 'from', 'to', 'window') + + ['panel' => $this->renderPartial('/orders/search/panel', ['response' => $orders[0]['supplies']])]), 'title' => 'Заказы', 'redirect' => '/orders', '_csrf' => yii::$app->request->getCsrfToken() diff --git a/mirzaev/skillparts/system/controllers/RegistrationController.php b/mirzaev/skillparts/system/controllers/RegistrationController.php index 39347ca..7336cc3 100644 --- a/mirzaev/skillparts/system/controllers/RegistrationController.php +++ b/mirzaev/skillparts/system/controllers/RegistrationController.php @@ -60,12 +60,14 @@ class RegistrationController extends Controller // Инициализация $notifications_button = $this->renderPartial('/notification/button'); $notifications_panel = $this->renderPartial('/notification/panel', ['notifications_panel_full' => true]); + $cart_button = $this->renderPartial('/cart/button', ['cart_amount' => Order::count(supplies: true)]); // Запись ответа $return = [ 'menu' => $this->renderPartial('/account/panel/authenticated', compact( 'notifications_button', - 'notifications_panel' + 'notifications_panel', + 'cart_button' )), '_csrf' => yii::$app->request->getCsrfToken() ]; diff --git a/mirzaev/skillparts/system/models/Order.php b/mirzaev/skillparts/system/models/Order.php index 6bdbf83..d7af66e 100644 --- a/mirzaev/skillparts/system/models/Order.php +++ b/mirzaev/skillparts/system/models/Order.php @@ -28,7 +28,7 @@ class Order extends Document implements DocumentInterface /** * Поставки для записи */ - public array $supplies; + public array|int $supplies; /** * Имя коллекции @@ -261,8 +261,18 @@ class Order extends Document implements DocumentInterface * * @todo Привести в порядок */ - public static function search(Account|string $account = null, string $type = 'current', int $limit = 1, int $page = 1, string $select = null, bool $supplies = false, int|null $from = null, int|null $to = null): self|array|null - { + public static function search( + Account|string $account = null, + string $type = 'current', + string|null $search = null, + int $limit = 1, + int $page = 1, + string|null $select = null, + bool $supplies = false, + int|null $from = null, + int|null $to = null, + bool $count = false + ): self|int|array|null { // Инициализация аккаунта if (empty($account) && isset(yii::$app->user->identity)) { // Данные не переданы @@ -322,7 +332,7 @@ class Order extends Document implements DocumentInterface $where = "edge._to == order._id"; } - // Запрос на поиск заказов + // Поиск заказов в базе данных $return = self::searchByEdge( from: 'account', to: 'order', @@ -333,9 +343,16 @@ class Order extends Document implements DocumentInterface offset: $offset, sort: ['DESC'], select: $select, - direction: 'INBOUND' + direction: 'INBOUND', + count: !$supplies && $count ? true : false ); + if (!$supplies && $count) { + // Запрошен подсчет заказов + + return $return; + } + if ($supplies) { // Запрошен поиск поставок @@ -354,7 +371,13 @@ class Order extends Document implements DocumentInterface } // Чтение полного содержания - $container['supplies'] = $buffer->content(30); + $container['supplies'] = $buffer->content($limit, $page, $search, count: $count); + + if ($count) { + // Запрошен подсчет поставок + + return $container['supplies']; + } } } @@ -378,11 +401,19 @@ class Order extends Document implements DocumentInterface * @todo В будущем возможно заказ не только поставок реализовать * Переписать реестр и проверку на дубликаты, не понимаю как они работают */ - public function content(int $limit = 1, int $page = 1): Supply|array|null + public function content(int $limit = 1, int $page = 1, string|null $search = null, bool $count = false): Supply|int|array|null { // Генерация сдвига по запрашиваемым данным (пагинация) $offset = $limit * ($page - 1); + if (!empty($search)) { + // Передан поиск по продуктам в заказах + + // Добавить ограничитель + + $limit = 9999; + } + // Поиск по рёбрам: ЗАКАЗ -> ПОСТАВКА $connections = Supply::searchByEdge( from: 'order', @@ -397,10 +428,18 @@ class Order extends Document implements DocumentInterface where: 'edge._to == supply._id', limit: $limit, offset: $offset, + filterStart: ['catn' => $search], direction: 'INBOUND', - select: '{supply, order_edge_supply}' + select: '{supply, order_edge_supply}', + count: $count ); + if ($count) { + // Запрошен подсчет + + return $connections; + } + // Рекурсивная фильтрации соединений recursive_connections_filtration: @@ -838,4 +877,17 @@ class Order extends Document implements DocumentInterface // Отправка return Notification::_write($text, type: $type); } + + /** + * Посчитать количство заказов или количество поставок в заказах + * + * @param int $limit Ограничение + * @param bool $supplies Считать поставки в активном заказе (иначе - заказы) + * + * @return int Количество + */ + public static function count(int $limit = 500, bool $supplies = false): int + { + return self::search(supplies: $supplies, type: $supplies ? 'current' : 'all', limit: $limit, count: true); + } } diff --git a/mirzaev/skillparts/system/models/Search.php b/mirzaev/skillparts/system/models/Search.php index 0e8ac4a..c1a8b57 100644 --- a/mirzaev/skillparts/system/models/Search.php +++ b/mirzaev/skillparts/system/models/Search.php @@ -35,6 +35,7 @@ class Search extends Document parent::attributes(), [ 'text', + 'type', 'ipv4', 'head' ] @@ -50,6 +51,7 @@ class Search extends Document parent::attributeLabels(), [ 'text' => 'Текст', + 'type' => 'Тип', 'ipv4' => 'IPv4', 'head' => 'Заголовки' ] @@ -86,9 +88,10 @@ class Search extends Document * Запись * * @param string $text Текст запроса + * @param string $type Тип запроса * @param Account|null $account Пользователь совершивший запрос */ - public static function write(string $text, Account|null $account = null): ?self + public static function write(string $text, string $type = 'general', Account|null $account = null): ?self { // Инициализация $vertex = new self; @@ -96,6 +99,7 @@ class Search extends Document // Настройки $vertex->text = $text; + $vertex->type = $type; if ($vertex->save()) { // Поиск записан diff --git a/mirzaev/skillparts/system/models/traits/SearchByEdge.php b/mirzaev/skillparts/system/models/traits/SearchByEdge.php index a147725..44d1bb0 100644 --- a/mirzaev/skillparts/system/models/traits/SearchByEdge.php +++ b/mirzaev/skillparts/system/models/traits/SearchByEdge.php @@ -16,11 +16,6 @@ trait SearchByEdge * Поиск через связи рёбрами с аккаунтом * * Аргумент $asArray и его реализацию пришлось добавить чтобы не переписывать кучу кода - * - * @param string $id Идентификатор пользователя - * @param int $limit Количество - * @param int $offset Сдвиг - * @param string $sort Сортировка */ public static function searchByEdge( string $from, @@ -37,9 +32,11 @@ trait SearchByEdge array|null $let = [], string|array $select = null, callable|null $handle = null, + array|null $filterStart = null, array $params = [], bool $asArray = true, - bool $debug = false + bool $debug = false, + bool $count = false ): mixed { $subquery = static::find() ->params($params) @@ -65,6 +62,12 @@ trait SearchByEdge $query->let(...$let); } + if (!empty($filterStart)) { + // Переданы дополнительные условия фильтрации + + $query->filter($filterStart, 'START_SENSETIVE'); + } + // Инициализация $request = $query ->foreach($foreach) @@ -80,7 +83,11 @@ trait SearchByEdge } // Запрос - if (isset($handle)) { + if ($count) { + // Запрошен подсчет + + return $query->count(); + } else if (isset($handle)) { // Передана функция для постобработки return $handle($request); diff --git a/mirzaev/skillparts/system/views/account/panel/authenticated.php b/mirzaev/skillparts/system/views/account/panel/authenticated.php index a8ad8d1..e664a07 100644 --- a/mirzaev/skillparts/system/views/account/panel/authenticated.php +++ b/mirzaev/skillparts/system/views/account/panel/authenticated.php @@ -6,9 +6,9 @@ use yii; ?> - - + +
user->identity->mail ?> diff --git a/mirzaev/skillparts/system/views/cart/button.php b/mirzaev/skillparts/system/views/cart/button.php new file mode 100644 index 0000000..611767e --- /dev/null +++ b/mirzaev/skillparts/system/views/cart/button.php @@ -0,0 +1,18 @@ + + + HTML; + } else { + // Новые уведомления найдены + + echo <<$cart_amount + + HTML; + } + ?> + diff --git a/mirzaev/skillparts/system/views/layouts/main.php b/mirzaev/skillparts/system/views/layouts/main.php index 5b4a588..e0430ed 100644 --- a/mirzaev/skillparts/system/views/layouts/main.php +++ b/mirzaev/skillparts/system/views/layouts/main.php @@ -82,7 +82,7 @@ AppAsset::register($this);