]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Прогноз товаров внутри вида
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 28 May 2025 10:47:14 +0000 (13:47 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 28 May 2025 10:47:14 +0000 (13:47 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/services/AutoPlannogrammaService.php
erp24/services/StorePlanService.php
erp24/views/auto-plannogramma/81.php [deleted file]
erp24/views/auto-plannogramma/82.php [deleted file]
erp24/views/auto-plannogramma/month-products-species-forecast.php [new file with mode: 0644]
erp24/views/auto-plannogramma/month-products-species-share.php [new file with mode: 0644]

index 18f9eb21a58a24612186e65b025b4aaaaae90a74..f9aebf2da4ba95478d1ee163b8dbc6eeb8f0168e 100644 (file)
@@ -660,7 +660,7 @@ class AutoPlannogrammaController extends BaseController
         ]);
     }
 
-    public function action81()
+    public function actionMonthProductsSpeciesShare()
     {
         $request = Yii::$app->request;
 
@@ -784,7 +784,138 @@ class AutoPlannogrammaController extends BaseController
                 'pagination' => ['pageSize' => 100],
             ]);
         }
-        return $this->render('81', [
+        return $this->render('month-products-species-share', [
+            'dataProvider' => $dataProvider,
+            'filters' => $filters,
+        ]);
+    }
+
+
+    public function actionMonthProductsSpeciesForecast()
+    {
+        $request = Yii::$app->request;
+
+        $filters = [
+            'category' => $request->get('category'),
+            'subcategory' => $request->get('subcategory') ?? null,
+            'species' => $request->get('species') ?? null,
+            'store_id' => $request->get('store_id') ?? [],
+            'year' => $request->get('year'),
+            'month' => $request->get('month'),
+            'type' => $request->get('type'),
+        ];
+
+        $dataProvider = new ArrayDataProvider([
+            'allModels' => [],
+            'pagination' => ['pageSize' => 100],
+        ]);
+
+        $bouquetSpeciesForecast = [];
+        // Обработка даты на год и месяц
+        if (!empty($filters['year']) && !empty($filters['month'])) {
+            $filters['plan_date'] = $filters['year'] . '-' . str_pad($filters['month'], 2, '0', STR_PAD_LEFT) . '-01';
+            //var_dump($filters); die();
+            $service = new AutoPlannogrammaService();
+
+            //$goals = $service->calculateFullGoalChain($filters);
+            $monthCategoryShare = $service->getMonthCategoryShareOrWriteOff($filters['plan_date'], $filters);
+            $monthCategoryGoal = $service->getMonthCategoryGoal($monthCategoryShare, $filters['plan_date']);
+            $monthSubcategoryShare = $service->getMonthSubcategoryShareOrWriteOff($filters['plan_date'], $filters);
+            $monthSubcategoryGoal = $service->getMonthSubcategoryGoal($monthSubcategoryShare, $monthCategoryGoal);
+            $monthSpeciesShare = $service->getMonthSpeciesShareOrWriteOff($filters['plan_date'], $filters);
+            $goals = $service->getMonthSpeciesGoalDirty($monthSpeciesShare, $monthSubcategoryGoal);
+
+            if ($filters['type'] == AutoPlannogrammaService::TYPE_WRITE_OFFS) {
+                $monthCategoryWriteOffsShare = $service->getMonthCategoryShareOrWriteOff($filters['plan_date'], $filters, $filters['type']);
+                $monthCategoryWriteOffsGoal = $service->getMonthCategoryGoal($monthCategoryWriteOffsShare, $filters['plan_date'], $filters['type']);
+                $monthSubcategoryWriteOffsShare = $service->getMonthSubcategoryShareOrWriteOff($filters['plan_date'], $filters, $filters['type']);
+                $monthSubcategoryWriteOffsGoals = $service->getMonthSubcategoryGoal($monthSubcategoryWriteOffsShare, $monthCategoryWriteOffsGoal, $filters['type']);
+                $monthSpeciesWriteOffShare = $service->getMonthSpeciesShareOrWriteOff($filters['plan_date'], $filters, $filters['type']);
+                $goals = $service->getMonthSpeciesGoalDirty($monthSpeciesWriteOffShare, $monthSubcategoryWriteOffsGoals, $filters['type'], $data);
+            }
+
+
+            $result = StorePlanService::calculateHistoricalShare(
+                $filters['store_id'],
+                $filters['month'],
+                $filters['year'],
+                $filters['category'],
+                $filters['subcategory'],
+                $filters['species']
+            );
+
+            $noHistoryProductData = $service->calculateSpeciesForecastForProductsWithoutHistory($filters['plan_date'], $filters);
+
+            $productSalesShare = StorePlanService::calculateProductSalesShareProductsWithHistory(
+                $filters['store_id'],
+                $filters['month'],
+                $result['with_history']
+            );
+
+            $productSalesForecast = $service->calculateProductForecastInPiecesProductsWithHistory(
+                $filters['store_id'],
+                $filters['month'],
+                $filters['category'],
+                $filters['subcategory'],
+                $filters['species'],
+                $productSalesShare,
+                $goals
+            );
+
+            $matrixForecast = MatrixBouquetForecast::find()
+                ->where(['year' => $filters['year'], 'month' => $filters['month']])
+                ->asArray()
+                ->all();
+            $matrixGroups = array_unique(ArrayHelper::getColumn($matrixForecast, 'group'));
+            $bouquetForecast = StorePlanService::getBouquetSpiecesMonthGoalFromForecast($filters['month'], $filters['year'], $filters['store_id'], $matrixGroups);
+            $speciesData = $bouquetForecast['final'];
+            foreach ($speciesData as $store_id  => $categoryData) {
+                foreach ($categoryData as $category => $subcategoryData) {
+                    foreach ($subcategoryData as $subcategory => $species) {
+                        foreach ($species as $speciesInd => $row) {
+                            $bouquetSpeciesForecast[] = [
+                                'category' => $category,
+                                'subcategory' => $subcategory,
+                                'store_id' => $store_id,
+                                'species' => $speciesInd,
+                                'goal' => $row
+                            ];
+                        }
+                    }
+                }
+
+            }
+            $cleanedSpeciesGoals = $service->subtractSpeciesGoals($goals, $bouquetSpeciesForecast, $noHistoryProductData);
+
+
+            $salesProductForecastShare = $service->calculateProductForecastShare($noHistoryProductData, $productSalesForecast);
+
+             $productForecastSpecies = $service->calculateProductSalesBySpecies($salesProductForecastShare, $cleanedSpeciesGoals);
+
+            //var_dump($salesProductForecastShare); die();
+
+
+
+
+
+            $flatData = array_filter($productForecastSpecies, function ($row) use ($filters) {
+                foreach ($filters as $key => $value) {
+                    if (empty($value)) continue;
+                    if (!isset($row[$key])) continue;
+
+                    if (stripos((string)$row[$key], (string)$value) === false) {
+                        return false;
+                    }
+                }
+                return true;
+            });
+
+            $dataProvider = new ArrayDataProvider([
+                'allModels' => $flatData,
+                'pagination' => ['pageSize' => 100],
+            ]);
+        }
+        return $this->render('month-products-species-forecast', [
             'dataProvider' => $dataProvider,
             'filters' => $filters,
         ]);
@@ -857,7 +988,7 @@ class AutoPlannogrammaController extends BaseController
             }
             //var_dump($bouquetSpeciesForecast); die();
             $noHistoryProductData = $service->calculateSpeciesForecastForProductsWithoutHistory($filters['plan_date'], $filters);
-            //var_dump($noHistoryProductData); die();
+           // var_dump($noHistoryProductData); die();
             $cleanedSpeciesGoals = $service->subtractSpeciesGoals($data, $bouquetSpeciesForecast, $noHistoryProductData);
             //var_dump($cleanedSpeciesGoals); die();
 
index 2731cbd064f3755a8025e5960be170711c828557..fd5308b046bee927c453309c01b10f9f1259bd50 100644 (file)
@@ -573,7 +573,6 @@ class AutoPlannogrammaService
      */
     public function calculateSpeciesForecastForProductsWithoutHistory($dateFrom, $filters): array
     {
-        $t0 = hrtime(true);
         // Получение ID видимых магазинов
         $storeIds = array_map(fn($store) => $store->id, $this->getVisibleStores());
 
@@ -589,8 +588,7 @@ class AutoPlannogrammaService
         $year = $date->format('Y');
 
         $result = [];
-        $initTime = (hrtime(true) - $t0) / 1e6; // миллисекунды
-        Yii::warning( "Init (getVisibleStores + filters): {$initTime} ms\n");
+
         foreach ($storeIds as $storeId) {
             $t1 = hrtime(true);
             $histResult = StorePlanService::calculateHistoricalShare(
@@ -601,8 +599,6 @@ class AutoPlannogrammaService
                 $subcategory,
                 $species
             );
-            $dur = (hrtime(true) - $t1) / 1e6;
-            Yii::warning( "calculateHistoricalShare for store {$storeId}: {$dur} ms\n");
 
             $productsWithoutHistory = $histResult['without_history'] ?? [];
             if (empty($productsWithoutHistory)) {
@@ -610,33 +606,26 @@ class AutoPlannogrammaService
             }
 
             // ——————— WEIGHTED SALES ————————
-            $t2 = hrtime(true);
+
             $medianResults = StorePlanService::calculateMedianSalesForProductsWithoutHistoryExtended(
                 $storeId, $month, $year, $productsWithoutHistory
             );
-            $dur = (hrtime(true) - $t2) / 1e6;
-            Yii::warning("calculateMedianSalesForProductsWithoutHistory for store {$storeId}: {$dur} ms\n");
 
             if (empty($medianResults)) {
                 continue;
             }
 
             // ——————— COST CALCULATION ————————
-            $t3 = hrtime(true);
+
             $costs = StorePlanService::calculateCostForProductsWithoutHistory(
                 $storeId, $month, $year, $medianResults
             );
-            $dur = (hrtime(true) - $t3) / 1e6;
-            Yii::warning( "calculateCostForProductsWithoutHistory for store {$storeId}: {$dur} ms\n");
 
             if (!empty($costs)) {
                 $result = array_merge($result, $costs);
             }
         }
 
-        $totalTime = (hrtime(true) - $t0) / 1e6;
-        Yii::warning( "Total calculateSpeciesForecastForProductsWithoutHistory: {$totalTime} ms\n");
-
         return $result;
     }
 
index ccf53f78d5260f46a648d5243f802eac58bad513..5d3f38dd2da23f823b595be6dd588ecdefae234f 100755 (executable)
@@ -317,24 +317,13 @@ class StorePlanService
      *
      * @param int    $storeId
      * @param array  $periods     Массив периодов, сформированный функцией getPeriods.
-     * @param string $category
+     * @param string|null $category
      * @param string|null $subcategory
      * @param string|null $species
      *
-     * @return array Структура данных:
-     *      [
-     *          'product_guid1' => [
-     *              'YYYY-MM' => [
-     *                  0 => salesCount_week1,
-     *                  1 => salesCount_week2,
-     *                  ...
-     *              ],
-     *              ...
-     *          ],
-     *          ...
-     *      ]
+     * @return array
      */
-    private static function getSalesHistory($storeId, $periods, $category, $subcategory = null, $species = null)
+    private static function getSalesHistory($storeId, $periods, $category = null, $subcategory = null, $species = null)
     {
         $salesHistory = [];
 
@@ -349,34 +338,40 @@ class StorePlanService
                 $query = Sales::find()->alias('s')
                     ->select([
                         'p1c.id as product_guid',
-                        'COUNT(*) as sales_count'
+                        'COUNT(*) as sales_count',
+                        'p1c.category',
+                        'p1c.subcategory',
+                        'p1c.species',
                     ])
                     ->innerJoin('sales_products sp', 's.id = sp.check_id')
                     ->innerJoin('products_1c_nomenclature p1c', 'p1c.id = sp.product_id')
                     ->where(['s.store_id' => $storeId])
                     ->andWhere(['between', 's.date', $dateStart, $dateEnd])
                     ->andWhere(['order_id' => ['', '0']])
-                    ->andWhere(['p1c.category' => $category]);
-
-                if ($subcategory !== null) {
-                    $query->andWhere(['p1c.subcategory' => $subcategory]);
-                }
-                if ($species !== null) {
-                    $query->andWhere(['p1c.species' => $species]);
-                }
+                    ->andFilterWhere(['p1c.category'    => $category])
+                    ->andFilterWhere(['p1c.subcategory' => $subcategory])
+                    ->andFilterWhere(['p1c.species'     => $species])
+                    ->groupBy([
+                        'p1c.id',
+                        'p1c.category',
+                        'p1c.subcategory',
+                        'p1c.species',
+                    ]);
 
-                $query->groupBy('p1c.id');
                 $results = $query->asArray()->all();
+                foreach ($results as $row) {
+                    $guid = $row['product_guid'];
 
-                foreach ($results as $result) {
-                    $guid = $result['product_guid'];
                     if (!isset($salesHistory[$guid])) {
-                        $salesHistory[$guid] = [];
-                    }
-                    if (!isset($salesHistory[$guid][$periodKey])) {
-                        $salesHistory[$guid][$periodKey] = [];
+                        $salesHistory[$guid] = [
+                            'category'    => $row['category'],
+                            'subcategory' => $row['subcategory'],
+                            'species'     => $row['species'],
+                            'data'        => [],
+                        ];
                     }
-                    $salesHistory[$guid][$periodKey][$weekIndex] = (int)$result['sales_count'];
+
+                    $salesHistory[$guid]['data'][$periodKey][$weekIndex] = (int)$row['sales_count'];
                 }
             }
         }
@@ -397,33 +392,36 @@ class StorePlanService
      *         'without_history' => [...],
      * ]
      */
