]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
9 шаг
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 21 May 2025 07:55:12 +0000 (10:55 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Wed, 21 May 2025 07:55:12 +0000 (10:55 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/services/AutoPlannogrammaService.php
erp24/services/StorePlanService.php
erp24/views/auto-plannogramma/9.php [new file with mode: 0644]

index c96a8fa1fa71ecf5636e3ae32666d36618816388..e6410cdb1aaaae2750e493a1ef83dd2476bbdb17 100644 (file)
@@ -568,14 +568,21 @@ class AutoPlannogrammaController extends BaseController
             $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  => $species) {
-                foreach ($species as $specieInd => $row) {
-                    $bouquetSpeciesForecast[] = [
-                        'store_id' => $store_id,
-                        'species' => $specieInd,
-                        'goal' => $row
-                        ];
+            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
+                            ];
+                        }
+                    }
                 }
+
             }
             //var_dump($matrixGroups); die();
             $flatData = array_filter($bouquetSpeciesForecast, function ($row) use ($filters) {
@@ -652,4 +659,99 @@ class AutoPlannogrammaController extends BaseController
             'filters' => $filters,
         ]);
     }
+
+
+    public function action9()
+    {
+        $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();
+            $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);
+            $data = $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']);
+                $data = $service->getMonthSpeciesGoalDirty($monthSpeciesWriteOffShare, $monthSubcategoryWriteOffsGoals, $filters['type'], $data);
+            }
+
+            //var_dump($data); die();
+            $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
+                            ];
+                        }
+                    }
+                }
+
+            }
+            //var_dump($bouquetSpeciesForecast); die();
+            $noHistoryProductData = $service->calculateSpeciesForecastForProductsWithoutHistory($filters['plan_date'], $filters);
+            var_dump($noHistoryProductData); die();
+            $cleanedSpeciesGoals = $service->subtractSpeciesGoals($data, $bouquetSpeciesForecast, $noHistoryProductData);
+
+
+            $flatData = array_filter($cleanedSpeciesGoals, 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('9', [
+            'dataProvider' => $dataProvider,
+            'filters' => $filters,
+        ]);
+    }
 }
index 28709a9ecb34fcd220555bf1011d9730423456d5..e41516a55a936caba330782319a9a43d85fd7777 100644 (file)
@@ -621,5 +621,44 @@ class AutoPlannogrammaService
         return $result;
     }
 
+    public function mapGoalsBySpecies(array $rows): array {
+        $mapped = [];
+        foreach ($rows as $row) {
+            $mapped[$row['store_id']][$row['category']][$row['subcategory']][$row['species']] = $row['goal'];
+        }
+        return $mapped;
+    }
+
+    public function subtractSpeciesGoals(array $data, array $forecast, array $noHistory): array {
+        $forecastMap = $this->mapGoalsBySpecies($forecast);
+        $noHistoryMap = $this->mapGoalsBySpecies($noHistory);
+        $result = [];
+
+        foreach ($data as $row) {
+            $storeId = $row['store_id'];
+            $category = $row['category'];
+            $subcategory = $row['subcategory'];
+            $species = $row['species'];
+            $originalGoal = $row['goal'];
+
+            $forecastGoal = $forecastMap[$storeId][$category][$subcategory][$species] ?? 0;
+            $noHistoryGoal = $noHistoryMap[$storeId][$category][$subcategory][$species] ?? 0;
+
+            $cleanGoal = $originalGoal - $forecastGoal - $noHistoryGoal;
+
+
+            $result[] = [
+                'store_id' => $storeId,
+                'category' => $category,
+                'subcategory' => $subcategory,
+                'species' => $species,
+                'goal' => $cleanGoal
+            ];
+        }
+
+        return $result;
+    }
+
+
 
 }
\ No newline at end of file
index fad3130d600b1caf26e671251fa1ad90be066b90..e505ea5c2b52f5c14a2f4745c6acfbb74a28b631 100755 (executable)
@@ -1122,7 +1122,7 @@ class StorePlanService
                 }
             }
             $speciesCache = Products1cNomenclature::find()
-                ->select(['id', 'species'])
+                ->select(['id', 'species', 'category', 'subcategory'])
                 ->where(['id' => array_unique($allComponentGuids)])
                 ->indexBy('id')->asArray()->all();
             foreach ($forecasts as $forecast) {
@@ -1168,11 +1168,13 @@ class StorePlanService
                         foreach ($products as $product) {
                             $guid = $product['product_guid'];
                             $species = $speciesCache[$guid]['species'] ?? 'Неизвестно';
+                            $category = $speciesCache[$guid]['category'] ?? 'Неизвестно';
+                            $subcategory = $speciesCache[$guid]['subcategory'] ?? 'Неизвестно';
                             $price = $priceCache[$regionId][$guid] ?? 0;
                             $raw = $price * $product['count'] * $typeSalesValue;
                             $cost = round($raw * BouquetCompositionPrice::SURCHARGE_ASSEMBLY, 2);
 
-                            $resultData[$sid][$species][$typeSales] = ($resultData[$sid][$species][$typeSales] ?? 0) + $cost;
+                            $resultData[$sid][$category][$subcategory][$species][$typeSales] = ($resultData[$sid][$category][$subcategory][$species][$typeSales] ?? 0) + $cost;
                             $detailData[$sid][$species][$typeSales][] = [
                                 'product_guid' => $guid,
                                 'price' => $price,
@@ -1189,10 +1191,15 @@ class StorePlanService
         }
 
         $finalResult = [];
-        foreach ($resultData as $storeId => $speciesData) {
-            foreach ($speciesData as $species => $salesData) {
-                $finalResult[$storeId][$species] = round(array_sum($salesData), 2);
+        foreach ($resultData as $storeId => $categoryData) {
+            foreach ($categoryData as $category => $subcategoryData) {
+                foreach ($subcategoryData as $subcategory => $speciesData) {
+                    foreach ($speciesData as $species => $salesData) {
+                        $finalResult[$storeId][$category][$subcategory][$species] = round(array_sum($salesData), 2);
+                    }
+                }
             }
+
         }
         return [
             'detail' => $resultData,
diff --git a/erp24/views/auto-plannogramma/9.php b/erp24/views/auto-plannogramma/9.php
new file mode 100644 (file)
index 0000000..620d819
--- /dev/null
@@ -0,0 +1,114 @@
+<?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_cleared_goal)") ?></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' => 'goal', 'label' => 'Сумма', 'format' => ['decimal', 2]],
+];
+
+
+?>
+<?= GridView::widget([
+    'dataProvider' => $dataProvider,
+    'columns' => $columns,
+]); ?>
+<?php