]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Выгрузка корректировки и филтрация по раскрытым спискам
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 25 Jul 2025 14:55:55 +0000 (17:55 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 25 Jul 2025 14:55:55 +0000 (17:55 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/services/AutoPlannogrammaService.php
erp24/views/auto-plannogramma/index.php
erp24/web/js/autoplannogramma/autoplannogramma.js

index 2cdee37327d669961fd6f5fd1c0062cde347eab7..df838f568f73b4189ae541f3752d6d4acd67a328 100644 (file)
@@ -102,8 +102,8 @@ class AutoPlannogrammaController extends BaseController
             ->andFilterWhere(['=', 'cp.address_city', $filters['city']])
             ->andFilterWhere(['=', 'cp.address_region', $filters['region']])
             ->andFilterWhere(['=', 'cp.address_district', $filters['district']])
-            ->andFilterWhere(['=', 'cp.store_type', $filters['store_type']])
-            ->andFilterWhere(['=', 'a.capacity_type', $filters['capacity_type']]);
+            ->andFilterWhere(['=', 'cp.store_type', $filters['store_type']]);
+
 
         if (!empty($filters['territorial_manager'])) {
             $territorialManagerStoreIds = StoreDynamic::find()
@@ -1432,19 +1432,13 @@ class AutoPlannogrammaController extends BaseController
         $this->layout = false;
         Yii::$app->response->format = Response::FORMAT_RAW;
 
-        $mappingTypes = [
-          'offline' => 'Офлайн',
-          'online' => 'Онлайн',
-          'write_offs' => 'Списания',
-          'marketplace' => 'Маркетплейс'
-        ];
 
         while (ob_get_level() > 0) {
             ob_end_clean();
         }
 
         $filters = [];
-            $request->get();
+        $request->get();
         $filters['year'] = (int)$request->get('year');
         $filters['week'] = (int)$request->get('week');
         $filters['city'] = $request->get('city', null);
@@ -1454,21 +1448,43 @@ class AutoPlannogrammaController extends BaseController
         $filters['store_type'] = is_numeric($request->get('store_type')) ? (int)$request->get('store_type') : null;
         $filters['territorial_manager'] = is_numeric($request->get('territorial_manager')) ? (int)$request->get('territorial_manager') : null;
         $filters['bush_chef_florist'] = is_numeric($request->get('bush_chef_florist')) ? (int)$request->get('bush_chef_florist') : null;
-
+        $filters['auto'] = (int)$request->get('auto', 0);
+        $filters['categories'] = [];
+        if ($catsJson = $request->get('categories')) {
+            $decoded = json_decode($catsJson, true);
+            if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
+                $filters['categories'] = $decoded;
+            }
+        }
         $query = Autoplannogramma::find()
             ->alias('a')
             ->leftJoin('products_1c_nomenclature p1n', 'p1n.id = a.product_id')
             ->leftJoin('city_store_params cp', 'cp.store_id = a.store_id')
             ->leftJoin('city_store c', 'c.id = a.store_id')
-           // ->where(['p1n.category' => $category])
-           // ->andWhere(['p1n.subcategory' => $subcategory])
+
             ->andFilterWhere(['=', 'a.year', $filters['year']])
             ->andFilterWhere(['=', 'a.week', $filters['week']])
             ->andFilterWhere(['=', 'cp.address_city', $filters['city']])
             ->andFilterWhere(['=', 'cp.address_region', $filters['region']])
             ->andFilterWhere(['=', 'cp.address_district', $filters['district']])
-            ->andFilterWhere(['=', 'cp.store_type', $filters['store_type']])
-            ->andFilterWhere(['=', 'a.capacity_type', $filters['capacity_type']]);
+            ->andFilterWhere(['=', 'cp.store_type', $filters['store_type']]);
+           // ->andFilterWhere(['=', 'a.capacity_type', $filters['capacity_type']]);
+
+        if (!empty($filters['categories'])) {
+            $or = ['or'];
+            foreach ($filters['categories'] as $pair) {
+                if (count($pair) === 2) {
+                    list($cat, $sub) = $pair;
+                    $or[] = ['and',
+                        ['p1n.category'    => $cat],
+                        ['p1n.subcategory' => $sub],
+                    ];
+                }
+            }
+            if (count($or) > 1) {
+                $query->andWhere($or);
+            }
+        }
 
         if (!empty($filters['territorial_manager'])) {
             $territorialManagerStoreIds = StoreDynamic::find()
@@ -1498,7 +1514,8 @@ class AutoPlannogrammaController extends BaseController
                 'a.store_id',
                 'c.name AS store_name',
                 'a.modify',
-                'a.capacity_type',
+                'a.calculate',
+                'a.total',
                 'a.details',
                 'a.month',
                 'a.year',
@@ -1507,48 +1524,120 @@ class AutoPlannogrammaController extends BaseController
             ->asArray()
             ->all();
 
-            $detailsData = [];
-            foreach ($autoplannogrammData as $product) {
-                $data = $product['details'];
-                while (is_string($data)) {
-                    $decoded = json_decode($data, true);
-                    if (json_last_error() !== JSON_ERROR_NONE) {
-                        break;
+        $detailsData = [];
+        $auto = $filters['auto'] == 1;
+
+        foreach ($autoplannogrammData as $product) {
+
+            $data = $product['details'];
+            while (is_string($data)) {
+                $decoded = json_decode($data, true);
+                if (json_last_error() !== JSON_ERROR_NONE) break;
+                $data = $decoded;
+            }
+            $detailsArray = $data ?? [];
+
+            if (!$auto && $product['modify'] !== null) {
+                $detailsData[] = [
+                    'product_name' => $product['product_name'],
+                    'category'     => $product['category'],
+                    'subcategory'  => $product['subcategory'],
+                    'species'      => $product['species'],
+                    'month'        => $product['month'],
+                    'year'         => $product['year'],
+                    'week'         => "{$product['week']}/{$product['year']}/{$product['month']}",
+                    'type_pm'      => $filters['capacity_type'] == 'max' ? 'max' : 'min',
+                    'shop'         => "{$product['store_id']} {$product['store_name']}",
+                    'group_name'   => 'Корректировка',
+                    'quantity'     => $product['modify'],
+                    'value_type'   => 'Корректировка',
+                ];
+                continue;
+            }
+
+
+            foreach ($detailsArray as $type => $typeArr) {
+
+                if ($type === AutoPlannogrammaService::TYPE_OFFLINE) {
+
+                    $detailsData[] = [
+                        'product_name' => $product['product_name'],
+                        'category'     => $product['category'],
+                        'subcategory'  => $product['subcategory'],
+                        'species'      => $product['species'],
+                        'month'        => $product['month'],
+                        'year'         => $product['year'],
+                        'week'         => "{$product['week']}/{$product['year']}/{$product['month']}",
+                        'type_pm'      => $filters['capacity_type'] == 'max' ? 'max' : 'min',
+                        'shop'         => "{$product['store_id']} {$product['store_name']}",
+                        'group_name'   => 'Оффлайн',
+                        'quantity'     => $product['calculate'],
+                        'value_type'   => AutoPlannogrammaService::TYPE_OFFLINE,
+                    ];
+                    // группы offline
+                    if (!empty($typeArr['groups']) && is_array($typeArr['groups'])) {
+                        foreach ($typeArr['groups'] as $groupKey => $qty) {
+                            $detailsData[] = [
+                                'product_name' => $product['product_name'],
+                                'category'     => $product['category'],
+                                'subcategory'  => $product['subcategory'],
+                                'species'      => $product['species'],
+                                'month'        => $product['month'],
+                                'year'         => $product['year'],
+                                'week'         => "{$product['week']}/{$product['year']}/{$product['month']}",
+                                'type_pm'      => $filters['capacity_type'] == 'max' ? 'max' : 'min',
+                                'shop'         => "{$product['store_id']} {$product['store_name']}",
+                                'group_name'   => $groupKey,
+                                'quantity'     => $qty,
+                                'value_type'   => AutoPlannogrammaService::TYPE_OFFLINE,
+                            ];
+                        }
                     }
-                    $data = $decoded;
+                    continue;
                 }
-                $detailsArray = $data ?? [];
-                foreach ($detailsArray as $type => $typeArr) {
-                    if (!isset($typeArr['groups']) && $type !== AutoPlannogrammaService::TYPE_WRITE_OFFS) {
-                        continue;
-                    }
-                    $groups = $typeArr['groups'] ?? [];
-                    $groups[$type] = $typeArr['quantity'];
-                    foreach ($groups as $group => $quantity) {
-                        if (in_array($group, array_keys($mappingTypes))) {
-                            $groupName = $mappingTypes[$group];
-                        } else {
-                            $groupName = $group;
-                        }
+
+                // writeOffs
+                if ($type === AutoPlannogrammaService::TYPE_WRITE_OFFS && isset($typeArr['quantity'])) {
+                    $detailsData[] = [
+                        'product_name' => $product['product_name'],
+                        'category'     => $product['category'],
+                        'subcategory'  => $product['subcategory'],
+                        'species'      => $product['species'],
+                        'month'        => $product['month'],
+                        'year'         => $product['year'],
+                        'week'         => "{$product['week']}/{$product['year']}/{$product['month']}",
+                        'type_pm'      => $filters['capacity_type'] == 'max' ? 'max' : 'min',
+                        'shop'         => "{$product['store_id']} {$product['store_name']}",
+                        'group_name'   => 'Списание',
+                        'quantity'     => $typeArr['quantity'],
+                        'value_type'   => AutoPlannogrammaService::TYPE_WRITE_OFFS,
+                    ];
+                    continue;
+                }
+
+                // --- остальные типы: только группы ---
+                if (!empty($typeArr['groups']) && is_array($typeArr['groups'])) {
+                    foreach ($typeArr['groups'] as $groupKey => $qty) {
                         $detailsData[] = [
                             'product_name' => $product['product_name'],
-                            'category' => $product['category'],
-                            'subcategory' => $product['subcategory'],
-                            'species' => $product['species'],
-                            'month' => $product['month'],
-                            'year' => $product['year'],
-                            'week' => $product['week'] . '/' . $product['year'] . '/' . $product['month'],
-                            'type_pm' => $product['capacity_type'] == 1 ? 'max' : 'min',
-                            'shop' => $product['store_id'] . ' ' . $product['store_name'],
-                            'group_name' => $groupName,
-                            'quantity' => $quantity,
-                            'value_type' => $type,
+                            'category'     => $product['category'],
+                            'subcategory'  => $product['subcategory'],
+                            'species'      => $product['species'],
+                            'month'        => $product['month'],
+                            'year'         => $product['year'],
+                            'week'         => "{$product['week']}/{$product['year']}/{$product['month']}",
+                            'type_pm'      => $filters['capacity_type'] == 'max' ? 'max' : 'min',
+                            'shop'         => "{$product['store_id']} {$product['store_name']}",
+                            'group_name'   => $groupKey,
+                            'quantity'     => $qty,
+                            'value_type'   => $type,
                         ];
                     }
-
                 }
             }
-            $spreadsheet = new Spreadsheet();
+        }
+
+        $spreadsheet = new Spreadsheet();
         $sheet = $spreadsheet->getActiveSheet();
         $sheet->setTitle('Отчёт');
 
index 12f0cb06d6239ffe707015f322cd7f3f6fa68029..3ba843b223a64ecc0a5b8f4b31f46b63c00ab04b 100644 (file)
@@ -31,6 +31,7 @@ class AutoPlannogrammaService
     private const CATEGORY_LOOKBACK_MONTHS = 3; // Период для анализа категорий (месяцы)
     private const LOOKBACK_MONTHS = 2; // Отступаемый шаг от плановой даты перед расчетами
     public const HELIUM_GUID = '2b72702a-792f-11e8-9edd-1c6f659fb563';
+    const TYPE_OFFLINE = 'offline';
 
     /**
      * Получение списка видимых магазинов
index 950f0727f1e03db3f376f562faff2d2c27b19ce5..f34a483f867f9cb0ddd54130a231644a6388769c 100644 (file)
@@ -188,11 +188,15 @@ $this->registerJsFile('/js/autoplannogramma/autoplannogramma.js', ['position' =>
 
                     <div class="buttons d-flex justify-content-end">
                         <?= Html::a('Auto', '#', [
-                            'class' => 'btn btn-success ms-1 btn-auto',
-                            'id' => 'export-excel-btn',
+                            'class' => 'btn btn-success ms-1 export-excel-btn',
+                            'data-auto' => '1',
+                            'target' => '_blank'
+                        ]) ?>
+                        <?= Html::a('Corrected', '#', [
+                            'class' => 'btn btn-success ms-1 export-excel-btn',
+                            'data-auto' => '0',
                             'target' => '_blank'
                         ]) ?>
-                        <?= Html::a('Corrected', '#', ['class' => 'btn btn-success ms-1 btn-corrected']) ?>
                     </div>
                 </th>
                 <?php foreach ($stores as $storeId => $storeName): ?>
@@ -246,7 +250,7 @@ $this->registerJsFile('/js/autoplannogramma/autoplannogramma.js', ['position' =>
 <style>
     .table {
         width: max-content;
-        table-layout: fixed;
+        /*table-layout: fixed;*/
         border-collapse: collapse;
     }
 
index 553d40f4857e3774b77f251c5d13e379d719773f..e2faf7a82b72c4190b1cd64564cd383abc3f68b3 100644 (file)
@@ -5,22 +5,38 @@ document.addEventListener("DOMContentLoaded", () => {
             row.style.display = "none";
         }
     });
-    $('#export-excel-btn').on('click', function (e) {
+    $('.export-excel-btn').on('click', function (e) {
         e.preventDefault();
 
+        const auto = $(this).data('auto');
+        const selectedPairs = [];
+        $('.subcategory.active .subcategory-label').each(function () {
+            const category    = $(this).data('category');
+            const subcategory = $(this).data('subcategory');
+            if (category && subcategory) {
+                selectedPairs.push([category, subcategory]);
+            }
+        });
+        console.log(selectedPairs.length)
+        if (selectedPairs.length === 0) {
+            alert("Нет данных для выгрузки");
+            return;
+        }
         const baseUrl = '/auto-plannogramma/export-excel';
         const params = {
             year: $('#year').val(),
             week: $('#week').val(),
             city: $('#city').val(),
             region: $('#region').val(),
+            district: $('#district').val(),
             store_type: $('#store-type').val(),
             capacity_type: $('#capacity-type').val() || null,
             bush_chef_florist: $('#bush_chef_florist').val(),
             territorial_manager: $('#territorial-manager').val(),
-            polnogramma_type: $('#polnogramma-type').val()
+            polnogramma_type: $('#polnogramma-type').val(),
+            auto: auto,
+            categories: JSON.stringify(selectedPairs)
         };
-
         const query = Object.entries(params)
             .filter(([_, v]) => v !== null && v !== '')
             .map(([k, v]) => k + '=' + encodeURIComponent(v))
@@ -36,6 +52,7 @@ document.addEventListener("DOMContentLoaded", () => {
             let row = this.closest("tr").nextElementSibling;
             let isOpen = row?.style.display === "table-row";
 
+
             while (row && !row.querySelector(".category")) {
                 row.style.display = "none";
                 row = row.nextElementSibling;
@@ -56,8 +73,19 @@ document.addEventListener("DOMContentLoaded", () => {
     document.querySelectorAll(".subcategory").forEach(sub => {
         sub.addEventListener("click", function (e) {
             e.stopPropagation();
-            let row = this.closest("tr").nextElementSibling;
-            let isOpen = row?.style.display === "table-row";
+
+            const tr = this.closest("tr");
+            let row= tr.nextElementSibling;
+
+            const isOpen= row && getComputedStyle(row).display === "table-row";
+
+            this.classList.toggle("active", isOpen);
+            console.log(isOpen);
+            if (isOpen) {
+                row.querySelector(".subcategory").classList.remove("active");
+            } else {
+                row.querySelector(".subcategory").classList.add("active");
+            }
 
             while (row && !row.querySelector(".subcategory") && !row.querySelector(".category")) {
                 row.style.display = isOpen ? "none" : "table-row";