]> gitweb.erp-flowers.ru Git - erp24_rep/yii-erp24/.git/commitdiff
Контроль
authorVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 26 Sep 2025 06:34:12 +0000 (09:34 +0300)
committerVladimir Fomichev <vladimir.fomichev@erp-flowers.ru>
Fri, 26 Sep 2025 06:34:12 +0000 (09:34 +0300)
erp24/controllers/AutoPlannogrammaController.php
erp24/services/AutoPlannogrammaService.php
erp24/services/StorePlanService.php

index 8b8bd5f94c273eeb2ddef4960e2c7f25767e1eb2..80caaa428bc6da617d498eca48532f17ee8d83fd 100644 (file)
@@ -1367,9 +1367,21 @@ class AutoPlannogrammaController extends BaseController
             $service = new AutoPlannogrammaService();
             //$goals = $service->calculateFullGoalChain($filters);
             //$forecast = $service->calculateFullForecastForWeek($filters);
+            //$noHistoryProductData = $service->calculateSpeciesForecastForProductsWithoutHistory($filters['plan_date'], $filters);
+
+            $historyProductData = $service->calculateSpeciesForecastForProductsWithHistory($filters['plan_date'], $filters, []);
+            var_dump($historyProductData); die();
+            $salesProductForecastShare = $service->calculateProductForecastShare($noHistoryProductData, $historyProductData);
+
+            $productForecastSpecies = $service->calculateProductSalesBySpecies($salesProductForecastShare, $cleanedSpeciesGoals);
+
+
             $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);
@@ -1439,7 +1451,7 @@ class AutoPlannogrammaController extends BaseController
             $cleanedSpeciesGoals = $service->subtractSpeciesGoals($goals, [], []);
 
             $salesProductForecastShare = $service->calculateProductForecastShare($noHistoryProductData, $historyProductData);
-
+            var_dump($salesProductForecastShare); die();
             $productForecastSpecies = $service->calculateProductSalesBySpecies($salesProductForecastShare, $cleanedSpeciesGoals);
 
             $weeklySales = $service->getHistoricalSpeciesShareByWeek($filters['plan_date'], $filters);
@@ -1978,7 +1990,7 @@ class AutoPlannogrammaController extends BaseController
 
 
             $salesProductForecastShare = $service->calculateProductForecastShare($noHistoryProductData, $productSalesForecast);
-
+            var_dump($salesProductForecastShare);die();
             $productForecastSpecies = $service->calculateProductSalesBySpecies($salesProductForecastShare, $cleanedSpeciesGoals);
 
 
index ed8720162bad928c56615cc8bf963bd527ee6a44..2767dc9f64ad1edad43578bd01c6060bcf3d27bb 100644 (file)
@@ -373,7 +373,7 @@ class AutoPlannogrammaService
                 'subcategory' => 'main.subcategory',
                 'total_sum' => 'main.total_sum',
                 'percent' => new Expression('ROUND(CAST(main.total_sum AS DECIMAL) / NULLIF(totals.total, 0), 4)'),
