]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
метод прогноза списаний
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 17 Jun 2025 10:33:01 +0000 (13:33 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Tue, 17 Jun 2025 10:33:01 +0000 (13:33 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/services/AutoPlannogrammaService.php

index 20066d0f6944a86373983736ab1aff542c57a985..5a39e992dd0d469b4fb5570d8d2ea2a9d6d07299 100644 (file)
@@ -14,6 +14,7 @@ use yii_app\records\MatrixBouquetForecast;
 use yii_app\records\PricesDynamic;
 use yii_app\records\Products1c;
 use yii_app\records\Products1cNomenclature;
+use yii_app\records\SalesWriteOffsPlan;
 use yii_app\services\AutoPlannogrammaService;
 use yii_app\services\StorePlanService;
 
@@ -1750,7 +1751,7 @@ class AutoPlannogrammaController extends BaseController
         Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
 
         $request = Yii::$app->request;
-        $storeIdRequest = $request->get('storeId');
+        $storeIdRequest = $request->get('storeId', null);
         $monthRequest   = $request->get('month');
         $yearRequest    = $request->get('year');
         $weekRequest    = $request->get('week');
@@ -1760,13 +1761,32 @@ class AutoPlannogrammaController extends BaseController
         }
 
         $service = new AutoPlannogrammaService();
-        $result = $service->getWeeklyBouquetProductsForecast($monthRequest, $yearRequest, $storeIdRequest);
-
+        //$result = $service->getWeeklyBouquetProductsForecast($monthRequest, $yearRequest, $storeIdRequest);
+        $writeOffs = $service->getWeeklyProductsWriteoffsForecast($monthRequest, $yearRequest, $storeIdRequest);
+        var_dump($writeOffs); die();
         if (!is_array($result)) {
             return ['success' => false, 'message' => 'Ошибка структуры данных'];
         }
 
         $grouped = [];
+        $salesShares = [];
+
+        $plans = SalesWriteOffsPlan::find()
+            ->where(['month' => $monthRequest, 'year' => $yearRequest])
+            ->indexBy('store_id')
+            ->asArray()
+            ->all();
+        if ($plans) {
+            foreach ($plans as $storeId => $plan) {
+                $total = $plan['total_sales_plan'];
+                $offline = $plan['offline_sales_plan'];
+                $online = $plan['online_sales_shop_plan'];
+                $market = $plan['online_sales_marketplace_plan'];
+                $salesShares[$storeId]['offline'] = round($offline / $total, 4);
+                $salesShares[$storeId]['online'] = round($online / $total, 4);
+                $salesShares[$storeId]['marketplace'] = round($market / $total, 4);
+            }
+        }
 
         foreach ($result as $item) {
             $weekItem = (int) $item['week'];
@@ -1775,6 +1795,9 @@ class AutoPlannogrammaController extends BaseController
             $group = (string) $item['matrix_group'];
             $type = (string) $item['type'];
             $forecastValue = (float) $item['week_forecast'];
+            if (isset($salesShares[$storeItem]) && isset($salesShares[$storeItem][$type])) {
+                $grouped[$weekItem][$storeItem][$type]['share'] = $salesShares[$storeItem][$type];
+            }
 
             $grouped[$weekItem][$storeItem][$guid][$type][$group] = $forecastValue;
         }
index 15d9c773fd2fe2d40d1f563fc2e82a71234c9551..4587c0b1807c4b5fbc72249a609edb48ff169a34 100644 (file)
@@ -2786,7 +2786,7 @@ class AutoPlannogrammaService
         return $pricesMap;
     }
 
