diff --git a/mirzaev/skillparts/system/controllers/CartController.php b/mirzaev/skillparts/system/controllers/CartController.php index ee6aeb6..cbf79cf 100644 --- a/mirzaev/skillparts/system/controllers/CartController.php +++ b/mirzaev/skillparts/system/controllers/CartController.php @@ -85,7 +85,7 @@ class CartController extends Controller $account = yii::$app->user->identity; // Поиск корзины (текущего заказа) - $model = Order::search(); + $model = Order::searchByType(); if (empty($model)) { // Корзина не инициализирована @@ -137,7 +137,7 @@ class CartController extends Controller goto end; } - if ($edges = OrderEdgeSupply::searchBySupplyCatn($catn, Order::search())) { + if ($edges = OrderEdgeSupply::searchBySupplyCatn($catn, Order::searchByType())) { // Рёбра найдены (связи заказа с поставкой) // Инициализация diff --git a/mirzaev/skillparts/system/controllers/OrderController.php b/mirzaev/skillparts/system/controllers/OrderController.php index d03a1ed..fedd9fa 100644 --- a/mirzaev/skillparts/system/controllers/OrderController.php +++ b/mirzaev/skillparts/system/controllers/OrderController.php @@ -266,7 +266,7 @@ class OrderController extends Controller } // Инициализация заказов - $orders = Order::search( + $orders = Order::searchByType( type: $type, limit: 10, page: 1, @@ -341,7 +341,7 @@ class OrderController extends Controller Order::searchById($account_edge_order->_to)->journal('accepted'); // Инициализация - $orders = Order::search(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}', supplies: true); + $orders = Order::searchByType(type: 'all', limit: 10, page: 1, select: '{account_edge_order, order}', supplies: true); $moderator_orders = self::genOrdersForModeration(); // Запись в буфер вывода @@ -391,7 +391,7 @@ class OrderController extends Controller ]; // Инициализация корзины - if (!$model = Order::search($account)) { + if (!$model = Order::searchByType($account)) { // Корзина не найдена (текущий заказ) // Инициализация @@ -424,7 +424,7 @@ class OrderController extends Controller $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets'); $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1; $account = yii::$app->user->identity; - $order = Order::search(); + $order = Order::searchByType(); if ($targets) { // Удаление выбранных целей (удаление из заказа) @@ -466,7 +466,7 @@ class OrderController extends Controller $edge->update(); // Реинициализация - $order = Order::search(); + $order = Order::searchByType(); if (empty($order)) { // Корзина не инициализирована @@ -509,7 +509,7 @@ class OrderController extends Controller $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets'); $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1; $account = yii::$app->user->identity; - $order = Order::search(); + $order = Order::searchByType(); $connections = $order->content(10, $page); foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) { @@ -583,7 +583,7 @@ class OrderController extends Controller public function actionRequest(): string|array|null { // Инициализация - $model = Order::search(supplies: true); + $model = Order::searchByType(supplies: true); // Поиск ребра $edge = AccountEdgeOrder::searchByVertex(yii::$app->user->id, $model->readId(), 'current'); @@ -650,11 +650,11 @@ class OrderController extends Controller * * @return array ['order' => array, 'order_edge_account' => array, 'supplies' => array] * - * @todo Уничтожить заменив на Order::search(supplies: true) + * @todo Уничтожить заменив на Order::searchByType(supplies: true) */ protected static function genOrdersForModeration(int $page = 1): array { - $orders = Order::search(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}'); + $orders = Order::searchByType(account: '@all', type: 'requested', limit: 10, page: 1, select: '{account_edge_order, order}'); foreach ($orders as &$order) { // Перебор заказов @@ -697,9 +697,9 @@ class OrderController extends Controller try { // Инициализация данных геолокации try { - $from = (int) $account['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36; + $from = (int) $account['opts']['delivery_from_terminal'] ?? Settings::searchActive()->delivery_from_default ?? 36; } catch (Exception $e) { - $from = (int) Settings::search()->delivery_from_default ?? 36; + $from = (int) Settings::searchActive()->delivery_from_default ?? 36; } try { diff --git a/mirzaev/skillparts/system/controllers/ProductController.php b/mirzaev/skillparts/system/controllers/ProductController.php index 91538ca..bf0beda 100644 --- a/mirzaev/skillparts/system/controllers/ProductController.php +++ b/mirzaev/skillparts/system/controllers/ProductController.php @@ -84,7 +84,7 @@ class ProductController extends Controller } if ($from = Product::searchByCatn($catn)) { - // Товар найден + // Найден товар if ($target = yii::$app->request->post('catn') ?? yii::$app->request->get('catn')) { // Инициализирован артикул товара для связи @@ -97,6 +97,9 @@ class ProductController extends Controller // Инициализация товара if ($to = Product::writeEmpty((string) $target)) { // Удалось записать товар + + // Запись в буфер возврата + $return['alert'] = "Не удалось записать новый товар: $target"; } else { // Не удалось записать товар @@ -111,14 +114,16 @@ class ProductController extends Controller } } - if (($edge = $from->synchronization($to)) instanceof ProductEdgeProduct) { - // Ребро создано + if ($from->synchronization($to) > 0) { + // Созданы рёбра // Запись в буфер возврата - $return['alert'] = "Продукты успешно соединены ребром: $edge->_key"; + $return['alert'] = 'Продукты успешно соединены'; } } } else { + // Не найден товар + // Запись кода ответа yii::$app->response->statusCode = 500; @@ -129,9 +134,7 @@ class ProductController extends Controller goto end; } - /** - * Конец алгоритма - */ + // Конец алгоритма end: if (yii::$app->request->isPost) { @@ -180,42 +183,25 @@ class ProductController extends Controller if ($from = Product::searchByCatn($catn)) { // Товар найден - if ($target = yii::$app->request->post('catn') ?? yii::$app->request->get('catn')) { - // Инициализирован артикул товара для связи + // Инициализация цели + $target = yii::$app->request->post('catn') ?? yii::$app->request->get('catn'); - if ($to = Product::searchByCatn($target)) { - // Существует товар который нужно отсоединить + if ($from->disconnect(Product::searchByCatn(empty($target) ? null : $target))) { + // Удалено ребро (связь) - if ($from->disconnect($to)) { - // Удалось удалить ребро (связь) + // Запись в буфер возврата + $return['alert'] = "Продукты успешно отсоединены"; + } else { + // Не удалено ребро (связь) - // Запись в буфер возврата - $return['alert'] = "Продукты успешно отсоединены"; - } else { + // Запись кода ответа + yii::$app->response->statusCode = 500; - // Не удалось удалить ребро (связь) + // Запись в буфер возврата + $return['alert'] = "Не удалось отсоединить $target от $catn"; - // Запись кода ответа - yii::$app->response->statusCode = 500; - - // Запись в буфер возврата - $return['alert'] = "Не удалось отсоединить $target от $catn"; - - // Переход в конец алгоритма - goto end; - } - } else { - // Не существует товар который нужно отсоединить - - // Запись кода ответа - yii::$app->response->statusCode = 500; - - // Запись в буфер возврата - $return['alert'] = "Не удалось найти товар который нужно отсоединить: $catn"; - - // Переход в конец алгоритма - goto end; - } + // Переход в конец алгоритма + goto end; } } else { // Запись кода ответа @@ -228,9 +214,7 @@ class ProductController extends Controller goto end; } - /** - * Конец алгоритма - */ + // Конец алгоритма end: if (yii::$app->request->isPost) { @@ -279,20 +263,35 @@ class ProductController extends Controller if ($product = Product::searchByCatn($catn)) { // Товар найден - if ($product->delete() > 0) { - // Удалось удалить + if ($product->disconnect()) { + // Отсоединён от аналогов - // Запись в буфер возврата - $return['alert'] = "Товар удалён: $catn"; - $return['location'] = '/'; + if ($product->delete() > 0) { + // Удалён + + // Запись в буфер возврата + $return['alert'] = "Товар удалён: $catn"; + $return['location'] = '/'; + } else { + // Не удалось удалить + + // Запись кода ответа + yii::$app->response->statusCode = 500; + + // Запись в буфер возврата + $return['alert'] = "Не удалось удалить товар: $catn"; + + // Переход в конец алгоритма + goto end; + } } else { - // Не удалось удалить + // Не отсоединён от аналогов // Запись кода ответа yii::$app->response->statusCode = 500; // Запись в буфер возврата - $return['alert'] = "Не удалось удалить товар: $catn"; + $return['alert'] = "Не удалось отсоединить от аналогов перед удалением: $catn"; // Переход в конец алгоритма goto end; @@ -355,12 +354,12 @@ class ProductController extends Controller // Инициализация $text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия'; - $model->name = $text; + $model->prod = $text; if ($model->save()) { // Товар обновлён - $return['name'] = $text; + $return['prod'] = $text; } } diff --git a/mirzaev/skillparts/system/controllers/ProfileController.php b/mirzaev/skillparts/system/controllers/ProfileController.php index d655aa3..ca18dbf 100644 --- a/mirzaev/skillparts/system/controllers/ProfileController.php +++ b/mirzaev/skillparts/system/controllers/ProfileController.php @@ -488,7 +488,7 @@ class ProfileController extends Controller // Инициализация $groups = []; - foreach (SupplyGroup::readAll() as $group) { + foreach (SupplyGroup::read() as $group) { // Перебор всех групп // Генерация [КЛЮЧ => ИМЯ] diff --git a/mirzaev/skillparts/system/controllers/SearchController.php b/mirzaev/skillparts/system/controllers/SearchController.php index 191f711..790bd4e 100644 --- a/mirzaev/skillparts/system/controllers/SearchController.php +++ b/mirzaev/skillparts/system/controllers/SearchController.php @@ -137,7 +137,7 @@ class SearchController extends Controller if ($response = Product::searchByPartialCatn($query, $limit, [ '_key' => '_key', 'catn' => 'catn', - 'name' => 'name', + 'prod' => 'prod', // Баг с названием DESC 'dscr' => 'dscr', 'catg' => 'catg', diff --git a/mirzaev/skillparts/system/models/AccountForm.php b/mirzaev/skillparts/system/models/AccountForm.php index c2e0c26..77205f5 100644 --- a/mirzaev/skillparts/system/models/AccountForm.php +++ b/mirzaev/skillparts/system/models/AccountForm.php @@ -103,16 +103,6 @@ class AccountForm extends Model ]; } - public function attributeLabels() - { - return [ - 'mail' => 'Почта', - 'pswd' => 'Пароль', - 'auto' => '', - 'pols' => 'Политика конфедециальности' - ]; - } - public function validateMail($attribute, $params) { if (!$this->hasErrors()) { diff --git a/mirzaev/skillparts/system/models/Document.php b/mirzaev/skillparts/system/models/Document.php index 7c3a3f5..ec56f60 100644 --- a/mirzaev/skillparts/system/models/Document.php +++ b/mirzaev/skillparts/system/models/Document.php @@ -62,10 +62,14 @@ abstract class Document extends ActiveRecord * @todo Подождать обновление от ебаного Yii2 и добавить * проверку типов передаваемых параметров */ - public function beforeSave($data): bool + public function beforeSave($create): bool { - if (parent::beforeSave($data)) { + if (parent::beforeSave($create)) { + // Пройдена родительская проверка + if ($this->isNewRecord) { + // Новая запись + // Запись в журнал $this->jrnl = array_merge( [[ @@ -127,6 +131,15 @@ abstract class Document extends ActiveRecord return isset($this->_key) && static::collectionName() ? static::collectionName() . '/' . $this->_key : null; } + /** + * Поиск + */ + public static function search(array $where, $limit = 1): array + { + return static::find()->where($where)->limit($limit)->all(); + } + + /** * Поиск по идентификатору */ @@ -142,7 +155,7 @@ abstract class Document extends ActiveRecord /** * Чтение всех записей - * + * * @deprecated */ public static function readAll(): array diff --git a/mirzaev/skillparts/system/models/Edge.php b/mirzaev/skillparts/system/models/Edge.php index 7f4584a..a264f14 100644 --- a/mirzaev/skillparts/system/models/Edge.php +++ b/mirzaev/skillparts/system/models/Edge.php @@ -161,7 +161,7 @@ abstract class Edge extends Document /** * Поиск рёбер по направлению */ - public static function search(string $target, string $direction = 'OUTBOUND', string $type = '', int $limit = 1): static|array|null + public static function searchByDirection(string $target, string $direction = 'OUTBOUND', string $type = '', int $limit = 1): static|array|null { if (str_contains($direction, 'OUTBOUND')) { // Исходящие рёбра @@ -174,7 +174,7 @@ abstract class Edge extends Document } else if (str_contains($direction, 'ANY')) { // Исходящие и входящие рёбра - return static::search(target: $target, direction: 'OUTBOUND', type: $type, limit: $limit) + static::search(target: $target, direction: 'INBOUND', type: $type, limit: $limit); + return static::searchByDirection(target: $target, direction: 'OUTBOUND', type: $type, limit: $limit) + static::searchByDirection(target: $target, direction: 'INBOUND', type: $type, limit: $limit); } if ($limit < 2) { diff --git a/mirzaev/skillparts/system/models/Order.php b/mirzaev/skillparts/system/models/Order.php index 0634605..31041d9 100644 --- a/mirzaev/skillparts/system/models/Order.php +++ b/mirzaev/skillparts/system/models/Order.php @@ -261,7 +261,7 @@ class Order extends Document implements DocumentInterface * * @todo Привести в порядок */ - public static function search( + public static function searchByType( Account|string $account = null, string $type = 'current', string|null $search = null, @@ -577,9 +577,9 @@ class Order extends Document implements DocumentInterface try { // Инициализация данных геолокации try { - $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } catch (Exception $e) { - $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } try { @@ -640,9 +640,9 @@ class Order extends Document implements DocumentInterface try { // Инициализация данных геолокации try { - $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } catch (Exception $e) { - $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } try { @@ -888,6 +888,6 @@ class Order extends Document implements DocumentInterface */ public static function count(int $limit = 500, bool $supplies = false): int { - return (int) self::search(supplies: $supplies, type: $supplies ? 'current' : 'all', limit: $limit, count: true); + return (int) self::searchByType(supplies: $supplies, type: $supplies ? 'current' : 'all', limit: $limit, count: true); } } diff --git a/mirzaev/skillparts/system/models/Product.php b/mirzaev/skillparts/system/models/Product.php index 56d152a..5ff6b96 100644 --- a/mirzaev/skillparts/system/models/Product.php +++ b/mirzaev/skillparts/system/models/Product.php @@ -16,8 +16,6 @@ use DateTime; use DateTimeZone; use Exception; -use phpDocumentor\Reflection\DocBlock\Tags\Var_; -use stdClass; /** * Продукт (в ассортименте магазина) @@ -81,7 +79,6 @@ class Product extends Document parent::attributes(), [ 'catn', - 'name', // В библеотеке есть баг на название DESC (неизвестно в моей или нет) 'dscr', 'prod', @@ -103,7 +100,6 @@ class Product extends Document parent::attributeLabels(), [ 'catn' => 'Каталожный номер (catn)', - 'name' => 'Название (name)', 'dscr' => 'Описание (dscr)', 'prod' => 'Производитель (prod)', 'dmns' => 'Габариты (dmns)', @@ -140,16 +136,35 @@ class Product extends Document 'string', 'message' => '{attribute} должен быть строкой' ], + [ + 'prod', + 'string', + 'length' => [3, 80], + 'message' => '{attribute} должен быть строкой от 3 до 80 символов' + ], [ 'imgs', 'arrayValidator', 'message' => '{attribute} должен быть массивом' ], + [ + 'dscr', + 'string', + 'length' => [3, 256], + 'message' => '{attribute} должен быть строкой от 3 до 256 символов' + ], [ 'dmns', 'arrayWithNumbersValidator', 'message' => '{attribute} должен быть массивом и хранить циферные значения' ], + [ + 'wght', + 'integer', + 'min' => 0, + 'max' => 30000, + 'message' => '{attribute} должен иметь значение от 0 до 30000' + ], [ 'file_excel', 'required', @@ -185,28 +200,6 @@ class Product extends Document 'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"', 'message' => 'Проблема при загрузке изображения', 'on' => self::SCENARIO_IMPORT_IMAGE - ], - [ - [ - 'name', - 'prod' - ], - 'string', - 'length' => [3, 80], - 'message' => '{attribute} должен быть строкой от 3 до 80 символов' - ], - [ - 'dscr', - 'string', - 'length' => [3, 256], - 'message' => '{attribute} должен быть строкой от 3 до 256 символов' - ], - [ - 'wght', - 'integer', - 'min' => 0, - 'max' => 30000, - 'message' => '{attribute} должен иметь значение от 0 до 30000' ] ] ); @@ -328,7 +321,8 @@ class Product extends Document { // Инициализация $data = []; - $amount = 0; + $created = 0; + $updated = 0; $account = Account::initAccount($account); if ($this->validate()) { @@ -336,7 +330,7 @@ class Product extends Document // Перебор файлов // Инициализация - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; $path = YII_PATH_PUBLIC . "/../assets/accounts/$account->_key/files/" . (new DateTime('now', new DateTimeZone($timezone)))->getTimestamp(); @@ -388,15 +382,29 @@ class Product extends Document if ($product->validate()) { // Проверка пройдена - // Запись документа - $product->save(); + if (($_product = $product->validateForUniqueness()) instanceof static) { + // Найден документ с такими параметрами - // Постинкрементация счётчика - $amount++; - // Запись группы - // $group = static::class . 'Group'; - // (new $group())->writeMember($product, $this->group); + // Инициализация буфера с параметрами загружаемого товара + $vars = $product->getAttributes(); + + // Удаление _key, чтобы не перезаписать его при замене параметров документа в буфере + unset($vars['_key']); + + // Перенос данных в буфер (существующий в базе данных дубликат) + $_product->setAttributes($vars, false); + + // Перезапись существующего документа + $_product->update(); + + $updated++; + } else { + // Не найден документ с такими параметрами + + // Запись нового документа + if ($product->save()) $created++; + } } else { // Проверка не пройдена @@ -412,14 +420,16 @@ class Product extends Document $this->file_excel = null; // Макрос действий после импорта - static::afterImportExcel($amount); + static::afterImportExcel($created, $updated); return true; } + // Запись ошибки $this->addError('erros', 'Неизвестная ошибка'); - static::afterImportExcel($amount); + // Макрос действий после импорта + static::afterImportExcel($created, $updated); return false; } @@ -432,7 +442,7 @@ class Product extends Document * * @todo Переделать нормально */ - public static function searchByCatn(string $catn, int $limit = 1, array $select = []): static|array|null + public static function searchByCatn(string|null $catn, int $limit = 1, array $select = []): static|array|null { if ($limit <= 1) { return static::findOne(['catn' => $catn]); @@ -488,23 +498,24 @@ class Product extends Document /** * Вызывается после загрузки поставок из excel-документа * - * @param int $amount Количество + * @param int $created Количество созданных документов + * @param int $updated Количество обновлённых документов */ - public static function afterImportExcel(int $amount = 0): bool + public static function afterImportExcel(int $created = 0, int $updated = 0): bool { // Инициализация параметров $model = new Notification; $account = yii::$app->user->identity; // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; // Инициализация даты $date = (new DateTime('now', new DateTimeZone($timezone)))->format('H:i d.m.Y'); // Настройка - $model->text = yii::$app->controller->renderPartial('@app/views/notification/system/afterImportExcel', compact('amount', 'date')); + $model->text = yii::$app->controller->renderPartial('@app/views/notification/system/afterImportExcel', compact('created', 'updated', 'date')); $model->type = $model::TYPE_NOTICE; // Отправка @@ -546,7 +557,7 @@ class Product extends Document } // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; $date = (new DateTime('now', new DateTimeZone($timezone)))->format('H:i d.m.Y'); @@ -685,20 +696,20 @@ class Product extends Document /** * Подключение аналога * - * СВЯЗЫВАЕТ ТОЛЬКО ДВА ТОВАРА, ГРУППА ОСТАНЕТСЯ НЕИЗМЕННОЙ - * * @param self $to Цель + * + * @return ProductEdgeProduct|null Ребро между товарами, если создалось */ public function connect(self $to): ?ProductEdgeProduct { - if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", limit: 1)) { - // Дубликат найден - } else if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$to->_key", Product::collectionName() . "/$this->_key", limit: 1)) { - // Дубликат найден (наоборот) + if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", type: 'analogue')) { + // Найдено ребро + } else if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$to->_key", Product::collectionName() . "/$this->_key", type: 'analogue')) { + // Найдено ребро (наоборот) - // Вероятно эта проверка здесь не нужна, так как мы знаем входные данные + // !!! Вероятно эта проверка здесь не нужна, так как мы знаем входные данные } else { - // Дубликаты не найдены + // Не найдены ребра if ($edge = ProductEdgeProduct::write(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", data: ['type' => 'analogue'])) { // Ребро сохранено @@ -723,24 +734,58 @@ class Product extends Document /** * Отключение аналога * - * @param self $to Цель + * @param self|null $to Цель (если null, то целью являются все подключенные аналоги) + * @param bool $all Удалить соединения со всеми членами группы */ - public function disconnect(self $to): bool + public function disconnect(self|null $to = null, bool $all = true): bool { - // Поиск ребра - if ($edge = @ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", type: 'analogue')[0]) { - // Найдено ребро (from: $this, to: $to) - } else if ($edge = @ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$to->_key", Product::collectionName() . "/$this->_key", type: 'analogue')[0]) { - // Найдено ребро (from: $to, to: $this) - } else { - // Не найдены ребра + if (isset($to)) { + // Передана цель для удаления (из её группы) - return false; + if ($edge = @ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", type: 'analogue')[0]) { + // Найдено ребро + } else if ($edge = @ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$to->_key", Product::collectionName() . "/$this->_key", type: 'analogue')[0]) { + // Найдено ребро (наоборот) + } else { + // Не найдены ребра + + return false; + } + } else { + // Не передана цель для удаления (из её группы) + + foreach ($this->connections() as $edge) { + // Перебор всех рёбер + + if (Product::collectionName() . "/$this->_key" !== $edge && $to = Product::searchById($edge)) { + // Найден товар (проверен на то, что не является самим собой) + + // Разъединение + $this->disconnect($to, all: false); + } + } + + return true; } if ($edge->delete() > 0) { // Удалось удалить ребро (связь) + if ($all) { + // Запрошено удаление соединений со всеми членами группы + + foreach ($to->connections() as $edge) { + // Перебор рёбер (найденных соединений с группой в которой находилась цель) + + if (Product::collectionName() . "/$this->_key" !== $edge && $to = Product::searchById($edge)) { + // Найден товар (проверен на то, что не является самим собой) + + // Разъединение + $this->disconnect($to, all: false); + } + } + } + // Запись в журнал о разъединении $this->journal('disconnect analogue', [ 'to' => Product::collectionName() . "/$to->_key" @@ -767,7 +812,7 @@ class Product extends Document // Инициализация буфера связанных товаров $products = []; - foreach (ProductEdgeProduct::search(self::collectionName() . "/$this->_key", direction: 'ANY', type: 'analogue', limit: $limit) as $edge) { + foreach (ProductEdgeProduct::searchByDirection(self::collectionName() . "/$this->_key", direction: 'ANY', type: 'analogue', limit: $limit) as $edge) { // Перебор связей для создания списка товаров (вершин) // Добавление товаров (вершин) в буфер (подразумевается, что без дубликатов) @@ -777,4 +822,31 @@ class Product extends Document return $products; } + + /** + * Проверка на уникальность + * + * @return bool|static true если создать новую запись, static если найден дубликат + * + * @todo + * 1. Обработка дубликатов + */ + public function validateForUniqueness(): bool|static + { + if ($supplies = self::search(['catn' => $this->catn, 'prod' => $this->prod], limit: 100)) { + // Найдены поставки с таким же артикулом (catn) и производителем (prod) + + // if (count($supplies) > 1) throw new exception ('В базе данных имеется более чем один дубликат', 500); + if (count($supplies) > 1) return false; + + // Запись обрабатываемой поставки + $supply = $supplies[0]; + + // Возврат (найден дубликат в базе данных) + return $supply; + } else return true; + + // Возврат (подразумевается ошибка) + return false; + } } diff --git a/mirzaev/skillparts/system/models/Search.php b/mirzaev/skillparts/system/models/Search.php index 70c104b..e1821ea 100644 --- a/mirzaev/skillparts/system/models/Search.php +++ b/mirzaev/skillparts/system/models/Search.php @@ -197,9 +197,9 @@ class Search extends Document // Инициализация данных геолокации try { - $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } catch (exception $e) { - $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } try { @@ -275,9 +275,9 @@ class Search extends Document } try { - $from = (int) $buffer_delivery_avia['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = (int) $buffer_delivery_avia['account']['opts']['delivery_from_terminal'] ?? empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } catch (Exception $e) { - $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; + $from = empty(Settings::searchActive()->delivery_from_default) ? 36 : (int) Settings::searchActive()->delivery_from_default; } try { @@ -357,42 +357,33 @@ class Search extends Document * Генерация HTML-кода с найденным товаром * * @param array $row Товар сгенерированный через Search::content() - * @param string|null $cpny Компания (сейчас пока что это $name - Название) - * @param string|null $covr Обложка - * @param string|null $catg Категория - * @param string|null $catn Артикул + * @param string|null $cover Обложка * @param array $empties Реестр не найденных товаров * * @return string HTML-элемент с товаром */ - public static function generate(array &$row, string|null &$cpny = null, string|null &$covr = null, string|null &$catg = null, string|null &$catn = null, array &$empties = []): string + public static function generate(array &$row, string|null &$cover = null, array &$empties = []): string { - // Инициализация - extract($row); - $cpny ?? $cpny = 'Без названия'; - // $dscr ?? $dscr = 'Описание'; - $catg ?? $catg = 'Категория'; - $catn ?? $catn = 'Неизвестно'; - foreach ($imgs ?? [] as $img) { + foreach ($row['imgs'] ?? [] as &$img) { // Перебор изображений для обложки if ($img['covr'] ?? false) { - // Обложка найдена + // Найдена обложка - $covr = $img['h150']; + $cover = $img['h150']; break; } } - if (is_null($covr)) { + if (is_null($cover)) { // Обложка не инициализирована - if (!$covr = $imgs[0]['h150'] ?? false) { + if (!$cover = $imgs[0]['h150'] ?? false) { // Не удалось использовать первое изображение как обложку // Запись обложки по умолчанию - $covr = '/img/covers/h150/product.png'; + $cover = '/img/covers/h150/product.png'; } } @@ -465,7 +456,7 @@ class Search extends Document HTML; // Запись в список ненайденных - $empties[] = $catn; + $empties[] = $row['catn']; // Запись блокировщика $empty_block = true; @@ -534,7 +525,7 @@ class Search extends Document $amount $delivery_icon $delivery дн $price - + diff --git a/mirzaev/skillparts/system/models/Settings.php b/mirzaev/skillparts/system/models/Settings.php index 61842a4..9ffc31e 100644 --- a/mirzaev/skillparts/system/models/Settings.php +++ b/mirzaev/skillparts/system/models/Settings.php @@ -79,7 +79,7 @@ class Settings extends Document * * @todo Доделать */ - public static function search(): ?self + public static function searchActive(): ?self { return static::findOne(['active' => true]); } diff --git a/mirzaev/skillparts/system/models/Supply.php b/mirzaev/skillparts/system/models/Supply.php index ce2adb0..5814401 100644 --- a/mirzaev/skillparts/system/models/Supply.php +++ b/mirzaev/skillparts/system/models/Supply.php @@ -16,6 +16,7 @@ use carono\exchange1c\interfaces\ProductInterface; use carono\exchange1c\controllers\ApiController; use Exception; +use Throwable; /** * Поставка (выгрузка товаров от поставщиков) @@ -68,10 +69,10 @@ class Supply extends Product implements ProductInterface, OfferInterface return array_merge( parent::attributeLabels(), [ - 'cost' => 'Стоимость (cost)', + 'cost' => 'Стоимость', 'onec' => 'Данные 1С', 'oemn' => 'OEM-номера', - 'ocid' => 'Идентификатор 1C (ocid)' + 'ocid' => 'Идентификатор 1C' ] ); } @@ -589,7 +590,7 @@ class Supply extends Product implements ProductInterface, OfferInterface return SupplyEdgeProduct::searchByVertex($_id, $product->readId(), type: 'connect', limit: 1)['onec']['Цены']['Цена']; } - return SupplyEdgeProduct::search($_id, type: 'connect', limit: 1)['onec']['Цены']['Цена']; + return SupplyEdgeProduct::searchByDirection($_id, type: 'connect', limit: 1)['onec']['Цены']['Цена']; } /** @@ -602,14 +603,15 @@ class Supply extends Product implements ProductInterface, OfferInterface return static::searchAccountById($this->readId()); } - public static function DeliveryToRussian(string $dlvr, int $type = 1): string { + public static function DeliveryToRussian(string $dlvr, int $type = 1): string + { if ($type === 1) { - return match($dlvr) { + return match ($dlvr) { 'avia' => 'доставкой самолётом', default => 'автоматической доставкой' }; } else { - return match($dlvr) { + return match ($dlvr) { 'avia' => 'Самолёт', default => 'Автоматическая' }; diff --git a/mirzaev/skillparts/system/models/SupplyEdgeProduct.php b/mirzaev/skillparts/system/models/SupplyEdgeProduct.php index eeba9c5..314d0b8 100644 --- a/mirzaev/skillparts/system/models/SupplyEdgeProduct.php +++ b/mirzaev/skillparts/system/models/SupplyEdgeProduct.php @@ -6,7 +6,6 @@ namespace app\models; use app\models\traits\Xml2Array; use carono\exchange1c\interfaces\OfferInterface; -use Zenwalker\CommerceML\Model\Offer; class SupplyEdgeProduct extends Edge implements OfferInterface { diff --git a/mirzaev/skillparts/system/models/connection/Dellin.php b/mirzaev/skillparts/system/models/connection/Dellin.php index c86b52a..800ac66 100644 --- a/mirzaev/skillparts/system/models/connection/Dellin.php +++ b/mirzaev/skillparts/system/models/connection/Dellin.php @@ -196,7 +196,7 @@ class Dellin extends Model } // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; // Инициализация @@ -354,7 +354,7 @@ class Dellin extends Model // Запрос прошел успешно // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; // Инициализация параметров diff --git a/mirzaev/skillparts/system/views/invoice/order/pattern.php b/mirzaev/skillparts/system/views/invoice/order/pattern.php index 15fce92..6bd10dc 100644 --- a/mirzaev/skillparts/system/views/invoice/order/pattern.php +++ b/mirzaev/skillparts/system/views/invoice/order/pattern.php @@ -86,7 +86,7 @@ use app\models\Settings; zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; ?> Счет на оплату №= $order['id'] ?> от = (new DateTime())->setTimestamp($order['date'])->setTimezone(new DateTimeZone($timezone))->format('d.m.Y') ?> diff --git a/mirzaev/skillparts/system/views/layouts/main.php b/mirzaev/skillparts/system/views/layouts/main.php index 1579cdf..1f6201b 100644 --- a/mirzaev/skillparts/system/views/layouts/main.php +++ b/mirzaev/skillparts/system/views/layouts/main.php @@ -95,14 +95,17 @@ AppAsset::register($this);
Записано $created новых товаров и $updated товара обновлено
+ HTML; +} else if ($created > 0) { + // Записаны новые документы + + echo <<Записано $created новых товаров + HTML; +} else if ($updated > 0) { + // Записаны новые документы + + echo <<Обновлено $updated товаров HTML; } else { echo <<Неудачная попытка импорта товаров из excel-документа ($date) +Неудачная попытка импорта товаров из excel-документа
HTML; } - -?> \ No newline at end of file diff --git a/mirzaev/skillparts/system/views/orders/index.php b/mirzaev/skillparts/system/views/orders/index.php index d1aab30..fd54dff 100644 --- a/mirzaev/skillparts/system/views/orders/index.php +++ b/mirzaev/skillparts/system/views/orders/index.php @@ -71,7 +71,7 @@ if (empty($window)) { } } - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; // Конвертация данных из буфера @@ -300,7 +300,7 @@ if (empty($window)) { // Найден принятый заказ // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; // Запись данных о дате заказа @@ -516,7 +516,7 @@ if (empty($window)) { orders_calendar_ready = false; zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; ?> diff --git a/mirzaev/skillparts/system/views/orders/search/panel.php b/mirzaev/skillparts/system/views/orders/search/panel.php index dc0bc2e..dbb4154 100644 --- a/mirzaev/skillparts/system/views/orders/search/panel.php +++ b/mirzaev/skillparts/system/views/orders/search/panel.php @@ -18,7 +18,7 @@ if (isset($history) && $history) { )) { // История поиска существует - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; foreach ($rows as $row) { diff --git a/mirzaev/skillparts/system/views/product/index.php b/mirzaev/skillparts/system/views/product/index.php index 6889322..b7518fe 100644 --- a/mirzaev/skillparts/system/views/product/index.php +++ b/mirzaev/skillparts/system/views/product/index.php @@ -71,7 +71,7 @@ use app\models\Product; // Перебор изображений для генерации полных версий // Инициализация - $name = $image['name'] ?? 'Без названия'; + $prod = $image['prod'] ?? 'Неизвестный'; $orig = $image['orig'] ?? '/img/covers/product.png'; if (($image['covr'] ?? false) || ($covr_not_found && $key === 0)) { @@ -135,9 +135,9 @@ use app\models\Product; && (yii::$app->user->identity->type === 'administrator' || yii::$app->user->identity->type === 'moderator') ) : ?> -= $model['dscr'] ?? 'Без описания' ?>
-= $model['name'] ?? 'Без описания' ?>
+= $model['prod'] ?? 'Без описания' ?>
jrnl; // Инициализация часового пояса - preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::search()['timezone_default'] ?? 'UTC+3', $timezone); + preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone); $timezone = $timezone[1][0]; $date = empty($row->jrnl) ? '' : (new DateTime())->setTimestamp(end($time)['date'])->setTimezone(new DateTimeZone($timezone))->format('H:i d.m.Y'); diff --git a/mirzaev/skillparts/system/views/search/index.php b/mirzaev/skillparts/system/views/search/index.php index 0169ef0..7c0241a 100644 --- a/mirzaev/skillparts/system/views/search/index.php +++ b/mirzaev/skillparts/system/views/search/index.php @@ -9,7 +9,7 @@ use app\models\Search; -