
diff --git a/.htaccess b/.htaccess index 809fad7..2984f4b 100644 --- a/.htaccess +++ b/.htaccess @@ -55,10 +55,12 @@ AddDefaultCharset utf-8 RewriteRule ^img/(.*)$ frontend/web/img/$1 [L] + RewriteRule ^files/(.*)$ frontend/web/files/$1 [L] + RewriteRule ^fonts/(.*)$ frontend/web/fonts/$1 [L] - RewriteCond %{REQUEST_URI} !^/(frontend|backend)/web/(assets|css|js|images|img|fonts)/ + RewriteCond %{REQUEST_URI} !^/(frontend|backend)/web/(assets|css|js|images|fonts|img|files)/ RewriteCond %{REQUEST_URI} !index.php diff --git a/backend/config/bootstrap.php b/backend/config/bootstrap.php index e446754..7e6294e 100755 --- a/backend/config/bootstrap.php +++ b/backend/config/bootstrap.php @@ -2,4 +2,4 @@ Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); Yii::setAlias('@uploadFileProducts', 'products.csv'); -Yii::setAlias('@productsDir', dirname(dirname(__DIR__)) . '/storage/products'); \ No newline at end of file +Yii::setAlias('@productsDir', 'images/products'); \ No newline at end of file diff --git a/backend/views/category/_form.php b/backend/views/category/_form.php index 55c750a..5aae4de 100755 --- a/backend/views/category/_form.php +++ b/backend/views/category/_form.php @@ -68,19 +68,6 @@ use kartik\select2\Select2; = $form->field($model, 'seo_text')->textarea(['rows' => 6]) ?> - = $form->field($model, 'remote_category')->widget(Select2::className(), [ - 'data' => \yii\helpers\ArrayHelper::map(\common\modules\product\models\RemoteCategories::find()->all(), 'ID', 'Name'), - 'language' => 'ru', - 'options' => [ - 'placeholder' => 'Select a remote category', - 'multiple' => true, - ], - 'pluginOptions' => [ - 'allowClear' => true - ], - ] - ) ?> - depth == 2) :?> = $form->field($model, 'populary')->checkbox() ?> diff --git a/backend/views/layouts/main-sidebar.php b/backend/views/layouts/main-sidebar.php index 1e6cc3a..f132d1b 100755 --- a/backend/views/layouts/main-sidebar.php +++ b/backend/views/layouts/main-sidebar.php @@ -25,14 +25,16 @@ use yii\widgets\Menu; ['label' => 'MAIN NAVIGATION', 'options'=>['class'=>'header']], ['label' => 'Заказы', 'url' => ['/orders/index'], 'template'=>' {label}'], [ - 'label' => 'Products', + 'label' => 'eCommerce', 'template'=>' {label}', 'url' => ['/product/manage'], 'items' => [ ['label' => 'Товары', 'url' => ['/product/manage']], - ['label' => 'Импорт товаров', 'url' => ['/product/manage/import']], ['label' => 'Категории', 'url' => ['/category']], ['label' => 'Бренды', 'url' => ['/brand']], + ['label' => 'Характеристики', 'url' => ['/rubrication/tax-group']], + ['label' => 'Единицы измерения', 'url' => ['/product/product-unit']], + ['label' => 'Статистика импорта', 'url' => ['/product/manage/import-stat']], ] ], [ diff --git a/common/modules/product/CatalogUrlManager.php b/common/modules/product/CatalogUrlManager.php index 9e26006..ff3967d 100755 --- a/common/modules/product/CatalogUrlManager.php +++ b/common/modules/product/CatalogUrlManager.php @@ -111,6 +111,7 @@ class CatalogUrlManager implements UrlRuleInterface { $params['word'] = [$params['word']]; } $url .= 'word:'. implode(';', $params['word']); + unset($params['word']); } $filter = []; @@ -147,6 +148,10 @@ class CatalogUrlManager implements UrlRuleInterface { $url .= 'filter:'. implode(';', $filter); } + if (!empty($params) && ($query = http_build_query($params)) !== '') { + $url .= '?' . $query; + } + return $url; break; @@ -155,6 +160,11 @@ class CatalogUrlManager implements UrlRuleInterface { $product_alias = is_object($params['product']) ? $params['product']->alias : strtolower($params['product']); } $url = 'product/'. $product_alias; + + if (!empty($params) && ($query = http_build_query($params)) !== '') { + $url .= '?' . $query; + } + return $url; break; } diff --git a/common/modules/product/controllers/ManageController.php b/common/modules/product/controllers/ManageController.php index ad70fa5..6f37b7d 100755 --- a/common/modules/product/controllers/ManageController.php +++ b/common/modules/product/controllers/ManageController.php @@ -4,6 +4,7 @@ namespace common\modules\product\controllers; use common\modules\product\helpers\ProductHelper; use common\modules\product\models\Category; +use common\modules\product\models\ProductImage; use common\modules\product\models\ProductVariant; use common\modules\product\models\RemoteProductsSearch; use Yii; @@ -12,6 +13,10 @@ use common\modules\product\models\ProductSearch; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; +use common\modules\product\models\Brand; +use common\modules\product\models\BrandName; +use common\modules\product\models\RemoteProducts; +use yii\web\UploadedFile; /** * ManageController implements the CRUD actions for Product model. @@ -119,8 +124,25 @@ class ManageController extends Controller { $model = new Product(); - if ($model->load(Yii::$app->request->post()) && $model->save()) { - return $this->redirect(['view', 'id' => $model->product_id]); + if ($model->load(Yii::$app->request->post())) { + $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); + + if ($model->save()) { + foreach ($model->images as $image) { + $image->delete(); + } + + if ( ($images = $model->imagesUpload()) !== FALSE) { + foreach ($images as $image) { + $imageModel = new ProductImage(); + $imageModel->product_id = $model->product_id; + $imageModel->image = $image; + $imageModel->save(); + } + } + + return $this->redirect(['view', 'id' => $model->product_id]); + } } else { return $this->render('create', [ 'model' => $model, @@ -138,8 +160,25 @@ class ManageController extends Controller { $model = $this->findModel($id); - if ($model->load(Yii::$app->request->post()) && $model->save()) { - return $this->redirect(['view', 'id' => $model->product_id]); + if ($model->load(Yii::$app->request->post())) { + $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); + + if ($model->save()) { + foreach ($model->images as $image) { + $image->delete(); + } + + if ( ($images = $model->imagesUpload()) !== FALSE) { + foreach ($images as $image) { + $imageModel = new ProductImage(); + $imageModel->product_id = $model->product_id; + $imageModel->image = $image; + $imageModel->save(); + } + } + + return $this->redirect(['view', 'id' => $model->product_id]); + } } else { $groups = $model->category->getTaxGroups(); @@ -163,6 +202,18 @@ class ManageController extends Controller return $this->redirect(['index']); } + public function actionDelimg($id) + { + $image = ProductImage::findOne($id); + + if ($image) { + $image->delete(); + } + + print '1'; + exit; + } + public function actionImport() { $searchModel = new RemoteProductsSearch(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); @@ -173,6 +224,47 @@ class ManageController extends Controller ]); } + public function actionImportStat() { + $all_products = $new_products = $linked_products = $orpahed_products = 0; + $remoteProducts = RemoteProducts::find()->all(); + + $not_linked_cats = []; + + foreach($remoteProducts as $product) { + if (!empty($product->product->product_id)) { + $linked_products++; + } elseif (!empty($product->remoteCategory) && !empty($product->remoteCategory->category) && !empty($product->remoteCategory->category->category_id)) { + $new_products++; + } else { + if (!empty($product->remoteCategory)) { + if (empty($not_linked_cats[$product->remoteCategory->ID])) { + $not_linked_cats[$product->remoteCategory->ID] = $product->remoteCategory->Name ." (". $product->remoteCategory->ID .")"; + } + } + $orpahed_products++; + } + $all_products++; + } + + $op = []; + + $op[] = "Всего $all_products товаров, $new_products новых и $linked_products уже связанных."; + if (!empty($not_linked_cats)) { + $op[] = "$orpahed_products товаров не привязаны к категориям:"; + foreach ($not_linked_cats as $not_linked_cat) { + $op[] = "$not_linked_cat"; + } + } + + return $this->render('import-stat', [ + 'all_products' => $all_products, + 'new_products' => $new_products, + 'linked_products' => $linked_products, + 'orpahed_products' => $orpahed_products, + 'not_linked_cats' => $not_linked_cats, + ]); + } + /** * Finds the Product model based on its primary key value. * If the model is not found, a 404 HTTP exception will be thrown. diff --git a/common/modules/product/controllers/ProductUnitController.php b/common/modules/product/controllers/ProductUnitController.php new file mode 100644 index 0000000..7ee6139 --- /dev/null +++ b/common/modules/product/controllers/ProductUnitController.php @@ -0,0 +1,124 @@ + [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * Lists all ProductUnit models. + * @return mixed + */ + public function actionIndex() + { + $searchModel = new ProductUnitSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * Displays a single ProductUnit model. + * @param integer $id + * @return mixed + */ + public function actionView($id) + { + return $this->render('view', [ + 'model' => $this->findModel($id), + ]); + } + + /** + * Creates a new ProductUnit model. + * If creation is successful, the browser will be redirected to the 'view' page. + * @return mixed + */ + public function actionCreate() + { + $model = new ProductUnit(); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->product_unit_id]); + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } + + /** + * Updates an existing ProductUnit model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) + { + $model = $this->findModel($id); + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->product_unit_id]); + } else { + return $this->render('update', [ + 'model' => $model, + ]); + } + } + + /** + * Deletes an existing ProductUnit model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + $this->findModel($id)->delete(); + + return $this->redirect(['index']); + } + + /** + * Finds the ProductUnit model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * @param integer $id + * @return ProductUnit the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) + { + if (($model = ProductUnit::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/common/modules/product/models/Brand.php b/common/modules/product/models/Brand.php index 79cb1e4..11d83fa 100755 --- a/common/modules/product/models/Brand.php +++ b/common/modules/product/models/Brand.php @@ -10,6 +10,7 @@ use Yii; * This is the model class for table "brand". * * @property integer $brand_id + * @property string $remote_id * @property integer $brand_name_id * @property string $alias * @property string $image @@ -24,6 +25,8 @@ use Yii; */ class Brand extends \yii\db\ActiveRecord { + public $imageUpload; + public function behaviors() { return [ @@ -39,7 +42,7 @@ class Brand extends \yii\db\ActiveRecord 'valueKeyName' => 'value', 'slugKeyName' => 'alias', 'translit' => true - ] + ], ], ]; } @@ -64,6 +67,9 @@ class Brand extends \yii\db\ActiveRecord [['alias', 'name'], 'string', 'max' => 250], [['image', 'meta_title'], 'string', 'max' => 255], [['meta_robots'], 'string', 'max' => 50], + [['remote_id'], 'string', 'max' => 25], + [['imageUpload'], 'safe'], + [['imageUpload'], 'file', 'extensions' => 'jpg, gif, png'], // [['brand_name_id'], 'exist', 'skipOnError' => true, 'targetClass' => BrandName::className(), 'targetAttribute' => ['brand_name_id' => 'brand_name_id']], ]; } @@ -79,10 +85,12 @@ class Brand extends \yii\db\ActiveRecord 'brand_name_id' => Yii::t('product', 'Brand Name ID'), 'alias' => Yii::t('product', 'Alias'), 'image' => Yii::t('product', 'Image'), + 'imageUrl' => Yii::t('product', 'Image'), 'meta_title' => Yii::t('product', 'Meta Title'), 'meta_desc' => Yii::t('product', 'Meta Desc'), 'meta_robots' => Yii::t('product', 'Meta Robots'), 'seo_text' => Yii::t('product', 'Seo Text'), + 'remote_id' => Yii::t('product', '1C brand name'), ]; } @@ -113,4 +121,12 @@ class Brand extends \yii\db\ActiveRecord public function getName() { return empty($this->brand_name_id) ? null : $this->brandName->value; } + + public function getImageFile() { + return empty($this->image) ? null : '/images/brand/'. $this->image; + } + + public function getImageUrl() { + return empty($this->image) ? null : '/images/brand/'. $this->image; + } } diff --git a/common/modules/product/models/BrandSearch.php b/common/modules/product/models/BrandSearch.php index 31cbb24..45041d4 100755 --- a/common/modules/product/models/BrandSearch.php +++ b/common/modules/product/models/BrandSearch.php @@ -12,6 +12,7 @@ use common\modules\product\models\Brand; */ class BrandSearch extends Brand { + public $brand_name; /** * @inheritdoc */ @@ -19,7 +20,7 @@ class BrandSearch extends Brand { return [ [['brand_id', 'brand_name_id'], 'integer'], - [['alias', 'image', 'meta_title', 'meta_desc', 'meta_robots', 'seo_text'], 'safe'], + [['alias', 'image', 'meta_title', 'meta_desc', 'meta_robots', 'seo_text', 'brand_name'], 'safe'], ]; } @@ -57,18 +58,28 @@ class BrandSearch extends Brand return $dataProvider; }*/ + $dataProvider->setSort([ + 'attributes' => [ + 'brand_name', + 'alias' + ] + ]); + // grid filtering conditions $query->andFilterWhere([ 'brand_id' => $this->brand_id, 'brand_name_id' => $this->brand_name_id, ]); - $query->andFilterWhere(['like', 'alias', $this->alias]) - ->andFilterWhere(['like', 'image', $this->image]) - ->andFilterWhere(['like', 'meta_title', $this->meta_title]) - ->andFilterWhere(['like', 'meta_desc', $this->meta_desc]) - ->andFilterWhere(['like', 'meta_robots', $this->meta_robots]) - ->andFilterWhere(['like', 'seo_text', $this->seo_text]); + $query->joinWith('brandName'); + + $query->andFilterWhere(['ilike', 'alias', $this->alias]) + ->andFilterWhere(['ilike', 'image', $this->image]) + ->andFilterWhere(['ilike', 'meta_title', $this->meta_title]) + ->andFilterWhere(['ilike', 'meta_desc', $this->meta_desc]) + ->andFilterWhere(['ilike', 'meta_robots', $this->meta_robots]) + ->andFilterWhere(['ilike', 'seo_text', $this->seo_text]) + ->andFilterWhere(['ilike', 'brand_name.value', $this->brand_name]); return $dataProvider; } diff --git a/common/modules/product/models/Category.php b/common/modules/product/models/Category.php index 0cb4b3f..144fee4 100755 --- a/common/modules/product/models/Category.php +++ b/common/modules/product/models/Category.php @@ -34,6 +34,8 @@ use Yii; */ class Category extends \yii\db\ActiveRecord { + public $imageUpload; + public function behaviors() { return [ @@ -89,7 +91,8 @@ class Category extends \yii\db\ActiveRecord [['populary'], 'boolean'], [['group_to_category', 'remote_category'], 'safe'], [['category_name_id'], 'exist', 'skipOnError' => true, 'targetClass' => CategoryName::className(), 'targetAttribute' => ['category_name_id' => 'category_name_id']], - // [['image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif'], + [['imageUpload'], 'safe'], + [['imageUpload'], 'file', 'extensions' => 'jpg, gif, png'], // [['product_unit_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductUnit::className(), 'targetAttribute' => ['product_unit_id' => 'product_unit_id']], ]; } @@ -105,6 +108,7 @@ class Category extends \yii\db\ActiveRecord 'path' => Yii::t('product', 'Path'), 'depth' => Yii::t('product', 'Depth'), 'image' => Yii::t('product', 'Image'), + 'imageUrl' => Yii::t('product', 'Image'), 'meta_title' => Yii::t('product', 'Meta Title'), 'meta_desc' => Yii::t('product', 'Meta Desc'), 'meta_robots' => Yii::t('product', 'Meta Robots'), @@ -117,7 +121,8 @@ class Category extends \yii\db\ActiveRecord ]; } - public static function find() { + public static function find() + { return new CategoryQuery(get_called_class()); } @@ -145,28 +150,38 @@ class Category extends \yii\db\ActiveRecord return $this->hasMany(ProductCategory::className(), ['category_id' => 'category_id']); } - public function getTaxGroups() { + public function getTaxGroups() + { return $this->getRelations('tax_group_to_category'); } - public function getRemote_category() { + public function getRemote_category() + { return ArtboxTreeHelper::getArrayField($this->remote_id); } - public function setRemote_category($value) { + public function setRemote_category($value) + { if (!empty($value) && is_array($value)) { $this->remote_id = ArtboxTreeHelper::setArrayField($value, false); } } - public function getCategoryName() { + public function getCategoryName() + { return $this->hasOne(CategoryName::className(), ['category_name_id' => 'category_name_id']); } - public function getName() { + public function getName() + { return empty($this->categoryName) ? null : $this->categoryName->value; } + public function getImageUrl() + { + return empty($this->image) ? null : '/images/category/' . $this->image; + } + public function beforeSave($insert) { if (parent::beforeSave($insert)) { diff --git a/common/modules/product/models/Product.php b/common/modules/product/models/Product.php index ba99ca2..3e3b7ad 100755 --- a/common/modules/product/models/Product.php +++ b/common/modules/product/models/Product.php @@ -7,23 +7,23 @@ use common\modules\rubrication\models\TaxOption; use Yii; use common\modules\relation\relationBehavior; use yii\db\ActiveQuery; +use yii\helpers\Html; +use yii\web\UploadedFile; /** * This is the model class for table "{{%product}}". * - * @property integer $product_id * @property string $name - * @property string $alias - * @property string $video - * @property string $description * @property integer $brand_id - * @property Brand $brand + * @property integer $product_id * @property Category $category * @property array $categories + * @property array of ProductVariant $variants * @property ProductVariant $variant - * @property array $variants * @property ProductImage $image * @property array $images + * @property boolean $is_top + * @property boolean $is_new */ class Product extends \yii\db\ActiveRecord { @@ -71,9 +71,10 @@ class Product extends \yii\db\ActiveRecord [['brand_id'], 'integer'], [['name'], 'string', 'max' => 150], [['alias'], 'string', 'max' => 250], - [['categories', 'variants', 'options'], 'safe'], -// [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif'], + [['categories', 'variants', 'options', 'imagesUpload'], 'safe'], + [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif', 'maxFiles' => 50], [['description', 'video'], 'safe'], + [['is_top', 'is_new'], 'boolean'], // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], ]; } @@ -91,6 +92,11 @@ class Product extends \yii\db\ActiveRecord 'category' => Yii::t('product', 'Category'), // relation behavior field 'image' => Yii::t('product', 'Image'), 'images' => Yii::t('product', 'Images'), + 'description' => Yii::t('product', 'Description'), + 'video' => Yii::t('product', 'Video embeded'), + 'variants' => Yii::t('product', 'Variants'), + 'is_top' => Yii::t('product', 'Is top'), + 'is_new' => Yii::t('product', 'Is new'), ]; } @@ -118,10 +124,6 @@ class Product extends \yii\db\ActiveRecord return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']); } - public function setImages($images) { - $this->_images = $images; - } - /** * @return \yii\db\ActiveQuery */ @@ -151,7 +153,8 @@ class Product extends \yii\db\ActiveRecord } public function getCategories() { - return $this->getRelations('product_categories'); + return $this->hasMany(Category::className(), ['category_id' => 'category_id'])->viaTable('product_category', ['product_id' => 'product_id']); +// return $this->getRelations('product_categories'); } public function getCategoriesNames() { @@ -163,12 +166,7 @@ class Product extends \yii\db\ActiveRecord } public function getCategory() { - /** @var ActiveQuery $categories */ - $categories = $this->getRelations('product_categories'); - $count = $categories->count(); - if ($count == 0) - return; - return $categories->one(); + return $this->hasOne(Category::className(), ['category_id' => 'category_id'])->viaTable('product_category', ['product_id' => 'product_id']); } public function getOptions() { @@ -188,8 +186,18 @@ class Product extends \yii\db\ActiveRecord { parent::afterSave($insert, $changedAttributes); -// foreach($this->imagesUpload as $image) { -// $image->saveAs('/images/items/' . $image->baseName .'_'. uniqid() . '.' . $image->extension); +// $images = UploadedFile::getInstance($this, 'imagesUpload'); +// var_dump($images);exit; + +// if (!empty($this->imagesUpload)) { +// if (!is_array($this->imagesUpload)) { +// $this->imagesUpload = [$this->imagesUpload]; +// } +// foreach($this->imagesUpload as $image) { +// $image->saveAs((Yii::getAlias('@frontend/web/storage/products/original/' . $image->baseName .'_'. uniqid() . '.' . $image->extension))); +// } +// +// // } $todel = []; @@ -214,4 +222,53 @@ class Product extends \yii\db\ActiveRecord ProductVariant::deleteAll(['product_variant_id' => $todel]); } } + + public function imagesUpload() + { + if ($this->validate()) { + $images = []; + foreach ($this->imagesUpload as $image) { + $imageName = $image->baseName .'.'. $image->extension; + $i = 0; + while(file_exists(Yii::getAlias('@frontend/web/images/products/' . $imageName))) { + $i++; + $imageName = $image->baseName .'_'. $i .'.'. $image->extension; + } + + $image->saveAs(Yii::getAlias('@frontend/web/images/products/' .$imageName)); + $images[] = $imageName; + } + return $images; + } else { + return false; + } + } + + public function getImagesHTML() { + $op = []; + if ($this->images) { + foreach ($this->images as $image) { + $op[] = Html::img($image->imageUrl); + } + } + return $op; + } + + public function getImagesConfig() { + $op = []; + if ($this->images) { + foreach ($this->images as $image) { + $op[] = [ + 'caption' => $image->image, + 'width' => '120px', + 'url' => \yii\helpers\Url::to(['/product/manage/delimg', 'id' => $image->product_image_id]), + 'key' => $image->product_image_id, + 'extra' => [ + 'id' => $image->product_image_id, + ], + ]; + } + } + return $op; + } } diff --git a/common/modules/product/models/ProductImage.php b/common/modules/product/models/ProductImage.php index 51eaf86..8612ff5 100755 --- a/common/modules/product/models/ProductImage.php +++ b/common/modules/product/models/ProductImage.php @@ -9,16 +9,17 @@ use yii\web\UploadedFile; * This is the model class for table "product_image". * * @property integer $product_image_id + * @property integer $product_id * @property integer $product_variant_id * @property string $image * @property string $alt * @property string $title - * * @property Product $product + * @property ProductVariant $productVariant */ class ProductImage extends \yii\db\ActiveRecord { - public $image; + public $imageUpload; /** * @inheritdoc */ @@ -33,12 +34,13 @@ class ProductImage extends \yii\db\ActiveRecord public function rules() { return [ - [['product_image_id', 'product_variant_id'], 'required'], - [['product_image_id', 'product_variant_id'], 'integer'], - [['alt', 'title'], 'string', 'max' => 255], - [['image'], 'safe'], + [['product_id'], 'required'], + [['product_image_id', 'product_id', 'product_variant_id'], 'integer'], + [['alt', 'title', 'image'], 'string', 'max' => 255], + [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], [['product_variant_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductVariant::className(), 'targetAttribute' => ['product_variant_id' => 'product_variant_id']], - [['image'], 'file', 'extensions'=>'jpg, gif, png'], + [['imageUpload'], 'safe'], + [['imageUpload'], 'file', 'extensions' => 'jpg, gif, png'], ]; } @@ -49,7 +51,11 @@ class ProductImage extends \yii\db\ActiveRecord { return [ 'product_image_id' => Yii::t('product', 'Product Image ID'), + 'product_id' => Yii::t('product', 'Product ID'), 'product_variant_id' => Yii::t('product', 'Product Variant ID'), + 'product' => Yii::t('product', 'Product'), + 'product' => Yii::t('product', 'Product'), + 'product_variant' => Yii::t('product', 'Product Variant'), 'image' => Yii::t('product', 'Image'), 'alt' => Yii::t('product', 'Alt'), 'title' => Yii::t('product', 'Title'), @@ -59,9 +65,21 @@ class ProductImage extends \yii\db\ActiveRecord /** * @return \yii\db\ActiveQuery */ + public function getProduct() + { + $return = $this->hasOne(Product::className(), ['product_id' => 'product_id']); + if (empty($return)) { + $return = $this->productVariant->product_id; + } + return $return; + } + + /** + * @return \yii\db\ActiveQuery + */ public function getProductVariant() { - return $this->hasOne(ProductVariant::className(), ['product_variant_id' => 'product_variant_id']); + return $this->hasOne(Product::className(), ['product_variant_id' => 'product_variant_id']); } /** @@ -79,7 +97,7 @@ class ProductImage extends \yii\db\ActiveRecord */ public function getImageFile() { - return isset($this->image) ? Yii::$app->params['uploadPath'] . $this->image : null; + return isset($this->image) ? '/images/products/' . $this->image : null; } /** @@ -89,8 +107,7 @@ class ProductImage extends \yii\db\ActiveRecord public function getImageUrl() { // return a default image placeholder if your source image is not found - $image = isset($this->image) ? $this->image : 'default.jpg'; - return Yii::$app->params['uploadUrl'] . $image; + return isset($this->image) ? '/images/products/'. $this->image : 'default.jpg'; } /** @@ -102,7 +119,7 @@ class ProductImage extends \yii\db\ActiveRecord // get the uploaded file instance. for multiple file uploads // the following data will return an array (you may need to use // getInstances method) - $image = UploadedFile::getInstance($this, 'image'); + $image = UploadedFile::getInstance($this, 'imageUpload'); // if no image was uploaded abort the upload if (empty($image)) { @@ -111,8 +128,7 @@ class ProductImage extends \yii\db\ActiveRecord // store the source file name $this->filename = $image->name; - $exploded = explode(".", $image->name); - $ext = end($exploded); + $ext = end((explode(".", $image->name))); // generate a unique file name $this->image = Yii::$app->security->generateRandomString().".{$ext}"; diff --git a/common/modules/product/models/ProductSearch.php b/common/modules/product/models/ProductSearch.php index 921d059..8bfe7a8 100755 --- a/common/modules/product/models/ProductSearch.php +++ b/common/modules/product/models/ProductSearch.php @@ -13,14 +13,18 @@ use yii\web\NotFoundHttpException; */ class ProductSearch extends Product { + public $brand_name; + public $category_name; + /** * @inheritdoc */ public function rules() { return [ - [['name'], 'safe'], + [['name', 'brand_name', 'category_name'], 'safe'], [['tax_brand_id', 'product_id'], 'integer'], + [['is_top', 'is_new'], 'boolean'], ]; } @@ -58,13 +62,27 @@ class ProductSearch extends Product return $dataProvider; } + $dataProvider->setSort([ + 'attributes' => [ + 'name', + 'brand_name', + 'category_name' + ] + ]); + + $query->joinWith(['brand', 'brand.brandNames', 'categories', 'categories.categoryNames']); + // grid filtering conditions $query->andFilterWhere([ 'tax_brand_id' => $this->tax_brand_id, 'product_id' => $this->product_id, + 'is_top' => (bool)$this->is_top, + 'is_new' => (bool)$this->is_new, ]); - $query->andFilterWhere(['like', 'name', $this->name]); + $query->andFilterWhere(['ilike', 'name', $this->name]); + $query->andFilterWhere(['ilike', 'brand_name.value', $this->brand_name]); + $query->andFilterWhere(['ilike', 'category_name.value', $this->category_name]); return $dataProvider; } diff --git a/common/modules/product/models/ProductUnitSearch.php b/common/modules/product/models/ProductUnitSearch.php new file mode 100644 index 0000000..8b0be90 --- /dev/null +++ b/common/modules/product/models/ProductUnitSearch.php @@ -0,0 +1,72 @@ + $query, + ]); + + $this->load($params); + + if (!$this->validate()) { + // uncomment the following line if you do not want to return any records when validation fails + // $query->where('0=1'); + return $dataProvider; + } + + // grid filtering conditions + $query->andFilterWhere([ + 'product_unit_id' => $this->product_unit_id, + 'is_default' => $this->is_default, + ]); + + $query->andFilterWhere(['like', 'name', $this->name]) + ->andFilterWhere(['like', 'code', $this->code]); + + return $dataProvider; + } +} diff --git a/common/modules/product/models/ProductVariant.php b/common/modules/product/models/ProductVariant.php index f6836b8..08aa5cb 100755 --- a/common/modules/product/models/ProductVariant.php +++ b/common/modules/product/models/ProductVariant.php @@ -16,12 +16,16 @@ use Yii; * @property double $price_old * @property double $stock * @property integer $product_unit_id - * @property ProductUnit $productUnit * @property integer $product_variant_type_id - * @property ProductVariantType $productVariantType + * @property ProductImage $image + * @property array $images + * + * @property ProductUnit $productUnit */ class ProductVariant extends \yii\db\ActiveRecord { + /** @var array $_images */ + public $imagesUpload = []; /** * @inheritdoc */ @@ -41,8 +45,9 @@ class ProductVariant extends \yii\db\ActiveRecord [['price', 'price_old', 'stock'], 'number'], [['name', 'sku'], 'string', 'max' => 255], [['remote_id'], 'string', 'max' => 20], + [['imagesUpload'], 'safe'], + [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif', 'maxFiles' => 50], [['product_unit_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductUnit::className(), 'targetAttribute' => ['product_unit_id' => 'product_unit_id']], - [['product_variant_type_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductVariantType::className(), 'targetAttribute' => ['product_variant_type_id' => 'product_variant_type_id']], ]; } @@ -59,8 +64,11 @@ class ProductVariant extends \yii\db\ActiveRecord 'price' => Yii::t('product', 'Price'), 'price_old' => Yii::t('product', 'Price Old'), 'stock' => Yii::t('product', 'Stock'), - 'product_unit_id' => Yii::t('product', 'Unit'), - 'product_variant_type_id' => 'Type of the variant', + 'product_unit_id' => Yii::t('product', 'Product Unit ID'), + 'product_variant_type_id' => Yii::t('product', 'Product Variant Type ID'), + 'stock_caption' => Yii::t('product', 'Stock'), + 'image' => Yii::t('product', 'Image'), + 'images' => Yii::t('product', 'Images'), ]; } @@ -75,30 +83,41 @@ class ProductVariant extends \yii\db\ActiveRecord /** * @return \yii\db\ActiveQuery */ - public function getProduct() + public function getProductVariantType() { - return $this->hasOne(Product::className(), ['product_id' => 'product_id']); + return $this->hasOne(ProductVariantType::className(), ['product_variant_type_id' => 'product_variant_type_id']); } /** * @return \yii\db\ActiveQuery */ - public function getProductVariantType() { - return $this->hasOne(ProductVariantType::className(), ['product_variant_type_id' => 'product_variant_type_id']); + public function getProduct() + { + return $this->hasOne(Product::className(), ['product_id' => 'product_id']); + } + + public function getEnabled() { + return $this->stock !== 0; + } + + public function getStock_caption() { + return is_null($this->stock) ? '∞' : intval($this->stock); } /** * @return \yii\db\ActiveQuery */ - public function getImages() { - return $this->hasMany(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); + public function getImage() + { + return $this->hasOne(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); } /** * @return \yii\db\ActiveQuery */ - public function getImage() { - return $this->hasOne(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); + public function getImages() + { + return $this->hasMany(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); } /** diff --git a/common/modules/product/models/RemoteCategories.php b/common/modules/product/models/RemoteCategories.php deleted file mode 100755 index b9b6ae2..0000000 --- a/common/modules/product/models/RemoteCategories.php +++ /dev/null @@ -1,63 +0,0 @@ - 100], - [['ID_chief', 'ID'], 'string', 'max' => 20], - ]; - } - - /** - * @inheritdoc - */ - public function attributeLabels() - { - return [ - 'Name' => Yii::t('product', 'Name'), - 'ID_chief' => Yii::t('product', 'Id Chief'), - 'ID' => Yii::t('product', 'ID'), - ]; - } - - public function getCategory() { - if (empty($this->ID)) { - return null; - } - return CategorySearch::findByRemoteID($this->ID); - } - - public static function findByID($id) { - /** @var CategoryQuery $query */ - $query = RemoteCategories::find() - ->andFilterWhere(['ID' => $id]); - if (($model = $query->one()) !== null) { - return $model; - } - return null; - } -} diff --git a/common/modules/product/models/RemoteCategoriesSearch.php b/common/modules/product/models/RemoteCategoriesSearch.php deleted file mode 100755 index 6cdc2b3..0000000 --- a/common/modules/product/models/RemoteCategoriesSearch.php +++ /dev/null @@ -1,71 +0,0 @@ - $query, - ]); - - $this->load($params); - - if (!$this->validate()) { - // uncomment the following line if you do not want to return any records when validation fails - // $query->where('0=1'); - return $dataProvider; - } - - // grid filtering conditions - $query->andFilterWhere([ - 'local_id' => $this->local_id, - ]); - - $query->andFilterWhere(['like', 'Name', $this->Name]) - ->andFilterWhere(['like', 'ID_chief', $this->ID_chief]) - ->andFilterWhere(['like', 'ID', $this->ID]); - - return $dataProvider; - } -} diff --git a/common/modules/product/models/RemoteProducts.php b/common/modules/product/models/RemoteProducts.php deleted file mode 100755 index 981f933..0000000 --- a/common/modules/product/models/RemoteProducts.php +++ /dev/null @@ -1,77 +0,0 @@ - 100], - [['ID_chief', 'Article', 'ID'], 'string', 'max' => 20], - [['Brand'], 'string', 'max' => 25], - ]; - } - - /** - * @inheritdoc - */ - public function attributeLabels() - { - return [ - 'Name' => Yii::t('product', 'Name'), - 'Price' => Yii::t('product', 'Price'), - 'Price_old' => Yii::t('product', 'Price Old'), - 'ID_chief' => Yii::t('product', 'Id Chief'), - 'Article' => Yii::t('product', 'Article'), - 'Brand' => Yii::t('product', 'Brand'), - 'ID' => Yii::t('product', 'ID'), - 'Date_create' => Yii::t('product', 'Date Create'), - 'local_id' => Yii::t('product', 'Local ID'), - ]; - } - - public function getRemoteCategory() { - if (empty($this->ID_chief)) { - return null; - } - return RemoteCategories::findByID($this->ID_chief); - } - - public function getProduct() { - if (empty($this->ID)) { - return null; - } - return ProductVariantSearch::findByRemoteID($this->ID); - } -} diff --git a/common/modules/product/models/RemoteProductsSearch.php b/common/modules/product/models/RemoteProductsSearch.php deleted file mode 100755 index 7766eab..0000000 --- a/common/modules/product/models/RemoteProductsSearch.php +++ /dev/null @@ -1,77 +0,0 @@ - $query, - ]); - - $this->load($params); - - if (!$this->validate()) { - // uncomment the following line if you do not want to return any records when validation fails - // $query->where('0=1'); - return $dataProvider; - } - - // grid filtering conditions - $query->andFilterWhere([ - 'Price' => $this->Price, - 'Price_old' => $this->Price_old, - 'Date_create' => $this->Date_create, - 'local_id' => $this->local_id, - ]); - - $query->andFilterWhere(['like', 'Name', $this->Name]) - ->andFilterWhere(['like', 'ID_chief', $this->ID_chief]) - ->andFilterWhere(['like', 'Article', $this->Article]) - ->andFilterWhere(['like', 'Brand', $this->Brand]) - ->andFilterWhere(['like', 'ID', $this->ID]); - - return $dataProvider; - } -} diff --git a/common/modules/product/views/manage/_form.php b/common/modules/product/views/manage/_form.php index 1baa2d3..8a782d4 100755 --- a/common/modules/product/views/manage/_form.php +++ b/common/modules/product/views/manage/_form.php @@ -17,12 +17,14 @@ use kartik\select2\Select2;
+ = Html::a(Yii::t('product', 'Create Product Unit'), ['create'], ['class' => 'btn btn-success']) ?> +
+ = GridView::widget([ + 'dataProvider' => $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + + 'name', + 'code:html', + 'is_default:boolean', + + ['class' => 'yii\grid\ActionColumn'], + ], + ]); ?> ++ = Html::a(Yii::t('product', 'Update'), ['update', 'id' => $model->product_unit_id], ['class' => 'btn btn-primary']) ?> + = Html::a(Yii::t('product', 'Delete'), ['delete', 'id' => $model->product_unit_id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => Yii::t('product', 'Are you sure you want to delete this item?'), + 'method' => 'post', + ], + ]) ?> +
+ + = DetailView::widget([ + 'model' => $model, + 'attributes' => [ + 'product_unit_id', + 'name', + 'code', + 'is_default:boolean', + ], + ]) ?> + +
- Доставка товара на следующий день после выставления счета. Мы доставим “День в
день” — уточните это у менеджера.
-
'.$product->variant->price.' грн.
'; + + echo ''; + + $ids = ViewProduct::listView (); + if (! empty($ids)) + { + $products = Products::find ()->where (['id' => ViewProduct::listView ()])->all (); + echo 'Вы просматривали'; + } + else + { + $products = Products::find ()->where (['new' => '1'])->orderBy ('id DESC')->innerJoinWith (['cost'])->groupBy ('id')->limit (4)->all (); + echo 'Товары со скидкой'; + } + echo '
'; + + echo ' +'.$item->cost->cost.' грн.
+ +'.$item->cost->cost.' грн.
- -Подписаться на акции
'/subscribe']); + $subscribe = new Subscribe; + $form = ActiveForm::begin (['action' => '/subscribe']); ?> field ($subscribe, 'email')->textInput (['placeholder' => 'E-mail'])->label (false); ?> = $form->field ($subscribe, 'sale')->dropDownList (['10' => '10%', '20' => '20%'], ['prompt' => 'Скидка'])->label (false); ?> @@ -364,29 +352,7 @@ $this->registerJs(" - - - - - +