]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
ERP-360 Сборка страницы автопм
authormarina <m.zozirova@gmail.com>
Thu, 5 Jun 2025 21:30:59 +0000 (00:30 +0300)
committermarina <m.zozirova@gmail.com>
Thu, 5 Jun 2025 21:30:59 +0000 (00:30 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/migrations/m250605_201027_create_autoplannagramma_table.php [new file with mode: 0644]
erp24/views/auto-plannogramma/calculating.php [deleted file]
erp24/views/auto-plannogramma/control.php [deleted file]
erp24/views/auto-plannogramma/index.php
erp24/web/js/autoplannogramma/autoplannogramma.js [new file with mode: 0644]

index 38f87910b65646a138f825133bbea0965625c4a3..eab7c55b863fb1bd7880ac9d4f1cd467430adc15 100644 (file)
@@ -8,6 +8,7 @@ use yii\db\Expression;
 use yii\db\Query;
 use yii\helpers\ArrayHelper;
 use yii_app\records\CityStore;
+use yii_app\records\CityStoreParams;
 use yii_app\services\AutoPlannogrammaService;
 
 class AutoPlannogrammaController extends BaseController
@@ -34,21 +35,21 @@ class AutoPlannogrammaController extends BaseController
                 new Expression("
                     CASE 
                         WHEN category ILIKE 'срезка' THEN 'Срезка'
-                        WHEN category ILIKE 'горшечные растения' THEN 'Горшечные растения'
+                        WHEN category ILIKE 'горшечные_растения' THEN 'Горшечные растения'
                         WHEN category ILIKE 'сухоцветы' THEN 'Сухоцветы'
                         ELSE 'Остальные категории' 
                     END AS category
                 "),
                 'subcategory',
-                new Expression('json_agg(name) AS products'),
             ])
+            ->andWhere(['is not', 'subcategory', null])
             ->from('products_1c_nomenclature')
             ->groupBy(['category', 'subcategory'])
             ->orderBy([
                 new Expression("
                     CASE 
                         WHEN category ILIKE 'срезка' THEN 1
-                        WHEN category ILIKE 'горшечные растения' THEN 2
+                        WHEN category ILIKE 'горшечные_растения' THEN 2
                         WHEN category ILIKE 'сухоцветы' THEN 3
                         ELSE 4
                     END
@@ -69,142 +70,73 @@ class AutoPlannogrammaController extends BaseController
         ]);
     }
 
-    public function actionCalculating()
+    public function actionGetProducts(string $category, string $subcategory): array
     {
-        $request = Yii::$app->request;
 
-        $filters = [
-            'category' => $request->get('category'),
-            'subcategory' => $request->get('subcategory'),
-            'product_name' => $request->get('product_name'),
-            'store_id' => $request->get('store_id'),
-            'plan_date' => $request->get('plan_date'),
-            'type' => $request->get('type'),
-        ];
 
-        $dataProvider = new ArrayDataProvider([
-            'allModels' => [],
-            'pagination' => ['pageSize' => 100],
-        ]);
+        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
 
-        if (!empty($filters['plan_date'])) {
-            $service = new AutoPlannogrammaService();
-            $dataProvider = new ArrayDataProvider([
-                'allModels' => $service->calculateFullGoalChain($filters),
-                'pagination' => ['pageSize' => 100],
-            ]);
-        }
-
-        return $this->render('calculating', [
-            'dataProvider' => $dataProvider,
-            'filters' => $filters,
-        ]);
+        return [
+            [
+                'name' => 'Роза Эквадор 60',
+                'guid' => '74876785y85',
+                'values' => [
+                    ['count' => 42,
+                        'store_id' => 1,
+                    ],
+                    [
+                        'count' => 13,
+                        'store_id' => 2,
+                    ],
+                ]
+            ],
+            [
+                'name' => 'Роза Эквадор 50',
+                'guid' => '74876e785y85',
+                'values' => [
+                    ['count' => 2,
+                        'store_id' => 1,
+                    ],
+                    [
+                        'count' => 1,
+                        'store_id' => 2,
+                    ],
+                ]
+            ],
+        ];
     }
 
