ПРОВЕРКА ПО CATN, PROD И ЦЕНЕ

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2021-10-27 11:26:03 +10:00
parent 1d06acf2e0
commit 1a1392d950
27 changed files with 341 additions and 271 deletions

View File

@ -85,7 +85,7 @@ class CartController extends Controller
$account = yii::$app->user->identity; $account = yii::$app->user->identity;
// Поиск корзины (текущего заказа) // Поиск корзины (текущего заказа)
$model = Order::search(); $model = Order::searchByType();
if (empty($model)) { if (empty($model)) {
// Корзина не инициализирована // Корзина не инициализирована
@ -137,7 +137,7 @@ class CartController extends Controller
goto end; goto end;
} }
if ($edges = OrderEdgeSupply::searchBySupplyCatn($catn, Order::search())) { if ($edges = OrderEdgeSupply::searchBySupplyCatn($catn, Order::searchByType())) {
// Рёбра найдены (связи заказа с поставкой) // Рёбра найдены (связи заказа с поставкой)
// Инициализация // Инициализация

View File

@ -266,7 +266,7 @@ class OrderController extends Controller
} }
// Инициализация заказов // Инициализация заказов
$orders = Order::search( $orders = Order::searchByType(
type: $type, type: $type,
limit: 10, limit: 10,
page: 1, page: 1,
@ -341,7 +341,7 @@ class OrderController extends Controller
Order::searchById($account_edge_order->_to)->journal('accepted'); 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(); $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'); $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1; $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
$account = yii::$app->user->identity; $account = yii::$app->user->identity;
$order = Order::search(); $order = Order::searchByType();
if ($targets) { if ($targets) {
// Удаление выбранных целей (удаление из заказа) // Удаление выбранных целей (удаление из заказа)
@ -466,7 +466,7 @@ class OrderController extends Controller
$edge->update(); $edge->update();
// Реинициализация // Реинициализация
$order = Order::search(); $order = Order::searchByType();
if (empty($order)) { if (empty($order)) {
// Корзина не инициализирована // Корзина не инициализирована
@ -509,7 +509,7 @@ class OrderController extends Controller
$targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets'); $targets = yii::$app->request->post('targets') ?? yii::$app->request->get('targets');
$page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1; $page = yii::$app->request->get('page') ?? yii::$app->request->post('page') ?? 1;
$account = yii::$app->user->identity; $account = yii::$app->user->identity;
$order = Order::search(); $order = Order::searchByType();
$connections = $order->content(10, $page); $connections = $order->content(10, $page);
foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) { 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 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'); $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] * @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 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) { foreach ($orders as &$order) {
// Перебор заказов // Перебор заказов
@ -697,9 +697,9 @@ class OrderController extends Controller
try { try {
// Инициализация данных геолокации // Инициализация данных геолокации
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) { } catch (Exception $e) {
$from = (int) Settings::search()->delivery_from_default ?? 36; $from = (int) Settings::searchActive()->delivery_from_default ?? 36;
} }
try { try {

View File

@ -84,7 +84,7 @@ class ProductController extends Controller
} }
if ($from = Product::searchByCatn($catn)) { if ($from = Product::searchByCatn($catn)) {
// Товар найден // Найден товар
if ($target = yii::$app->request->post('catn') ?? yii::$app->request->get('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)) { if ($to = Product::writeEmpty((string) $target)) {
// Удалось записать товар // Удалось записать товар
// Запись в буфер возврата
$return['alert'] = "Не удалось записать новый товар: $target";
} else { } 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 { } else {
// Не найден товар
// Запись кода ответа // Запись кода ответа
yii::$app->response->statusCode = 500; yii::$app->response->statusCode = 500;
@ -129,9 +134,7 @@ class ProductController extends Controller
goto end; goto end;
} }
/** // Конец алгоритма
* Конец алгоритма
*/
end: end:
if (yii::$app->request->isPost) { if (yii::$app->request->isPost) {
@ -180,42 +183,25 @@ class ProductController extends Controller
if ($from = Product::searchByCatn($catn)) { 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'] = "Продукты успешно отсоединены"; yii::$app->response->statusCode = 500;
} else {
// Не удалось удалить ребро (связь) // Запись в буфер возврата
$return['alert'] = "Не удалось отсоединить $target от $catn";
// Запись кода ответа // Переход в конец алгоритма
yii::$app->response->statusCode = 500; goto end;
// Запись в буфер возврата
$return['alert'] = "Не удалось отсоединить $target от $catn";
// Переход в конец алгоритма
goto end;
}
} else {
// Не существует товар который нужно отсоединить
// Запись кода ответа
yii::$app->response->statusCode = 500;
// Запись в буфер возврата
$return['alert'] = "Не удалось найти товар который нужно отсоединить: $catn";
// Переход в конец алгоритма
goto end;
}
} }
} else { } else {
// Запись кода ответа // Запись кода ответа
@ -228,9 +214,7 @@ class ProductController extends Controller
goto end; goto end;
} }
/** // Конец алгоритма
* Конец алгоритма
*/
end: end:
if (yii::$app->request->isPost) { if (yii::$app->request->isPost) {
@ -279,20 +263,35 @@ class ProductController extends Controller
if ($product = Product::searchByCatn($catn)) { if ($product = Product::searchByCatn($catn)) {
// Товар найден // Товар найден
if ($product->delete() > 0) { if ($product->disconnect()) {
// Удалось удалить // Отсоединён от аналогов
// Запись в буфер возврата if ($product->delete() > 0) {
$return['alert'] = "Товар удалён: $catn"; // Удалён
$return['location'] = '/';
// Запись в буфер возврата
$return['alert'] = "Товар удалён: $catn";
$return['location'] = '/';
} else {
// Не удалось удалить
// Запись кода ответа
yii::$app->response->statusCode = 500;
// Запись в буфер возврата
$return['alert'] = "Не удалось удалить товар: $catn";
// Переход в конец алгоритма
goto end;
}
} else { } else {
// Не удалось удалить // Не отсоединён от аналогов
// Запись кода ответа // Запись кода ответа
yii::$app->response->statusCode = 500; yii::$app->response->statusCode = 500;
// Запись в буфер возврата // Запись в буфер возврата
$return['alert'] = "Не удалось удалить товар: $catn"; $return['alert'] = "Не удалось отсоединить от аналогов перед удалением: $catn";
// Переход в конец алгоритма // Переход в конец алгоритма
goto end; goto end;
@ -355,12 +354,12 @@ class ProductController extends Controller
// Инициализация // Инициализация
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия'; $text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
$model->name = $text; $model->prod = $text;
if ($model->save()) { if ($model->save()) {
// Товар обновлён // Товар обновлён
$return['name'] = $text; $return['prod'] = $text;
} }
} }

View File

@ -488,7 +488,7 @@ class ProfileController extends Controller
// Инициализация // Инициализация
$groups = []; $groups = [];
foreach (SupplyGroup::readAll() as $group) { foreach (SupplyGroup::read() as $group) {
// Перебор всех групп // Перебор всех групп
// Генерация [КЛЮЧ => ИМЯ] // Генерация [КЛЮЧ => ИМЯ]

View File

@ -137,7 +137,7 @@ class SearchController extends Controller
if ($response = Product::searchByPartialCatn($query, $limit, [ if ($response = Product::searchByPartialCatn($query, $limit, [
'_key' => '_key', '_key' => '_key',
'catn' => 'catn', 'catn' => 'catn',
'name' => 'name', 'prod' => 'prod',
// Баг с названием DESC // Баг с названием DESC
'dscr' => 'dscr', 'dscr' => 'dscr',
'catg' => 'catg', 'catg' => 'catg',

View File

@ -103,16 +103,6 @@ class AccountForm extends Model
]; ];
} }
public function attributeLabels()
{
return [
'mail' => 'Почта',
'pswd' => 'Пароль',
'auto' => '<i class="fas fa-unlock"></i>',
'pols' => 'Политика конфедециальности'
];
}
public function validateMail($attribute, $params) public function validateMail($attribute, $params)
{ {
if (!$this->hasErrors()) { if (!$this->hasErrors()) {

View File

@ -62,10 +62,14 @@ abstract class Document extends ActiveRecord
* @todo Подождать обновление от ебаного Yii2 и добавить * @todo Подождать обновление от ебаного Yii2 и добавить
* проверку типов передаваемых параметров * проверку типов передаваемых параметров
*/ */
public function beforeSave($data): bool public function beforeSave($create): bool
{ {
if (parent::beforeSave($data)) { if (parent::beforeSave($create)) {
// Пройдена родительская проверка
if ($this->isNewRecord) { if ($this->isNewRecord) {
// Новая запись
// Запись в журнал // Запись в журнал
$this->jrnl = array_merge( $this->jrnl = array_merge(
[[ [[
@ -127,6 +131,15 @@ abstract class Document extends ActiveRecord
return isset($this->_key) && static::collectionName() ? static::collectionName() . '/' . $this->_key : null; 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 * @deprecated
*/ */
public static function readAll(): array public static function readAll(): array

View File

@ -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')) { if (str_contains($direction, 'OUTBOUND')) {
// Исходящие рёбра // Исходящие рёбра
@ -174,7 +174,7 @@ abstract class Edge extends Document
} else if (str_contains($direction, 'ANY')) { } 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) { if ($limit < 2) {

View File

@ -261,7 +261,7 @@ class Order extends Document implements DocumentInterface
* *
* @todo Привести в порядок * @todo Привести в порядок
*/ */
public static function search( public static function searchByType(
Account|string $account = null, Account|string $account = null,
string $type = 'current', string $type = 'current',
string|null $search = null, string|null $search = null,
@ -577,9 +577,9 @@ class Order extends Document implements DocumentInterface
try { try {
// Инициализация данных геолокации // Инициализация данных геолокации
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) { } 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 { try {
@ -640,9 +640,9 @@ class Order extends Document implements DocumentInterface
try { try {
// Инициализация данных геолокации // Инициализация данных геолокации
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) { } 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 { try {
@ -888,6 +888,6 @@ class Order extends Document implements DocumentInterface
*/ */
public static function count(int $limit = 500, bool $supplies = false): int 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);
} }
} }

View File

@ -16,8 +16,6 @@ use DateTime;
use DateTimeZone; use DateTimeZone;
use Exception; use Exception;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
use stdClass;
/** /**
* Продукт (в ассортименте магазина) * Продукт (в ассортименте магазина)
@ -81,7 +79,6 @@ class Product extends Document
parent::attributes(), parent::attributes(),
[ [
'catn', 'catn',
'name',
// В библеотеке есть баг на название DESC (неизвестно в моей или нет) // В библеотеке есть баг на название DESC (неизвестно в моей или нет)
'dscr', 'dscr',
'prod', 'prod',
@ -103,7 +100,6 @@ class Product extends Document
parent::attributeLabels(), parent::attributeLabels(),
[ [
'catn' => 'Каталожный номер (catn)', 'catn' => 'Каталожный номер (catn)',
'name' => 'Название (name)',
'dscr' => 'Описание (dscr)', 'dscr' => 'Описание (dscr)',
'prod' => 'Производитель (prod)', 'prod' => 'Производитель (prod)',
'dmns' => 'Габариты (dmns)', 'dmns' => 'Габариты (dmns)',
@ -140,16 +136,35 @@ class Product extends Document
'string', 'string',
'message' => '{attribute} должен быть строкой' 'message' => '{attribute} должен быть строкой'
], ],
[
'prod',
'string',
'length' => [3, 80],
'message' => '{attribute} должен быть строкой от 3 до 80 символов'
],
[ [
'imgs', 'imgs',
'arrayValidator', 'arrayValidator',
'message' => '{attribute} должен быть массивом' 'message' => '{attribute} должен быть массивом'
], ],
[
'dscr',
'string',
'length' => [3, 256],
'message' => '{attribute} должен быть строкой от 3 до 256 символов'
],
[ [
'dmns', 'dmns',
'arrayWithNumbersValidator', 'arrayWithNumbersValidator',
'message' => '{attribute} должен быть массивом и хранить циферные значения' 'message' => '{attribute} должен быть массивом и хранить циферные значения'
], ],
[
'wght',
'integer',
'min' => 0,
'max' => 30000,
'message' => '{attribute} должен иметь значение от 0 до 30000'
],
[ [
'file_excel', 'file_excel',
'required', 'required',
@ -185,28 +200,6 @@ class Product extends Document
'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"', 'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"',
'message' => 'Проблема при загрузке изображения', 'message' => 'Проблема при загрузке изображения',
'on' => self::SCENARIO_IMPORT_IMAGE '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 = []; $data = [];
$amount = 0; $created = 0;
$updated = 0;
$account = Account::initAccount($account); $account = Account::initAccount($account);
if ($this->validate()) { 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]; $timezone = $timezone[1][0];
$path = YII_PATH_PUBLIC . "/../assets/accounts/$account->_key/files/" . (new DateTime('now', new DateTimeZone($timezone)))->getTimestamp(); $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()) { if ($product->validate()) {
// Проверка пройдена // Проверка пройдена
// Запись документа if (($_product = $product->validateForUniqueness()) instanceof static) {
$product->save(); // Найден документ с такими параметрами
// Постинкрементация счётчика
$amount++;
// Запись группы // Инициализация буфера с параметрами загружаемого товара
// $group = static::class . 'Group'; $vars = $product->getAttributes();
// (new $group())->writeMember($product, $this->group);
// Удаление _key, чтобы не перезаписать его при замене параметров документа в буфере
unset($vars['_key']);
// Перенос данных в буфер (существующий в базе данных дубликат)
$_product->setAttributes($vars, false);
// Перезапись существующего документа
$_product->update();
$updated++;
} else {
// Не найден документ с такими параметрами
// Запись нового документа
if ($product->save()) $created++;
}
} else { } else {
// Проверка не пройдена // Проверка не пройдена
@ -412,14 +420,16 @@ class Product extends Document
$this->file_excel = null; $this->file_excel = null;
// Макрос действий после импорта // Макрос действий после импорта
static::afterImportExcel($amount); static::afterImportExcel($created, $updated);
return true; return true;
} }
// Запись ошибки
$this->addError('erros', 'Неизвестная ошибка'); $this->addError('erros', 'Неизвестная ошибка');
static::afterImportExcel($amount); // Макрос действий после импорта
static::afterImportExcel($created, $updated);
return false; return false;
} }
@ -432,7 +442,7 @@ class Product extends Document
* *
* @todo Переделать нормально * @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) { if ($limit <= 1) {
return static::findOne(['catn' => $catn]); return static::findOne(['catn' => $catn]);
@ -488,23 +498,24 @@ class Product extends Document
/** /**
* Вызывается после загрузки поставок из excel-документа * Вызывается после загрузки поставок из 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; $model = new Notification;
$account = yii::$app->user->identity; $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]; $timezone = $timezone[1][0];
// Инициализация даты // Инициализация даты
$date = (new DateTime('now', new DateTimeZone($timezone)))->format('H:i d.m.Y'); $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; $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]; $timezone = $timezone[1][0];
$date = (new DateTime('now', new DateTimeZone($timezone)))->format('H:i d.m.Y'); $date = (new DateTime('now', new DateTimeZone($timezone)))->format('H:i d.m.Y');
@ -685,20 +696,20 @@ class Product extends Document
/** /**
* Подключение аналога * Подключение аналога
* *
* СВЯЗЫВАЕТ ТОЛЬКО ДВА ТОВАРА, ГРУППА ОСТАНЕТСЯ НЕИЗМЕННОЙ
*
* @param self $to Цель * @param self $to Цель
*
* @return ProductEdgeProduct|null Ребро между товарами, если создалось
*/ */
public function connect(self $to): ?ProductEdgeProduct public function connect(self $to): ?ProductEdgeProduct
{ {
if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_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", limit: 1)) { } else if (ProductEdgeProduct::searchByVertex(Product::collectionName() . "/$to->_key", Product::collectionName() . "/$this->_key", type: 'analogue')) {
// Дубликат найден (наоборот) // Найдено ребро (наоборот)
// Вероятно эта проверка здесь не нужна, так как мы знаем входные данные // !!! Вероятно эта проверка здесь не нужна, так как мы знаем входные данные
} else { } else {
// Дубликаты не найдены // Не найдены ребра
if ($edge = ProductEdgeProduct::write(Product::collectionName() . "/$this->_key", Product::collectionName() . "/$to->_key", data: ['type' => 'analogue'])) { 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 (isset($to)) {
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 {
// Не найдены ребра
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 ($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', [ $this->journal('disconnect analogue', [
'to' => Product::collectionName() . "/$to->_key" 'to' => Product::collectionName() . "/$to->_key"
@ -767,7 +812,7 @@ class Product extends Document
// Инициализация буфера связанных товаров // Инициализация буфера связанных товаров
$products = []; $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 $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;
}
} }

View File

@ -197,9 +197,9 @@ class Search extends Document
// Инициализация данных геолокации // Инициализация данных геолокации
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) { } 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 { try {
@ -275,9 +275,9 @@ class Search extends Document
} }
try { 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) { } 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 { try {
@ -357,42 +357,33 @@ class Search extends Document
* Генерация HTML-кода с найденным товаром * Генерация HTML-кода с найденным товаром
* *
* @param array $row Товар сгенерированный через Search::content() * @param array $row Товар сгенерированный через Search::content()
* @param string|null $cpny Компания (сейчас пока что это $name - Название) * @param string|null $cover Обложка
* @param string|null $covr Обложка
* @param string|null $catg Категория
* @param string|null $catn Артикул
* @param array $empties Реестр не найденных товаров * @param array $empties Реестр не найденных товаров
* *
* @return string HTML-элемент с товаром * @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
{ {
// Инициализация foreach ($row['imgs'] ?? [] as &$img) {
extract($row);
$cpny ?? $cpny = 'Без названия';
// $dscr ?? $dscr = 'Описание';
$catg ?? $catg = 'Категория';
$catn ?? $catn = 'Неизвестно';
foreach ($imgs ?? [] as $img) {
// Перебор изображений для обложки // Перебор изображений для обложки
if ($img['covr'] ?? false) { if ($img['covr'] ?? false) {
// Обложка найдена // Найдена обложка
$covr = $img['h150']; $cover = $img['h150'];
break; 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; HTML;
// Запись в список ненайденных // Запись в список ненайденных
$empties[] = $catn; $empties[] = $row['catn'];
// Запись блокировщика // Запись блокировщика
$empty_block = true; $empty_block = true;
@ -534,7 +525,7 @@ class Search extends Document
<small class="col-1 my-auto pl-2 pr-0 text-center">$amount</small> <small class="col-1 my-auto pl-2 pr-0 text-center">$amount</small>
<small class="col-auto mr-2 my-auto pl-2 pr-0 text-left" title="Ориентировочно">$delivery_icon $delivery дн</small> <small class="col-auto mr-2 my-auto pl-2 pr-0 text-left" title="Ориентировочно">$delivery_icon $delivery дн</small>
<b class="col-auto my-auto my-auto text-center">$price</b> <b class="col-auto my-auto my-auto text-center">$price</b>
<a class="col-1 ml-0 py-2 text-dark d-flex button_white rounded" title="Добавить $catn в корзину" role="button" onclick="return cart_write('{$supply['_id']}', '$delivery_type');"> <a class="col-1 ml-0 py-2 text-dark d-flex button_white rounded" title="Добавить {$row['catn']} в корзину" role="button" onclick="return cart_write('{$supply['_id']}', '$delivery_type');">
<i class="fas fa-cart-arrow-down pr-1 m-auto"></i> <i class="fas fa-cart-arrow-down pr-1 m-auto"></i>
</a> </a>
</div> </div>

View File

@ -79,7 +79,7 @@ class Settings extends Document
* *
* @todo Доделать * @todo Доделать
*/ */
public static function search(): ?self public static function searchActive(): ?self
{ {
return static::findOne(['active' => true]); return static::findOne(['active' => true]);
} }

View File

@ -16,6 +16,7 @@ use carono\exchange1c\interfaces\ProductInterface;
use carono\exchange1c\controllers\ApiController; use carono\exchange1c\controllers\ApiController;
use Exception; use Exception;
use Throwable;
/** /**
* Поставка (выгрузка товаров от поставщиков) * Поставка (выгрузка товаров от поставщиков)
@ -68,10 +69,10 @@ class Supply extends Product implements ProductInterface, OfferInterface
return array_merge( return array_merge(
parent::attributeLabels(), parent::attributeLabels(),
[ [
'cost' => 'Стоимость (cost)', 'cost' => 'Стоимость',
'onec' => 'Данные 1С', 'onec' => 'Данные 1С',
'oemn' => 'OEM-номера', '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::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()); 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) { if ($type === 1) {
return match($dlvr) { return match ($dlvr) {
'avia' => 'доставкой самолётом', 'avia' => 'доставкой самолётом',
default => 'автоматической доставкой' default => 'автоматической доставкой'
}; };
} else { } else {
return match($dlvr) { return match ($dlvr) {
'avia' => 'Самолёт', 'avia' => 'Самолёт',
default => 'Автоматическая' default => 'Автоматическая'
}; };

View File

@ -6,7 +6,6 @@ namespace app\models;
use app\models\traits\Xml2Array; use app\models\traits\Xml2Array;
use carono\exchange1c\interfaces\OfferInterface; use carono\exchange1c\interfaces\OfferInterface;
use Zenwalker\CommerceML\Model\Offer;
class SupplyEdgeProduct extends Edge implements OfferInterface class SupplyEdgeProduct extends Edge implements OfferInterface
{ {

View File

@ -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]; $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]; $timezone = $timezone[1][0];
// Инициализация параметров // Инициализация параметров

View File

@ -86,7 +86,7 @@ use app\models\Settings;
<?php <?php
// Инициализация часового пояса // Инициализация часового пояса
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]; $timezone = $timezone[1][0];
?> ?>
<b>Счет на оплату <?= $order['id'] ?> от <?= (new DateTime())->setTimestamp($order['date'])->setTimezone(new DateTimeZone($timezone))->format('d.m.Y') ?></b> <b>Счет на оплату <?= $order['id'] ?> от <?= (new DateTime())->setTimestamp($order['date'])->setTimezone(new DateTimeZone($timezone))->format('d.m.Y') ?></b>

View File

@ -95,14 +95,17 @@ AppAsset::register($this);
<h5 class="row mb-2 unselectable"><b>Контакты</b></h5> <h5 class="row mb-2 unselectable"><b>Контакты</b></h5>
<small class="row mb-1"><b>Адрес:&nbsp;</b>Хабаровск, Промышленная 3, 105</small> <small class="row mb-1"><b>Адрес:&nbsp;</b>Хабаровск, Промышленная 3, 105</small>
<small class="row mb-1"><b>Время работы:&nbsp;</b>пн-пт 09:00-18:00</small> <small class="row mb-1"><b>Время работы:&nbsp;</b>пн-пт 09:00-18:00</small>
<small class="row mb-1"><b>Телефон:&nbsp;</b>+7 (4212) 35-85-34</small> <small class="row mb-1"><b>Телефон:&nbsp;</b><a href="tel:+74212358534">+7 (4212) 35-85-34</a></small>
<small class="row mb-1"><b>Почта:&nbsp;</b>info@skillparts.ru</small> <small class="row"><b>Почта:&nbsp;</b><a href="mailto:info@skillparts.ru">info@skillparts.ru</a></small>
</div> </div>
<div class="col-md-auto mr-md-5 partnership unselectable"> <div class="col-md-auto mr-md-5 partnership unselectable">
<h5 class="row mb-2"><b>Партнёрство</b></h5> <h5 class="row mb-2"><b>Партнёрство</b></h5>
<small class="row mb-1"><a href="/buyers">Покупателям</a></small> <small class="row mb-1"><a href="/buyers">Покупателям</a></small>
<small class="row mb-1"><a href="/suppliers">Поставщикам</a></small> <small class="row mb-1"><a href="/suppliers">Поставщикам</a></small>
<small class="row mb-1"><a href="/partners">Сеть филиалов</a></small> <small class="row"><a href="/partners">Сеть филиалов</a></small>
</div>
<div class="mt-auto ml-auto col-auto unselectable">
<small class="row"><a href="mailto:info@skillparts.ru?subject=Ошибка на сайте">Сообщить об ошибке</a></small>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -14,7 +14,7 @@ foreach ($notification->jrnl as $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]; $timezone = $timezone[1][0];
// Инициализация данных для генерации HTML // Инициализация данных для генерации HTML

View File

@ -1,13 +1,25 @@
<?php <?php
if($amount > 0) { if ($created > 0 && $updated > 0) {
// Записаны новые и обновлены существующие документы
echo <<<HTML echo <<<HTML
<p>Импортировано $amount товаров из excel-документа <span>($date)</span></p> <p>Записано $created новых товаров и $updated товара обновлено</p>
HTML;
} else if ($created > 0) {
// Записаны новые документы
echo <<<HTML
<p>Записано $created новых товаров</p>
HTML;
} else if ($updated > 0) {
// Записаны новые документы
echo <<<HTML
<p>Обновлено $updated товаров</p>
HTML; HTML;
} else { } else {
echo <<<HTML echo <<<HTML
<p>Неудачная попытка импорта товаров из excel-документа <span>($date)</span></p> <p>Неудачная попытка импорта товаров из excel-документа</p>
HTML; HTML;
} }
?>

View File

@ -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]; $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]; $timezone = $timezone[1][0];
// Запись данных о дате заказа // Запись данных о дате заказа
@ -516,7 +516,7 @@ if (empty($window)) {
orders_calendar_ready = false; orders_calendar_ready = false;
<?php <?php
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]; $timezone = $timezone[1][0];
?> ?>

View File

@ -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]; $timezone = $timezone[1][0];
foreach ($rows as $row) { foreach ($rows as $row) {

View File

@ -71,7 +71,7 @@ use app\models\Product;
// Перебор изображений для генерации полных версий // Перебор изображений для генерации полных версий
// Инициализация // Инициализация
$name = $image['name'] ?? 'Без названия'; $prod = $image['prod'] ?? 'Неизвестный';
$orig = $image['orig'] ?? '/img/covers/product.png'; $orig = $image['orig'] ?? '/img/covers/product.png';
if (($image['covr'] ?? false) || ($covr_not_found && $key === 0)) { 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 === 'administrator'
|| yii::$app->user->identity->type === 'moderator') || yii::$app->user->identity->type === 'moderator')
) : ?> ) : ?>
<h3 id="title_<?= $model['catn'] ?>" class="my-auto pointer-event product_title" role="button" onclick="return product_panel_title_edit('<?= $model['catn'] ?>', this);"><?= $model['name'] ?? 'Без названия' ?></h3> <h3 id="title_<?= $model['catn'] ?>" class="my-auto pointer-event product_title" role="button" onclick="return product_panel_title_edit('<?= $model['catn'] ?>', this);"><?= $model['prod'] ?? 'Без названия' ?></h3>
<?php else : ?> <?php else : ?>
<h3 id="title_<?= $model['catn'] ?>" class="my-auto"><?= $model['name'] ?? 'Без названия' ?></h3> <h3 id="title_<?= $model['catn'] ?>" class="my-auto"><?= $model['prod'] ?? 'Без названия' ?></h3>
<?php endif ?> <?php endif ?>
</div> </div>
@ -207,7 +207,7 @@ use app\models\Product;
) : ?> ) : ?>
<p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break pointer-event product_description" role="button" onclick="return product_panel_description_edit('<?= $model['catn'] ?>', this);"><?= $model['dscr'] ?? 'Без описания' ?></p> <p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break pointer-event product_description" role="button" onclick="return product_panel_description_edit('<?= $model['catn'] ?>', this);"><?= $model['dscr'] ?? 'Без описания' ?></p>
<?php else : ?> <?php else : ?>
<p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break product_description"><?= $model['name'] ?? 'Без описания' ?></p> <p id="description_<?= $model['catn'] ?>" class="mt-0 ml-0 text-break product_description"><?= $model['prod'] ?? 'Без описания' ?></p>
<?php endif ?> <?php endif ?>
<p class="mt-0"> <p class="mt-0">
<?php <?php

View File

@ -41,7 +41,7 @@ $panel ?? $panel = 'profile_panel_monitoring_input_search_history';
$time = $row->jrnl; $time = $row->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]; $timezone = $timezone[1][0];
$date = empty($row->jrnl) ? '' : (new DateTime())->setTimestamp(end($time)['date'])->setTimezone(new DateTimeZone($timezone))->format('H:i d.m.Y'); $date = empty($row->jrnl) ? '' : (new DateTime())->setTimestamp(end($time)['date'])->setTimezone(new DateTimeZone($timezone))->format('H:i d.m.Y');

View File

@ -9,7 +9,7 @@ use app\models\Search;
<link href="/css/pages/search.css" rel="stylesheet"> <link href="/css/pages/search.css" rel="stylesheet">
<div id="page_search" class="container flex-grow-1 d-flex"> <div id="page_search" class="px-0 py-4 container flex-grow-1 d-flex flex-column">
<?php <?php
if (isset($timer) && $timer > 0) : ?> if (isset($timer) && $timer > 0) : ?>
@ -28,90 +28,78 @@ use app\models\Search;
<?php else : ?> <?php else : ?>
<?php if (isset($response) && is_array($response) && $response) : ?> <?php if (isset($response) && is_array($response) && $response) : ?>
<div class="row py-4 w-100 flex-column"> <section class="mb-4 col-auto">
<section class="col-auto mb-4"> <h4 class="ml-4 mb-3">Товары по запросу: "<?= $query ?? 'ошибка чтения запроса' ?>"</h4>
<h4 class="ml-4 mb-3">Товары по запросу: "<?= $query ?? 'ошибка чтения запроса' ?>"</h4>
<?php foreach ($response as $row) : ?> <?php foreach ($response as $row) : ?>
<?php <?php
// Инициализация данных товара // Инициализация данных товара
$cpny = $covr = $catg = $catn = null; $covr = null;
$prod = $row['prod'] ?? 'Неизвестно';
$catn = $row['catn'] ?? 'Неизвестно';
// Инициализация реестра пустышек (товаров без поставок или с ошибками) // Инициализация реестра пустышек (товаров без поставок или с ошибками)
$empties = []; $empties = [];
// Генерация списка товаров // Генерация списка товаров
$supplies_html = Search::generate($row, $cpny, $covr, $catg, $catn, $empties); $supplies_html = Search::generate($row, $covr, $empties);
?>
extract($row); <div class="col mb-2">
?> <div class="row p-2 rounded">
<div class="col mb-2"> <img class="ml-0 rounded" src="<?= $covr ?>" />
<div class="row p-2 rounded"> <div class="col-3 ml-3 p-0 d-flex flex-column row_fixed_height">
<img class="ml-0 h-100 img-fluid rounded" src="<?= $covr ?>" /> <a class="my-auto text-dark" href="/product/<?= $catn ?>">
<div class="col-3 ml-3 p-0 d-flex flex-column row_fixed_height"> <h5 class="m-0"><?= $catn ?></h5>
<a class="my-auto text-dark" href="/product/<?= $catn ?>"> <h6 class="m-0"><small><?= $prod ?></small></h6>
<h5 class="m-0"><?= $cpny ?></h5> </a>
<h6 class="m-0"><small><?= $catn ?></small></h6> </div>
</a> <div class="col ml-3 p-0 d-flex flex-column">
</div> <?= $supplies_html ?>
<!-- <div class="col-1 ml-2 p-0 d-flex flex-column row_fixed_height">
<a class="my-auto text-dark" href="/product/<?= $catn ?>">
<small><?= $catg ?></small>
</a>
</div> -->
<div class="col ml-3 p-0 d-flex flex-column">
<?= $supplies_html ?>
</div>
</div> </div>
</div> </div>
<?php endforeach ?> </div>
</section> <?php endforeach ?>
</section>
<?php if (!empty($empties)) : ?> <?php if (!empty($empties)) : ?>
<section class="col"> <section class="col">
<?php foreach ($empties as $catn) : ?> <?php foreach ($empties as $catn) : ?>
<?php if ($products = Search::content(products: Product::searchAnalogs($catn))) : ?> <?php if ($products = Search::content(products: Product::searchAnalogs($catn))) : ?>
<h4 class="ml-4 mb-3">Аналогичные товары</h4> <h4 class="ml-4 mb-3">Аналогичные товары</h4>
<?php foreach ($products as $product) : ?> <?php foreach ($products as $product) : ?>
<?php <?php
// Инициализация данных товара // Инициализация данных товара
$cpny = $covr = $catg = $catn = null; $covr = null;
$prod = $product['prod'] ?? 'Неизвестно';
$catn = $product['catn'] ?? 'Неизвестно';
// Генерация списка товаров // Генерация списка товаров
$supplies_html = Search::generate($product, $cpny, $covr, $catg, $catn); $supplies_html = Search::generate($product, $covr);
?>
extract($product); <div class="col mb-2">
?> <div class="row p-2 rounded">
<div class="col mb-2"> <img class="ml-0 rounded" src="<?= $covr ?>" />
<div class="row p-2 rounded"> <div class="col-3 ml-3 p-0 d-flex flex-column row_fixed_height">
<img class="ml-0 h-100 img-fluid rounded" src="<?= $covr ?>" />
<div class="col-3 ml-3 p-0 d-flex flex-column row_fixed_height">
<a class="my-auto text-dark" href="/product/<?= $catn ?>">
<h5 class="m-0"><?= $cpny ?></h5>
<h6 class="m-0"><small><?= $catn ?></small></h6>
</a>
</div>
<!-- <div class="col-1 ml-2 p-0 d-flex flex-column row_fixed_height">
<a class="my-auto text-dark" href="/product/<?= $catn ?>"> <a class="my-auto text-dark" href="/product/<?= $catn ?>">
<small><?= $catg ?></small> <h5 class="m-0"><?= $catn ?></h5>
<h6 class="m-0"><small><?= $prod ?></small></h6>
</a> </a>
</div> --> </div>
<div class="col ml-3 p-0 d-flex flex-column"> <div class="col ml-3 p-0 d-flex flex-column">
<?= $supplies_html ?> <?= $supplies_html ?>
</div>
</div> </div>
</div> </div>
<?php endforeach ?> </div>
<?php endforeach ?>
<?php endif ?> <?php endif ?>
<?php endforeach ?> <?php endforeach ?>
</section> </section>
<?php endif ?> <?php endif ?>
</div>
<?php else : ?> <?php else : ?>
<?php if ($advanced ?? false) : ?> <?php if ($advanced ?? false) : ?>

View File

@ -24,7 +24,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]; $timezone = $timezone[1][0];
foreach ($rows as $row) { foreach ($rows as $row) {

View File

@ -12,6 +12,7 @@
#page_search section>div>div>img { #page_search section>div>div>img {
object-fit: cover; object-fit: cover;
width: calc(65px - 1rem); width: calc(65px - 1rem);
height: calc(65px - 1rem);
} }
/* #page_search nav > div, #page_search section > div:hover > div { /* #page_search nav > div, #page_search section > div:hover > div {

View File

@ -328,7 +328,7 @@ function product_panel_disconnect(catn) {
dataType: 'json', dataType: 'json',
data: { data: {
'_csrf': yii.getCsrfToken(), '_csrf': yii.getCsrfToken(),
'catn': prompt('Отключить аналог') 'catn': prompt('Отсоединить аналог (пустое поле - все аналоги)')
}, },
success: product_response_success, success: product_response_success,
error: product_response_error error: product_response_error