-    private static function analyzeHistory($salesHistory, $periods)
+    private static function analyzeHistory(array $salesHistory, array $periods)
     {
         $productsWithHistory    = [];
         $productsWithoutHistory = [];
 
-        foreach ($salesHistory as $guid => $monthsData) {
+        foreach ($salesHistory as $guid => $info) {
+            $monthsData    = $info['data'];
+            $metaFields    = [
+                'category'    => $info['category'],
+                'subcategory' => $info['subcategory'],
+                'species'     => $info['species'],
+            ];
             $hasHistoryInAllPeriods = true;
-            $weeklySalesData = [];
+            $weeklySalesData        = [];
 
             foreach ($periods as $periodKey => $periodData) {
                 $weeksCount = count($periodData['weeks']);
 
                 if (!isset($monthsData[$periodKey])) {
                     $hasHistoryInAllPeriods = false;
-                    // Заполняем пустыми значениями столько недель, сколько их есть в периоде.
                     $weekData = array_fill(0, $weeksCount, 0);
                 } else {
-                    $weekData = [];
+                    $weekData    = [];
                     $activeWeeks = 0;
 
-                    for ($weekIndex = 0; $weekIndex < $weeksCount; $weekIndex++) {
-                        $salesCount = isset($monthsData[$periodKey][$weekIndex]) ? $monthsData[$periodKey][$weekIndex] : 0;
-                        $weekData[$weekIndex] = $salesCount;
-                        if ($weekIndex == 4) {
-                            continue; //пропускаем 5 неполную неделю в учете активных продаж
-                        }
-                        if ($salesCount > 0) {
+                    for ($i = 0; $i < $weeksCount; $i++) {
+                        $count = $monthsData[$periodKey][$i] ?? 0;
+                        $weekData[$i] = $count;
+
+                        if ($i < 4 && $count > 0) {
                             $activeWeeks++;
                         }
                     }
@@ -432,18 +430,20 @@ class StorePlanService
                         $hasHistoryInAllPeriods = false;
                     }
                 }
+
                 $weeklySalesData[$periodKey] = $weekData;
             }
 
-            $productData = [
-                'guid'         => $guid,
-                'weekly_sales' => $weeklySalesData,
-            ];
+            $item = array_merge(
+                ['guid' => $guid],
+                $metaFields,
+                ['weekly_sales' => $weeklySalesData]
+            );
 
             if ($hasHistoryInAllPeriods) {
-                $productsWithHistory[] = $productData;
+                $productsWithHistory[] = $item;
             } else {
-                $productsWithoutHistory[] = $productData;
+                $productsWithoutHistory[] = $item;
             }
         }
 
@@ -454,6 +454,7 @@ class StorePlanService
     }
 
 
+
     /**
      * Метод вычисляет значение продаж для товаров без истории.
      *
@@ -470,48 +471,43 @@ class StorePlanService
      */
     public static function calculateMedianSalesForProductsWithoutHistoryExtended($storeId, $selectedMonth, $selectedYear, $productsWithoutHistory)
     {
-        $t0 = hrtime(true);
         $targetDate = strtotime("{$selectedYear}-{$selectedMonth}-01");
         $periods = self::getPeriods($targetDate, 3);
 
         $medianSalesResults = [];
-        $initTime = (hrtime(true) - $t0) / 1e6; // миллисекунды
-        Yii::warning( "Init (periods): {$initTime} ms\n");
+
         foreach ($productsWithoutHistory as $product) {
             $guid = $product['guid'];
-            $t1 = hrtime(true);
+
+
             $similarProductIds = self::getSimilarProductIDs($guid);
             if (empty($similarProductIds)) {
                 $medianSalesResults[$guid] = 0;
                 continue;
             }
-            $dur = (hrtime(true) - $t1) / 1e6;
-            Yii::warning( "getSimilarProductIDs for product {$guid} {$storeId}: {$dur} ms\n");
+
             $medianSales = [];
             $salesValuesForEachMonth = [];
-            $t2 = hrtime(true);
+
             foreach ($periods as $periodKey => $monthInfo) {
                 list($median, $salesValues) = self::calculateMedianSalesForPeriod($storeId, $similarProductIds, $monthInfo);
                 $medianSales[$periodKey]             = $median;
                 $salesValuesForEachMonth[$periodKey]   = $salesValues;
             }
-            $dur = (hrtime(true) - $t2) / 1e6;
-            Yii::warning("calculateMedianSalesForPeriod  for product {$guid} {$storeId}: {$dur} ms\n");
 
-            $t3 = hrtime(true);
             $median3 = self::calculateMedianSalesOverPeriods($storeId, $similarProductIds, $periods);
 
             $medianSalesResults[$guid] = [
+                'store_id' => $storeId,
+                'category'    => $product['category'],
+                'subcategory' => $product['subcategory'],
+                'species'     => $product['species'],
                 'weightedValue' => $median3,
                 'medianSales'   => $medianSales,
                 'salesValues'   => $salesValuesForEachMonth,
             ];
-            $dur = (hrtime(true) - $t3) / 1e6;
-            Yii::warning( "computeWeightedValue for product {$guid} {$storeId}: {$dur} ms\n");
-        }
 
-        $totalTime = (hrtime(true) - $t0) / 1e6;
-        Yii::warning( "Total  calculateWeightedSalesForProductsWithoutHistory: {$totalTime} ms\n");
+        }
 
         return $medianSalesResults;
     }
@@ -683,8 +679,8 @@ class StorePlanService
         $guidToGroup   = [];
 
 
-        foreach ($medianProductsWithoutHistory as $guid => $qty) {
-            $q = (float)$qty;
+        foreach ($medianProductsWithoutHistory as $guid => $data) {
+            $q = (float)$data['weightedValue'];
             if ($q <= 0) continue;
 
             $price = self::getPriceForProductAtOffsetMonthWeekly(
@@ -692,10 +688,9 @@ class StorePlanService
             );
             $prices[$guid] = $price;
 
-            $nom = Products1cNomenclature::findOne($guid);
-            $cat = $nom->category    ?? '';
-            $sub = $nom->subcategory ?? '';
-            $sp  = $nom->species     ?? '';
+            $cat = $data['category'];
+            $sub = $data['subcategory'];
+            $sp  = $data['species'];
             $groupKey = implode('|', [$cat,$sub,$sp]);
             $guidToGroup[$guid] = $groupKey;
 
diff --git a/erp24/views/auto-plannogramma/81.php b/erp24/views/auto-plannogramma/81.php
deleted file mode 100644 (file)
index 36934c0..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-?>
-    <div class="filter-form" style="margin-bottom: 20px;">
-        <?php use kartik\date\DatePicker;
-        use kartik\grid\GridView;
-        use kartik\select2\Select2;
-        use yii\helpers\ArrayHelper;
-        use yii\helpers\Html;
-        use yii\widgets\ActiveForm;
-        use yii_app\records\CityStore;
-        use yii_app\records\Products1cNomenclature;
-        ?>
-        <h1 class="ms-3 mb-4"><?= Html::encode("Расчет доли товара от общего количества внутри вида (month_goods_sales_share)") ?></h1>
-        <?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(['species' => $filters['species'] ?? '']), 'species')->widget(Select2::class, [
-                    'data' => ArrayHelper::map(
-                        Products1cNomenclature::find()->select('species')->distinct()->asArray()->all(),
-                        'species',
-                        'species'
-                    ),
-                    'options' => ['placeholder' => 'Тип товара', 'name' => 'species'],
-                    '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(['month' => $filters['month'] ?? '']), 'month')->dropDownList(\yii_app\helpers\DateHelper::MONTH_NUMBER_NAMES, [
-                    'prompt' => 'Месяц',
-                    'name' => 'month',
-                ])->label('Плановый месяц') ?>
-            </div>
-
-            <div class="col-md">
-                <?= $form->field(new \yii\base\DynamicModel(['year' => $filters['year'] ?? '']), 'year')->dropDownList(['2025' => 2025, '2026' => 2026], [
-                    'prompt' => 'Год',
-                    'name' => 'year',
-                ])->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-plannogramma/8'], ['class' => 'btn btn-default']) ?>
-            </div>
-        </div>
-
-        <?php ActiveForm::end(); ?>
-    </div>
-
-
-
-<?php
-$columns = [
-    ['attribute' => 'store_id', 'label' => 'Магазин', 'value' => function ($data) {
-        return CityStore::findOne($data['store_id'])->name ?? null;
-    }],
-    ['attribute' => 'category', 'label' => 'Категория'],
-    ['attribute' => 'subcategory', 'label' => 'Подкатегория'],
-    ['attribute' => 'species', 'label' => 'Тип'],
-    ['attribute' => 'product_id', 'label' => 'GUID Товара', ],
-    ['attribute' => 'product_id', 'label' => 'Имя Товара',
-        'value' => function ($data) {
-            return \yii_app\records\Products1c::findOne($data['product_id'])->name ?? null;
-        },
-        ],
-    ['attribute' => 'forecast_pieces', 'label' => 'Прогноз в шт', 'format' => ['decimal', 2]],
-    ['attribute' => 'share', 'label' => 'Доля',
-
-        'format' => ['percent', 2]],
-
-    ['attribute' => 'history_status', 'label' => 'Статус товара', ],
-];
-
-
-?>
-<?= GridView::widget([
-    'dataProvider' => $dataProvider,
-    'columns' => $columns,
-]); ?>
-<?php
diff --git a/erp24/views/auto-plannogramma/82.php b/erp24/views/auto-plannogramma/82.php
deleted file mode 100644 (file)
index 6ccb744..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-?>
-    <div class="filter-form" style="margin-bottom: 20px;">
-        <?php use kartik\date\DatePicker;
-        use kartik\grid\GridView;
-        use kartik\select2\Select2;
-        use yii\helpers\ArrayHelper;
-        use yii\helpers\Html;
-        use yii\widgets\ActiveForm;
-        use yii_app\records\CityStore;
-        use yii_app\records\Products1cNomenclature;
-        ?>
-        <h1 class="ms-3 mb-4"><?= Html::encode("Расчет доли товара от общего количества внутри вида (month_goods_sales_share)") ?></h1>
-        <?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(['species' => $filters['species'] ?? '']), 'species')->widget(Select2::class, [
-                    'data' => ArrayHelper::map(
-                        Products1cNomenclature::find()->select('species')->distinct()->asArray()->all(),
-                        'species',
-                        'species'
-                    ),
-                    'options' => ['placeholder' => 'Тип товара', 'name' => 'species'],
-                    '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(['month' => $filters['month'] ?? '']), 'month')->dropDownList(\yii_app\helpers\DateHelper::MONTH_NUMBER_NAMES, [
-                    'prompt' => 'Месяц',
-                    'name' => 'month',
-                ])->label('Плановый месяц') ?>
-            </div>
-
-            <div class="col-md">
-                <?= $form->field(new \yii\base\DynamicModel(['year' => $filters['year'] ?? '']), 'year')->dropDownList(['2025' => 2025, '2026' => 2026], [
-                    'prompt' => 'Год',
-                    'name' => 'year',
-                ])->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-plannogramma/8'], ['class' => 'btn btn-default']) ?>
-            </div>
-        </div>
-
-        <?php ActiveForm::end(); ?>
-    </div>
-
-
-
-<?php
-$columns = [
-    ['attribute' => 'store_id', 'label' => 'Магазин', 'value' => function ($data) {
-        return CityStore::findOne($data['store_id'])->name ?? null;
-    }],
-    ['attribute' => 'category', 'label' => 'Категория'],
-    ['attribute' => 'subcategory', 'label' => 'Подкатегория'],
-    ['attribute' => 'species', 'label' => 'Тип'],
-    ['attribute' => 'product_id', 'label' => 'GUID Товара', ],
-    ['attribute' => 'product_id', 'label' => 'Имя Товара',
-        'value' => function ($data) {
-            return \yii_app\records\Products1c::findOne($data['product_id'])->name ?? null;
-        },
-        ],
-    ['attribute' => 'forecast_pieces', 'label' => 'Прогноз в шт', 'format' => ['decimal', 2]],
-    ['attribute' => 'share', 'label' => 'Доля',
-
-        'format' => ['percent', 2]],
-    ['attribute' => 'cleanGoal', 'label' => 'Цель вида очищенная', 'format' => ['decimal', 2]],
-    ['attribute' => 'product_sales', 'label' => 'Прогноз в стоимости внутри вида', 'format' => ['decimal', 2]],
-    ['attribute' => 'history_status', 'label' => 'Статус товара', ],
-];
-
-
-?>
-<?= GridView::widget([
-    'dataProvider' => $dataProvider,
-    'columns' => $columns,
-]); ?>
-<?php
diff --git a/erp24/views/auto-plannogramma/month-products-species-forecast.php b/erp24/views/auto-plannogramma/month-products-species-forecast.php
new file mode 100644 (file)
index 0000000..ae4969b
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+?>
+    <div class="filter-form" style="margin-bottom: 20px;">
+        <?php use kartik\date\DatePicker;
+        use kartik\grid\GridView;
+        use kartik\select2\Select2;
+        use yii\helpers\ArrayHelper;
+        use yii\helpers\Html;
+        use yii\widgets\ActiveForm;
+        use yii_app\records\CityStore;
+        use yii_app\records\Products1cNomenclature;
+        ?>
+        <h1 class="ms-3 mb-4"><?= Html::encode("Расчет прогноза товаров внутри вида (month_goods_sales_share)") ?></h1>
+        <?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(['species' => $filters['species'] ?? '']), 'species')->widget(Select2::class, [
+                    'data' => ArrayHelper::map(
+                        Products1cNomenclature::find()->select('species')->distinct()->asArray()->all(),
+                        'species',
+                        'species'
+                    ),
+                    'options' => ['placeholder' => 'Тип товара', 'name' => 'species'],
+                    '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(['month' => $filters['month'] ?? '']), 'month')->dropDownList(\yii_app\helpers\DateHelper::MONTH_NUMBER_NAMES, [
+                    'prompt' => 'Месяц',
+                    'name' => 'month',
+                ])->label('Плановый месяц') ?>
+            </div>
+
+            <div class="col-md">
+                <?= $form->field(new \yii\base\DynamicModel(['year' => $filters['year'] ?? '']), 'year')->dropDownList(['2025' => 2025, '2026' => 2026], [
+                    'prompt' => 'Год',
+                    'name' => 'year',
+                ])->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-plannogramma/8'], ['class' => 'btn btn-default']) ?>
+            </div>
+        </div>
+
+        <?php ActiveForm::end(); ?>
+    </div>
+
+
+
+<?php
+$columns = [
+    ['attribute' => 'store_id', 'label' => 'Магазин', 'value' => function ($data) {
+        return CityStore::findOne($data['store_id'])->name ?? null;
+    }],
+    ['attribute' => 'category', 'label' => 'Категория'],
+    ['attribute' => 'subcategory', 'label' => 'Подкатегория'],
+    ['attribute' => 'species', 'label' => 'Тип'],
+    ['attribute' => 'product_id', 'label' => 'GUID Товара', ],
+    ['attribute' => 'product_id', 'label' => 'Имя Товара',
+        'value' => function ($data) {
+            return \yii_app\records\Products1c::findOne($data['product_id'])->name ?? null;
+        },
+        ],
+    ['attribute' => 'forecast_pieces', 'label' => 'Прогноз в шт', 'format' => ['decimal', 2]],
+    ['attribute' => 'share', 'label' => 'Доля',
+
+        'format' => ['percent', 2]],
+    ['attribute' => 'cleanGoal', 'label' => 'Цель вида очищенная', 'format' => ['decimal', 2]],
+    ['attribute' => 'product_sales', 'label' => 'Прогноз в стоимости внутри вида', 'format' => ['decimal', 2]],
+    ['attribute' => 'history_status', 'label' => 'Статус товара', ],
+];
+
+
+?>
+<?= GridView::widget([
+    'dataProvider' => $dataProvider,
+    'columns' => $columns,
+]); ?>
+<?php
diff --git a/erp24/views/auto-plannogramma/month-products-species-share.php b/erp24/views/auto-plannogramma/month-products-species-share.php
new file mode 100644 (file)
index 0000000..36934c0
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+?>
+    <div class="filter-form" style="margin-bottom: 20px;">
+        <?php use kartik\date\DatePicker;
+        use kartik\grid\GridView;
+        use kartik\select2\Select2;
+        use yii\helpers\ArrayHelper;
+        use yii\helpers\Html;
+        use yii\widgets\ActiveForm;
+        use yii_app\records\CityStore;
+        use yii_app\records\Products1cNomenclature;
+        ?>
+        <h1 class="ms-3 mb-4"><?= Html::encode("Расчет доли товара от общего количества внутри вида (month_goods_sales_share)") ?></h1>
+        <?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(['species' => $filters['species'] ?? '']), 'species')->widget(Select2::class, [
+                    'data' => ArrayHelper::map(
+                        Products1cNomenclature::find()->select('species')->distinct()->asArray()->all(),
+                        'species',
+                        'species'
+                    ),
+                    'options' => ['placeholder' => 'Тип товара', 'name' => 'species'],
+                    '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(['month' => $filters['month'] ?? '']), 'month')->dropDownList(\yii_app\helpers\DateHelper::MONTH_NUMBER_NAMES, [
+                    'prompt' => 'Месяц',
+                    'name' => 'month',
+                ])->label('Плановый месяц') ?>
+            </div>
+
+            <div class="col-md">
+                <?= $form->field(new \yii\base\DynamicModel(['year' => $filters['year'] ?? '']), 'year')->dropDownList(['2025' => 2025, '2026' => 2026], [
+                    'prompt' => 'Год',
+                    'name' => 'year',
+                ])->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-plannogramma/8'], ['class' => 'btn btn-default']) ?>
+            </div>
+        </div>
+
+        <?php ActiveForm::end(); ?>
+    </div>
+
+
+
+<?php
+$columns = [
+    ['attribute' => 'store_id', 'label' => 'Магазин', 'value' => function ($data) {
+        return CityStore::findOne($data['store_id'])->name ?? null;
+    }],
+    ['attribute' => 'category', 'label' => 'Категория'],
+    ['attribute' => 'subcategory', 'label' => 'Подкатегория'],
+    ['attribute' => 'species', 'label' => 'Тип'],
+    ['attribute' => 'product_id', 'label' => 'GUID Товара', ],
+    ['attribute' => 'product_id', 'label' => 'Имя Товара',
+        'value' => function ($data) {
+            return \yii_app\records\Products1c::findOne($data['product_id'])->name ?? null;
+        },
+        ],
+    ['attribute' => 'forecast_pieces', 'label' => 'Прогноз в шт', 'format' => ['decimal', 2]],
+    ['attribute' => 'share', 'label' => 'Доля',
+
+        'format' => ['percent', 2]],
+
+    ['attribute' => 'history_status', 'label' => 'Статус товара', ],
+];
+
+
+?>
+<?= GridView::widget([
+    'dataProvider' => $dataProvider,
+    'columns' => $columns,
+]); ?>
+<?php