-    public function actionControl()
+    public function actionGetVisibleStores()
     {
-        $filters = Yii::$app->request->get();
-        $params = [];
-        $conditions = [];
+        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
 
-        if (!empty($filters['product_name'])) {
-            $conditions[] = 'p1n.name LIKE :product_name';
-            $params[':product_name'] = '%' . $filters['product_name'] . '%';
-        }
-
-        if (!empty($filters['category'])) {
-            $conditions[] = 'p1n.category = :category';
-            $params[':category'] = $filters['category'];
-        }
-
-        if (!empty($filters['subcategory'])) {
-            $conditions[] = 'p1n.subcategory = :subcategory';
-            $params[':subcategory'] = $filters['subcategory'];
-        }
-
-        if (!empty($filters['city_name'])) {
-            $conditions[] = 'c.name LIKE :city_name';
-            $params[':city_name'] = '%' . $filters['city_name'] . '%';
-        }
+        $filters = Yii::$app->request->get();
 
-        if (!empty($filters['plan_date'])) {
-            $date = \DateTime::createFromFormat('d-m-Y', $filters['plan_date']);
-            if ($date) {
-                $startDate = $date->format('Y-m-d');
-                $endDate = $date->modify('+1 month')->format('Y-m-d');
-
-                if ($filters['type'] === 'writeOffs') {
-                    $conditions[] = 'DATE(w.date) >= :start_date';
-                    $conditions[] = 'DATE(w.date) < :end_date';
-                } else {
-                    $conditions[] = 'DATE(s.date) >= :start_date';
-                    $conditions[] = 'DATE(s.date) < :end_date';
-                }
+        $query = CityStoreParams::find()
+            ->alias('p')
+            ->joinWith(['store s'])
+            ->select('p.store_id')
+            ->where(['s.visible' => CityStore::IS_VISIBLE]);
+
+        $fields = [
+            'city' => 's.city_id',
+            'storeType' => 's.type_id',
+            'territorialManager' => 's.territorial_manager_id',
+            'region' => 's.region_id',
+            'district' => 's.district_id',
+            'bushChefFlorist' => 's.bush_chef_florist_id',
+        ];
 
-                $params[':start_date'] = $startDate;
-                $params[':end_date'] = $endDate;
+        foreach ($fields as $param => $column) {
+            if (!empty($filters[$param])) {
+                $query->andWhere([$column => $filters[$param]]);
             }
         }
 
-        $where = !empty($conditions) ? 'WHERE ' . implode(' AND ', $conditions) : '';
-
-        if (isset($filters['type']) && $filters['type'] === 'writeOffs') {
-            $query = Yii::$app->db->createCommand("
-                SELECT 
-                    c.name AS city_name,
-                    p1n.category,
-                    p1n.subcategory,
-                    item ->> 'product_id' AS product_id,
-                    p1n.name AS product_name,
-                    SUM(CAST(item ->> 'quantity' AS NUMERIC)) AS count,
-                    SUM(CAST(item ->> 'summ' AS NUMERIC)) AS sum
-                FROM write_offs w
-                JOIN export_import_table ex ON ex.export_val = w.store_id
-                JOIN city_store c ON c.id = ex.entity_id
-                JOIN LATERAL jsonb_array_elements(w.items::jsonb) AS item ON true
-                LEFT JOIN products_1c_nomenclature p1n ON p1n.id = item ->> 'product_id'
-                $where
-                GROUP BY w.store_id, c.name, p1n.category, p1n.subcategory, product_id, p1n.name
-                ORDER BY w.store_id, p1n.category, p1n.subcategory, p1n.name
-            ")->bindValues($params)->queryAll();
-        } else {
-            $query = Yii::$app->db->createCommand("
-                SELECT 
-                    c.name AS city_name,
-                    p1n.name AS product_name,
-                    p1n.category, 
-                    p1n.subcategory,
-                    SUM(CASE 
-                        WHEN s.operation = 'Продажа' THEN sp.quantity 
-                        WHEN s.operation = 'Возврат' THEN -sp.quantity 
-                        ELSE 0 
-                    END) AS count,
-                    SUM(CASE 
-                        WHEN s.operation = 'Продажа' THEN sp.summ 
-                        WHEN s.operation = 'Возврат' THEN -sp.summ 
-                        ELSE 0 
-                    END) AS sum
-                FROM sales s
-                LEFT JOIN sales_products sp ON sp.check_id = s.id
-                LEFT JOIN products_1c_nomenclature p1n ON p1n.id = sp.product_id
-                LEFT JOIN export_import_table ex ON ex.export_val = store_id_1c
-                LEFT JOIN city_store c ON c.id = entity_id
-                $where
-                GROUP BY p1n.name, p1n.category, p1n.subcategory, c.name, c.id
-                ORDER BY c.id DESC, category, subcategory, p1n.name
-            ")->bindValues($params)->queryAll();
-        }
+        return ['store_ids' => $query->column()];
+    }
 
-        $dataProvider = new ArrayDataProvider([
-            'allModels' => $query,
-            'pagination' => ['pageSize' => 20],
-        ]);
 
-        return $this->render('control', [
-            'dataProvider' => $dataProvider,
-            'filters' => $filters,
-        ]);
-    }
 
     public function action1()
     {
@@ -223,7 +155,6 @@ class AutoPlannogrammaController extends BaseController
             'pagination' => ['pageSize' => 100],
         ]);
 
-        // Обработка даты на год и месяц
         if (!empty($filters['year']) && !empty($filters['month'])) {
             $filters['plan_date'] = $filters['year'] . '-' . str_pad($filters['month'], 2, '0', STR_PAD_LEFT) . '-01';
 
diff --git a/erp24/migrations/m250605_201027_create_autoplannagramma_table.php b/erp24/migrations/m250605_201027_create_autoplannagramma_table.php
new file mode 100644 (file)
index 0000000..34a4616
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+use yii\db\Migration;
+
+/**
+ * Handles the creation of table `{{%autoplannagramma}}`.
+ */
+class m250605_201027_create_autoplannagramma_table extends Migration
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function safeUp()
+    {
+        $this->createTable('{{%autoplannogramma}}', [
+            'id' => $this->primaryKey(),
+            'week' => $this->integer()->comment('Неделя'),
+            'year' => $this->integer()->comment('Год'),
+            'product_id' => $this->string()->comment('GUID продукта'),
+            'store_id' => $this->integer()->comment('ID магазина'),
+            'capacity_type' => $this->integer()->comment('Тип планограммы'),
+            'auto_forecast' => $this->boolean()->comment('Прогнозированное значение'),
+            'quantity' => $this->integer()->comment('Количество'),
+            'created_at' => $this->dateTime()->comment('Дата создания'),
+            'updated_at' => $this->dateTime()->comment('Дата обновления'),
+            'created_by' => $this->integer()->comment('Автор создания'),
+            'updated_by' => $this->integer()->comment('Автор обновления'),
+        ]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function safeDown()
+    {
+        $this->dropTable('{{%autoplannogramma}}');
+    }
+}
diff --git a/erp24/views/auto-plannogramma/calculating.php b/erp24/views/auto-plannogramma/calculating.php
deleted file mode 100644 (file)
index d267d77..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-
-use kartik\date\DatePicker;
-use kartik\select2\Select2;
-use yii\helpers\ArrayHelper;
-use yii\helpers\Html;
-use yii\widgets\ActiveForm;
-use yii\grid\GridView;
-use yii_app\records\CityStore;
-use yii_app\records\Products1cNomenclature;
-
-/** @var array $filters */
-?>
-
-<div class="filter-form" style="margin-bottom: 20px;">
-    <?php $form = ActiveForm::begin(['method' => 'get']); ?>
-    <div class="row p-3">
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['category' => $filters['category'] ?? '']), 'category')->widget(Select2::class, [
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('category')->distinct()->asArray()->all(),
-                    'category',
-                    'category'
-                ),
-                'options' => ['placeholder' => 'Категория', 'name' => 'category'],
-                'pluginOptions' => ['allowClear' => true],
-            ])->label('Категория') ?>
-        </div>
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['subcategory' => $filters['subcategory'] ?? '']), 'subcategory')->widget(Select2::class, [
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('subcategory')->distinct()->asArray()->all(),
-                    'subcategory',
-                    'subcategory'
-                ),
-                'options' => ['placeholder' => 'Подкатегория', 'name' => 'subcategory'],
-                'pluginOptions' => ['allowClear' => true],
-            ])->label('Подкатегория') ?>
-        </div>
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['product_name' => $filters['product_name'] ?? '']), 'product_name')->widget(Select2::class, [
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('name')->distinct()->asArray()->all(),
-                    'name',
-                    'name'
-                ),
-                'options' => ['placeholder' => 'Название товара', 'name' => 'product_name'],
-                'pluginOptions' => ['allowClear' => true],
-            ])->label('Товар') ?>
-        </div>
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['store_id' => $filters['store_id'] ?? '']), 'store_id')->widget(Select2::class, [
-                'data' => ArrayHelper::map(
-                    CityStore::findAll(['visible' => CityStore::IS_VISIBLE]),
-                    'id',
-                    'name'
-                ),
-                'options' => ['placeholder' => 'Магазин', 'name' => 'store_id'],
-                'pluginOptions' => ['allowClear' => true],
-            ])->label('Магазин') ?>
-        </div>
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['plan_date' => $filters['plan_date'] ?? '']), 'plan_date')->widget(DatePicker::class, [
-                'pluginOptions' => [
-                    'autoclose' => true,
-                    'format' => 'dd-mm-yyyy',
-                ],
-                'options' => [
-                    'class' => 'form-control',
-                    'placeholder' => 'Плановая дата',
-                    'name' => 'plan_date',
-                ],
-            ])->label('Плановая дата') ?>
-        </div>
-        <div class="col-md">
-            <?= $form->field(new \yii\base\DynamicModel(['type' => $filters['type'] ?? '']), 'type')->widget(Select2::class, [
-                'data' => [
-                    'writeOffs' => 'Списания',
-                    'sales' => 'Продажи'
-                ],
-                'options' => ['placeholder' => 'Тип', 'name' => 'type'],
-                'pluginOptions' => ['allowClear' => true],
-            ])->label('По дефолту продажи!') ?>
-        </div>
-        <div class="col-md">
-            <?= Html::submitButton('Фильтровать', ['class' => 'btn btn-primary']) ?>
-        </div>
-        <div class="col-md">
-            <?= Html::a('Сбросить', ['auto-planogramma/test-sales'], ['class' => 'btn btn-default']) ?>
-        </div>
-    </div>
-
-    <?php ActiveForm::end(); ?>
-</div>
-
-<?= GridView::widget([
-    'dataProvider' => $dataProvider,
-    'columns' => [
-        'category',
-        'subcategory',
-        'product_name',
-        'store_id',
-        'store_name',
-        [
-            'attribute' => 'goal',
-            'label' => 'План закупок (RUB)',
-        ],
-    ],
-]); ?>
diff --git a/erp24/views/auto-plannogramma/control.php b/erp24/views/auto-plannogramma/control.php
deleted file mode 100644 (file)
index 67e4647..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-<div class="filter-form" style="margin-bottom: 20px;">
-    <?php use kartik\date\DatePicker;
-    use kartik\select2\Select2;
-    use yii\grid\GridView;
-    use yii\helpers\ArrayHelper;
-    use yii\helpers\Html;
-    use yii\widgets\ActiveForm;
-    use yii_app\records\CityStore;
-    use yii_app\records\Products1cNomenclature;
-
-    $form = ActiveForm::begin(['method' => 'get']); ?>
-    <div class="row">
-        <div class="col-md">
-            <?= Select2::widget([
-                'name' => 'category',
-                'value' => $filters['category'] ?? '',
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('category')->distinct()->orderBy('category')->asArray()->all(),
-                    'category',
-                    'category'
-                ),
-                'options' => ['placeholder' => 'Категория'],
-                'pluginOptions' => ['allowClear' => true],
-            ]) ?>
-        </div>
-
-        <div class="col-md">
-            <?= Select2::widget([
-                'name' => 'subcategory',
-                'value' => $filters['subcategory'] ?? '',
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('subcategory')->distinct()->orderBy('subcategory')->asArray()->all(),
-                    'subcategory',
-                    'subcategory'
-                ),
-                'options' => ['placeholder' => 'Подкатегория'],
-                'pluginOptions' => ['allowClear' => true],
-            ]) ?>
-        </div>
-        <div class="col-md">
-            <?= Select2::widget([
-                'name' => 'product_name',
-                'value' => $filters['product_name'] ?? '',
-                'data' => ArrayHelper::map(
-                    Products1cNomenclature::find()->select('name')->distinct()->orderBy('name')->asArray()->all(),
-                    'name',
-                    'name'
-                ),
-                'options' => ['placeholder' => 'Товар'],
-                'pluginOptions' => ['allowClear' => true],
-            ]) ?>
-        </div>
-
-
-        <div class="col-md">
-            <?= Select2::widget([
-                'name' => 'city_name',
-                'value' => $filters['city_name'] ?? '',
-                'data' => ArrayHelper::map(
-                    CityStore::find()->select(['name'])->distinct()->orderBy('name')->asArray()->all(),
-                    'name',
-                    'name'
-                ),
-                'options' => ['placeholder' => 'Магазин'],
-                'pluginOptions' => ['allowClear' => true],
-            ]) ?>
-        </div>
-
-        <div class="col-md">
-            <?= DatePicker::widget([
-                'name' => 'plan_date',
-                'value' => $filters['plan_date'] ?? '',
-                'pluginOptions' => [
-                    'autoclose' => true,
-                    'format' => 'dd-mm-yyyy',
-                ],
-                'options' => [
-                    'class' => 'form-control',
-                    'placeholder' => 'Плановая дата',
-                ],
-            ]) ?>
-        </div>
-
-        <div class="col-md">
-            <?= Select2::widget([
-                'name' => 'type',
-                'value' => $filters['type'] ?? '',
-                'data' => [
-                    'writeOffs' => 'Списания',
-                    'sales' => 'Продажи'
-                ],
-                'options' => ['placeholder' => 'Тип'],
-                'pluginOptions' => ['allowClear' => true],
-            ]) ?>
-        </div>
-
-
-        <div class="col-md">
-            <?= Html::submitButton('Фильтровать', ['class' => 'btn btn-primary']) ?>
-        </div>
-        <div class="col-md">
-            <?= Html::a('Сбросить', ['auto-planogramma/sales'], ['class' => 'btn btn-default']) ?>
-        </div>
-    </div>
-    <?php ActiveForm::end(); ?>
-</div>
-
-<?= GridView::widget([
-    'dataProvider' => $dataProvider,
-    'columns' => [
-        'category',
-        'subcategory',
-        ['attribute' => 'product_name', 'label' => 'Товар'],
-        ['attribute' => 'city_name', 'label' => 'Магазин'],
-        ['attribute' => 'count', 'label' => 'Кол-во'],
-        ['attribute' => 'sum', 'label' => 'Сумма'],
-    ],
-]) ?>
index 7201c532b48286ecc48889df6d478dbc61298bbe..daf2cd11df4d5627be4376bbd051466f404bc763 100644 (file)
@@ -4,6 +4,7 @@ use kartik\grid\GridView;
 use kartik\select2\Select2;
 use yii\helpers\ArrayHelper;
 use yii\helpers\Html;