-                'type' => new Expression(':type', ['type' => $type]),
+                'type' => new Expression(':type', [':type' => $type]),
                 'totals_total' => 'totals.total',
             ])
             ->from([
@@ -429,41 +429,64 @@ class AutoPlannogrammaService
 
         foreach ($storeIds as $sid) {
             foreach ($periods as $dt) {
-                $items = $this->getProductsComponentsInCategory(
-                    $sid,
-                    (int)$dt->format('n'),
-                    (int)$dt->format('Y'),
-                    $type
-                );
-                if (empty($items)) {
+                try {
+                    $items = $this->getProductsComponentsInCategory(
+                        $sid,
+                        (int)$dt->format('n'),
+                        (int)$dt->format('Y'),
+                        $type
+                    );
+                } catch (\Throwable $e) {
                     continue;
                 }
 
-                $filtered = match ($mode) {
-                    'offline'   => array_filter($items, fn($it) => in_array($it['order_id'], ['', '0'], true)),
-                    'online'    => array_filter($items, fn($it) => !in_array($it['order_id'], ['', '0'], true)),
-                    default     => $items,  // для writeOffs — всё
+                if (empty($items) || !is_array($items)) {
+                    continue;
+                }
+
+                $normalizeOrderId = static function($row): string {
+                    if (!is_array($row)) return '';
+                    $oid = $row['order_id'] ?? '';
+                    if ($oid === null) return '';
+                    return (string)$oid;
                 };
 
-                $allComponentsProductIds[$sid] = array_merge(
-                    $allComponentsProductIds[$sid] ?? [],
-                    array_column($filtered, 'product_id')
-                );
+                try {
+                    $filtered = match ($mode) {
+                        'offline' => array_filter($items, fn($it) => in_array($normalizeOrderId($it), ['', '0'], true)),
+                        'online'  => array_filter($items, fn($it) => !in_array($normalizeOrderId($it), ['', '0'], true)),
+                        default   => $items,
+                    };
+                } catch (\Throwable $e) {
 
-                $sums = $this->sumProductsComponentsByGroup($filtered, $type, 'subcategory');
+                    $filtered = $items;
+                }
 
-                $allComponentsProductIds[$sid] = array_values(array_unique($allComponentsProductIds[$sid]));
+
+                $productIds = [];
+                foreach ($filtered as $row) {
+                    if (is_array($row) && array_key_exists('product_id', $row)) {
+                        $productIds[] = $row['product_id'];
+                    }
+                }
+                $allComponentsProductIds[$sid] = array_values(array_unique(array_merge(
+                    $allComponentsProductIds[$sid] ?? [],
+                    $productIds
+                )));
+
+                $sums = $this->sumProductsComponentsByGroup($filtered, $type, 'subcategory') ?? [];
 
                 foreach ($sums as $sr) {
-                    $cat = $sr['category'];
-                    $subcat = $sr['subcategory'];
-                    $val = $sr['sum'];
+                    if (!is_array($sr)) { continue; }
+                    $cat    = $sr['category']    ?? null;
+                    $subcat = $sr['subcategory'] ?? null;
+                    $val    = (float)($sr['sum'] ?? 0);
 
-                    $componentAdds[$sid][$cat][$subcat] =
-                        ($componentAdds[$sid][$cat][$subcat] ?? 0) + $val;
+                    if ($cat === null || $subcat === null) { continue; }
+
+                    $componentAdds[$sid][$cat][$subcat] = ($componentAdds[$sid][$cat][$subcat] ?? 0) + $val;
+                    $componentAddsSumAll[$sid][$cat]    = ($componentAddsSumAll[$sid][$cat]    ?? 0) + $val;
 
-                    $componentAddsSumAll[$sid][$cat] =
-                        ($componentAddsSumAll[$sid][$cat] ?? 0) + $val;
                 }
             }
         }
@@ -1820,8 +1843,8 @@ private function buildCategoryGoals(array $rawGoals, bool $subtractMatrix, int $
             }
 
             $productSalesShare = StorePlanService::calculateProductSalesShareProductsWithHistory(
-                $filters['store_id'],
-                $filters['month'],
+                $storeId,
+                $month,
                 $productsWithHistory
             );
 
@@ -1830,8 +1853,8 @@ private function buildCategoryGoals(array $rawGoals, bool $subtractMatrix, int $
             }
 
             $productSalesForecast = $this->calculateProductForecastInPiecesProductsWithHistory(
-                $filters['store_id'],
-                $filters['month'],
+                $storeId,
+                $month,
                 $year,
                 $goals,
                 $productSalesShare
@@ -1923,6 +1946,7 @@ private function buildCategoryGoals(array $rawGoals, bool $subtractMatrix, int $
 
         foreach ($productSalesShare as $productId => $data) {
             $share = $data['share'] ?? 0.0;
+            $avgWeightedSumm = $data['avgWeightedSum'] ?? 0.0;
 
             if ($share <= 0.0) {
                 continue;
@@ -1942,15 +1966,18 @@ private function buildCategoryGoals(array $rawGoals, bool $subtractMatrix, int $
                     $goalsMap[$storeId],
                     $goalsMap[$storeId][$cat],
                     $goalsMap[$storeId][$cat][$sub],
-                    $goalsMap[$storeId][$cat][$sub][$spec]
+                   // $goalsMap[$storeId][$cat][$sub][$spec]
                 )
             ) {
                 continue;
             }
-
-            $goal = $goalsMap[$storeId][$cat][$sub][$spec];
-
-            $forecastSum = $goal * $share;
+            $isGoalExists = isset($goalsMap[$storeId][$cat][$sub][$spec]);
+            $goal = $goalsMap[$storeId][$cat][$sub][$spec] ?? 0;
+            if ($goal !== 0) {
+                $forecastSum = $goal * $share;
+            } else {
+                $forecastSum = $avgWeightedSumm;
+            }
 
             $forecastCount = $forecastSum / $price;
 
@@ -1966,6 +1993,7 @@ private function buildCategoryGoals(array $rawGoals, bool $subtractMatrix, int $
                 'category' => $data['category'],
                 'subcategory' => $data['subcategory'],
                 'species' => $data['species'],
+                'is_goal_exists' => $isGoalExists
             ];
         }
 
index 805fb6e482726648c5612699c95956830c1796f8..af18f492bb1a088ee93da68593ea46ce861b19c9 100755 (executable)
@@ -29,6 +29,8 @@ use yii_app\records\WriteOffsErp;
 
 class StorePlanService
 {
+    const PERIOD_COUNT = 3;
+
     /**
      * @param int $month
      * @param int $year
@@ -258,7 +260,7 @@ class StorePlanService
         $baseDate = strtotime("{$selectedYear}-{$selectedMonth}-01");
 
         // Получаем периоды за 3 предыдущих месяца.
-        $periods = self::getPeriods($baseDate, 3, true);
+        $periods = self::getPeriods($baseDate, self::PERIOD_COUNT, true);
 
         // Получаем историю продаж для каждого периода.
         $salesHistory = self::getSalesHistory($storeId, $periods, $category, $subcategory, $species);
@@ -492,7 +494,7 @@ class StorePlanService
     public static function calculateMedianSalesForProductsWithoutHistoryExtended($storeId, $selectedMonth, $selectedYear, $productsWithoutHistory)
     {
         $targetDate = strtotime("{$selectedYear}-{$selectedMonth}-01");
-        $periods = self::getPeriods($targetDate, 3);
+        $periods = self::getPeriods($targetDate, self::PERIOD_COUNT);
 
         $medianSalesResults = [];
 
@@ -782,7 +784,7 @@ class StorePlanService
         array $productsWithoutHistory
     ): array {
         $targetDate = strtotime("{$selectedYear}-{$selectedMonth}-01");
-        $periods    = self::getPeriods($targetDate, 3);
+        $periods    = self::getPeriods($targetDate, self::PERIOD_COUNT);
 
         $results = [];
         foreach ($productsWithoutHistory as $prod) {
@@ -985,7 +987,7 @@ class StorePlanService
     {
         $targetDate = strtotime(date('Y') . "-$selectedMonth-01");
 
-        $weightedPeriods = self::getPeriods($targetDate, 3, false, true);
+        $weightedPeriods = self::getPeriods($targetDate, self::PERIOD_COUNT, false, true);
 
         $productsData = [];
         $globalTotal = 0;
@@ -999,6 +1001,12 @@ class StorePlanService
 
         foreach ($productsData as $guid => &$data) {
             $data['share'] = ($globalTotal > 0) ? $data['weightedSum'] / $globalTotal : 0;
+            if (!empty($weightedPeriods)) {
+                $countPeriods = count($weightedPeriods);
+            } else {
+                $countPeriods = self::PERIOD_COUNT;
+            }
+            $data['avgWeightedSum'] = $data['weightedSum'] ? $data['weightedSum'] / $countPeriods : 0;
         }
         unset($data);