diff --git a/backend/controllers/CrossingUploadController.php b/backend/controllers/CrossingUploadController.php new file mode 100644 index 0000000..cb323c6 --- /dev/null +++ b/backend/controllers/CrossingUploadController.php @@ -0,0 +1,115 @@ + [ + 'class' => AccessControl::className(), + 'rules' => [ + [ + 'actions' => ['index', 'result'], + 'allow' => true, + 'roles' => ['@'], + ], + ], + ], +// 'verbs' => [ +// 'class' => VerbFilter::className(), +// 'actions' => [ +// 'logout' => ['post'], +// ], +// ], + ]; + } + + /** + * @inheritdoc + */ + public function actions() + { + return [ + 'error' => [ + 'class' => 'yii\web\ErrorAction', + ], + ]; + } + + + public function actionIndex() + { + $model = new UploadFileCrossingForm(); + return $this->render('index', ['model' => $model]); + } + + public function actionResult() + { + $model = new UploadFileCrossingForm(); + $data = []; + if ($model->load(Yii::$app->request->post())) { + $model->file = UploadedFile::getInstance($model, 'file'); + + if ($model->validate()) { + $file_name = $model->file->name; + $model->file_path = Yii::getAlias('@temp_upload') . '/' . $file_name; + + $model->file->saveAs($model->file_path); + //запускаем парсинг + // доп. опции для парсера - удаление префикса в артикулах + $options['mode'] = 'crosses'; + $fields = []; + if ($model->delete_prefix1) { + $fields[] = 'ARTICLE'; + } + if ($model->delete_prefix2) { + $fields[] = 'CROSS_ARTICLE'; + } + if ( $fields ) { + $options [ 'converter_conf' ] = [ 'configuration' => [ "article" => $fields , + "string" => ['ARTICLE', 'CROSS_ARTICLE'],] ]; + } else { + $options [ 'converter_conf' ] = [ 'configuration' => [ "string" => ['ARTICLE', 'CROSS_ARTICLE'], ] ]; + } + + $data = $model->readFile( $options ); + $crosses_model = new DetailsCrosses(); + $crosses_model->ManualInsertWithIgnore( $data ); + + Yii::$app->session->setFlash('success', 'Файл кроссов успешно загружен'); + return $this->render('index', ['model' => $model]); + }else{ + // не прошла валидация форма загрузки файлов + $errors_str = ''; + foreach ($model->getErrors() as $error) { + $errors_str .= implode( array_values($error) ); + } + throw new \ErrorException( $errors_str ); + } + + } else { + throw new \ErrorException( 'Ошибка загрузки данных' ); + } + } +} \ No newline at end of file diff --git a/backend/controllers/ParserController.php b/backend/controllers/ParserController.php index 09ef226..c035606 100644 --- a/backend/controllers/ParserController.php +++ b/backend/controllers/ParserController.php @@ -10,7 +10,6 @@ use backend\models\UploadFileParsingForm; use yii\web\UploadedFile; use yii\data\ArrayDataProvider; use yii\multiparser\DynamicFormHelper; -use backend\components\parsers\CustomParserConfigurator; use backend\models\ImportersFiles; use backend\models\Importers; use yii\base\ErrorException; diff --git a/backend/models/DetailsCrosses.php b/backend/models/DetailsCrosses.php index ed4747c..b10ff57 100644 --- a/backend/models/DetailsCrosses.php +++ b/backend/models/DetailsCrosses.php @@ -2,6 +2,7 @@ namespace backend\models; +use common\components\CustomVarDamp; use Yii; /** @@ -17,6 +18,10 @@ use Yii; class DetailsCrosses extends \backend\components\base\BaseActiveRecord { /** + * int - размер пакета запроса + */ + const BATCH = 1000; + /** * @inheritdoc */ public static function tableName() @@ -50,4 +55,31 @@ class DetailsCrosses extends \backend\components\base\BaseActiveRecord 'timestamp' => Yii::t('app', 'Timestamp'), ]; } + + /** + * вставка данных с игнором дублей прямым запросом SQL + * @param $data - массив вставляемых данный, вставка будет прозводится пакетами размером указанным в константе BATCH + * @throws \yii\db\Exception + */ + //@todo - вынести все ручные инсерты в отдельный класс + public function ManualInsertWithIgnore( $data ) + { + // \common\components\CustomVarDamp::dumpAndDie($data); + $table_name = self::tableName(); + $keys_arr = array_keys($data[0]); + + // запросы будем выполнять пакетами + // размер пакета установлен в константе + // разобъем массив на пакеты и будем их проходить + $data = array_chunk($data, $this::BATCH); + foreach ($data as $current_batch_array) { + + //воспользуемся пакетной вставкой от фреймворка + $query = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql; + // добавим ключевое слово - ignore + $query = preg_replace('/INSERT/','INSERT IGNORE', $query); + Yii::$app->db->createCommand($query)->execute(); + + } + } } diff --git a/backend/models/UploadFileCrossingForm.php b/backend/models/UploadFileCrossingForm.php new file mode 100644 index 0000000..6c4239c --- /dev/null +++ b/backend/models/UploadFileCrossingForm.php @@ -0,0 +1,69 @@ + 'Не выбран файл!' ], + [['file'], 'file', 'extensions' => 'csv', 'checkExtensionByMimeType'=>false ], + [['delete_prefix1', 'delete_prefix2'], 'boolean' ], + + ]; + } + + public function attributeLabels() + { + return [ + 'file' => Yii::t('app', 'Источник'), + 'delete_prefix1' => Yii::t('app', 'Удалять префикс в артикуле товара 1'), + 'delete_prefix2' => Yii::t('app', 'Удалять префикс в артикуле товара 2'), + ]; + } + + public function readFile( $options = [] ){ + + $data = Yii::$app->multiparser->parse( $this->file_path, $options ); + if( !is_array( $data ) ){ + throw new ErrorException("Ошибка чтения из файла кроссов {$this->file_path}"); + } + // файл больше не нужен - данные прочитаны и сохранены в кеш + if( file_exists($this->file_path) ) + unlink($this->file_path); + + return $data; + } + + public function fields() + { + return [ + + 'delete_price1', + 'delete_price2' + + ]; + } + + +} \ No newline at end of file diff --git a/backend/models/UploadFileParsingForm.php b/backend/models/UploadFileParsingForm.php index 3dd3d62..c66ab5e 100644 --- a/backend/models/UploadFileParsingForm.php +++ b/backend/models/UploadFileParsingForm.php @@ -48,9 +48,7 @@ class UploadFileParsingForm extends Model return [ ['importer_id', 'required', 'message' => 'Не указан поставщик!' ], ['file', 'required', 'message' => 'Не выбран файл!' ], - //@todo - not working this file validator!!! - fixed - [['file'], 'file'],// 'extensions' => ['csv', 'xml'] ], - // 'wrongMimeType' => 'Указан неподдерживаемый тип файла. Можно выбирать csv, xml файлы.' ], + [['file'], 'file', 'extensions' => ['csv', 'xml'], 'checkExtensionByMimeType'=>false ], ['importer_id', 'integer','max' => 999999, 'min' => 0 ], [['action','delete_prefix', 'delete_price', 'success'], 'boolean', 'except' => 'auto' ], // только для ручной загрузки ['delimiter', 'string', 'max' => 1], diff --git a/backend/views/crossing-upload/index.php b/backend/views/crossing-upload/index.php new file mode 100644 index 0000000..7b8cf4d --- /dev/null +++ b/backend/views/crossing-upload/index.php @@ -0,0 +1,28 @@ + +