+use yii\web\View;
 use yii_app\helpers\DateHelper;
 use yii_app\records\Admin;
 use yii_app\records\AdminGroup;
@@ -18,7 +19,9 @@ use yii\jui\Accordion;
 
 use yii\data\ArrayDataProvider;
 
-$tooltipText = "Оффлайн: 50&#10;Флаумак (off-line): 20&#10;Флаумак (on-line): 10&#10;Флаумак (market): 10&#10;Изумительная (off-line): 30&#10;Списания: 20"; ?>
+$tooltipText = "Оффлайн: 50&#10;Флаумак (off-line): 20&#10;Флаумак (on-line): 10&#10;Флаумак (market): 10&#10;Изумительная (off-line): 30&#10;Списания: 20";
+$this->registerJsFile('/js/autoplannogramma/autoplannogramma.js', ['position' => View::POS_END]);
+?>
 
 <h1 class="ms-3 mb-4"><?= Html::encode("Автопланограмма") ?></h1>
 <div class="autopolnogramma p-3 px-4">
@@ -114,7 +117,9 @@ $tooltipText = "Оффлайн: 50&#10;Флаумак (off-line): 20&#10;Фла
                 </div>
                 <div class="col-md d-flex">
                 </div>
-                <div class="col-md d-flex"></div>
+                <div class="col-md d-flex">
+                    <?= Html::submitButton('Сбросить', ['class' => 'btn btn-reset btn-warning', 'style' => 'width:100%']); ?>
+                </div>
             </div>
             <div class="row">
                 <div class="col-md d-flex">
@@ -167,130 +172,56 @@ $tooltipText = "Оффлайн: 50&#10;Флаумак (off-line): 20&#10;Фла
                     </div>
                 </th>
 
-                <?php foreach ($stores as $store) { ?>
+                <?php foreach ($stores as $store): ?>
                     <th scope="col" class="fixed-column">
                         <?= Html::label($store, null, [
                             'style' => 'writing-mode: sideways-lr; text-align: center; white-space: nowrap; 
-                                font-weight: bold; transform-origin: left bottom; padding-right: 7%;'
+                            font-weight: bold; transform-origin: left bottom; padding-right: 7%;'
                         ]) ?>
                     </th>
-                <?php } ?>
+                <?php endforeach; ?>
             </tr>
             </thead>
-            <tbody>
+            <tbody id="autoplannogramma">
             <?php
             $groupedCategories = [];
-
-            // Группируем данные по категориям и подкатегориям
             foreach ($categories as $item) {
-                $groupedCategories[$item['category']][$item['subcategory']] = $item['products'];
+                $groupedCategories[$item['category']][] = $item['subcategory'];
             }
+            ?>
 
-            foreach ($groupedCategories as $category => $subcategories): ?>
+            <?php foreach ($groupedCategories as $category => $subcategories): ?>
                 <tr>
                     <td class="category">
                         <a class="list-group-item list-group-item-action">
                             <?= Html::encode($category) ?> ▲
                         </a>
                     </td>
