Активные и неактивные товары
This commit is contained in:
parent
a971aef392
commit
4c91c3192a
|
@ -589,21 +589,27 @@ class OrderController extends Controller
|
||||||
$model = Order::searchByType(supplies: true);
|
$model = Order::searchByType(supplies: true);
|
||||||
|
|
||||||
// Поиск ребра
|
// Поиск ребра
|
||||||
$edge = AccountEdgeOrder::searchByVertex(yii::$app->user->id, $model->readId(), 'current');
|
$account_edge_order = AccountEdgeOrder::searchByVertex(yii::$app->user->id, $model->readId(), 'current')[0];
|
||||||
|
|
||||||
if (count($edge) > 1) {
|
if ($supplies = OrderEdgeSupply::searchByDirection($account_edge_order->to)) {
|
||||||
|
// Поставки найдены
|
||||||
|
|
||||||
|
// Добавить проверку на то, что товары активны
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($supplies); die;
|
||||||
|
|
||||||
|
if (count($account_edge_order) > 1) {
|
||||||
// Найден более чем 1 заказ
|
// Найден более чем 1 заказ
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
$edge = $edge[0];
|
|
||||||
|
|
||||||
// Запись
|
// Запись
|
||||||
$edge->type = 'requested';
|
$account_edge_order->type = 'requested';
|
||||||
|
|
||||||
if ($edge->update()) {
|
if ($account_edge_order->update()) {
|
||||||
// Удалось сохранить изменения
|
// Удалось сохранить изменения
|
||||||
|
|
||||||
// Запись в журнал
|
// Запись в журнал
|
||||||
|
@ -613,6 +619,8 @@ class OrderController extends Controller
|
||||||
$supplies = [];
|
$supplies = [];
|
||||||
|
|
||||||
foreach ($model['supplies'] as $supply) {
|
foreach ($model['supplies'] as $supply) {
|
||||||
|
// Перебор поставок
|
||||||
|
|
||||||
$supplies[] = [
|
$supplies[] = [
|
||||||
'title' => $supply['supply']['catn'],
|
'title' => $supply['supply']['catn'],
|
||||||
'amount' => [
|
'amount' => [
|
||||||
|
@ -634,13 +642,13 @@ class OrderController extends Controller
|
||||||
],
|
],
|
||||||
'order' => [
|
'order' => [
|
||||||
'id' => $model->_key,
|
'id' => $model->_key,
|
||||||
'date' => $edge->date ?? time(),
|
'date' => $account_edge_order->date ?? time(),
|
||||||
'entries' => $supplies
|
'entries' => $supplies
|
||||||
]
|
]
|
||||||
]));
|
]));
|
||||||
|
|
||||||
// Отправка уведомлений модераторам
|
// Отправка уведомлений модераторам
|
||||||
Notification::_write($this->renderPartial('/notification/system/orders/new', ['id' => $edge->_key]), true, '@auth', Notification::TYPE_MODERATOR_ORDER_NEW);
|
Notification::_write($this->renderPartial('/notification/system/orders/new', ['id' => $account_edge_order->_key]), true, '@auth', Notification::TYPE_MODERATOR_ORDER_NEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->actionIndex();
|
return $this->actionIndex();
|
||||||
|
|
|
@ -5,18 +5,82 @@ declare(strict_types=1);
|
||||||
namespace app\controllers;
|
namespace app\controllers;
|
||||||
|
|
||||||
use yii;
|
use yii;
|
||||||
use yii\filters\AccessControl;
|
|
||||||
use yii\web\Controller;
|
use yii\web\Controller;
|
||||||
use yii\web\Response;
|
use yii\web\Response;
|
||||||
use yii\web\HttpException;
|
use yii\web\HttpException;
|
||||||
use yii\web\UploadedFile;
|
use yii\web\UploadedFile;
|
||||||
|
use yii\filters\AccessControl;
|
||||||
|
|
||||||
use app\models\Product;
|
use app\models\Product;
|
||||||
|
use app\models\Settings;
|
||||||
use app\models\SupplyEdgeProduct;
|
use app\models\SupplyEdgeProduct;
|
||||||
use app\models\Supply;
|
use app\models\Supply;
|
||||||
|
use app\models\Account;
|
||||||
|
use app\models\Notification;
|
||||||
|
use app\models\OrderEdgeSupply;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class ProductController extends Controller
|
class ProductController extends Controller
|
||||||
{
|
{
|
||||||
|
public function behaviors()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'access' => [
|
||||||
|
'class' => AccessControl::class,
|
||||||
|
'rules' => [
|
||||||
|
[
|
||||||
|
'allow' => true,
|
||||||
|
'actions' => [
|
||||||
|
'index',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'allow' => true,
|
||||||
|
'roles' => ['@'],
|
||||||
|
'actions' => []
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'allow' => true,
|
||||||
|
'actions' => [
|
||||||
|
'read',
|
||||||
|
'write',
|
||||||
|
'delete',
|
||||||
|
'connect',
|
||||||
|
'disconnect',
|
||||||
|
'edit-title',
|
||||||
|
'edit-catn',
|
||||||
|
'edit-dscr',
|
||||||
|
'edit-dmns',
|
||||||
|
'edit-wght',
|
||||||
|
'write-image',
|
||||||
|
'delete-image',
|
||||||
|
'write-cover',
|
||||||
|
'write-image',
|
||||||
|
'status'
|
||||||
|
],
|
||||||
|
'matchCallback' => function ($rule, $action): bool {
|
||||||
|
if (
|
||||||
|
!yii::$app->user->isGuest
|
||||||
|
&& (yii::$app->user->identity->type === 'administrator'
|
||||||
|
|| yii::$app->user->identity->type === 'moderator')
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'allow' => false,
|
||||||
|
'roles' => ['?'],
|
||||||
|
'denyCallback' => [$this, 'accessDenied']
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function actionIndex(string $catn): array|string|null
|
public function actionIndex(string $catn): array|string|null
|
||||||
{
|
{
|
||||||
if ($model = Product::searchByCatn($catn)) {
|
if ($model = Product::searchByCatn($catn)) {
|
||||||
|
@ -143,6 +207,44 @@ class ProductController extends Controller
|
||||||
return $this->redirect("/");
|
return $this->redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Чтение товаров
|
||||||
|
*
|
||||||
|
* @param string $stts Статус
|
||||||
|
*
|
||||||
|
* @return string|array|null
|
||||||
|
*/
|
||||||
|
public function actionRead(string $stts = 'all'): string|array|null
|
||||||
|
{
|
||||||
|
if (yii::$app->request->isPost) {
|
||||||
|
// POST-запрос
|
||||||
|
|
||||||
|
// Инициализация входных параметров
|
||||||
|
$amount = yii::$app->request->post('amount') ?? yii::$app->request->get('amount') ?? 50;
|
||||||
|
$order = yii::$app->request->post('order') ?? yii::$app->request->get('order') ?? ['DESC'];
|
||||||
|
|
||||||
|
// Инициализация cookie
|
||||||
|
$cookies = yii::$app->response->cookies;
|
||||||
|
|
||||||
|
|
||||||
|
// Инициализация аккаунта
|
||||||
|
$account ?? $account = Account::initAccount();
|
||||||
|
|
||||||
|
// Чтение товаров
|
||||||
|
$products = Product::read(where: $stts === 'all' || $stts === 'inactive' ? [] : ['stts' => $stts], limit: $amount, order: $order);
|
||||||
|
|
||||||
|
// Запись формата ответа
|
||||||
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'products' => $this->renderPartial('/product/list', compact('account', 'products')),
|
||||||
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Удаление товара
|
* Удаление товара
|
||||||
*
|
*
|
||||||
|
@ -307,7 +409,7 @@ class ProductController extends Controller
|
||||||
yii::$app->response->statusCode = 500;
|
yii::$app->response->statusCode = 500;
|
||||||
|
|
||||||
// Запись в буфер возврата
|
// Запись в буфер возврата
|
||||||
$return['alert'] = "Не удалось найти товар к которому требуется соединение: $catn";
|
$return['alert'] = "Не удалось найти товар: $catn";
|
||||||
|
|
||||||
// Переход в конец алгоритма
|
// Переход в конец алгоритма
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -848,4 +950,81 @@ class ProductController extends Controller
|
||||||
return $this->redirect('/');
|
return $this->redirect('/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Изменение статуса
|
||||||
|
*
|
||||||
|
* @param string $catn Артикул
|
||||||
|
*/
|
||||||
|
public function actionStatus(string $catn): array|string|null
|
||||||
|
{
|
||||||
|
if (yii::$app->request->isPost) {
|
||||||
|
// POST-запрос
|
||||||
|
|
||||||
|
// Запись заголовка с форматом ответа
|
||||||
|
yii::$app->response->format = Response::FORMAT_JSON;
|
||||||
|
|
||||||
|
// Инициализация буфера ответа
|
||||||
|
$return = [
|
||||||
|
'_csrf' => yii::$app->request->getCsrfToken()
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($catn)) {
|
||||||
|
// Не получен артикул
|
||||||
|
|
||||||
|
// Запись кода ответа
|
||||||
|
yii::$app->response->statusCode = 500;
|
||||||
|
|
||||||
|
// Переход в конец алгоритма
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($product = Product::searchByCatn($catn)) {
|
||||||
|
// Найден товар
|
||||||
|
|
||||||
|
// Запись старого статуса
|
||||||
|
$old = $product->stts;
|
||||||
|
|
||||||
|
// Запись параметров
|
||||||
|
$product->stts = $stts = yii::$app->request->post('stts') ?? 'inactive';
|
||||||
|
|
||||||
|
if ($product->update() > 0) {
|
||||||
|
// Записаны изменения
|
||||||
|
|
||||||
|
// Запись в журнал
|
||||||
|
$product->journal(data: [
|
||||||
|
'stts' => [
|
||||||
|
'old' => $old,
|
||||||
|
'new' => $stts
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$return['main'] = $this->renderPartial('index', ['model' => $product]);
|
||||||
|
} else {
|
||||||
|
// Не записаны изменения
|
||||||
|
|
||||||
|
// Отправка уведомления
|
||||||
|
Notification::_write("Не удалось изменить статус на $stts у товара $catn", type: Notification::TYPE_ERROR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Не найден товар
|
||||||
|
|
||||||
|
// Запись кода ответа
|
||||||
|
yii::$app->response->statusCode = 500;
|
||||||
|
|
||||||
|
// Отправка уведомления
|
||||||
|
Notification::_write("Не удалось найти товар $catn", type: Notification::TYPE_ERROR);
|
||||||
|
|
||||||
|
// Переход в конец алгоритма
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Конец алгоритма
|
||||||
|
end:
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ class SearchController extends Controller
|
||||||
|
|
||||||
$limit = yii::$app->request->isPost ? 10 : 20;
|
$limit = yii::$app->request->isPost ? 10 : 20;
|
||||||
|
|
||||||
if ($response = Product::searchByPartialCatn($query, $limit, [
|
if ($response = Product::searchByPartialCatn($query, 'active', $limit, [
|
||||||
'_key' => '_key',
|
'_key' => '_key',
|
||||||
'catn' => 'catn',
|
'catn' => 'catn',
|
||||||
'prod' => 'prod',
|
'prod' => 'prod',
|
||||||
|
|
|
@ -168,9 +168,9 @@ abstract class Document extends ActiveRecord
|
||||||
/**
|
/**
|
||||||
* Чтение записей по максимальному ограничению
|
* Чтение записей по максимальному ограничению
|
||||||
*/
|
*/
|
||||||
public static function read(int $limit = 100, array|null $order = null): array
|
public static function read(?array $where = [], int $limit = 100, ?array $order = null): array
|
||||||
{
|
{
|
||||||
return static::find()->limit($limit)->orderby($order)->all();
|
return static::find()->where($where)->orderby($order)->limit($limit)->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -89,6 +89,7 @@ class Product extends Document
|
||||||
'imgs',
|
'imgs',
|
||||||
'time',
|
'time',
|
||||||
'bffr',
|
'bffr',
|
||||||
|
'stts'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +110,7 @@ class Product extends Document
|
||||||
'imgs' => 'Изображения (imgs)',
|
'imgs' => 'Изображения (imgs)',
|
||||||
'time' => 'Срок доставки (time)',
|
'time' => 'Срок доставки (time)',
|
||||||
'bffr' => 'Буфер',
|
'bffr' => 'Буфер',
|
||||||
|
'stts' => 'Статус',
|
||||||
'file_excel' => 'Документ (file_excel)',
|
'file_excel' => 'Документ (file_excel)',
|
||||||
'file_image' => 'Изображение (file_image)',
|
'file_image' => 'Изображение (file_image)',
|
||||||
'group' => 'Группа (group)',
|
'group' => 'Группа (group)',
|
||||||
|
@ -168,6 +170,12 @@ class Product extends Document
|
||||||
'max' => 30000,
|
'max' => 30000,
|
||||||
'message' => '{attribute} должен иметь значение от 0 до 30000'
|
'message' => '{attribute} должен иметь значение от 0 до 30000'
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'stts',
|
||||||
|
'string',
|
||||||
|
'length' => [4, 20],
|
||||||
|
'message' => '{attribute} должен быть строкой от 4 до 20 символов'
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'file_excel',
|
'file_excel',
|
||||||
'file',
|
'file',
|
||||||
|
@ -201,6 +209,29 @@ class Product extends Document
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Перед сохранением
|
||||||
|
*
|
||||||
|
* @todo Подождать обновление от ебаного Yii2 и добавить
|
||||||
|
* проверку типов передаваемых параметров
|
||||||
|
*/
|
||||||
|
public function beforeSave($create): bool
|
||||||
|
{
|
||||||
|
if (parent::beforeSave($create)) {
|
||||||
|
// Пройдена родительская проверка
|
||||||
|
|
||||||
|
if ($this->isNewRecord) {
|
||||||
|
// Новая запись
|
||||||
|
|
||||||
|
$this->stts = 'inactive';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Запись пустого продукта
|
* Запись пустого продукта
|
||||||
*/
|
*/
|
||||||
|
@ -346,11 +377,12 @@ class Product extends Document
|
||||||
*
|
*
|
||||||
* @todo Переделать нормально
|
* @todo Переделать нормально
|
||||||
*/
|
*/
|
||||||
public static function searchByPartialCatn(string $catn, int $limit = 1, array $select = []): static|array|null
|
public static function searchByPartialCatn(string $catn, string $stts = 'active', int $limit = 1, array $select = []): static|array|null
|
||||||
{
|
{
|
||||||
$query = self::find()
|
$query = self::find()
|
||||||
->for('product')
|
->for('product')
|
||||||
->in('product_search')
|
->in('product_search')
|
||||||
|
->where(['stts' => $stts])
|
||||||
->filter(['catn' => $catn], 'START_SENSETIVE')
|
->filter(['catn' => $catn], 'START_SENSETIVE')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
->orderBy(['catn' => 'ASC'])
|
->orderBy(['catn' => 'ASC'])
|
||||||
|
|
|
@ -118,7 +118,7 @@ class Search extends Document
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Поиск содержимого поиска
|
* Поиск содержимого поиска (продуктов)
|
||||||
*
|
*
|
||||||
* @todo В будущем возможно заказ не только поставок реализовать
|
* @todo В будущем возможно заказ не только поставок реализовать
|
||||||
* Переписать реестр и проверку на дубликаты, не понимаю как они работают
|
* Переписать реестр и проверку на дубликаты, не понимаю как они работают
|
||||||
|
@ -343,6 +343,7 @@ class Search extends Document
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Запись обработанных данных
|
// Запись обработанных данных
|
||||||
$_row['supplies'] = array_merge($connections, $buffer_connections);
|
$_row['supplies'] = array_merge($connections, $buffer_connections);
|
||||||
|
|
||||||
|
|
|
@ -459,7 +459,7 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
$analogs = explode(',', $row['Артикул'] ?? $row['артикул'] ?? $row['Article'] ?? $row['article'] ?? $row['catn'], 50);
|
$analogs = explode(',', $row['Артикул'] ?? $row['артикул'] ?? $row['Article'] ?? $row['article'] ?? $row['catn'], 50);
|
||||||
|
|
||||||
// Инициализация функции создания поставки
|
// Инициализация функции создания поставки
|
||||||
$create = function (string $_supply) use ($row, $analogs, &$created, &$updated, &$imported, $amount, $account) {
|
$create = function (string $_supply) use ($row, $analogs, &$created, &$updated, &$imported, $amount, $account): bool {
|
||||||
// Очистка
|
// Очистка
|
||||||
$_supply = trim($_supply);
|
$_supply = trim($_supply);
|
||||||
|
|
||||||
|
@ -591,21 +591,35 @@ class Supply extends Product implements ProductInterface, OfferInterface
|
||||||
if ($product = Product::searchByCatn($supply->catn)) {
|
if ($product = Product::searchByCatn($supply->catn)) {
|
||||||
// Найден товар подходящий для привязки с только что созданной поставкой
|
// Найден товар подходящий для привязки с только что созданной поставкой
|
||||||
|
|
||||||
if (isset($product->prod) && $product->prod === $supply->prod) {
|
// Приведение типа (для анализатора)
|
||||||
// Производитель совпадает с тем, что указан в товаре
|
if (is_array($product)) $product = $product[0];
|
||||||
|
|
||||||
for ($i = 0; $i++ < $amount;) {
|
|
||||||
// Перебор создаваемых рёбер (так работает обозначение количества товаров в наличии)
|
|
||||||
|
|
||||||
// Запись ребра (с проверкой на дубликат)
|
|
||||||
SupplyEdgeProduct::writeSafe($supply->readId(), $product->readId(), data: ['type' => 'connect']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Не найден товар подходящий для привязки с только что созданной поставкой
|
// Не найден товар подходящий для привязки с только что созданной поставкой
|
||||||
|
|
||||||
// Отправка уведомления
|
if ($product = Product::writeEmpty($supply->catn)) {
|
||||||
Notification::_write("Не найден товар подходящий для связи с поставкой: $supply->catn", account: '@authorized');
|
// Удалось записать новый товар (НЕАКТИВНЫЙ)
|
||||||
|
|
||||||
|
// Отправка уведомления
|
||||||
|
// Notification::_write("Не найден товар подходящий для связи с поставкой: $supply->catn", account: '@authorized');
|
||||||
|
} else {
|
||||||
|
// Не удалось записать новый товар
|
||||||
|
|
||||||
|
// Отправка уведомления
|
||||||
|
Notification::_write("Не удалось создать новый товар: $supply->catn", account: '@authorized');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($product->prod) && $product->prod === $supply->prod) {
|
||||||
|
// Производитель совпадает с тем, что указан в товаре
|
||||||
|
|
||||||
|
for ($i = 0; $i++ < $amount;) {
|
||||||
|
// Перебор создаваемых рёбер (так работает обозначение количества товаров в наличии)
|
||||||
|
|
||||||
|
// Запись ребра (с проверкой на дубликат)
|
||||||
|
SupplyEdgeProduct::writeSafe($supply->readId(), $product->readId(), data: ['type' => 'connect']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Проверка не пройдена
|
// Проверка не пройдена
|
||||||
|
|
|
@ -87,6 +87,7 @@ 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')
|
||||||
) {
|
) {
|
||||||
|
// Инициализация артикула
|
||||||
$catn = $model['catn'];
|
$catn = $model['catn'];
|
||||||
|
|
||||||
echo <<<HTML
|
echo <<<HTML
|
||||||
|
@ -114,21 +115,21 @@ use app\models\Product;
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 px-3 d-flex flex-column w-50"> <?php if (
|
<div class="ml-4 px-3 d-flex flex-column w-50"> <?php if (
|
||||||
!yii::$app->user->isGuest
|
!yii::$app->user->isGuest
|
||||||
&& yii::$app->user->identity->type === 'administrator'
|
&& yii::$app->user->identity->type === 'administrator'
|
||||||
) : ?>
|
) : ?>
|
||||||
<nav class="row my-2 py-2 px-3 rounded product_admin_menu">
|
<nav class="row my-2 py-2 px-3 rounded product_admin_menu">
|
||||||
<a id="product_info_admin_connect" class="mr-2 h-100 text-dark d-flex" title="Подсоединить аналог" role="button" onclick="return product_panel_connect('<?= $model['catn'] ?>');">
|
<a id="product_info_admin_connect" class="mr-2 h-100 text-dark d-flex" title="Подсоединить аналог" role="button" onclick="return product_panel_connect('<?= $model['catn'] ?>');">
|
||||||
<i class="fas fa-plus-square my-auto"></i>
|
<i class="fas fa-plus-square my-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<a id="product_info_admin_connect" class="mr-2 h-100 text-dark d-flex" title="Отсоединить аналог" role="button" onclick="return product_panel_disconnect('<?= $model['catn'] ?>');">
|
<a id="product_info_admin_connect" class="mr-2 h-100 text-dark d-flex" title="Отсоединить аналог" role="button" onclick="return product_panel_disconnect('<?= $model['catn'] ?>');">
|
||||||
<i class="fas fa-minus-square my-auto"></i>
|
<i class="fas fa-minus-square my-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
<a id="product_info_admin_connect" class="ml-auto h-100 text-dark d-flex" title="Удалить" role="button" onclick="return product_panel_delete('<?= $model['catn'] ?>');">
|
<a id="product_info_admin_connect" class="ml-auto h-100 text-dark d-flex" title="Удалить" role="button" onclick="return product_panel_delete('<?= $model['catn'] ?>');">
|
||||||
<i class="fas fa-trash-alt my-auto"></i>
|
<i class="fas fa-trash-alt my-auto"></i>
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<?php if (
|
<?php if (
|
||||||
!yii::$app->user->isGuest
|
!yii::$app->user->isGuest
|
||||||
|
@ -219,24 +220,22 @@ use app\models\Product;
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$form = ActiveForm::begin([
|
if (isset($model['stts']) && $model['stts'] === 'active') {
|
||||||
'id' => 'form_product_cart',
|
// Товар активен
|
||||||
'action' => false,
|
|
||||||
'fieldConfig' => [
|
|
||||||
'template' => '{input}',
|
|
||||||
],
|
|
||||||
'options' => [
|
|
||||||
'onsubmit' => 'return false;',
|
|
||||||
'class' => 'row mt-auto'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Просто для теста
|
echo <<<HTML
|
||||||
$model = new Product();
|
<button class="row btn button_red button_clean" onclick="return product_panel_product_stts('$catn', 'inactive');">Деактивировать</button>
|
||||||
|
HTML;
|
||||||
|
} else {
|
||||||
|
// Товар неактивен, либо что-то с ним ещё
|
||||||
|
|
||||||
|
echo <<<HTML
|
||||||
|
<button class="row btn button_green button_clean" onclick="return product_panel_product_stts('$catn', 'active');">Активировать</button>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php ActiveForm::end(); ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use app\models\Settings;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use DateTimeZone;
|
||||||
|
|
||||||
|
// Инициализация счетчика аккаунтов
|
||||||
|
$amount = 0;
|
||||||
|
|
||||||
|
// Инициализация часового пояса
|
||||||
|
preg_match_all('/UTC([\+\-0-9:]*)/', $account->zone ?? Settings::searchActive()['timezone_default'] ?? 'UTC+3', $timezone);
|
||||||
|
$timezone = $timezone[1][0];
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php foreach ($products as $product) : ?>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
foreach ($product->jrnl ?? [] as $jrnl) {
|
||||||
|
// Перебор записей в журнале
|
||||||
|
|
||||||
|
if ($jrnl['action'] === 'create') {
|
||||||
|
// Найдена дата создания
|
||||||
|
|
||||||
|
// Инициализация даты
|
||||||
|
$create = (new DateTime())->setTimestamp($jrnl['date'])->setTimezone(new DateTimeZone($timezone))->format('H:i d.m.Y') ?? 'Неизвестно';
|
||||||
|
|
||||||
|
// Выход из цикла
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<div class="pr-0 col-auto"><?= ++$amount ?>.</div>
|
||||||
|
<a class="pr-0 col overflow-hidden" title="<?= $product->name ?? 'Открыть страницу товара' ?>" href="/product/<?= $product->catn ?? 'Неизвестно' ?>">
|
||||||
|
<?= $product->catn ?? 'Неизвестно' ?>
|
||||||
|
</a>
|
||||||
|
<div class="my-auto pr-0 col-auto text-right">
|
||||||
|
<?= $create ?? 'Неизвестно' ?>
|
||||||
|
</div>
|
||||||
|
<a class="my-auto col-auto fas fa-trash-alt text-dark" type="button" onclick="page_profile_supplies_delete()"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($amount < count($products)) : ?>
|
||||||
|
<div class="dropdown-divider mb-3"></div>
|
||||||
|
<?php endif ?>
|
||||||
|
<?php endforeach ?>
|
|
@ -159,47 +159,13 @@ $timezone = $timezone[1][0];
|
||||||
<input type="radio" id="profile_panel_input_products" name="main_panel" <?= $panel === 'profile_panel_input_products' ? 'checked' : null ?> />
|
<input type="radio" id="profile_panel_input_products" name="main_panel" <?= $panel === 'profile_panel_input_products' ? 'checked' : null ?> />
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h5>Список товаров</h5>
|
<h5>Список товаров</h5>
|
||||||
|
<div class="col-auto orders_panel_menu ml-auto text-right">
|
||||||
|
<a class="btn btn-sm button_white button_clean font-weight-bold mb-0 mr-2" type="button" onclick="return profile_panel_products_read('@last', 'all');">Все</a>
|
||||||
|
<a class="btn btn-sm button_white button_clean font-weight-bold mb-0 mr-2" type="button" onclick="return profile_panel_products_read('@last', 'active');">Активные</a>
|
||||||
|
<a class="btn btn-sm button_white button_clean font-weight-bold mb-0 mr-2" type="button" onclick="return profile_panel_products_read('@last', 'inactive');">Неактивные</a>
|
||||||
|
</div>
|
||||||
<div class="dropdown-divider mb-4"></div>
|
<div class="dropdown-divider mb-4"></div>
|
||||||
<?php
|
<div id="profile_panel_input_products_wrap"></div>
|
||||||
// Инициализация счетчика аккаунтов
|
|
||||||
$amount = 0;
|
|
||||||
|
|
||||||
// Чтение аккаунтов
|
|
||||||
$products = Product::read(limit: 100, order: ['desc']);
|
|
||||||
?>
|
|
||||||
<?php foreach ($products ?? [] as $product) : ?>
|
|
||||||
<?php
|
|
||||||
|
|
||||||
foreach ($product->jrnl ?? [] as $jrnl) {
|
|
||||||
// Перебор записей в журнале
|
|
||||||
|
|
||||||
if ($jrnl['action'] === 'create') {
|
|
||||||
// Найдена дата создания
|
|
||||||
|
|
||||||
// Инициализация даты
|
|
||||||
$create = (new DateTime())->setTimestamp($jrnl['date'])->setTimezone(new DateTimeZone($timezone))->format('H:i d.m.Y') ?? 'Неизвестно';
|
|
||||||
|
|
||||||
// Выход из цикла
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="mb-3 row">
|
|
||||||
<div class="pr-0 col-auto"><?= ++$amount ?>.</div>
|
|
||||||
<a class="pr-0 col overflow-hidden" title="<?= $product->name ?? 'Открыть страницу товара' ?>" href="/product/<?= $product->catn ?? 'Неизвестно' ?>">
|
|
||||||
<?= $product->catn ?? 'Неизвестно' ?>
|
|
||||||
</a>
|
|
||||||
<div class="my-auto pr-0 col-auto text-right">
|
|
||||||
<?= $create ?? 'Неизвестно' ?>
|
|
||||||
</div>
|
|
||||||
<a class="my-auto col-auto fas fa-trash-alt text-dark" type="button" onclick="page_profile_supplies_delete()"></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if ($amount < count($products)) : ?>
|
|
||||||
<div class="dropdown-divider mb-3"></div>
|
|
||||||
<?php endif ?>
|
|
||||||
<?php endforeach ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="radio" id="profile_panel_input_supplies" name="main_panel" <?= $panel === 'profile_panel_input_supplies' ? 'checked' : null ?> />
|
<input type="radio" id="profile_panel_input_supplies" name="main_panel" <?= $panel === 'profile_panel_input_supplies' ? 'checked' : null ?> />
|
||||||
|
|
|
@ -178,6 +178,25 @@ main {
|
||||||
transition: 0s;
|
transition: 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button_green {
|
||||||
|
color: #eee;
|
||||||
|
background-color: #00c431;
|
||||||
|
transition: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button_green:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #04d639;
|
||||||
|
transition: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button_green:active,
|
||||||
|
.button_green:focus {
|
||||||
|
color: #ddd;
|
||||||
|
background-color: #01ae2c;
|
||||||
|
transition: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
.button_white,
|
.button_white,
|
||||||
.button_white_small {
|
.button_white_small {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
|
@ -437,7 +437,7 @@ function product_panel_images_cover_write(catn, index) {
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: {
|
data: {
|
||||||
'_csrf': yii.getCsrfToken(),
|
'_csrf': yii.getCsrfToken(),
|
||||||
'index': index
|
index
|
||||||
},
|
},
|
||||||
success: product_response_success,
|
success: product_response_success,
|
||||||
error: product_response_error
|
error: product_response_error
|
||||||
|
@ -461,3 +461,23 @@ function product_panel_handler_save(save, catn, element, ...vars) {
|
||||||
document.body.addEventListener('click', product_panel_handler_save_function, true);
|
document.body.addEventListener('click', product_panel_handler_save_function, true);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function product_panel_product_stts(catn, stts) {
|
||||||
|
if (catn !== null && catn !== undefined && stts !== null && stts !== undefined) {
|
||||||
|
$.ajax({
|
||||||
|
url: '/product/' + catn + '/status',
|
||||||
|
type: 'post',
|
||||||
|
dataType: 'json',
|
||||||
|
data: {
|
||||||
|
'_csrf': yii.getCsrfToken(),
|
||||||
|
stts
|
||||||
|
},
|
||||||
|
success: product_response_success,
|
||||||
|
error: product_response_error
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
|
@ -72,23 +72,32 @@ function page_profile_panel_choose(button = 'profile_panel_input_accounts') {
|
||||||
document.querySelector('[for="profile_panel_input_notifications"]').classList.remove('active');
|
document.querySelector('[for="profile_panel_input_notifications"]').classList.remove('active');
|
||||||
document.querySelector('[for="profile_panel_input_settings"]').classList.remove('active');
|
document.querySelector('[for="profile_panel_input_settings"]').classList.remove('active');
|
||||||
|
|
||||||
|
// Активация запрошенной вкладки
|
||||||
|
document.getElementById(button).checked = true;
|
||||||
|
document.getElementById(button).removeAttribute('onclick');
|
||||||
|
document.querySelector('[for="' + button + '"]').classList.add('active');
|
||||||
|
|
||||||
|
if (button === 'profile_panel_input_products') {
|
||||||
|
// Открытие вкладки с товарами
|
||||||
|
|
||||||
|
profile_panel_products_read('@last', 'all');
|
||||||
|
}
|
||||||
|
|
||||||
if (button === 'disable') {
|
if (button === 'disable') {
|
||||||
// Инициализация активной подвкладки вкладки "Аккаунты"
|
// Инициализация активной подвкладки вкладки "Аккаунты"
|
||||||
|
|
||||||
page_profile_panel_accounts_choose('disable', true);
|
page_profile_panel_accounts_choose('disable', true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (button === 'profile_panel_input_accounts') {
|
} else if (button === 'profile_panel_input_accounts') {
|
||||||
// Инициализация активной подвкладки вкладки "Аккаунты"
|
// Инициализация активной подвкладки вкладки "Аккаунты"
|
||||||
|
|
||||||
page_profile_panel_accounts_choose(undefined, true);
|
page_profile_panel_accounts_choose(undefined, true);
|
||||||
} else if (button !== 'profile_panel_input_accounts') {
|
} else if (button !== 'profile_panel_input_accounts') {
|
||||||
// Инициализация активной подвкладки вкладки "Аккаунты"
|
// Инициализация активной подвкладки вкладки "Аккаунты"
|
||||||
|
|
||||||
page_profile_panel_accounts_choose('disable', true);
|
page_profile_panel_accounts_choose('disable', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация запрошенной вкладки
|
|
||||||
document.getElementById(button).checked = true;
|
|
||||||
document.getElementById(button).removeAttribute('onclick');
|
|
||||||
document.querySelector('[for="' + button + '"]').classList.add('active');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function page_profile_panel_accounts_choose(button = 'profile_panel_input_accounts_control', active = false) {
|
function page_profile_panel_accounts_choose(button = 'profile_panel_input_accounts_control', active = false) {
|
||||||
|
@ -729,3 +738,44 @@ function profile_panel_input_suppliers_accounts_create_product(button, _key) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Прочитать товары
|
||||||
|
function profile_panel_products_read(search = '@last', type = '@last', from = '@last', to = '@last') {
|
||||||
|
// '@last' - оставить без изменений и взять данные из cookie
|
||||||
|
|
||||||
|
if (search.length > 1) {
|
||||||
|
// Проверка на длину запроса пройдена
|
||||||
|
|
||||||
|
// Инициализация буфера с данными запроса
|
||||||
|
let data = {
|
||||||
|
'_csrf': yii.getCsrfToken(),
|
||||||
|
search,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
};
|
||||||
|
|
||||||
|
// Запрос
|
||||||
|
$.ajax({
|
||||||
|
url: '/products/read/' + type,
|
||||||
|
type: 'post',
|
||||||
|
dataType: 'json',
|
||||||
|
data: data,
|
||||||
|
success: (data, status, xhr) => {
|
||||||
|
// Инициализация оболочки
|
||||||
|
let element = document.getElementById('profile_panel_input_products_wrap');
|
||||||
|
|
||||||
|
if (data.products !== undefined && element !== null) {
|
||||||
|
// Передан список продуктов и найден элемент-оболочка продуктов
|
||||||
|
|
||||||
|
// Запись полученного содержимого
|
||||||
|
element.innerHTML = data.products;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page_profile_response_success(data, status, xhr);
|
||||||
|
},
|
||||||
|
error: page_profile_response_error
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue