]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Создание справочника feature_fomichev_erp-285_city_department_list origin/feature_fomichev_erp-285_city_department_list
authorfomichev <vladimir.fomichev@erp-flowers.ru>
Thu, 16 Jan 2025 20:20:56 +0000 (23:20 +0300)
committerfomichev <vladimir.fomichev@erp-flowers.ru>
Thu, 16 Jan 2025 20:20:56 +0000 (23:20 +0300)
erp24/controllers/StoreCityListController.php [new file with mode: 0644]
erp24/migrations/m250116_112743_create_store_city_list_table.php
erp24/records/StoreCityList.php [new file with mode: 0644]
erp24/records/StoreCityListSearch.php [new file with mode: 0644]
erp24/views/store-city-list/_form.php [new file with mode: 0644]
erp24/views/store-city-list/_search.php [new file with mode: 0644]
erp24/views/store-city-list/create.php [new file with mode: 0644]
erp24/views/store-city-list/index.php [new file with mode: 0644]
erp24/views/store-city-list/update.php [new file with mode: 0644]
erp24/views/store-city-list/view.php [new file with mode: 0644]
erp24/web/js/store_city_list/_form.js [new file with mode: 0644]

diff --git a/erp24/controllers/StoreCityListController.php b/erp24/controllers/StoreCityListController.php
new file mode 100644 (file)
index 0000000..eb9860b
--- /dev/null
@@ -0,0 +1,229 @@
+<?php
+
+namespace app\controllers;
+
+use Yii;
+use yii\web\UploadedFile;
+use yii_app\records\StoreCityList;
+use yii_app\records\StoreCityListSearch;
+use yii\web\Controller;
+use yii\web\NotFoundHttpException;
+use yii\filters\VerbFilter;
+use yii_app\records\StoreRegionList;
+
+/**
+ * StoreCityListController implements the CRUD actions for StoreCityList model.
+ */
+class StoreCityListController extends Controller
+{
+    /**
+     * @inheritDoc
+     */
+    public function behaviors()
+    {
+        return array_merge(
+            parent::behaviors(),
+            [
+                'verbs' => [
+                    'class' => VerbFilter::className(),
+                    'actions' => [
+                        'delete' => ['POST'],
+                    ],
+                ],
+            ]
+        );
+    }
+
+    /**
+     * Lists all StoreCityList models.
+     *
+     * @return string
+     */
+    public function actionIndex()
+    {
+        $searchModel = new StoreCityListSearch();
+        $dataProvider = $searchModel->search($this->request->queryParams);
+
+        return $this->render('index', [
+            'searchModel' => $searchModel,
+            'dataProvider' => $dataProvider,
+        ]);
+    }
+
+    public function actionImport()
+    {
+        if (Yii::$app->request->isPost) {
+            $file = UploadedFile::getInstanceByName('importFile');
+
+            if ($file) {
+                $filePath = Yii::getAlias('@runtime/') . $file->name;
+
+                if ($file->saveAs($filePath)) {
+                    try {
+                        $this->processImportFile($filePath);
+                        Yii::$app->session->setFlash('success', 'Данные успешно загружены.');
+                    } catch (\Exception $e) {
+                        Yii::$app->session->setFlash('error', 'Ошибка при обработке файла: ' . $e->getMessage());
+                    }
+                } else {
+                    Yii::$app->session->setFlash('error', 'Не удалось загрузить файл.');
+                }
+            } else {
+                Yii::$app->session->setFlash('error', 'Файл не выбран.');
+            }
+        }
+
+        return $this->redirect(['index']);
+    }
+
+
+    protected function processImportFile($filePath)
+    {
+        $data = [];
+
+        if (pathinfo($filePath, PATHINFO_EXTENSION) === 'csv') {
+
+            if (($handle = fopen($filePath, 'r')) !== false) {
+                $header = fgetcsv($handle);
+                while (($row = fgetcsv($handle)) !== false) {
+                    $data[] = array_combine($header, $row);
+                }
+                fclose($handle);
+            }
+        } else {
+            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath);
+            $sheet = $spreadsheet->getActiveSheet();
+            $data = $sheet->toArray(null, true, true, true);
+        }
+
+        foreach ($data as $row) {
+            $model = new StoreCityList();
+            $model->name = $row['name'] ?? $row['A'];
+            $model->parent_id = $row['parent_id'] ?? $row['B'];
+            $model->type = $row['type'] ?? $row['C'];
+
+            if (!$model->save()) {
+                Yii::error("Ошибка при сохранении: " . json_encode($model->errors));
+            }
+        }
+    }
+
+    public function actionParentOptions($q = null, $type = null)
+    {
+        $query = StoreCityList::find()
+            ->select(['id', 'name'])
+            ->andFilterWhere(['like', 'name', $q]);
+
+        if ($type === 'region') {
+            $query->andWhere(['type' => 'region']);
+        } elseif ($type === 'city') {
+            $query->andWhere(['type' => 'city']);
+        }
+
+        $result = $query->asArray()->all();
+
+        return $this->asJson([
+            'results' => array_map(function ($item) {
+                return ['id' => $item['id'], 'text' => $item['name']];
+            }, $result),
+        ]);
+    }
+
+    /**
+     * Displays a single StoreCityList model.
+     * @param int $id Первичный ключ
+     * @return string
+     * @throws NotFoundHttpException if the model cannot be found
+     */
+    public function actionView($id)
+    {
+        return $this->render('view', [
+            'model' => $this->findModel($id),
+        ]);
+    }
+
+    /**
+     * Creates a new StoreCityList model.
+     * If creation is successful, the browser will be redirected to the 'view' page.
+     * @return string|\yii\web\Response
+     */
+    public function actionCreate()
+    {
+        $model = new StoreCityList();
+
+        if ($this->request->isPost) {
+            if ($model->load($this->request->post()) && $model->save()) {
+                return $this->redirect(['view', 'id' => $model->id]);
+            }
+        } else {
+            $model->loadDefaultValues();
+        }
+
+        return $this->render('create', [
+            'model' => $model,
+        ]);
+    }
+
+    /**
+     * Updates an existing StoreCityList model.
+     * If update is successful, the browser will be redirected to the 'view' page.
+     * @param int $id Первичный ключ
+     * @return string|\yii\web\Response
+     * @throws NotFoundHttpException if the model cannot be found
+     */
+    public function actionUpdate($id)
+    {
+        $model = $this->findModel($id);
+
+        $parentData = [];
+        if ($model->parent_id) {
+            $parent = StoreCityList::find()
+                ->select(['id', 'name'])
+                ->where(['id' => $model->parent_id])
+                ->asArray()
+                ->one();
+            if ($parent) {
+                $parentData = [$parent['id'] => $parent['name']];
+            }
+        }
+
+        if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
+            return $this->redirect(['view', 'id' => $model->id]);
+        }
+
+        return $this->render('update', [
+            'model' => $model,
+            'parentData' => $parentData,
+        ]);
+    }
+
+    /**
+     * Deletes an existing StoreCityList model.
+     * If deletion is successful, the browser will be redirected to the 'index' page.
+     * @param int $id Первичный ключ
+     * @return \yii\web\Response
+     * @throws NotFoundHttpException if the model cannot be found
+     */
+    public function actionDelete($id)
+    {
+        $this->findModel($id)->delete();
+
+        return $this->redirect(['index']);
+    }
+
+    /**
+     * Finds the StoreCityList model based on its primary key value.
+     * If the model is not found, a 404 HTTP exception will be thrown.
+     * @param int $id Первичный ключ
+     * @return StoreCityList the loaded model
+     * @throws NotFoundHttpException if the model cannot be found
+     */
+    protected function findModel($id)
+    {
+        if (($model = StoreCityList::findOne(['id' => $id])) !== null) {
+            return $model;
+        }
+
+        throw new NotFoundHttpException('The requested page does not exist.');
+    }
+}
index bb29d302c47c0ccbc7040e7f547105628f820f54..e57dc5dc39a2d244a4d3be29b50f1ba77f73ae23 100644 (file)
@@ -8,9 +8,7 @@ use yii\db\Migration;
 class m250116_112743_create_store_city_list_table extends Migration
 {
     const TABLE_NAME = 'erp24.store_city_list';
-    /**
-     * {@inheritdoc}
-     */
+
     public function safeUp()
     {
         $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
@@ -27,6 +25,14 @@ class m250116_112743_create_store_city_list_table extends Migration
                     ->comment('Дата создания записи'),
             ]);
 
+            // Создаём индекс для внешнего ключа
+            $this->createIndex(
+                'idx-store_city_list-parent_id',
+                self::TABLE_NAME,
+                'parent_id'
+            );
+
+            // Добавляем внешний ключ
             $this->addForeignKey(
                 'fk-store_city_list-parent_id',
                 self::TABLE_NAME,
@@ -39,14 +45,13 @@ class m250116_112743_create_store_city_list_table extends Migration
         }
     }
 
-    /**
-     * {@inheritdoc}
-     */
     public function safeDown()
     {
         $tableSchema = $this->db->getTableSchema(self::TABLE_NAME);
         if (isset($tableSchema)) {
             $this->dropForeignKey('fk-store_city_list-parent_id', self::TABLE_NAME);
+            $this->dropIndex('idx-store_city_list-parent_id', self::TABLE_NAME);
+
             $this->dropTable(self::TABLE_NAME);
         }
     }
diff --git a/erp24/records/StoreCityList.php b/erp24/records/StoreCityList.php
new file mode 100644 (file)
index 0000000..9c8c0bf
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+
+namespace yii_app\records;
+
+use Yii;
+
+/**
+ * This is the model class for table "store_city_list".
+ *
+ * @property int $id Первичный ключ
+ * @property int|null $parent_id Идентификатор родителя
+ * @property string $name Название (регион, город, район)
+ * @property string $type Тип (region, city, district)
+ * @property string $created_at Дата создания записи
+ *
+ * @property StoreCityList $parent
+ * @property StoreCityList[] $storeCityLists
+ */
+class StoreCityList extends \yii\db\ActiveRecord
+{
+    const TYPE_REGION = 'region';
+    const TYPE_CITY = 'city';
+    const TYPE_DISTRICT = 'district';
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return 'store_city_list';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['parent_id'], 'default', 'value' => null],
+            [['parent_id'], 'integer'],
+            [['name', 'type'], 'required'],
+            [['created_at', 'parent_id'], 'safe'],
+            [['name', 'type'], 'string', 'max' => 255],
+            [['type'], 'in', 'range' => [self::TYPE_REGION, self::TYPE_CITY, self::TYPE_DISTRICT]],
+            [['parent_id'], 'exist', 'skipOnError' => true, 'targetClass' => StoreCityList::class, 'targetAttribute' => ['parent_id' => 'id']],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'id' => 'Первичный ключ',
+            'parent_id' => 'Идентификатор родителя',
+            'name' => 'Название (регион, город, район)',
+            'type' => 'Тип (region, city, district)',
+            'created_at' => 'Дата создания записи',
+        ];
+    }
+
+    /**
+     * Gets query for [[Parent]].
+     *
+     * @return \yii\db\ActiveQuery
+     */
+    public function getParent()
+    {
+        return $this->hasOne(StoreCityList::class, ['id' => 'parent_id']);
+    }
+
+    /**
+     * Gets query for [[StoreCityLists]].
+     *
+     * @return \yii\db\ActiveQuery
+     */
+    public function getStoreCityLists()
+    {
+        return $this->hasMany(StoreCityList::class, ['parent_id' => 'id']);
+    }
+
+    public static function getTypes()
+    {
+        return [
+            self::TYPE_REGION => 'Region',
+            self::TYPE_CITY => 'City',
+            self::TYPE_DISTRICT => 'District',
+        ];
+    }
+}
diff --git a/erp24/records/StoreCityListSearch.php b/erp24/records/StoreCityListSearch.php
new file mode 100644 (file)
index 0000000..03e3d1f
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+
+namespace yii_app\records;
+
+use yii\base\Model;
+use yii\data\ActiveDataProvider;
+use yii_app\records\StoreCityList;
+
+/**
+ * StoreCityListSearch represents the model behind the search form of `yii_app\records\StoreCityList`.
+ */
+class StoreCityListSearch extends StoreCityList
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['id', 'parent_id'], 'integer'],
+            [['name', 'type', 'created_at'], 'safe'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function scenarios()
+    {
+        // bypass scenarios() implementation in the parent class
+        return Model::scenarios();
+    }
+
+    /**
+     * Creates data provider instance with search query applied
+     *
+     * @param array $params
+     *
+     * @return ActiveDataProvider
+     */
+    public function search($params)
+    {
+        $query = StoreCityList::find();
+
+        // add conditions that should always apply here
+
+        $dataProvider = new ActiveDataProvider([
+            'query' => $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([
+            'id' => $this->id,
+            'parent_id' => $this->parent_id,
+            'created_at' => $this->created_at,
+        ]);
+
+        $query->andFilterWhere(['ilike', 'name', $this->name])
+            ->andFilterWhere(['ilike', 'type', $this->type]);
+
+        return $dataProvider;
+    }
+}
diff --git a/erp24/views/store-city-list/_form.php b/erp24/views/store-city-list/_form.php
new file mode 100644 (file)
index 0000000..d559a4e
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+use yii\helpers\Html;
+use yii\widgets\ActiveForm;
+use kartik\select2\Select2;
+use yii\web\JsExpression;
+
+/** @var yii\web\View $this */
+/** @var yii_app\records\StoreCityList $model */
+/** @var yii\widgets\ActiveForm $form */
+/** @var array|null $parentData */
+$this->registerJsFile('/js/store_city_list/_form.js', ['position' => \yii\web\View::POS_END]);
+?>
+
+<div class="store-city-list-form">
+
+    <?php $form = ActiveForm::begin(); ?>
+
+    <?= $form->field($model, 'type')->dropDownList([
+        'region' => 'Регион',
+        'city' => 'Город',
+        'district' => 'Район',
+    ], [
+        'prompt' => 'Выберите тип',
+        'id' => 'type-selector',
+    ]) ?>
+
+    <div id="parent-id-field" style="display: none;">
+        <?= $form->field($model, 'parent_id')->widget(Select2::class, [
+            'options' => ['placeholder' => 'Выберите родительский элемент'],
+            'pluginOptions' => [
+                'allowClear' => true,
+                'ajax' => [
+                    'url' => \yii\helpers\Url::to(['store-city-list/parent-options']),
+                    'dataType' => 'json',
+                    'data' => new JsExpression('function(params) {
+                    return {
+                        q: params.term,
+                        type: $("#type-selector").val() === "city" ? "region" : "city"
+                    };
+                }'),
+                ],
+            ],
+            'data' => $parentData,
+        ]) ?>
+    </div>
+
+    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
+
+    <div class="form-group">
+        <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
+    </div>
+
+    <?php ActiveForm::end(); ?>
+
+</div>
diff --git a/erp24/views/store-city-list/_search.php b/erp24/views/store-city-list/_search.php
new file mode 100644 (file)
index 0000000..7de0dfa
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+use yii\helpers\Html;
+use yii\widgets\ActiveForm;
+
+/** @var yii\web\View $this */
+/** @var yii_app\records\StoreCityListSearch $model */
+/** @var yii\widgets\ActiveForm $form */
+?>
+
+<div class="store-city-list-search">
+
+    <?php $form = ActiveForm::begin([
+        'action' => ['index'],
+        'method' => 'get',
+    ]); ?>
+
+    <?= $form->field($model, 'id') ?>
+
+    <?= $form->field($model, 'parent_id') ?>
+
+    <?= $form->field($model, 'name') ?>
+
+    <?= $form->field($model, 'type') ?>
+
+    <?= $form->field($model, 'created_at') ?>
+
+    <div class="form-group">
+        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
+        <?= Html::resetButton('Reset', ['class' => 'btn btn-outline-secondary']) ?>
+    </div>
+
+    <?php ActiveForm::end(); ?>
+
+</div>
diff --git a/erp24/views/store-city-list/create.php b/erp24/views/store-city-list/create.php
new file mode 100644 (file)
index 0000000..323f6d8
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+use yii\helpers\Html;
+
+/** @var yii\web\View $this */
+/** @var yii_app\records\StoreCityList $model */
+
+$this->title = 'Создание элемента адреса (регион, город, район)';
+$this->params['breadcrumbs'][] = ['label' => 'Store City Lists', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+?>
+<div class="store-city-list-create p-4">
+    <?= Html::a('Назад', ['index'], ['class' => 'btn btn-primary my-4']) ?>
+    <h1><?= Html::encode($this->title) ?></h1>
+
+    <?= $this->render('_form', [
+        'model' => $model,
+        'parentData' => null,
+    ]) ?>
+
+</div>
diff --git a/erp24/views/store-city-list/index.php b/erp24/views/store-city-list/index.php
new file mode 100644 (file)
index 0000000..6f9e529
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+
+use yii_app\records\StoreCityList;
+use yii\helpers\Html;
+use yii\helpers\Url;
+use yii\grid\ActionColumn;
+use yii\grid\GridView;
+
+/** @var yii\web\View $this */
+/** @var yii_app\records\StoreCityListSearch $searchModel */
+/** @var yii\data\ActiveDataProvider $dataProvider */
+
+$this->title = 'Справочник адресов (регион, город, район)';
+$this->params['breadcrumbs'][] = $this->title;
+?>
+<div class="store-city-list-index p-4">
+
+    <div class="row my-4">
+        <h1 class="upload-form col-8"><?= Html::encode($this->title) ?></h1>
+
+        <div class="upload-form col-4">
+            <p>
+                Загрузка из excel регионов в справочник
+            </p>
+            <?= Html::beginForm(['store-city-list/import'], 'post', ['enctype' => 'multipart/form-data', 'class' => 'row row-cols-lg-auto g-3 align-items-center']) ?>
+
+            <div class="form-group">
+                <?= Html::fileInput('importFile', null, ['class' => 'form-control']) ?>
+            </div>
+
+            <div class="form-group">
+                <?= Html::submitButton('Загрузить файл', ['class' => 'btn btn-primary']) ?>
+            </div>
+
+            <?= Html::endForm() ?>
+        </div>
+
+    </div>
+
+    <p>
+        <?= Html::a('Создать элемента адреса', ['create'], ['class' => 'btn btn-success']) ?>
+    </p>
+
+
+
+    <?php // echo $this->render('_search', ['model' => $searchModel]); ?>
+
+    <?= GridView::widget([
+        'dataProvider' => $dataProvider,
+        'filterModel' => $searchModel,
+        'columns' => [
+            ['class' => 'yii\grid\SerialColumn'],
+
+            'id',
+            [
+                'attribute' => 'parent_id',
+                'value' => function ($model) {
+                    return $model->parent ? $model->parent->name : '';
+                },
+                'label' => 'Родитель',
+            ],
+            'name',
+            'type',
+            'created_at',
+            [
+                'class' => ActionColumn::class,
+                'urlCreator' => function ($action, StoreCityList $model, $key, $index, $column) {
+                    return Url::toRoute([$action, 'id' => $model->id]);
+                }
+            ],
+        ],
+    ]); ?>
+
+
+</div>
diff --git a/erp24/views/store-city-list/update.php b/erp24/views/store-city-list/update.php
new file mode 100644 (file)
index 0000000..dfd1b0f
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+
+use yii\helpers\Html;
+
+/** @var yii\web\View $this */
+/** @var array $parentData */
+/** @var yii_app\records\StoreCityList $model */
+
+$this->title = 'Редактирование элемента адреса (регион, город, район):  ' . $model->name;
+$this->params['breadcrumbs'][] = ['label' => 'Store City Lists', 'url' => ['index']];
+$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
+$this->params['breadcrumbs'][] = 'Update';
+?>
+<div class="store-city-list-update p-4">
+    <?= Html::a('Назад', ['index'], ['class' => 'btn btn-primary my-4']) ?>
+    <h1><?= Html::encode($this->title) ?></h1>
+
+    <?= $this->render('_form', [
+        'model' => $model,
+        'parentData' => $parentData,
+    ]) ?>
+
+</div>
diff --git a/erp24/views/store-city-list/view.php b/erp24/views/store-city-list/view.php
new file mode 100644 (file)
index 0000000..d1bf064
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+use yii\helpers\Html;
+use yii\widgets\DetailView;
+
+/** @var yii\web\View $this */
+/** @var yii_app\records\StoreCityList $model */
+
+$this->title = $model->name;
+$this->params['breadcrumbs'][] = ['label' => 'Store City Lists', 'url' => ['index']];
+$this->params['breadcrumbs'][] = $this->title;
+\yii\web\YiiAsset::register($this);
+?>
+<div class="store-city-list-view p-4">
+    <?= Html::a('Назад', ['index'], ['class' => 'btn btn-primary my-4']) ?>
+    <h1><?= Html::encode($this->title) ?></h1>
+
+    <p>
+        <?= Html::a('Редактирование', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
+        <?= Html::a('Удаление', ['delete', 'id' => $model->id], [
+            'class' => 'btn btn-danger',
+            'data' => [
+                'confirm' => 'Вы уверены, что хотите удалить элемент?',
+                'method' => 'post',
+            ],
+        ]) ?>
+    </p>
+
+    <?= DetailView::widget([
+        'model' => $model,
+        'attributes' => [
+            'id',
+            'parent_id',
+            'name',
+            'type',
+            'created_at',
+        ],
+    ]) ?>
+
+</div>
diff --git a/erp24/web/js/store_city_list/_form.js b/erp24/web/js/store_city_list/_form.js
new file mode 100644 (file)
index 0000000..f123f01
--- /dev/null
@@ -0,0 +1,16 @@
+document.addEventListener('DOMContentLoaded', function() {
+    const typeSelector = document.getElementById('type-selector');
+    const parentIdField = document.getElementById('parent-id-field');
+
+    function toggleParentField() {
+        const selectedType = typeSelector.value;
+        if (selectedType === 'region') {
+            parentIdField.style.display = 'none';
+        } else {
+            parentIdField.style.display = 'block';
+        }
+    }
+
+    typeSelector.addEventListener('change', toggleParentField);
+    toggleParentField();
+});
\ No newline at end of file