+                    <?php foreach ($stores as $id => $storeName): ?>
+                        <td data-store-id="<?= $id ?>" data-category="<?=$category?>"></td>
+                    <?php endforeach; ?>
                 </tr>
 
-                <?php foreach ($subcategories as $subcategory => $products): ?>
+                <?php foreach ($subcategories as $subcategory): ?>
                     <tr>
                         <td style="position: relative; display: flex; justify-content: flex-end;" class="subcategory">
-                            <a class="list-group-item list-group-item-action" style="width: 95%;">
+                            <a href="#" class="list-group-item list-group-item-action subcategory-link"
+                               style="width: 95%;"
+                               data-category="<?= Html::encode($category) ?>"
+                               data-subcategory="<?= Html::encode($subcategory) ?>">
                                 <?= Html::encode($subcategory) ?> ▶
                             </a>
                         </td>
+                        <?php foreach ($stores as $id => $storeName): ?>
+                            <td data-store-id="<?= $id ?>" data-category="<?= $category?>" data-subcategory="<?= $subcategory ?>"></td>
+                        <?php endforeach; ?>
                     </tr>
-                    <?php
-                    $products = is_string($products) ? json_decode($products, true) : $products;
-                    ?>
-                    <?php foreach ($products as $product): ?>
-                        <tr>
-                            <td style="position: relative; display: flex; justify-content: flex-end;">
-                                <a class="list-group-item list-group-item-action" style="width: 90%;">
-                                    <?= Html::encode($product) ?>
-                                </a>
-                            </td>
-
-                            <?php foreach ($stores as $store): ?>
-                                <td class="items">
-                                    <div style="display: flex; align-items: center;">
-                                        <?= Html::input('text', '', 50, [
-                                            'class' => 'btn btn-primary input',
-                                            'data-bs-toggle' => 'tooltip',
-                                            'data-bs-placement' => 'top',
-                                            'title' => $tooltipText,
-                                        ]) ?>
-                                        <button style="border: none; background: transparent; cursor: pointer; margin-left: 5px;">
-                                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-                                                <path d="M20 11v5a1 1 0 0 1-2 0v-4H7.414l1.293 1.293a1 1 0 0 1-1.414 1.414l-3-3a1 1 0 0 1 0-1.416l3-3a1 1 0 1 1 1.414 1.416L7.414 10H19a1 1 0 0 1 1 1z"
-                                                      fill="grey" stroke="none"/>
-                                            </svg>
-                                        </button>
-                                    </div>
-                                </td>
-                            <?php endforeach; ?>
-                        </tr>
-                    <?php endforeach; ?>
                 <?php endforeach; ?>
             <?php endforeach; ?>
             </tbody>
         </table>
     </div>
 </div>
