From: Vladimir Fomichev Date: Tue, 17 Jun 2025 10:33:01 +0000 (+0300) Subject: метод прогноза списаний X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=aac3268796b5bcc28e078887f0002fab42544cb3;p=erp24_rep%2Fyii-erp24%2F.git метод прогноза списаний --- diff --git a/erp24/controllers/AutoPlannogrammaController.php b/erp24/controllers/AutoPlannogrammaController.php index 20066d0f..5a39e992 100644 --- a/erp24/controllers/AutoPlannogrammaController.php +++ b/erp24/controllers/AutoPlannogrammaController.php @@ -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; } diff --git a/erp24/services/AutoPlannogrammaService.php b/erp24/services/AutoPlannogrammaService.php index 15d9c773..4587c0b1 100644 --- a/erp24/services/AutoPlannogrammaService.php +++ b/erp24/services/AutoPlannogrammaService.php @@ -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