}
- public function actionControlSpeciesOld()
- {
- $model = new DynamicModel([
- 'storeId', 'month', 'type',
-
- ]);
- $model->addRule(['month', 'type'], 'required')
- ->addRule('storeId', 'integer');
-
- $storeList = CityStore::find()
- ->select(['name', 'id'])
- ->where(['visible' => CityStore::IS_VISIBLE])
- ->indexBy('id')
- ->column();
-
- $monthsList = [];
- for ($i = 0; $i < 12; $i++) {
- // получаем метку вида "03-2025"
- $ts = strtotime("first day of -{$i} month");
- $key = date('m-Y', $ts);
- $monthsList[$key] = $key;
- }
-
- $monthResult = [];
- $totals = [];
- $weeksData = [];
- $weeksShareResult = [];
- $weeksGoalResult = [];
- $monthCategoryShareResult = [];
- $weeksProductForecast = [];
-
- if ($model->load(Yii::$app->request->post()) && $model->validate()) {
- $filters = [];
-
- list($m, $y) = explode('-', $model->month);
- $dateFrom = date("Y-m-d 00:00:00", strtotime(sprintf('%04d-%02d-01', $y, $m)));
- $dateTo = date("Y-m-t 23:59:59", strtotime($dateFrom));
-
- if ($model->storeId) {
- $filters['store_id'] = $model->storeId;
- $filters['type'] = $model->type;
- $filters['plan_date'] = $dateFrom;
- }
-
- $service = new AutoPlannogrammaService();
-
- if ($model->storeId) {
- $totals = $service->getStoreTotals(
- [$model->storeId],
- $dateFrom,
- null,
- $model->type,
- $dateTo
- );
- }
-
- $monthSpeciesGoals = $service->calculateFullGoalChainWeighted($filters);
- $monthSpeciesGoalsMap = [];
- foreach ($monthSpeciesGoals as $monthSpeciesGoal) {
- $monthSpeciesGoalsMap[$monthSpeciesGoal['store_id']]
- [$monthSpeciesGoal['category']]
- [$monthSpeciesGoal['subcategory']]
- [$monthSpeciesGoal['species']] = $monthSpeciesGoal['goal'];
- }
-
- $weeksShareResult = $service->getHistoricalWeeklySpeciesShare($model->month, $filters, null, 'writeOffs');
- $weeksData = $service->calculateWeeklySpeciesGoals($weeksShareResult['weeksData'], $monthSpeciesGoals);
-
- $datePlan = $filters['plan_date'];
- $monthCategoryShare = $service->getMonthCategoryShareOrWriteOffWeighted($datePlan, $filters, null, $filters['type']);
- $monthCategoryGoal = $service->getMonthCategoryGoal($monthCategoryShare, $datePlan, $filters['type']);
- foreach ($monthCategoryShare as $sid => $cats) {
- foreach ($cats as $cat) {
- $monthCategoryShareResult[$sid][$cat['category']]['total_sum_cat'] = $cat['total_sum_cat'];
- $monthCategoryShareResult[$sid][$cat['category']]['share_of_total'] = $cat['share_of_total'];
- }
-
- }
- foreach ($monthCategoryGoal as $cats) {
- $monthCategoryShareResult[$cats['store_id']][$cats['category']]['goal'] = $cats['goal'];
-
- }
-
- $monthSubcategoryShare = $service->getMonthSubcategoryShareOrWriteOffWeighted($datePlan, $filters, null, $filters['type']);
- $monthSubcategoryGoal = $service->getMonthSubcategoryGoal($monthSubcategoryShare, $monthCategoryGoal);
-
- if ($filters['type'] === 'writeOffs') {
- $salesSubShare = $service->getMonthSubcategoryShareOrWriteOffWeighted($datePlan, $filters, null, 'sales');
- $salesSubGoal = $service->getMonthSubcategoryGoal($salesSubShare, $monthCategoryGoal);
-
- $catGoalMap = [];
- foreach ($monthCategoryGoal as $row) {
- $catGoalMap[$row['category']] = $row['goal'];
- }
- $salesSubGoalMap = [];
- foreach ($salesSubGoal as $row) {
- $salesSubGoalMap[$row['category']][$row['subcategory']] = $row['goal'];
- }
-
-
- foreach ($monthSubcategoryShare as &$row) {
- $cat = $row['category'];
- $sub = $row['subcategory'];
-
- $writeShare = $row['percent_of_month'];
-
- $writeGoal = ($catGoalMap[$cat] ?? 0) * $writeShare;
- $saleGoal = $salesSubGoalMap[$cat][$sub] ?? 0;
-
- if ($saleGoal > 0 && $writeGoal > 0.1 * $saleGoal) {
- $row['share'] = 0.1;
- }
- }
- unset($row);
- $monthSubcategoryGoal = $service->getMonthSubcategoryGoal($monthSubcategoryShare, $monthCategoryGoal);
- }
-
- foreach ($monthSubcategoryShare as $subcat) {
- $monthCategoryShareResult[$subcat['store_id']][$subcat['category']][$subcat['subcategory']]['total_sum'] = $subcat['total_sum'];
- $monthCategoryShareResult[$subcat['store_id']][$subcat['category']][$subcat['subcategory']]['percent_of_month'] = $subcat['percent_of_month'];
- }
- foreach ($monthSubcategoryGoal as $cats) {
- $monthCategoryShareResult[$cats['store_id']][$cats['category']][$cats['subcategory']]['goal'] = $cats['goal'];
-
- }
- $monthSpeciesShare = $service->getMonthSpeciesShareOrWriteOffWeighted($datePlan, $datePlan, $filters, null, $filters['type']);
- $monthSpeciesGoal = $service->getMonthSpeciesGoalDirty($monthSpeciesShare, $monthSubcategoryGoal);
- if ($filters['type'] === 'writeOffs') {
- $salesSpecShare = $service->getMonthSpeciesShareOrWriteOffWeighted($datePlan, $datePlan, $filters, null, 'sales');
- $salesSpecGoal = $service->getMonthSpeciesGoalDirty($salesSpecShare, $monthSubcategoryGoal);
-
- $subGoalMap = [];
- foreach ($monthSubcategoryGoal as $row) {
- $subGoalMap[$row['category']][$row['subcategory']] = $row['goal'];
- }
- $salesSpecGoalMap = [];
- foreach ($salesSpecGoal as $row) {
- $salesSpecGoalMap[$row['category']][$row['subcategory']][$row['species']] = $row['goal'];
- }
-
- foreach ($monthSpeciesShare as &$row) {
- $cat = $row['category'];
- $sub = $row['subcategory'];
- $spec = $row['species'];
-
- $writeShare = $row['percent_of_month'];
- $writeGoal = ($subGoalMap[$cat][$sub] ?? 0) * $writeShare;
- $saleGoal = $salesSpecGoalMap[$cat][$sub][$spec] ?? 0;
-
- if ($saleGoal > 0 && $writeGoal > 0.1 * $saleGoal) {
- $row['share'] = 0.1;
- }
- }
- unset($row);
-
- $monthSpeciesGoal = $service->getMonthSpeciesGoalDirty($monthSpeciesShare, $monthSubcategoryGoal);
- }
- foreach ($monthSpeciesShare as $species) {
- $monthCategoryShareResult[$species['store_id']][$species['category']][$species['subcategory']][$species['species']]['total_sum'] = $species['total_sum'];
- $monthCategoryShareResult[$species['store_id']][$species['category']][$species['subcategory']][$species['species']]['percent_of_month'] = $species['percent_of_month'];
-
- }
- foreach ($weeksShareResult['weeksData'] as $row) {
- $monthCategoryShareResult[$row['store_id']][$row['category']][$row['subcategory']][$row['species']][$row['week']]['sumWeek'] = $row['sumWeek'];
-
- }
-
-
- foreach ($weeksData as $r) {
- $forecasts = $service->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'],
- ];
- }
- }
-
- usort($weeksProductForecast, function ($a, $b) {
- foreach (['category', 'subcategory', 'species', 'name', 'week'] as $key) {
- $va = $a[$key];
- $vb = $b[$key];
- if ($va < $vb) return -1;
- if ($va > $vb) return 1;
- }
- return 0;
- });
-
- }
-
- return $this->render('control-species-old', [
- 'model' => $model,
- 'result' => $monthResult,
- 'weeksData' => $weeksData,
- 'monthCategoryShare' => $monthCategoryShareResult,
- 'weeksProductForecast' => $weeksProductForecast,
- 'totals' => $totals,
- 'storeList' => $storeList,
- 'monthsList' => $monthsList,
-
- ]);
- }
-
public function actionControlSpecies()
{
// альтернативные методы расчета списаний
- public function calculateFullGoalChainWeighted(array $filters): array
- {
- $datePlan = $filters['plan_date'];
- $dateFromForCategory = (new \DateTime($datePlan))->modify('-' . (self::CATEGORY_LOOKBACK_MONTHS + self::LOOKBACK_MONTHS) . ' months')->format('Y-m-d');
-
- $monthCategoryShare = $this->getMonthCategoryShareOrWriteOffWeighted($datePlan, $filters, null, $filters['type']);
- $monthCategoryGoal = $this->getMonthCategoryGoal($monthCategoryShare, $datePlan, $filters);
-
- $monthSubcategoryShare = $this->getMonthSubcategoryShareOrWriteOff($datePlan, $filters);
- $monthSubcategoryShare = $this->getMonthSubcategoryShareOrWriteOffWeighted($datePlan, $filters, null, $filters['type']);
- $monthSubcategoryGoal = $this->getMonthSubcategoryGoal($monthSubcategoryShare, $monthCategoryGoal);
-
- $monthSpeciesShare = $this->getMonthSpeciesShareOrWriteOff($datePlan, $filters);
- if ($filters['type'] === 'writeOffs') {
- $salesSubShare = $this->getMonthSubcategoryShareOrWriteOffWeighted($datePlan, $filters, null, 'sales');
- $salesSubGoal = $this->getMonthSubcategoryGoal($salesSubShare, $monthCategoryGoal);
-
- $catGoalMap = [];
- foreach ($monthCategoryGoal as $row) {
- $catGoalMap[$row['category']] = $row['goal'];
- }
- $salesSubGoalMap = [];
- foreach ($salesSubGoal as $row) {
- $salesSubGoalMap[$row['category']][$row['subcategory']] = $row['goal'];
- }
-
-
- foreach ($monthSubcategoryShare as &$row) {
- $cat = $row['category'];
- $sub = $row['subcategory'];
-
- $writeShare = $row['percent_of_month'];
-
- $writeGoal = ($catGoalMap[$cat] ?? 0) * $writeShare;
- $saleGoal = $salesSubGoalMap[$cat][$sub] ?? 0;
-
- if ($saleGoal > 0 && $writeGoal > 0.1 * $saleGoal) {
- $row['share'] = 0.1;
- }
- }
- unset($row);
- $monthSubcategoryGoal = $this->getMonthSubcategoryGoal($monthSubcategoryShare, $monthCategoryGoal);
- }
-
- $monthSpeciesShare = $this->getMonthSpeciesShareOrWriteOffWeighted($datePlan, $datePlan, $filters, null, $filters['type']);
- $monthSpeciesGoal = $this->getMonthSpeciesGoalDirty($monthSpeciesShare, $monthSubcategoryGoal);
- if ($filters['type'] === 'writeOffs') {
- $salesSpecShare = $this->getMonthSpeciesShareOrWriteOffWeighted($datePlan, $datePlan, $filters, null, 'sales');
- $salesSpecGoal = $this->getMonthSpeciesGoalDirty($salesSpecShare, $monthSubcategoryGoal);
-
- $subGoalMap = [];
- foreach ($monthSubcategoryGoal as $row) {
- $subGoalMap[$row['category']][$row['subcategory']] = $row['goal'];
- }
- $salesSpecGoalMap = [];
- foreach ($salesSpecGoal as $row) {
- $salesSpecGoalMap[$row['category']][$row['subcategory']][$row['species']] = $row['goal'];
- }
-
- foreach ($monthSpeciesShare as &$row) {
- $cat = $row['category'];
- $sub = $row['subcategory'];
- $spec = $row['species'];
-
- $writeShare = $row['percent_of_month'];
- $writeGoal = ($subGoalMap[$cat][$sub] ?? 0) * $writeShare;
- $saleGoal = $salesSpecGoalMap[$cat][$sub][$spec] ?? 0;
-
- if ($saleGoal > 0 && $writeGoal > 0.1 * $saleGoal) {
- $row['share'] = 0.1;
- }
- }
- unset($row);
-
- $monthSpeciesGoal = $this->getMonthSpeciesGoalDirty($monthSpeciesShare, $monthSubcategoryGoal);
- }
-
- $filtered = array_filter($monthSpeciesGoal, function ($row) use ($filters) {
- foreach ($filters as $key => $value) {
- if ($value === null || $value === '') {
- continue;
- }
-
- if (!array_key_exists($key, $row)) {
- continue;
- }
-
- if (is_numeric($row[$key]) && is_numeric($value)) {
- if ((float)$row[$key] !== (float)$value) {
- return false;
- }
- } else {
- if (stripos((string)$row[$key], (string)$value) === false) {
- return false;
- }
- }
- }
- return true;
- });
-
- return array_values($filtered);
- }
-
-
/**
* Строит карту цен за последние 20 дней.
*
}
foreach ($weeklyForecasts as $item) {
- $groupsArr = explode('_', (string)$item['matrix_group']);
- $baseGroup = $groupsArr[0];
- $storeItem = (int)$item['store_id'];
$guid = (string)$item['product_guid'];
if (!in_array($guid, $actualProducts)) {
continue;
}
+ $groupsArr = explode('_', (string)$item['matrix_group']);
+ $baseGroup = $groupsArr[0];
+ $storeItem = (int)$item['store_id'];
$group = $baseGroup;
$type = (string)$item['type'];
$forecastValue = (float)$item['week_forecast'];