-<script>
-    document.addEventListener("DOMContentLoaded", function () {
-        // Изначально скрываем все строки, кроме .category и .head
-        document.querySelectorAll("tr").forEach(row => {
-            if (!row.querySelector(".category") && !row.classList.contains("head")) {
-                row.style.display = "none";
-            }
-        });
-
-        // Обработчик кликов для категорий
-        document.querySelectorAll(".category").forEach(category => {
-            category.addEventListener("click", function () {
-                let nextRow = this.parentElement.nextElementSibling;
-                let isVisible = nextRow?.style.display === "table-row";
-
-                // Закрываем все элементы внутри категории
-                while (nextRow && !nextRow.querySelector(".category")) {
-                    nextRow.style.display = "none";
-                    nextRow = nextRow.nextElementSibling;
-                }
-
-                // Если категория была закрыта — открываем подкатегории
-                if (!isVisible) {
-                    nextRow = this.parentElement.nextElementSibling;
-                    while (nextRow && !nextRow.querySelector(".category")) {
-                        if (nextRow.querySelector(".subcategory")) {
-                            nextRow.style.display = "table-row";
-                        }
-                        nextRow = nextRow.nextElementSibling;
-                    }
-                }
-            });
-        });
-
-        // Обработчик кликов для подкатегорий
-        document.querySelectorAll(".subcategory").forEach(subcategory => {
-            subcategory.addEventListener("click", function (event) {
-                event.stopPropagation(); // Чтобы клик по подкатегории не закрывал категорию
-
-                let nextRow = this.parentElement.nextElementSibling;
-                let isVisible = nextRow?.style.display === "table-row";
-
-                // Переключаем видимость только айтемов внутри этой подкатегории
-                while (nextRow && !nextRow.querySelector(".subcategory") && !nextRow.querySelector(".category")) {
-                    nextRow.style.display = isVisible ? "none" : "table-row";
-                    nextRow = nextRow.nextElementSibling;
-                }
-            });
-        });
-    });
-</script>
 
 <style>
     /* Стили для таблицы */