-    public function getWeeklyBouquetProductsForecast($month, $year, $storeId)
+   /* public function getWeeklyBouquetProductsForecast($month, $year, $storeId)
     {
         $matrixGroups = ArrayHelper::map(
             MatrixBouquetForecast::find()->select(['group'])->distinct()->asArray()->all(),
@@ -2841,6 +2841,145 @@ class AutoPlannogrammaService
         }
         return $weeklyForecasts;
 
+    }*/
+
+    public function getWeeklyBouquetProductsForecast($month, $year, $storeId = null, $weekNumber = null)
+    {
+        $matrixGroups = ArrayHelper::map(
+            MatrixBouquetForecast::find()->select(['group'])->distinct()->asArray()->all(),
+            'group',
+            'group'
+        );
+
+        $date = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01';
+
+        $result = StorePlanService::getBouquetSpiecesMonthGoalFromForecast($month, $year, $storeId, $matrixGroups);
+        $weekShares = $this->getHistoricalSpeciesShareByWeek($date);
+        $flatData = $result['flatData'];
+
+        $weekIndex = [];
+        foreach ($weekShares as $shareRow) {
+            $key = implode('|', [
+                $shareRow['store_id'],
+                $shareRow['category'],
+                $shareRow['subcategory'],
+                $shareRow['species'],
+            ]);
+            $weekIndex[$key][] = $shareRow;
+        }
+
+        $weeklyForecasts = [];
+
+        foreach ($flatData as $item) {
+            $key = implode('|', [
+                $item['store_id'],
+                $item['category'],
+                $item['subcategory'],
+                $item['species'],
+            ]);
+
+            if (!isset($weekIndex[$key])) {
+                continue;
+            }
+
+            foreach ($weekIndex[$key] as $weekShare) {
+                if ($weekNumber !== null && (int)$weekShare['week'] !== (int)$weekNumber) {
+                    continue; // фильтрация по неделе
+                }
+
+                $weeklyForecasts[] = [
+                    'store_id' => $item['store_id'],
+                    'category' => $item['category'],
+                    'subcategory' => $item['subcategory'],
+                    'species' => $item['species'],
+                    'type' => $item['type'],
+                    'product_guid' => $item['product_guid'],
+                    'week_forecast' => round($item['full_forecast'] * $weekShare['share'], 2),
+                    'full_forecast' => $item['full_forecast'],
+                    'week' => $weekShare['week'],
+                    'matrix_group' => $item['matrix_group'],
+                    'month' => $item['month'],
+                    'year' => $item['year'],
+                ];
+            }
+        }
+
+        $grouped = [];
+        $salesShares = [];
+
+        $plans = SalesWriteOffsPlan::find()
+            ->where(['month' => $month, 'year' => $year])
+            ->indexBy('store_id')
+            ->asArray()
+            ->all();
+        if ($plans) {
+            foreach ($plans as $storeId => $plan) {
+                $total = $plan['total_sales_plan'];
+                $offline = $plan['offline_sales_plan'];
+                $online = $plan['online_sales_shop_plan'];
+                $market = $plan['online_sales_marketplace_plan'];
+                $salesShares[$storeId]['offline'] = round($offline / $total, 4);
+                $salesShares[$storeId]['online'] = round($online / $total, 4);
+                $salesShares[$storeId]['marketplace'] = round($market / $total, 4);
+            }
+        }
+        foreach ($weeklyForecasts as $item) {
+            $storeItem = (int)$item['store_id'];
+            $guid = (string)$item['product_guid'];
+            $group = (string)$item['matrix_group'];
+            $type = (string)$item['type'];
+            $forecastValue = (float)$item['week_forecast'];
+            if (isset($salesShares[$storeItem]) && isset($salesShares[$storeItem][$type])) {
+                $grouped[$storeItem][$type]['share'] = $salesShares[$storeItem][$type];
+            }
+            $grouped[$storeItem][$guid][$type][$group] = $forecastValue;
+        }
+
+        return $grouped;
+    }
+
+    public function getWeeklyProductsWriteoffsForecast($month, $year, $storeId = null, $weekNumber = null)
+    {
+        $weeksProductForecast = [];
+        $filters = [];
+
+        $dateFrom = date("Y-m-d 00:00:00", strtotime(sprintf('%04d-%02d-01', $year, $month)));
+        $monthYear = date("m-Y", strtotime($dateFrom));
+        $filters['store_id'] = $storeId;
+        $filters['type'] = self::TYPE_WRITE_OFFS;
+        $filters['plan_date'] = $dateFrom;
+
+        $monthSpeciesGoals = $this->calculateFullGoalChain($filters);
+        $monthSpeciesGoalsMap = [];
+        foreach ($monthSpeciesGoals as $monthSpeciesGoal) {
+            $monthSpeciesGoalsMap[$monthSpeciesGoal['store_id']]
+            [$monthSpeciesGoal['category']]
+            [$monthSpeciesGoal['subcategory']]
+            [$monthSpeciesGoal['species']] = $monthSpeciesGoal['goal'];
+        }
+
+        $weeksShareResult = $this->getHistoricalWeeklySpeciesShare($monthYear, $filters, null, 'writeOffs');
+        $weeksData = $this->calculateWeeklySpeciesGoals($weeksShareResult, $monthSpeciesGoals);
+
+        foreach ($weeksData as $r) {
+            $forecasts = $this->calculateWeekForecastSpeciesProducts($r['category'], $r['subcategory'], $r['species'], $r['store_id'], $r['weekly_goal']);
+
+            foreach ($forecasts as $forecast) {
+                $weeksProductForecast[] = [
+                    'category' => $forecast['category'] ?? '',
+                    'subcategory' => $forecast['subcategory'] ?? '',
+                    'species' => $forecast['species'] ?? '',
+                    'product_id' => $forecast['product_id'] ?? '',
+                    'name' => $forecast['name'] ?? '',
+                    'price' => $forecast['price'] ?? '',
+                    'goal' => $forecast['goal'] ?? 0,
+                    'forecast' => $forecast['forecast'] ?? 0,
+                    'week' => $r['week'],
+                ];
+            }
+        }
+
+        return $weeksProductForecast;
     }
 
 }
\ No newline at end of file