В контроллер скопипастил модель... Исправление
This commit is contained in:
parent
c169347687
commit
b50049eb67
|
@ -2,469 +2,238 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
namespace app\controllers;
|
||||
|
||||
use yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
use yii\web\HttpException;
|
||||
use yii\web\UploadedFile;
|
||||
use yii\imagine\Image;
|
||||
|
||||
use app\models\traits\SearchByEdge;
|
||||
use Exception;
|
||||
use moonland\phpexcel\Excel;
|
||||
use app\models\Product;
|
||||
|
||||
/**
|
||||
* Продукт (в ассортименте магазина)
|
||||
*
|
||||
* Представляет собой лот состоящий из предложений от поставщиков
|
||||
*
|
||||
* @see Supply Поставки для продуктов
|
||||
*/
|
||||
class Product extends Document
|
||||
class ProductController extends Controller
|
||||
{
|
||||
use SearchByEdge;
|
||||
|
||||
/**
|
||||
* Сценарий импорта .excel документа
|
||||
*
|
||||
* Использовать для обхода правил при загрузке файла
|
||||
*/
|
||||
const SCENARIO_IMPORT_EXCEL = 'import_excel';
|
||||
|
||||
/**
|
||||
* Сценарий импорта изображений
|
||||
*
|
||||
* Использовать для обхода правил при загрузке файла
|
||||
*/
|
||||
const SCENARIO_IMPORT_IMAGE = 'import_image';
|
||||
|
||||
/**
|
||||
* Сценарий записи товара
|
||||
*/
|
||||
const SCENARIO_WRITE = 'write';
|
||||
|
||||
/**
|
||||
* Файл .excel для импорта товаров
|
||||
*/
|
||||
public Excel|string|array|null $file_excel = null;
|
||||
|
||||
/**
|
||||
* Изображение для импорта
|
||||
*/
|
||||
public UploadedFile|string|array|null $file_image = null;
|
||||
|
||||
/**
|
||||
* Группа в которой состоит товар
|
||||
*/
|
||||
public ProductGroup|null $group = null;
|
||||
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
public static function collectionName(): string
|
||||
public function actionIndex(string $catn): array|string|null
|
||||
{
|
||||
return 'product';
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
if (yii::$app->request->isAjax) {
|
||||
// AJAX-POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('index', compact('model')),
|
||||
'redirect' => '/product/' . $catn,
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Свойства
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'catn',
|
||||
'name',
|
||||
// В библеотеке есть баг на название DESC (неизвестно в моей или нет)
|
||||
'dscr',
|
||||
'prod',
|
||||
'dmns',
|
||||
'imgs',
|
||||
'time'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метки свойств
|
||||
*/
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'catn' => 'Каталожный номер (catn)',
|
||||
'name' => 'Название (name)',
|
||||
'dscr' => 'Описание (dscr)',
|
||||
'prod' => 'Производитель (prod)',
|
||||
'dmns' => 'Габариты (dmns)',
|
||||
'imgs' => 'Изображения (imgs)',
|
||||
'time' => 'Срок доставки (time)',
|
||||
'file_excel' => 'Документ (file_excel)',
|
||||
'file_image' => 'Изображение (file_image)',
|
||||
'group' => 'Группа (group)'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
'catn',
|
||||
'required',
|
||||
'message' => 'Заполните поля: {attribute}',
|
||||
'on' => self::SCENARIO_WRITE,
|
||||
'except' => [self::SCENARIO_IMPORT_EXCEL, self::SCENARIO_IMPORT_IMAGE]
|
||||
],
|
||||
[
|
||||
'catn',
|
||||
'string',
|
||||
'message' => '{attribute} должен быть строкой'
|
||||
],
|
||||
[
|
||||
'imgs',
|
||||
'arrayValidator',
|
||||
'message' => '{attribute} должен быть массивом'
|
||||
],
|
||||
[
|
||||
'dmns',
|
||||
'arrayWithNumbersValidator',
|
||||
'message' => '{attribute} должен быть массивом и хранить циферные значения'
|
||||
],
|
||||
[
|
||||
'file_excel',
|
||||
'required',
|
||||
'message' => 'Заполните поля: {attribute}',
|
||||
'on' => self::SCENARIO_IMPORT_EXCEL
|
||||
],
|
||||
[
|
||||
'file_excel',
|
||||
'file',
|
||||
'skipOnEmpty' => false,
|
||||
'extensions' => 'xlsx',
|
||||
'checkExtensionByMimeType' => false,
|
||||
'maxFiles' => 5,
|
||||
'maxSize' => 1024 * 1024 * 30,
|
||||
'wrongExtension' => 'Разрешены только документы в формате: ".xlsx"',
|
||||
'message' => 'Проблема при чтении документа',
|
||||
'on' => self::SCENARIO_IMPORT_EXCEL
|
||||
],
|
||||
[
|
||||
'file_image',
|
||||
'required',
|
||||
'message' => 'Загрузите изображение',
|
||||
'on' => self::SCENARIO_IMPORT_IMAGE
|
||||
],
|
||||
[
|
||||
'file_image',
|
||||
'file',
|
||||
'skipOnEmpty' => false,
|
||||
'extensions' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
|
||||
'checkExtensionByMimeType' => true,
|
||||
'maxFiles' => 10,
|
||||
'maxSize' => 1024 * 1024 * 30,
|
||||
'wrongExtension' => 'Разрешены только изображения в формате: ".jpg", ".jpeg", ".png", ".gif", ".webp"',
|
||||
'message' => 'Проблема при загрузке изображения',
|
||||
'on' => self::SCENARIO_IMPORT_IMAGE
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись пустого продукта
|
||||
*/
|
||||
public static function writeEmpty(string $catn): ?self
|
||||
{
|
||||
// Инициализация
|
||||
$model = new self;
|
||||
|
||||
// Настройки
|
||||
$model->catn = $catn;
|
||||
|
||||
// Запись
|
||||
return $model->save() ? $model : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Импорт изображений
|
||||
*
|
||||
* @return int Количество сохранённых изображений
|
||||
*/
|
||||
public function importImages(): int
|
||||
{
|
||||
// Инициализация
|
||||
$amount = 0;
|
||||
|
||||
if ($this->validate()) {
|
||||
// Проверка пройдена
|
||||
|
||||
foreach ($this->file_image as $file) {
|
||||
// Перебор обрабатываемых изображений
|
||||
|
||||
if (!file_exists(YII_PATH_PUBLIC . $catalog = '/img/products/' . $this->_key)) {
|
||||
// Директория для изображений продукта не найдена
|
||||
|
||||
if (!mkdir(YII_PATH_PUBLIC . $catalog, 0775, true)) {
|
||||
// Не удалось записать директорию
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (!file_exists(YII_PATH_PUBLIC . $catalog_h150 = '/img/products/' . $this->_key . '/h150')) {
|
||||
// Директория для обложек изображений продукта не найдена
|
||||
|
||||
if (!mkdir(YII_PATH_PUBLIC . $catalog_h150, 0775, true)) {
|
||||
// Не удалось записать директорию
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
// Запись на сервер
|
||||
$file->saveAs(YII_PATH_PUBLIC . $catalog . '/' . $file->baseName . '.' . $file->extension . '.original');
|
||||
|
||||
// Конвертация изображения для сохранения полного изображения
|
||||
Image::resize(YII_PATH_PUBLIC . $catalog . '/' . $file->baseName . '.' . $file->extension . '.original', 800, 800)
|
||||
->save(YII_PATH_PUBLIC . $catalog . '/' . $file->baseName . '.' . $file->extension, ['quality' => 80]);
|
||||
|
||||
// Конвертация изображения для сохранения обложки (150px)
|
||||
Image::resize(YII_PATH_PUBLIC . $catalog . '/' . $file->baseName . '.' . $file->extension, 150, 150)
|
||||
->save(YII_PATH_PUBLIC . $catalog_h150 . '/' . $file->baseName . '.' . $file->extension, ['quality' => 80]);
|
||||
|
||||
// Инициализация
|
||||
$this->imgs ?? $this->imgs = [];
|
||||
|
||||
// Запись в базу данных
|
||||
$this->imgs = array_merge(
|
||||
$this->imgs,
|
||||
[[
|
||||
'covr' => count($this->imgs) === 0 ? true : false,
|
||||
'orig' => $catalog . '/' . $file->baseName . '.' . $file->extension,
|
||||
'h150' => $catalog_h150 . '/' . $file->baseName . '.' . $file->extension
|
||||
]]
|
||||
);
|
||||
|
||||
$this->scenario = self::SCENARIO_WRITE;
|
||||
|
||||
if ($this->save()) {
|
||||
// Изменения сохранены в базе данных
|
||||
|
||||
// Постинкрементация счётчика
|
||||
$amount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->hasErrors()) {
|
||||
// Получены ошибки
|
||||
|
||||
foreach ($this->getErrors() as $attribute => $errors) {
|
||||
// Перебор атрибутов
|
||||
|
||||
foreach ($errors as $error) {
|
||||
// Перебор ошибок атрибутов
|
||||
|
||||
$label = $this->getAttributeLabel($attribute);
|
||||
|
||||
Notification::_write("$label: $error", type: Notification::TYPE_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Импорт товаров
|
||||
*
|
||||
* На данный момент обрабатывает только импорт из
|
||||
* файлов с расширением .excel
|
||||
*/
|
||||
public function importExcel(): bool
|
||||
{
|
||||
// Инициализация
|
||||
$data = [];
|
||||
$amount = 0;
|
||||
|
||||
if ($this->validate()) {
|
||||
foreach ($this->file_excel as $file) {
|
||||
// Перебор файлов
|
||||
|
||||
// Инициализация
|
||||
$dir = '../assets/import/' . date('Y_m_d#H-i', time()) . '/excel/';
|
||||
|
||||
// Сохранение на диск
|
||||
if (!file_exists($dir)) {
|
||||
mkdir($dir, 0775, true);
|
||||
}
|
||||
$file->saveAs($path = $dir . $file->baseName . '.' . $file->extension);
|
||||
|
||||
$data[] = Excel::import($path, [
|
||||
'setFirstRecordAsKeys' => true,
|
||||
'setIndexSheetByName' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
foreach ($data as $data) {
|
||||
// Перебор конвертированных файлов
|
||||
|
||||
if (count($data) < 1) {
|
||||
// Не найдены строки с товарами
|
||||
|
||||
$this->addError('erros', 'Не удалось найти данные товаров');
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
// Перебор найденных товаров
|
||||
throw new HttpException(404);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $doc) {
|
||||
// Перебор полученных документов
|
||||
public function actionEditTitle(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
// Сохранение в базе данных
|
||||
$product = new static($doc);
|
||||
if (is_null($catn)) {
|
||||
// Не получен артикул
|
||||
|
||||
$product->scenario = $product::SCENARIO_WRITE;
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
if ($product->validate()) {
|
||||
// Проверка пройдена
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Запись документа
|
||||
$product->save();
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Постинкрементация счётчика
|
||||
$amount++;
|
||||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
|
||||
// Запись группы
|
||||
// $group = static::class . 'Group';
|
||||
// (new $group())->writeMember($product, $this->group);
|
||||
$model->name = $text;
|
||||
|
||||
if ($model->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['name'] = $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
// Проверка не пройдена
|
||||
foreach ($product->errors as $attribute => $error) {
|
||||
$this->addError($attribute, $error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
// Деинициализация
|
||||
$this->file_excel = '';
|
||||
|
||||
static::afterImportExcel($amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->addError('erros', 'Неизвестная ошибка');
|
||||
|
||||
static::afterImportExcel($amount);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск по каталожному номеру
|
||||
*
|
||||
* Ищет продукт и возвращает его,
|
||||
* либо выполняет поиск через представление
|
||||
*
|
||||
* @todo Переделать нормально
|
||||
*/
|
||||
public static function searchByCatn(string $catn, int $limit = 1, array $select = []): static|array|null
|
||||
{
|
||||
if ($limit <= 1) {
|
||||
return static::findOne(['catn' => $catn]);
|
||||
}
|
||||
|
||||
$query = self::find()
|
||||
->where(['catn' => $catn])
|
||||
->limit($limit)
|
||||
->select($select)
|
||||
->createCommand()
|
||||
->execute()
|
||||
->getAll();
|
||||
|
||||
foreach ($query as &$attribute) {
|
||||
// Приведение всех свойств в массив и очистка от лишних данных
|
||||
|
||||
$attribute = $attribute->getAll();
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск по каталожному номеру (через представления)
|
||||
*
|
||||
* Ищет продукт и возвращает его,
|
||||
* либо выполняет поиск через представление
|
||||
*
|
||||
* @todo Переделать нормально
|
||||
*/
|
||||
public static function searchByPartialCatn(string $catn, int $limit = 1, array $select = []): static|array|null
|
||||
{
|
||||
$query = self::find()
|
||||
->for('product')
|
||||
->in('product_search')
|
||||
->search(['catn' => $catn])
|
||||
->limit($limit)
|
||||
->select($select)
|
||||
->createCommand()
|
||||
->execute()
|
||||
->getAll();
|
||||
|
||||
foreach ($query as &$attribute) {
|
||||
// Приведение всех свойств в массив и очистка от лишних данных
|
||||
|
||||
$attribute = $attribute->getAll();
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вызывается после загрузки поставок из excel-документа
|
||||
*
|
||||
* @param int $amount Количество
|
||||
*/
|
||||
public static function afterImportExcel(int $amount = 0): bool
|
||||
public function actionEditCatn(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$model = new Notification;
|
||||
$date = date('H:i d.m.Y', time());
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
// Настройка
|
||||
$model->text = yii::$app->controller->renderPartial('/notification/system/afterImportExcel', compact('amount', 'date'));
|
||||
$model->type = $model::TYPE_NOTICE;
|
||||
if (is_null($catn)) {
|
||||
// Не получен артикул
|
||||
|
||||
// Отправка
|
||||
return (bool) $model->write();
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
|
||||
$model->catn = $text;
|
||||
|
||||
if ($model->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['main'] = $this->renderPartial('index', compact('model'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Вызывается после загрузки поставок из 1С
|
||||
*
|
||||
* @param int $amount Количество
|
||||
* Конец алгоритма
|
||||
*/
|
||||
public static function afterImport1c(): bool
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function actionEditDesc(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$model = new Notification;
|
||||
$date = date('H:i d.m.Y', time());
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
// Настройка
|
||||
$model->text = yii::$app->controller->renderPartial('/notification/system/afterImport1c', compact('amount', 'date'));
|
||||
$model->type = $model::TYPE_NOTICE;
|
||||
if (is_null($catn)) {
|
||||
// Не получен артикул
|
||||
|
||||
// Отправка
|
||||
return (bool) $model->write();
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($product = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$text = yii::$app->request->get('text') ?? yii::$app->request->post('text') ?? 'Без названия';
|
||||
|
||||
$product->desc = $text;
|
||||
|
||||
if ($product->save()) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['description'] = $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function actionWriteImage(string $catn): array|string|null
|
||||
{
|
||||
// Инициализация
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
if (is_null($catn)) {
|
||||
// Не получен артикул
|
||||
|
||||
yii::$app->response->statusCode = 500;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
$model->file_image = UploadedFile::getInstancesByName('images');
|
||||
$model->scenario = $model::SCENARIO_IMPORT_IMAGE;
|
||||
|
||||
if ($model->importImages() > 0) {
|
||||
// Товар обновлён
|
||||
|
||||
$return['main'] = $this->renderPartial('index', compact('model'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Конец алгоритма
|
||||
*/
|
||||
end:
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
return $this->render('index', compact('model'));
|
||||
} else {
|
||||
return $this->redirect('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -454,14 +454,14 @@ class Product extends Document
|
|||
*
|
||||
* @param int $amount Количество
|
||||
*/
|
||||
public static function afterImportOnec(): bool
|
||||
public static function afterImport1c(): bool
|
||||
{
|
||||
// Инициализация
|
||||
$model = new Notification;
|
||||
$date = date('H:i d.m.Y', time());
|
||||
|
||||
// Настройка
|
||||
$model->text = yii::$app->controller->renderPartial('/notification/system/afterImportOnec', compact('amount', 'date'));
|
||||
$model->text = yii::$app->controller->renderPartial('/notification/system/afterImport1c', compact('amount', 'date'));
|
||||
$model->type = $model::TYPE_NOTICE;
|
||||
|
||||
// Отправка
|
||||
|
|
Reference in New Issue