Commit e8ccb1b4b180af34bea03cadb3d4cb9591462214

Authored by Yarik
1 parent 14cd7eed

Import beta

common/modules/language/behaviors/LanguageBehavior.php
@@ -271,6 +271,9 @@ @@ -271,6 +271,9 @@
271 $this->_transaction->commit(); 271 $this->_transaction->commit();
272 $this->_transaction_status = true; 272 $this->_transaction_status = true;
273 } 273 }
  274 + if($owner->hasAttribute('remote_id') && empty($owner->remote_id)) {
  275 + $owner->remote_id = (int) $owner->primaryKey;
  276 + }
274 } 277 }
275 278
276 /** 279 /**
common/modules/language/models/Language.php
@@ -17,7 +17,10 @@ @@ -17,7 +17,10 @@
17 */ 17 */
18 class Language extends \yii\db\ActiveRecord 18 class Language extends \yii\db\ActiveRecord
19 { 19 {
20 - 20 +
  21 + /**
  22 + * @var null|self
  23 + */
21 public static $current = null; 24 public static $current = null;
22 25
23 /** 26 /**
common/modules/product/controllers/ManageController.php
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 use common\models\ProductCertificate; 5 use common\models\ProductCertificate;
6 use common\models\ProductSpec; 6 use common\models\ProductSpec;
  7 + use common\modules\language\models\Language;
7 use common\modules\product\models\Export; 8 use common\modules\product\models\Export;
8 use common\modules\product\models\Import; 9 use common\modules\product\models\Import;
9 use common\modules\product\models\ProductImage; 10 use common\modules\product\models\ProductImage;
@@ -313,7 +314,19 @@ @@ -313,7 +314,19 @@
313 { 314 {
314 $model = new Import(); 315 $model = new Import();
315 316
  317 + $languages = Language::find()
  318 + ->select([
  319 + 'name',
  320 + 'language_id',
  321 + ])
  322 + ->where([ 'status' => 1 ])
  323 + ->orderBy([ 'default' => SORT_DESC ])
  324 + ->asArray()
  325 + ->indexBy('language_id')
  326 + ->column();
  327 +
316 if($model->load(Yii::$app->request->post())) { 328 if($model->load(Yii::$app->request->post())) {
  329 + \Yii::$app->session->set('export_lang', $model->lang);
317 $file = UploadedFile::getInstances($model, 'file'); 330 $file = UploadedFile::getInstances($model, 'file');
318 $method = 'go' . ucfirst($model->type); 331 $method = 'go' . ucfirst($model->type);
319 $target = Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFile' . ucfirst($model->type)); 332 $target = Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFile' . ucfirst($model->type));
@@ -337,7 +350,8 @@ @@ -337,7 +350,8 @@
337 } 350 }
338 351
339 return $this->render('import', [ 352 return $this->render('import', [
340 - 'model' => $model, 353 + 'model' => $model,
  354 + 'languages' => $languages,
341 ]); 355 ]);
342 } 356 }
343 357
@@ -349,7 +363,7 @@ @@ -349,7 +363,7 @@
349 363
350 if(Yii::$app->request->isAjax) { 364 if(Yii::$app->request->isAjax) {
351 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 365 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
352 - return $model->goProducts($from, 10); 366 + return $model->goProducts($from, 1);
353 } 367 }
354 } 368 }
355 369
@@ -371,7 +385,7 @@ @@ -371,7 +385,7 @@
371 $model = new Export(); 385 $model = new Export();
372 if(Yii::$app->request->isAjax) { 386 if(Yii::$app->request->isAjax) {
373 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; 387 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
374 - return $model->process($filename,$from); 388 + return $model->process($filename, $from);
375 } 389 }
376 } 390 }
377 391
@@ -382,8 +396,8 @@ @@ -382,8 +396,8 @@
382 if($model->load(Yii::$app->request->post())) { 396 if($model->load(Yii::$app->request->post())) {
383 \Yii::$app->session->set('export_lang', $model->lang); 397 \Yii::$app->session->set('export_lang', $model->lang);
384 return $this->render('export-process', [ 398 return $this->render('export-process', [
385 - 'model' => $model,  
386 - 'method' => 'export', 399 + 'model' => $model,
  400 + 'method' => 'export',
387 ]); 401 ]);
388 } 402 }
389 403
common/modules/product/models/Import.php
1 <?php 1 <?php
2 -  
3 -namespace common\modules\product\models;  
4 -  
5 -use common\modules\rubrication\models\TaxGroup;  
6 -use common\modules\rubrication\models\TaxOption;  
7 -use Yii;  
8 -use yii\base\Model;  
9 -use yii\helpers\ArrayHelper;  
10 -  
11 -class Import extends Model {  
12 - public $file;  
13 - public $type;  
14 -  
15 - public $errors = [];  
16 - public $output = [];  
17 -  
18 - /**  
19 - * @inheritdoc  
20 - */  
21 - public function rules()  
22 - {  
23 - return [  
24 - [['type'], 'required'],  
25 - [['type'], 'string'],  
26 - [['file'], 'file', 'extensions' => 'csv'],  
27 - ];  
28 - }  
29 -  
30 - /**  
31 - * @inheritdoc  
32 - */  
33 - public function attributeLabels() 2 +
  3 + namespace common\modules\product\models;
  4 +
  5 + use common\modules\language\models\Language;
  6 + use common\modules\rubrication\models\TaxGroup;
  7 + use common\modules\rubrication\models\TaxOption;
  8 + use Yii;
  9 + use yii\base\Model;
  10 + use yii\helpers\ArrayHelper;
  11 +
  12 + class Import extends Model
34 { 13 {
35 - return [  
36 - 'file' => Yii::t('product', 'File'),  
37 - ];  
38 - }  
39 -  
40 - public function getType() {  
41 - if (!$this->type) {  
42 - $this->type = 'products';  
43 - }  
44 - return $this->type;  
45 - }  
46 -  
47 - public function goPrices($from = 0, $limit = null) {  
48 - set_time_limit(0);  
49 -  
50 - if ( !($handle = $this->getProductsFile('uploadFilePrices')) ) {  
51 - $this->errors[] = 'File not found';  
52 - return FALSE; 14 +
  15 + public $file;
  16 +
  17 + public $type;
  18 +
  19 + public $lang;
  20 +
  21 + public $errors = [];
  22 +
  23 + public $output = [];
  24 +
  25 + /**
  26 + * @inheritdoc
  27 + */
  28 + public function rules()
  29 + {
  30 + return [
  31 + [
  32 + [
  33 + 'type',
  34 + 'lang',
  35 + ],
  36 + 'required',
  37 + ],
  38 + [
  39 + [ 'lang' ],
  40 + 'integer',
  41 + ],
  42 + [
  43 + [ 'type' ],
  44 + 'string',
  45 + ],
  46 + [
  47 + [ 'file' ],
  48 + 'file',
  49 + 'extensions' => 'csv',
  50 + ],
  51 + ];
53 } 52 }
54 -  
55 - $filesize = filesize(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'));  
56 - if ($from) {  
57 - fseek($handle, $from); 53 +
  54 + /**
  55 + * @inheritdoc
  56 + */
  57 + public function attributeLabels()
  58 + {
  59 + return [
  60 + 'file' => Yii::t('product', 'File'),
  61 + ];
58 } 62 }
59 -  
60 - $j = 0;  
61 -  
62 - $is_utf = (preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'), null, null, null, 1000000)));  
63 -  
64 - while (($data = fgetcsv ($handle, 10000, ";")) !== FALSE && (empty($limit) || $j++ < $limit)) 63 +
  64 + public function getType()
65 { 65 {
66 - foreach ($data as &$value)  
67 - {  
68 - if (!$is_utf) {  
69 - $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);  
70 - }  
71 - $value = trim ($value);  
72 - }  
73 -  
74 - // данные строк  
75 - $modification_code = @$data[0];  
76 - $price = floatval(@$data[1]);  
77 - $price_promo = floatval(@$data[2]);  
78 - $count = intval(@$data[3]);  
79 - $city_name = @$data[4];  
80 - $product_title = @$data[5];  
81 -  
82 - if (empty ($modification_code)) {  
83 - continue; 66 + if(!$this->type) {
  67 + $this->type = 'products';
84 } 68 }
85 - // товары в пути  
86 - if (empty ($city_name))  
87 - {  
88 - $this->output[] = 'Товар '. $product_title . ' в пути';  
89 - continue; 69 + return $this->type;
  70 + }
  71 +
  72 + public function goPrices($from = 0, $limit = NULL)
  73 + {
  74 + set_time_limit(0);
  75 +
  76 + if(!( $handle = $this->getProductsFile('uploadFilePrices') )) {
  77 + $this->errors[] = 'File not found';
  78 + return false;
90 } 79 }
91 -  
92 - if ( ($productVariant = ProductVariant::find()->filterWhere(['sku' => $modification_code])->one()) === null ) {  
93 - $this->output[] = 'Для товара '. $product_title . ' не найдено соотвествие';  
94 - continue; 80 +
  81 + $filesize = filesize(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFilePrices'));
  82 + if($from) {
  83 + fseek($handle, $from);
95 } 84 }
96 - // ===== Set stock ====  
97 - if ( $city_name ) {  
98 - if ( ($stock = Stock::find()->filterWhere(['name' => trim($city_name)])->one()) === null ) {  
99 - // Create stock  
100 - $stock = new Stock();  
101 - $stock->name = trim($city_name);  
102 - $stock->save(); 85 +
  86 + $j = 0;
  87 +
  88 + $is_utf = ( preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFilePrices'), NULL, NULL, NULL, 1000000)) );
  89 +
  90 + while(( empty( $limit ) || $j++ < $limit ) && ( $data = fgetcsv($handle, 10000, ";") ) !== false) {
  91 + foreach($data as &$value) {
  92 + if(!$is_utf) {
  93 + $value = iconv('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
  94 + }
  95 + $value = trim($value);
103 } 96 }
104 -  
105 - $productStock = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id, 'stock_id' => $stock->stock_id])->one();  
106 - if(!$productStock instanceof ProductStock) {  
107 - $productStock = new ProductStock;  
108 - $productStock->product_variant_id = $productVariant->product_variant_id;  
109 - $productStock->stock_id = $stock->stock_id;  
110 - $productStock->product_id = $productVariant->product_id; 97 +
  98 + // данные строк
  99 + $modification_code = @$data[ 0 ];
  100 + $price = floatval(@$data[ 1 ]);
  101 + $price_promo = floatval(@$data[ 2 ]);
  102 + $count = intval(@$data[ 3 ]);
  103 + $city_name = @$data[ 4 ];
  104 + $product_title = @$data[ 5 ];
  105 +
  106 + if(empty ( $modification_code )) {
  107 + continue;
111 } 108 }
112 - $productStock->quantity = $count;  
113 -  
114 - $productStock->save();  
115 - $productStocks = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id])->andWhere(['<>', 'stock_id', $stock->stock_id])->all();  
116 -  
117 - $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count;  
118 - } else {  
119 -  
120 - $productStocks = ProductStock::find()->where(['product_variant_id' => $productVariant->product_variant_id])->all();  
121 -  
122 - if($productStocks instanceof ProductStock){ 109 + // товары в пути
  110 + if(empty ( $city_name )) {
  111 + $this->output[] = 'Товар ' . $product_title . ' в пути';
  112 + continue;
  113 + }
  114 +
  115 + if(( $productVariant = ProductVariant::find()
  116 + ->filterWhere([ 'sku' => $modification_code ])
  117 + ->one() ) === NULL
  118 + ) {
  119 + $this->output[] = 'Для товара ' . $product_title . ' не найдено соотвествие';
  120 + continue;
  121 + }
  122 + // ===== Set stock ====
  123 + if($city_name) {
  124 + if(( $stock = Stock::find()
  125 + ->filterWhere([ 'name' => trim($city_name) ])
  126 + ->one() ) === NULL
  127 + ) {
  128 + // Create stock
  129 + $stock = new Stock();
  130 + $stock->name = trim($city_name);
  131 + $stock->save();
  132 + }
  133 +
  134 + $productStock = ProductStock::find()
  135 + ->where([
  136 + 'product_variant_id' => $productVariant->product_variant_id,
  137 + 'stock_id' => $stock->stock_id,
  138 + ])
  139 + ->one();
  140 + if(!$productStock instanceof ProductStock) {
  141 + $productStock = new ProductStock;
  142 + $productStock->product_variant_id = $productVariant->product_variant_id;
  143 + $productStock->stock_id = $stock->stock_id;
  144 + $productStock->product_id = $productVariant->product_id;
  145 + }
  146 + $productStock->quantity = $count;
  147 +
  148 + $productStock->save();
  149 + $productStocks = ProductStock::find()
  150 + ->where([ 'product_variant_id' => $productVariant->product_variant_id ])
  151 + ->andWhere([
  152 + '<>',
  153 + 'stock_id',
  154 + $stock->stock_id,
  155 + ])
  156 + ->all();
  157 +
123 $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count; 158 $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count;
124 } else { 159 } else {
125 - $quantity = 0; 160 +
  161 + $productStocks = ProductStock::find()
  162 + ->where([ 'product_variant_id' => $productVariant->product_variant_id ])
  163 + ->all();
  164 +
  165 + if($productStocks instanceof ProductStock) {
  166 + $quantity = array_sum(ArrayHelper::getColumn($productStocks, 'quantity')) + $count;
  167 + } else {
  168 + $quantity = 0;
  169 + }
  170 +
126 } 171 }
127 - 172 +
  173 + if($price_promo) {
  174 + $productVariant->price_old = $price;
  175 + $productVariant->price = $price_promo;
  176 + } else {
  177 + $productVariant->price = $price;
  178 + $productVariant->price_old = $price_promo;
  179 + }
  180 +
  181 + $productVariant->stock = $quantity;
  182 +
  183 + $productVariant->save();
  184 +
  185 + $this->output[] = '<font style="color:blue">Товар ' . $product_title . ' успешно сохранен</font>';
128 } 186 }
129 -  
130 - if ($price_promo) {  
131 - $productVariant->price_old = $price;  
132 - $productVariant->price = $price_promo;  
133 - } else {  
134 - $productVariant->price = $price;  
135 - $productVariant->price_old = $price_promo; 187 +
  188 + $result = [
  189 + 'end' => feof($handle),
  190 + 'from' => ftell($handle),
  191 + 'totalsize' => $filesize,
  192 + 'items' => $this->output,
  193 +
  194 + ];
  195 +
  196 + fclose($handle);
  197 +
  198 + if($result[ 'end' ]) {
  199 + unlink(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFilePrices'));
136 } 200 }
137 -  
138 - $productVariant->stock = $quantity;  
139 -  
140 - $productVariant->save();  
141 -  
142 - $this->output[] = '<font style="color:blue">Товар '. $product_title .' успешно сохранен</font>';  
143 - }  
144 -  
145 - $result = [  
146 - 'end' => feof($handle),  
147 - 'from' => ftell($handle),  
148 - 'totalsize' => $filesize,  
149 - 'items' => $this->output,  
150 -  
151 - ];  
152 -  
153 - fclose ($handle);  
154 -  
155 - if ($result['end']) {  
156 - unlink(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices'));  
157 - }  
158 -  
159 - return $result;  
160 - }  
161 -  
162 - public function goProducts($from = 0, $limit = null) {  
163 -  
164 - set_time_limit(0);  
165 -  
166 - if ( !($handle = $this->getProductsFile('uploadFileProducts')) ) {  
167 - $this->errors[] = 'File not found';  
168 - return FALSE; 201 +
  202 + return $result;
169 } 203 }
170 -  
171 - $filesize = filesize(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'));  
172 204
173 - if ($from) {  
174 - fseek($handle, $from);  
175 - }  
176 -  
177 - $j = 0;  
178 -  
179 - $is_utf = (preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'), null, null, null, 1000000)));  
180 -  
181 - $result_items = [];  
182 -  
183 - while (($data = fgetcsv ($handle, 10000, ";")) !== FALSE && (empty($limit) || $j++ < $limit)) 205 + /**
  206 + * @param string $name
  207 + *
  208 + * @return array
  209 + */
  210 + private function parseName(string $name):array
184 { 211 {
185 - foreach ($data as &$value)  
186 - {  
187 - if (!$is_utf) {  
188 - $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);  
189 - }  
190 - $value = trim ($value);  
191 - }  
192 - // будет всегда 19 элементов  
193 - for ($i = 0; $i <= 18; $i++)  
194 - {  
195 - if (! isset ($data[$i]))  
196 - {  
197 - $data[$i] = null; 212 + $pattern = '/^(?P<name>.*)(?:\(#(?P<remote_id>\w+)#\))?$/U';
  213 + $name = trim($name);
  214 + $matches = [];
  215 + if(preg_match($pattern, $name, $matches)) {
  216 + if(!isset($matches['remote_id'])) {
  217 + $matches['remote_id'] = '';
198 } 218 }
  219 + return $matches;
199 } 220 }
200 - // 1 Группа (категория)  
201 - $catalog_names = explode(',',$data[0]);  
202 - if (empty ($catalog_names))  
203 - {  
204 - $result_items[] = "Не указана категория (строка $j)";  
205 - continue;  
206 - }  
207 -  
208 - // 2 Бренд  
209 - $brand_name = $data[1];  
210 - if (empty ($brand_name))  
211 - {  
212 - $result_items[] = "Не указан бренд (строка $j)";  
213 - continue;  
214 - }  
215 -  
216 - // 3 Название товара  
217 - $product_name = $data[2];  
218 - if (empty ($product_name))  
219 - {  
220 - $result_items[] = "Не указано наименование товара (строка $j)";  
221 - continue;  
222 - }  
223 -  
224 - // 4 Описание Укр  
225 - $product_body_uk = $data[3];  
226 -  
227 - // 5 Описание Рус  
228 - $product_body_ru = $data[4];  
229 -  
230 - // 6 Фильтр  
231 - $filters = explode ('*', $data[5]);  
232 -  
233 - // 11 Цена акция  
234 - $product_cost_old = floatval($data[7]);  
235 -  
236 - // 10 Цена  
237 - if ($product_cost_old) {  
238 - $product_cost_old = floatval($data[6]);  
239 - $product_cost = floatval($data[7]);  
240 - }  
241 -  
242 - // 12 Акция  
243 - $product_akciya = (bool)$data[8];  
244 -  
245 - // 13 Сопуд. Тов.  
246 - $similar = explode (',', $data[9]);  
247 -  
248 - // 14 Новинки  
249 - $product_new = (bool)$data[10];  
250 -  
251 - // 15 Топ продаж  
252 - $product_top = (bool)$data[11];  
253 -  
254 - // 17 ВИДЕО КОД  
255 - $product_video = $data[12];  
256 -  
257 - // 18 Галлерея фото  
258 - if (trim($data[13])) {  
259 - $fotos = explode (',', trim($data[13]));  
260 - }  
261 -  
262 - // 19 Штрих код товара.  
263 - // расшифровал - это модификации товара!  
264 -  
265 - $product_image = explode ('=', $data[14]);  
266 - $product_image = @$product_image[3];  
267 -  
268 - if ( ($_product = Product::find()->filterWhere(['ilike', 'name', trim($product_name)])->one()) === null ) {  
269 - $_product = new Product();  
270 - }  
271 -  
272 - $is_new_product = empty($_product->product_id);  
273 - 221 + return [
  222 + 'name' => $name,
  223 + 'remote_id' => '',
  224 + ];
  225 + }
  226 +
  227 + /**
  228 + * @param array $catalog_names
  229 + *
  230 + * @return array
  231 + * @throws \Exception
  232 + */
  233 + private function saveCatalog(array $catalog_names):array
  234 + {
274 $category_id = []; 235 $category_id = [];
275 236
276 - foreach($catalog_names as $catalog_name){ 237 + foreach($catalog_names as $catalog_name) {
277 // ==== Set category ==== 238 // ==== Set category ====
278 - if ( ($category = Category::find()->filterWhere(['ilike', 'name', trim($catalog_name)])->one()) === null ) { 239 + $parsed_name = $this->parseName($catalog_name);
  240 + if(!empty($parsed_name['remote_id']) && ( $category = Category::find()
  241 + ->joinWith('lang')
  242 + ->andFilterWhere([ 'remote_id' => $parsed_name[ 'remote_id' ] ])
  243 + ->one() ) !== NULL
  244 + ) {
  245 + if(!empty( $category->lang )) {
  246 + $category->lang->name = $parsed_name[ 'name' ];
  247 + $category->lang->save();
  248 + } else {
  249 + throw new \Exception('Category with ID ' . $category->category_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  250 + }
  251 +
  252 + } else {
279 // Create category 253 // Create category
280 $category = new Category(); 254 $category = new Category();
281 - $category->name = trim($catalog_name); 255 + $category->generateLangs();
  256 + $category_langs = $category->model_langs;
  257 + foreach($category_langs as $category_lang) {
  258 + $category_lang->name = $parsed_name[ 'name' ];
  259 + }
  260 + $category->remote_id = $parsed_name[ 'remote_id' ];
282 $category->save(); 261 $category->save();
283 } 262 }
284 $category_id[] = $category->category_id; 263 $category_id[] = $category->category_id;
285 } 264 }
286 -  
287 - $_product->categories = $category_id;  
288 -  
289 - // ===== Set brand ====  
290 - if ( $brand_name ) { 265 + return $category_id;
  266 + }
  267 +
  268 + /**
  269 + * @param string|NULL $brand_name
  270 + *
  271 + * @return int|null
  272 + * @throws \Exception
  273 + */
  274 + private function saveBrand(string $brand_name = NULL):int
  275 + {
  276 +
  277 + $parsed_name = $this->parseName($brand_name);
  278 + if(!empty( $brand_name )) {
291 /** 279 /**
292 * @var Brand $brand 280 * @var Brand $brand
293 */ 281 */
294 - if ( ($brand = Brand::find()->filterWhere(['ilike', 'name', trim($brand_name)])->one()) !== null ) {  
295 - $_product->brand_id = $brand->brand_id; 282 + if(!empty($parsed_name['remote_id']) && ($brand = Brand::find()
  283 + ->joinWith('lang')
  284 + ->andFilterWhere([ 'remote_id' => $parsed_name[ 'remote_id' ] ])
  285 + ->one() ) !== NULL
  286 + ) {
  287 + if(!empty( $brand->lang )) {
  288 + $brand->lang->name = $parsed_name[ 'name' ];
  289 + $brand->lang->save();
  290 + } else {
  291 + throw new \Exception('Brand with ID ' . $brand->brand_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  292 + }
  293 + return $brand->brand_id;
296 } else { 294 } else {
297 // Create brand 295 // Create brand
298 $brand = new Brand(); 296 $brand = new Brand();
299 - $brand->name = trim($brand_name); 297 + $brand->generateLangs();
  298 + $brand_langs = $brand->model_langs;
  299 + foreach($brand_langs as $brand_lang) {
  300 + $brand_lang->name = $parsed_name[ 'name' ];
  301 + }
  302 + $brand->remote_id = $parsed_name[ 'remote_id' ];
300 $brand->save(); 303 $brand->save();
301 - $_product->brand_id = $brand->brand_id; 304 + return $brand->brand_id;
302 } 305 }
303 } 306 }
304 -  
305 - $_product->name = $product_name;  
306 - $_product->video = $product_video;  
307 - $_product->description = $product_body_ru;  
308 - $_product->is_top = $product_top;  
309 - $_product->akciya = $product_akciya;  
310 - $_product->is_new = $product_new;  
311 -  
312 - if (!$_product->save()) {  
313 - $result_items[] = 'Product #'. $_product->name .' not saved' . " (строка $j)";  
314 - continue;  
315 - }  
316 -  
317 - if (!empty($fotos)) { 307 + return NULL;
  308 + }
  309 +
  310 + /**
  311 + * @param array $fotos
  312 + * @param int $product_id
  313 + * @param int $product_variant_id
  314 + */
  315 + private function saveFotos(array $fotos, int $product_id, int $product_variant_id = NULL)
  316 + {
  317 + if(!empty( $fotos )) {
318 foreach($fotos as $foto) { 318 foreach($fotos as $foto) {
319 - $source_image = Yii::getAlias('@uploadDir') . '/product_images/'. urlencode($foto);  
320 -  
321 - if (file_exists($source_image)) {  
322 - if (($productImage = ProductImage::find()->andFilterWhere(['ilike', 'image', $foto])->andFilterWhere(['product_id' => $_product->product_id])->one()) === null) { 319 + $source_image = Yii::getAlias('@uploadDir') . '/product_images/' . urlencode($foto);
  320 + if(file_exists($source_image)) {
  321 + if(( $productImage = ProductImage::find()
  322 + ->andWhere([ 'image' => $foto ])
  323 + ->andWhere([ 'product_id' => $product_id ])
  324 + ->andFilterWhere([ 'product_variant_id' => $product_variant_id ])
  325 + ->one() ) === NULL
  326 + ) {
323 copy($source_image, Yii::getAlias('@productsDir') . "/" . $foto); 327 copy($source_image, Yii::getAlias('@productsDir') . "/" . $foto);
324 $productImage = new ProductImage(); 328 $productImage = new ProductImage();
325 - $productImage->product_id = $_product->product_id; 329 + $productImage->product_id = $product_id;
  330 + $productImage->product_variant_id = $product_variant_id;
326 $productImage->image = $foto; 331 $productImage->image = $foto;
327 $productImage->save(); 332 $productImage->save();
328 } 333 }
329 } 334 }
330 } 335 }
331 } 336 }
332 -  
333 - // нужно для проставления характеристик относящихся к модификациям 337 + }
  338 +
  339 + /**
  340 + * @param array $data
  341 + * @param float $product_cost_old
  342 + * @param float $product_cost
  343 + * @param int $product_id
  344 + * @param array $category_id
  345 + *
  346 + * @return array
  347 + */
  348 + private function saveVariants(array $data, float $product_cost_old, int $product_id, array $category_id, float $product_cost = NULL):array
  349 + {
334 $MOD_ARRAY = []; 350 $MOD_ARRAY = [];
335 -  
336 - for ($i = 14; $i < count ($data); $i ++)  
337 - {  
338 - if (! empty ($data[$i]))  
339 - {  
340 - $mod_arr = explode ('=', $data[$i]);  
341 - $mod_art = $mod_arr[0];  
342 - $variant_filters = explode ('*', $mod_arr[1]);  
343 - $mod_color = $mod_arr[2];  
344 - $mod_image = $mod_arr[3];  
345 - $mod_stock = isset($mod_arr[4]) ?$mod_arr[4]:1;  
346 - $mod_cost = isset($product_cost) ? floatval($product_cost) : 0; 351 + for($i = 13; $i < count($data); $i++) {
  352 + if(!empty ( $data[ $i ] )) {
  353 + $mod_arr = explode('=', $data[ $i ]);
  354 + $mod_art = $mod_arr[ 0 ];
  355 + $variant_filters = explode('*', $mod_arr[ 1 ]);
  356 + $mod_name = $mod_arr[ 2 ];
  357 + if(empty( $mod_name )) {
  358 + $mod_name = $mod_art;
  359 + }
  360 + $mod_image = $mod_arr[ 3 ];
  361 + $mod_stock = isset( $mod_arr[ 4 ] ) ? $mod_arr[ 4 ] : 1;
  362 + $mod_cost = isset( $product_cost ) ? floatval($product_cost) : 0;
347 $mod_old_cost = floatval($product_cost_old); 363 $mod_old_cost = floatval($product_cost_old);
348 // Check product variant 364 // Check product variant
349 - if ( ($_productVariant = ProductVariant::find()->andFilterWhere(['ilike', 'sku', $mod_art])->andFilterWhere(['product_id' => $_product->product_id])->one()) === null ) { 365 + /**
  366 + * @var ProductVariant $_productVariant
  367 + */
  368 + if(( $_productVariant = ProductVariant::find()
  369 + ->joinWith('lang')
  370 + ->andFilterWhere([ 'sku' => $mod_art ])
  371 + ->andFilterWhere([ 'product_variant.product_id' => $product_id ])
  372 + ->one() ) === NULL
  373 + ) {
350 $_productVariant = new ProductVariant(); 374 $_productVariant = new ProductVariant();
351 - $_productVariant->product_id = $_product->product_id; 375 + $_productVariant->product_id = $product_id;
  376 + $_productVariant->generateLangs();
  377 + $product_variant_langs = $_productVariant->model_langs;
  378 + foreach($product_variant_langs as $product_variant_lang) {
  379 + $product_variant_lang->name = $mod_name;
  380 + }
  381 + } else {
  382 + if(!empty( $_productVariant->lang )) {
  383 + $_productVariant->lang->name = $mod_name;
  384 + $_productVariant->lang->save();
  385 + } else {
  386 + throw new \Exception('Product variant with ID ' . $_productVariant->product_variant_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  387 + }
352 } 388 }
353 $_productVariant->product_unit_id = 1; 389 $_productVariant->product_unit_id = 1;
354 $_productVariant->sku = $mod_art; 390 $_productVariant->sku = $mod_art;
355 $_productVariant->price = $mod_cost; 391 $_productVariant->price = $mod_cost;
356 $_productVariant->price_old = $mod_old_cost; 392 $_productVariant->price_old = $mod_old_cost;
357 $_productVariant->stock = $mod_stock; 393 $_productVariant->stock = $mod_stock;
358 -  
359 - if (! empty ($mod_color)) {  
360 - $_productVariant->name = $mod_color; 394 +
  395 + if(!empty ( $variant_filters )) {
  396 + $variants_options = $this->saveFilters($variant_filters, 1, $category_id);
361 } 397 }
362 -  
363 - if (! empty ($variant_filters)) {  
364 - $variants_options = $this->saveFilters($variant_filters,1,$category_id);  
365 - }  
366 -  
367 -  
368 - if (isset($variants_options) && !empty($variants_options)) { 398 +
  399 + if(isset( $variants_options ) && !empty( $variants_options )) {
369 $_productVariant->options = $variants_options; 400 $_productVariant->options = $variants_options;
370 } 401 }
371 - 402 +
  403 + /**
  404 + * @todo set to false
  405 + */
372 $_productVariant->save(false); 406 $_productVariant->save(false);
373 - 407 +
374 $MOD_ARRAY[] = $_productVariant->product_variant_id; 408 $MOD_ARRAY[] = $_productVariant->product_variant_id;
  409 +
  410 + $this->saveFotos([ $mod_image ], $product_id, $_productVariant->product_variant_id);
  411 + }
  412 + }
  413 + return $MOD_ARRAY;
  414 + }
  415 +
  416 + private function debug($start_time, $message) {
  417 + echo $message.': '.(time()-$start_time).'s passed';
  418 + }
  419 +
  420 + public function goProducts($from = 0, $limit = NULL)
  421 + {
  422 + $start_time = time();
  423 + set_time_limit(0);
  424 +
  425 + if(!( $handle = $this->getProductsFile('uploadFileProducts') )) {
  426 + $this->errors[] = 'File not found';
  427 + return false;
  428 + }
375 429
376 - if ($mod_image) {  
377 - $source_image = Yii::getAlias('@uploadDir') . '/product_images/'. urlencode($mod_image);  
378 - if (file_exists($source_image)) {  
379 - if (($variantImage = ProductImage::find()->andFilterWhere(['ilike', 'image', $mod_image])->andFilterWhere(['product_variant_id' => $_productVariant->product_variant_id])->one()) === null) {  
380 - copy($source_image, Yii::getAlias('@productsDir') . "/" . $mod_image);  
381 - $variantImage = new ProductImage();  
382 - $variantImage->product_id = $_product->product_id;  
383 - $variantImage->product_variant_id = $_productVariant->product_variant_id;  
384 - $variantImage->image = $mod_image;  
385 - $variantImage->save();  
386 - } 430 + $filesize = filesize(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFileProducts'));
  431 +
  432 + if($from) {
  433 + fseek($handle, $from);
  434 + }
  435 +
  436 + $j = 0;
  437 +
  438 + $is_utf = ( preg_match('//u', file_get_contents(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFileProducts'), NULL, NULL, NULL, 1000000)) );
  439 +
  440 + $result_items = [];
  441 +
  442 + while(( empty( $limit ) || $j++ < $limit ) && ( $data = fgetcsv($handle, 10000, ";") ) !== false) {
  443 +
  444 + try {
  445 + foreach($data as &$value) {
  446 + if(!$is_utf) {
  447 + $value = iconv('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
  448 + }
  449 + $value = trim($value);
  450 + }
  451 + // будет всегда 19 элементов
  452 + for($i = 0; $i <= 18; $i++) {
  453 + if(!isset ( $data[ $i ] )) {
  454 + $data[ $i ] = NULL;
  455 + }
  456 + }
  457 + // 1 Группа (категория)
  458 + $catalog_names = explode(',', $data[ 0 ]);
  459 + if(empty ( $catalog_names )) {
  460 + $result_items[] = "Не указана категория (строка $j)";
  461 + continue;
  462 + }
  463 +
  464 + // 2 Бренд
  465 + $brand_name = $data[ 1 ];
  466 + // if(empty ( $brand_name )) {
  467 + // $result_items[] = "Не указан бренд (строка $j)";
  468 + // continue;
  469 + // }
  470 +
  471 + // 3 Название товара
  472 + $product_name = $data[ 2 ];
  473 + if(empty ( $product_name )) {
  474 + $result_items[] = "Не указано наименование товара (строка $j)";
  475 + continue;
  476 + }
  477 +
  478 + // 5 Описание товара
  479 + $product_body = $data[ 3 ];
  480 +
  481 + // 6 Фильтр
  482 + $filters = explode('*', $data[ 4 ]);
  483 +
  484 + // 11 Цена акция
  485 + $product_cost_old = floatval($data[ 6 ]);
  486 +
  487 + $product_cost = NULL;
  488 + // 10 Цена
  489 + if($product_cost_old) {
  490 + $product_cost_old = floatval($data[ 5 ]);
  491 + $product_cost = floatval($data[ 6 ]);
  492 + }
  493 +
  494 + // 12 Акция
  495 + $product_akciya = (bool) $data[ 7 ];
  496 +
  497 + // 13 Сопуд. Тов.
  498 + $similar = explode(',', $data[ 8 ]);
  499 +
  500 + // 14 Новинки
  501 + $product_new = (bool) $data[ 9 ];
  502 +
  503 + // 15 Топ продаж
  504 + $product_top = (bool) $data[ 10 ];
  505 +
  506 + // 17 ВИДЕО КОД
  507 + $product_video = $data[ 11 ];
  508 +
  509 + // 18 Галлерея фото
  510 + $fotos = [];
  511 + if(trim($data[ 12 ])) {
  512 + $fotos = explode(',', trim($data[ 12 ]));
  513 + }
  514 +
  515 +// $lang = \Yii::$app->session->get('export_lang', Language::getDefaultLanguage()->language_id);
  516 +// /**
  517 +// * @var Language $language
  518 +// */
  519 +// $language = Language::find()
  520 +// ->where([ 'language_id' => $lang ])
  521 +// ->one();
  522 +// Language::setCurrent($language->url);
  523 + $start_time = time();
  524 + $categories = $this->saveCatalog($catalog_names);
  525 + $this->debug($start_time, 'Categories');
  526 + $start_time = time();
  527 + $brand_id = $this->saveBrand($brand_name);
  528 + $this->debug($start_time, 'Brands');
  529 +
  530 + $options = [];
  531 + if(!empty ( $filters )) {
  532 + $start_time = time();
  533 + $options = $this->saveFilters($filters, 0, $categories);
  534 + $this->debug($start_time, 'saveFilters');
  535 + }
  536 + $parsed_name = $this->parseName($product_name);
  537 + /**
  538 + * @var Product $_product
  539 + */
  540 + $start_time = time();
  541 + if(!empty($parsed_name['remote_id']) && ( $_product = Product::find()
  542 + ->joinWith('lang')
  543 + ->andFilterWhere([ 'remote_id' => $parsed_name[ 'remote_id' ] ])
  544 + ->one() ) !== NULL
  545 + ) {
  546 + if(!empty( $_product->lang )) {
  547 + $_product->lang->name = $parsed_name[ 'name' ];
  548 + $_product->lang->description = $product_body;
  549 + $_product->lang->save();
  550 + } else {
  551 + throw new \Exception('Product with ID ' . $_product->product_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  552 + }
  553 + } else {
  554 + $_product = new Product();
  555 + $_product->generateLangs();
  556 + $product_langs = $_product->model_langs;
  557 + foreach($product_langs as $product_lang) {
  558 + $product_lang->name = $parsed_name[ 'name' ];
  559 + $product_lang->description = $product_body;
  560 + }
  561 + }
  562 +
  563 + $is_new_product = empty( $_product->product_id );
  564 +
  565 + $_product->categories = $categories;
  566 +
  567 + $_product->brand_id = $brand_id;
  568 +
  569 + $_product->video = $product_video;
  570 + $_product->is_top = $product_top;
  571 + $_product->akciya = $product_akciya;
  572 + $_product->is_new = $product_new;
  573 + $this->debug($start_time, 'Product');
  574 + if(!$_product->save()) {
  575 + if(!empty( $_product->lang )) {
  576 + $product_name_inserted = $_product->lang->name;
  577 + } else {
  578 + $product_name_inserted = $_product->model_langs[ Language::$current->language_id ]->name;
387 } 579 }
  580 + $result_items[] = 'Product #' . $product_name_inserted . ' not saved' . " (line $j)";
  581 + continue;
388 } 582 }
  583 + $start_time = time();
  584 + $this->saveFotos($fotos, $_product->product_id);
  585 + $this->debug($start_time, 'saveFotos');
  586 + // нужно для проставления характеристик относящихся к модификациям
  587 + $start_time = time();
  588 + $this->saveVariants($data, $product_cost_old, $_product->product_id, $_product->categories, $product_cost);
  589 + $this->debug($start_time, 'saveVariants');
  590 + if(!empty( $options )) {
  591 + $_product->options = $options;
  592 + }
  593 +
  594 + $_product->save();
  595 +
  596 + $result_items[] = "Product {$_product->lang->name} #{$_product->product_id} saved (" . ( $is_new_product ? 'new product' : 'exists product' ) . ")" . " (line $j)";
  597 +
  598 + } catch(\Exception $e) {
  599 + print $result_items[] = $e->getMessage() . '(line ' . $j . ')';
389 } 600 }
  601 +
390 } 602 }
391 -  
392 -  
393 -  
394 - if (! empty ($filters)) {  
395 - $options = $this->saveFilters($filters,0,$category_id);  
396 - }  
397 -  
398 -  
399 - if (isset($options) && !empty($options)) {  
400 - $_product->options = $options; 603 +
  604 + $result = [
  605 + 'end' => feof($handle),
  606 + 'from' => ftell($handle),
  607 + 'totalsize' => $filesize,
  608 + 'items' => $result_items,
  609 + ];
  610 +
  611 + fclose($handle);
  612 +
  613 + if($result[ 'end' ]) {
  614 +// unlink(Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@uploadFileProducts'));
401 } 615 }
402 -  
403 - $_product->save();  
404 -  
405 - $result_items[] = "Product {$_product->name} #{$_product->product_id} saved (". ($is_new_product ? 'new product' : 'exists product') .")" . " (строка $j)";  
406 - }  
407 -  
408 - $result = [  
409 - 'end' => feof($handle),  
410 - 'from' => ftell($handle),  
411 - 'totalsize' => $filesize,  
412 - 'items' => $result_items,  
413 - ];  
414 -  
415 - fclose ($handle);  
416 -  
417 - if ($result['end']) {  
418 - unlink(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'));  
419 - }  
420 -  
421 - return $result;  
422 - }  
423 -  
424 - private function getProductsFile($file_type) {  
425 - $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@'. $file_type);  
426 - if (!is_file($filename)) {  
427 - $this->errors[] = "File $filename not found";  
428 - return FALSE; 616 +
  617 + return $result;
429 } 618 }
430 - return fopen ($filename, 'r');  
431 - }  
432 -  
433 - private function saveNotFoundRecord (array $line, $filename)  
434 - {  
435 - $str = implode (';', $line)."\n";  
436 - $str = iconv ("UTF-8//TRANSLIT//IGNORE", "windows-1251", $str);  
437 - $fg = fopen (Yii::getAlias('@uploadDir') .'/'. $filename, 'a+');  
438 - fputs ($fg, $str);  
439 - fclose ($fg);  
440 - }  
441 -  
442 -  
443 - /**  
444 - * @param $filters array of filters like [['pol'='мужской'],['god' = '2013'],['volume'='25 л']*['size'='49 x 30 x 20см'],['composition'='600D полиэстер']]  
445 - * @param $level 0 for products and 1 for product variant  
446 - * @param $catalog_names array catalogs id  
447 - * @return array  
448 - */  
449 - private function saveFilters($filters, $level,$catalog_names){  
450 - $options = [];  
451 - foreach($filters as $filter) {  
452 -  
453 - preg_match_all('/\[(.*):(.*)\]/',$filter,$filter);  
454 -  
455 - if (empty($filter[1][0])) {  
456 - continue;  
457 - }  
458 - $filter_name = trim($filter[1][0]);  
459 -  
460 - $taxGroup = TaxGroup::find()->where(['alias'=>$filter_name])->one();  
461 - if(!$taxGroup instanceof TaxGroup){  
462 - $taxGroup = new TaxGroup();  
463 - $taxGroup->alias = $filter_name;  
464 - $taxGroup->level = $level;  
465 - $taxGroup->name = $filter_name;  
466 - $taxGroup->categories = $catalog_names;  
467 - $taxGroup->is_filter = FALSE;  
468 - $taxGroup->save(); 619 +
  620 + private function getProductsFile($file_type)
  621 + {
  622 + $filename = Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@' . $file_type);
  623 + if(!is_file($filename)) {
  624 + $this->errors[] = "File $filename not found";
  625 + return false;
469 } 626 }
470 -  
471 - $filters_options = explode(',',$filter[2][0]);  
472 -  
473 - foreach($filters_options as $filter_options){  
474 - $option = TaxOption::find()->andFilterWhere(['ilike', 'value', $filters_options])->andFilterWhere(['tax_group_id' => $taxGroup->tax_group_id])->one();  
475 -  
476 - if ($option === NULL) {  
477 - // Create option  
478 - $option = new TaxOption();  
479 - $option->tax_group_id = $taxGroup->tax_group_id;  
480 - $option->value = $filter_options;  
481 - $option->save(); 627 + return fopen($filename, 'r');
  628 + }
  629 +
  630 + /**
  631 + * @param $filters array of filters like [['pol'='мужской'],['god' =
  632 + * '2013'],['volume'='25 л']*['size'='49 x 30 x
  633 + * 20см'],['composition'='600D полиэстер']]
  634 + * @param int $level 0 for products and 1 for product variant
  635 + * @param $catalog_names array catalogs id
  636 + *
  637 + * @return array
  638 + * @throws \Exception
  639 + */
  640 + private function saveFilters(array $filters, int $level, array $catalog_names):array
  641 + {
  642 + $options = [];
  643 + foreach($filters as $filter) {
  644 +
  645 + preg_match_all('/\[(.*):(.*)\]/', $filter, $filter);
  646 +
  647 + if(empty( $filter[ 1 ][ 0 ] )) {
  648 + continue;
  649 + }
  650 + $filter_name = trim($filter[ 1 ][ 0 ]);
  651 + $parsed_group_name = $this->parseName($filter_name);
  652 + $start_time = time();
  653 + /**
  654 + * @var TaxGroup $taxGroup
  655 + */
  656 + if(!empty($parsed_group_name['remote_id']) && ($taxGroup = TaxGroup::find()
  657 + ->joinWith('lang')
  658 + ->andFilterWhere([ 'remote_id' => $parsed_group_name[ 'remote_id' ] ])
  659 + ->one()) !== NULL) {
  660 + if(!empty( $taxGroup->lang )) {
  661 + $taxGroup->lang->name = $parsed_group_name[ 'name' ];
  662 + $taxGroup->lang->save();
  663 + } else {
  664 + throw new \Exception('Tax group with ID ' . $taxGroup->tax_group_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  665 + }
  666 + } else {
  667 + $taxGroup = new TaxGroup();
  668 + $taxGroup->generateLangs();
  669 + $tax_group_langs = $taxGroup->model_langs;
  670 + foreach($tax_group_langs as $tax_group_lang) {
  671 + $tax_group_lang->name = $parsed_group_name[ 'name' ];
  672 + }
  673 + $taxGroup->level = $level;
  674 + $taxGroup->categories = $catalog_names;
  675 + $taxGroup->is_filter = false;
  676 + $taxGroup->save();
  677 + }
  678 + print $this->debug($start_time, 'TaxGroup');
  679 + $filters_options = explode(',', $filter[ 2 ][ 0 ]);
  680 + foreach($filters_options as $filter_options) {
  681 + $parsed_option_name = $this->parseName($filter_options);
  682 + /**
  683 + * @var TaxOption $option
  684 + */
  685 + $start_time = time();
  686 + if(!empty($parsed_option_name['remote_id']) && ($option = TaxOption::find()
  687 + ->joinWith('lang')
  688 + ->andFilterWhere([ 'remote_id' => $parsed_option_name[ 'remote_id' ] ])
  689 + ->andFilterWhere([ 'tax_group_id' => $taxGroup->tax_group_id ])
  690 + ->one()) !== NULL) {
  691 + if(!empty( $option->lang )) {
  692 + $option->lang->value = $parsed_option_name[ 'name' ];
  693 + $option->lang->save();
  694 + } else {
  695 + throw new \Exception('Tax option with ID ' . $option->tax_option_id . ' and lang ' . Language::getCurrent()->language_id . ' doesn\'t exist');
  696 + }
  697 + } else {
  698 + // Create option
  699 + $option = new TaxOption();
  700 + $option->generateLangs();
  701 + $option_langs = $option->model_langs;
  702 + foreach($option_langs as $option_lang) {
  703 + $option_lang->value = $parsed_option_name[ 'name' ];
  704 + }
  705 + $option->tax_group_id = $taxGroup->tax_group_id;
  706 + $option->save();
  707 + }
  708 + $options[] = $option->tax_option_id;
  709 + print $this->debug($start_time, 'TaxOption');
482 } 710 }
483 - $options[] = $option->tax_option_id;  
484 -  
485 } 711 }
  712 + return $options;
486 } 713 }
487 -  
488 - return $options;  
489 - }  
490 -}  
491 \ No newline at end of file 714 \ No newline at end of file
  715 + }
492 \ No newline at end of file 716 \ No newline at end of file
common/modules/product/models/Product.php
@@ -344,46 +344,51 @@ @@ -344,46 +344,51 @@
344 ->where([ 'product_id' => $this->product_id ]) 344 ->where([ 'product_id' => $this->product_id ])
345 ->sum('quantity'); 345 ->sum('quantity');
346 } 346 }
347 - 347 +
348 public function afterSave($insert, $changedAttributes) 348 public function afterSave($insert, $changedAttributes)
349 { 349 {
350 parent::afterSave($insert, $changedAttributes); 350 parent::afterSave($insert, $changedAttributes);
351 -  
352 - $this->unlinkAll('categories', true);  
353 - $this->unlinkAll('options', true);  
354 -  
355 - $categories = Category::findAll($this->categories);  
356 - $options = TaxOption::findAll($this->options);  
357 -  
358 - foreach($options as $option) {  
359 - $this->link('options', $option); 351 +
  352 +
  353 + if(!empty($this->categories)){
  354 + $categories = Category::findAll($this->categories);
  355 + $this->unlinkAll('categories', true);
  356 + foreach($categories as $category){
  357 + $this->link('categories', $category);
  358 + }
360 } 359 }
361 - foreach($categories as $category) {  
362 - $this->link('categories', $category); 360 +
  361 + if(!empty($this->options)){
  362 + $options = TaxOption::findAll($this->options);
  363 + $this->unlinkAll('options',true);
  364 + foreach($options as $option){
  365 + $this->link('options', $option);
  366 + }
363 } 367 }
364 -  
365 - if(!empty( $this->_variants )) { 368 +
  369 +
  370 + if (!empty($this->_variants)) {
366 $todel = []; 371 $todel = [];
367 - foreach($this->variants ? : [] as $_variant) {  
368 - $todel[ $_variant->product_variant_id ] = $_variant->product_variant_id; 372 + foreach ($this->variants ?: [] as $_variant) {
  373 + $todel[$_variant->product_variant_id] = $_variant->product_variant_id;
369 } 374 }
370 - foreach($this->_variants as $_variant) {  
371 - if(!is_array($_variant)) { 375 + foreach ($this->_variants as $_variant) {
  376 + if (!is_array($_variant)) {
372 return; 377 return;
373 } 378 }
374 - if(!empty( $_variant[ 'product_variant_id' ] )) {  
375 - unset( $todel[ $_variant[ 'product_variant_id' ] ] );  
376 - $model = ProductVariant::findOne($_variant[ 'product_variant_id' ]); 379 + if (!empty($_variant['product_variant_id'])) {
  380 + unset($todel[$_variant['product_variant_id']]);
  381 + $model = ProductVariant::findOne($_variant['product_variant_id']);
377 } else { 382 } else {
378 $model = new ProductVariant(); 383 $model = new ProductVariant();
379 } 384 }
380 - $_variant[ 'product_id' ] = $this->product_id;  
381 - $model->load([ 'ProductVariant' => $_variant ]); 385 + $_variant['product_id'] = $this->product_id;
  386 + $model->load(['ProductVariant' => $_variant]);
382 $model->product_id = $this->product_id; 387 $model->product_id = $this->product_id;
383 $model->save(); 388 $model->save();
384 } 389 }
385 - if(!empty( $todel )) {  
386 - ProductVariant::deleteAll([ 'product_variant_id' => $todel ]); 390 + if (!empty($todel)) {
  391 + ProductVariant::deleteAll(['product_variant_id' => $todel]);
387 } 392 }
388 } 393 }
389 } 394 }
common/modules/product/models/ProductVariant.php
@@ -333,15 +333,29 @@ @@ -333,15 +333,29 @@
333 ->where([ 'tax_group_to_category.category_id' => $categories ]) 333 ->where([ 'tax_group_to_category.category_id' => $categories ])
334 ->where([ 'level' => $level ]); 334 ->where([ 'level' => $level ]);
335 } 335 }
336 - 336 +
337 public function afterSave($insert, $changedAttributes) 337 public function afterSave($insert, $changedAttributes)
338 { 338 {
339 - parent::afterSave($insert, $changedAttributes);  
340 - $this->unlinkAll('options', true);  
341 - $options = TaxOption::findAll($this->options);  
342 - foreach($options as $option) {  
343 - $this->link('options', $option); 339 +
  340 + if(!empty($this->_options)){
  341 + $options = TaxOption::findAll($this->_options);
  342 + $this->unlinkAll('options',true);
  343 + foreach($options as $option){
  344 + $this->link('options', $option);
  345 + }
344 } 346 }
  347 +
  348 +
  349 + if (!empty($this->stocks)) {
  350 + ProductStock::deleteAll(['product_variant_id' => $this->product_variant_id]);
  351 + $values = [];
  352 + foreach ($this->stocks as $id => $quantity) {
  353 + $productStock = ProductStock::find()->where(['product_variant_id' => $this->product_variant_id, 'stock_id' => $id])->one();
  354 + $productStock->quantity = $quantity;
  355 + $productStock->save();
  356 + }
  357 + }
  358 + parent::afterSave($insert, $changedAttributes);
345 } 359 }
346 360
347 public function imagesUpload() 361 public function imagesUpload()
common/modules/product/views/manage/import-process.php
1 <?php 1 <?php
2 -  
3 -use yii\helpers\Html;  
4 -use yii\widgets\ActiveForm;  
5 -  
6 $this->registerJs(" 2 $this->registerJs("
7 -  
8 -");  
9 -?>  
10 -  
11 -<script type="text/javascript">  
12 - jQuery(document).ready(function () {  
13 - var in_process=false; 3 +var in_process=false;
14 var count=1; 4 var count=1;
15 5
16 in_process=true; 6 in_process=true;
@@ -21,7 +11,7 @@ $this-&gt;registerJs(&quot; @@ -21,7 +11,7 @@ $this-&gt;registerJs(&quot;
21 from = typeof(from) != 'undefined' ? from : 0; 11 from = typeof(from) != 'undefined' ? from : 0;
22 console.log('go', from); 12 console.log('go', from);
23 $.ajax({ 13 $.ajax({
24 - url: "<?= Yii::$app->request->baseUrl .'/product/manage/'. $method?>", 14 + url: '".\Yii::$app->request->baseUrl .'/product/manage/'. $method."',
25 data: {from:from}, 15 data: {from:from},
26 dataType: 'json', 16 dataType: 'json',
27 success: function(data){ 17 success: function(data){
@@ -46,13 +36,11 @@ $this-&gt;registerJs(&quot; @@ -46,13 +36,11 @@ $this-&gt;registerJs(&quot;
46 } 36 }
47 }, 37 },
48 error: function(xhr, status, errorThrown) { 38 error: function(xhr, status, errorThrown) {
49 - alert(errorThrown+'\n'+xhr.responseText);  
50 } 39 }
51 }); 40 });
52 } 41 }
53 -  
54 - });  
55 -</script> 42 +");
  43 +//?>
56 44
57 <div class="product-import-process-form"> 45 <div class="product-import-process-form">
58 <h1>Импорт <?= $method == 'prices' ? 'цен' : 'данных'?> товаров</h1> 46 <h1>Импорт <?= $method == 'prices' ? 'цен' : 'данных'?> товаров</h1>
common/modules/product/views/manage/import.php
1 <?php 1 <?php
  2 +
  3 + /**
  4 + * @var Import $model
  5 + * @var array $languages
  6 + */
  7 +
  8 + use common\modules\product\models\Import;
  9 + use yii\helpers\Html;
  10 + use yii\widgets\ActiveForm;
2 11
3 -use yii\helpers\Html;  
4 -use yii\widgets\ActiveForm;  
5 ?> 12 ?>
6 13
7 <div class="product-import-form"> 14 <div class="product-import-form">
8 <?php $form = ActiveForm::begin([ 15 <?php $form = ActiveForm::begin([
9 'enableClientValidation' => false, 16 'enableClientValidation' => false,
10 - 'options' => ['enctype' => 'multipart/form-data'] 17 + 'options' => [ 'enctype' => 'multipart/form-data' ],
11 ]); ?> 18 ]); ?>
12 -  
13 - <?php if($model->errors) :?>  
14 - <div class="error">  
15 - <?= implode("<br>\n", $model->errors);?>  
16 - </div>  
17 - <?php endif?>  
18 -  
19 - <?php if($model->output) :?> 19 +
  20 + <?php if($model->errors) : ?>
  21 + <div class="error">
  22 + <?= implode("<br>\n", $model->errors); ?>
  23 + </div>
  24 + <?php endif ?>
  25 +
  26 + <?php if($model->output) : ?>
20 <h2>Лог операции</h2> 27 <h2>Лог операции</h2>
21 - <div class="success" style="height: 10em;overflow: auto;border: 1px solid #000">  
22 - <?= implode("<br>\n", $model->output);?>  
23 - </div>  
24 - <?php endif?>  
25 -  
26 - <?= $form->field($model, 'type')->radioList([  
27 - 'products' => Yii::t('product', 'Load products'),  
28 - 'prices' => Yii::t('product', 'Load prices'),  
29 - ]);?>  
30 -  
31 - <?= $form->field($model, 'file')->fileInput(['multiple' => false,])?>  
32 - 28 + <div class="success" style="height: 10em;overflow: auto;border: 1px solid #000">
  29 + <?= implode("<br>\n", $model->output); ?>
  30 + </div>
  31 + <?php endif ?>
  32 +
  33 + <?= $form->field($model, 'type')
  34 + ->radioList([
  35 + 'products' => Yii::t('product', 'Load products'),
  36 + 'prices' => Yii::t('product', 'Load prices'),
  37 + ]); ?>
  38 +
  39 + <?= $form->field($model, 'lang')
  40 + ->dropDownList($languages); ?>
  41 +
  42 + <?= $form->field($model, 'file')
  43 + ->fileInput([ 'multiple' => false, ]) ?>
  44 +
33 <?php /*= $form->field($model, 'file')->widget(\kartik\file\FileInput::classname(), [ 45 <?php /*= $form->field($model, 'file')->widget(\kartik\file\FileInput::classname(), [
34 'language' => 'ru', 46 'language' => 'ru',
35 'options' => [ 47 'options' => [
@@ -41,11 +53,11 @@ use yii\widgets\ActiveForm; @@ -41,11 +53,11 @@ use yii\widgets\ActiveForm;
41 'showRemove' => false, 53 'showRemove' => false,
42 'showUpload' => false, 54 'showUpload' => false,
43 ], 55 ],
44 - ])*/?>  
45 - 56 + ])*/ ?>
  57 +
46 <div class="form-group"> 58 <div class="form-group">
47 - <?= Html::submitButton(Yii::t('product', 'Import'), ['class' => 'btn btn-primary']) ?> 59 + <?= Html::submitButton(Yii::t('product', 'Import'), [ 'class' => 'btn btn-primary' ]) ?>
48 </div> 60 </div>
49 - 61 +
50 <?php ActiveForm::end(); ?> 62 <?php ActiveForm::end(); ?>
51 </div> 63 </div>
common/modules/rubrication/models/TaxOption.php
@@ -63,10 +63,10 @@ @@ -63,10 +63,10 @@
63 ], 63 ],
64 ], 64 ],
65 ], 65 ],
66 - 'artboxtree' => [  
67 - 'class' => ArtboxTreeBehavior::className(),  
68 - 'keyNameGroup' => 'tax_group_id',  
69 - ], 66 +// 'artboxtree' => [
  67 +// 'class' => ArtboxTreeBehavior::className(),
  68 +// 'keyNameGroup' => 'tax_group_id',
  69 +// ],
70 'language' => [ 70 'language' => [
71 'class' => LanguageBehavior::className(), 71 'class' => LanguageBehavior::className(),
72 ], 72 ],
console/controllers/ImportController.php
@@ -20,15 +20,15 @@ class ImportController extends Controller { @@ -20,15 +20,15 @@ class ImportController extends Controller {
20 } 20 }
21 21
22 public function actionProducts() { 22 public function actionProducts() {
23 - if (file_exists(Yii::getAlias('@uploadDir/goProducts.lock'))) {  
24 - $this->errors[] = 'Task already executed';  
25 - return Controller::EXIT_CODE_ERROR;  
26 - }  
27 - $ff = fopen(Yii::getAlias('@uploadDir/goProducts.lock'), 'w+');  
28 - fclose($ff); 23 +// if (file_exists(Yii::getAlias('@uploadDir/goProducts.lock'))) {
  24 +// $this->errors[] = 'Task already executed';
  25 +// return Controller::EXIT_CODE_ERROR;
  26 +// }
  27 +// $ff = fopen(Yii::getAlias('@uploadDir/goProducts.lock'), 'w+');
  28 +// fclose($ff);
29 $model = new Import(); 29 $model = new Import();
30 $model->goProducts(0, null); 30 $model->goProducts(0, null);
31 - unlink(Yii::getAlias('@uploadDir/goProducts.lock')); 31 +// unlink(Yii::getAlias('@uploadDir/goProducts.lock'));
32 return Controller::EXIT_CODE_NORMAL; 32 return Controller::EXIT_CODE_NORMAL;
33 } 33 }
34 34
console/migrations/m161011_104931_create_stock_lang_table.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +/**
  6 + * Handles the creation for table `stock_lang`.
  7 + */
  8 +class m161011_104931_create_stock_lang_table extends Migration
  9 +{
  10 + /**
  11 + * @inheritdoc
  12 + */
  13 + public function up()
  14 + {
  15 + $this->createTable('stock_lang', [
  16 + 'stock_id' => $this->integer()
  17 + ->notNull(),
  18 + 'language_id' => $this->integer()
  19 + ->notNull(),
  20 + 'name' => $this->string()
  21 + ->notNull(),
  22 + ]);
  23 + $this->createIndex('stock_lang_stock_language_key', 'stock_lang', [
  24 + 'stock_id',
  25 + 'language_id',
  26 + ], true);
  27 +
  28 + $this->addForeignKey('stock_fk', 'stock_lang', 'stock_id', 'stock', 'stock_id', 'CASCADE', 'CASCADE');
  29 + $this->addForeignKey('language_fk', 'stock_lang', 'language_id', 'language', 'language_id', 'RESTRICT', 'CASCADE');
  30 + }
  31 +
  32 + /**
  33 + * @inheritdoc
  34 + */
  35 + public function down()
  36 + {
  37 + $this->dropTable('stock_lang');
  38 + }
  39 +}