diff --git a/erp24/web/js/autoplannogramma/autoplannogramma.js b/erp24/web/js/autoplannogramma/autoplannogramma.js
new file mode 100644 (file)
index 0000000..530477c
--- /dev/null
@@ -0,0 +1,217 @@
+document.addEventListener("DOMContentLoaded", function () {
+    // Изначально скрываем все строки, кроме .category и .head
+    document.querySelectorAll("tr").forEach(row => {
+        if (!row.querySelector(".category") && !row.classList.contains("head")) {
+            row.style.display = "none";
+        }
+    });
+
+    // Обработчик кликов для категорий
+    document.querySelectorAll(".category").forEach(category => {
+        category.addEventListener("click", function () {
+            let nextRow = this.parentElement.nextElementSibling;
+            let isVisible = nextRow?.style.display === "table-row";
+
+            // Закрываем все элементы внутри категории
+            while (nextRow && !nextRow.querySelector(".category")) {
+                nextRow.style.display = "none";
+                nextRow = nextRow.nextElementSibling;
+            }
+
+            // Если категория была закрыта — открываем подкатегории
+            if (!isVisible) {
+                nextRow = this.parentElement.nextElementSibling;
+                while (nextRow && !nextRow.querySelector(".category")) {
+                    if (nextRow.querySelector(".subcategory")) {
+                        nextRow.style.display = "table-row";
+                    }
+                    nextRow = nextRow.nextElementSibling;
+                }
+            }
+        });
+    });
+
+    // Обработчик кликов для подкатегорий
+    document.querySelectorAll(".subcategory").forEach(subcategory => {
+        subcategory.addEventListener("click", function (event) {
+            event.stopPropagation(); // Чтобы клик по подкатегории не закрывал категорию
+
+            let nextRow = this.parentElement.nextElementSibling;
+            let isVisible = nextRow?.style.display === "table-row";
+
+            // Переключаем видимость только айтемов внутри этой подкатегории
+            while (nextRow && !nextRow.querySelector(".subcategory") && !nextRow.querySelector(".category")) {
+                nextRow.style.display = isVisible ? "none" : "table-row";
+                nextRow = nextRow.nextElementSibling;
+            }
+        });
+    });
+});
+
+$('.subcategory-link').on('click', function (e) {
+    e.preventDefault();
+
+    const $link = $(this);
+    const category = $link.data('category');
+    const subcategory = $link.data('subcategory');
+    const $row = $link.closest('tr');
+
+    $.ajax({
+        url: '/auto-plannogramma/get-products',
+        type: 'GET',
+        data: {
+            category: category,
+            subcategory: subcategory
+        },
+        success: function (response) {
+            // Удаляем предыдущие строки
+            $row.nextAll('tr.inserted-row').remove();
+
+            response.forEach(item => {
+                const tr = $('<tr class="inserted-row"></tr>');
+
+                // Подкатегория
+                const subcategoryTd = $(`
+            <td class="subcategory" style="display: flex; justify-content: flex-end;">
+                <a href="#" class="list-group-item list-group-item-action subcategory-link"
+                   style="width: 90%;"
+                   data-category="${category}" data-subcategory="${subcategory}">
+                    ${item.name}
+                </a>
+            </td>
+        `);
+                tr.append(subcategoryTd);
+
+                // Карта store_id => count
+                const valuesMap = {};
+                item.values.forEach(val => {
+                    valuesMap[val.store_id] = {
+                        count: val.count,
+                        guid: item.guid
+                    };
+                });
+
+                // Берём колонку из текущей строки, чтобы соблюсти порядок
+                $row.find('td[data-store-id]').each(function () {
+                    const td = $(this);
+                    const storeId = td.data('store-id');
+                    const val = valuesMap[storeId] ?? { count: '', guid: '' };
+
+                    const newTd = $(`
+                <td data-store-id="${storeId}">
+                    <div style="display: flex; align-items: center;">
+                        <input type="text"
+                               class="btn btn-primary input"
+                               value="${val.count}"
+                               data-guid="${val.guid}"
+                               data-store_id="${storeId}"
+                               data-bs-toggle="tooltip"
+                               data-bs-placement="top"
+                               data-original-value="${val.count}"
+                               style="width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.375rem; border: 1px solid #0d6efd;">
+                        <button class="reject-btn" style="border: none; background: transparent; cursor: pointer; margin-left: 5px;">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+                                <path d="M20 11v5a1 1 0 0 1-2 0v-4H7.414l1.293 1.293a1 1 0 0 1-1.414 1.414l-3-3a1 1 0 0 1 0-1.416l3-3a1 1 0 1 1 1.414 1.416L7.414 10H19a1 1 0 0 1 1 1z"
+                                      fill="grey" stroke="none"/>
+                            </svg>
+                        </button>
+                    </div>
+                </td>
+            `);
+
+                    tr.append(newTd);
+                });
+
+                $row.after(tr);
+            });
+        },
+        error: function (xhr) {
+            alert('Ошибка: ' + xhr.responseText);
+        }
+    });
+});
+
+$('#autoplannogramma').on('change, input', '.input', function () {
+    const $input = $(this);
+    const newValue = $input.val();
+console.log(3)
+    const $td = $input.closest('td');
+    const $svg = $td.find('svg');
+
+    $svg.find('path').attr('fill', 'red');
+});
+
+$('#autoplannogramma').on('click', '.reject-btn', function () {
+    const $button = $(this);
+    const $td = $button.closest('td');
+    const $input = $td.find('input.input');
+    const $svg = $td.find('svg');
+
+    const originalValue = $input.data('original-value');
+
+    if (originalValue !== undefined) {
+        $input.val(originalValue);
+        $svg.find('path').attr('fill', 'grey');
+    }
+});
+
+function getFilterData() {
+    return {
+        year: $('#year').val(),
+        city: $('#city').val(),
+        storeType: $('#store-type').val(),
+        territorialManager: $('#territorial-manger').val(),
+        polnogrammaType: $('#polnogramma-type').val(),
+        week: $('#week').val(),
+        region: $('#region').val(),
+        bushChefFlorist: $('#bush_chef_florist').val(),
+        district: $('#district').val(),
+    };
+}
+
+// Скрываем ячейки магазинов, не подходящих по фильтру
+function applyStoreFilter() {
+    const filterData = getFilterData();
+
+    $.ajax({
+        url: '/auto-plannogramma/get-visible-stores',
+        type: 'GET',
+        data: filterData,
+        success: function (response) {
+            const allowedStoreIds = response.store_ids.map(id => String(id));
+
+            $('td[data-store-id], th[data-store-id]').each(function () {
+                const storeId = $(this).data('store-id').toString();
+                if (!allowedStoreIds.includes(storeId)) {
+                    $(this).hide(); // скрываем
+                } else {
+                    $(this).show(); // показываем нужное
+                }
+            });
+        },
+        error: function (xhr) {
+            console.error('Ошибка при фильтрации магазинов:', xhr.responseText);
+        }
+    });
+}
+
+// Показываем всё обратно при сбросе
+function resetStoreFilter() {
+    $('td[data-store-id], th[data-store-id]').show(); // показываем все
+}
+
+// Вешаем события
+$('.btn-apply').on('click', function () {
+    applyStoreFilter();
+});
+
+$('.btn-reset').on('click', function () {
+    // Сброс значений фильтров
+    $('#year, #city, #store-type, #territorial-manger, #polnogramma-type, #week, #region, #bush_chef_florist, #district').val('');
+
+    resetStoreFilter();
+});
+
+
+
+