}
- $weeksShareResult = $service->getWeeksSpeciesShareOrWriteOff($dateFrom, $dateTo, $filters, null, 'writeOffs');
+ $weeksShareResult = $service->getHistoricalWeeklySpeciesShare($model->month, $filters, null, 'writeOffs');
$weeksData = $weeksShareResult['weeksData'];
- $weeksShareResult = $weeksShareResult['weeksShare'];
+ // $weeksShareResult = $weeksShareResult['weeksShare'];
}
-//var_dump($monthSpeciesGoalsMap); die();
+//var_dump($weeksData); die();
return $this->render('control-species', [
'model' => $model,
'result' => $monthResult,
'weeksData' => $weeksData,
- 'weeksShareResult' => $weeksShareResult,
- 'weeksGoalResult' => $weeksGoalResult,
+ // 'weeksShareResult' => $weeksShareResult,
+ // 'weeksGoalResult' => $weeksGoalResult,
'totals' => $totals,
'storeList' => $storeList,
'monthsList' => $monthsList,
$dateFrom = sprintf('%04d-%02d-01 00:00:00', $year, $month);
$dateTo = date('Y-m-d H:i:s', strtotime($dateFrom . ' +1 month -1 second'));
-
+ //var_dump($monthYear); die();
$stores = $this->getVisibleStores();
$storeIds = array_map(fn($s)=>$s->id, $stores);
if (!empty($filters['store_id'])) {
}
$query = (new Query())->select([
- 'week' => new Expression('$weekIndex'),
+ 'week' => new Expression((string)$ind),
'store_id' => 'ex.entity_id',
'category' => 'p1c.category',
'subcategory' => 'p1c.subcategory',
}
/**
- * Строит исторический недельный отчёт за аналогичные месяцы предыдущих лет (2020–year-1)
- * и вычисляет долю каждой недели от исторического месячного итога по видам.
+ * Исторический недельный отчёт и доли по видам без вложенных циклов.
*
- * @param string $monthYear месяц-год в формате MM-YYYY, например '03-2025'
- * @param array|null $filters опциональные фильтры ['store_id'=>...]
- * @param array|null $productFilter опциональный фильтр по product_id
- * @param string $type 'sales' или 'writeOffs'
+ * @param string $monthYear месяц-год в формате MM-YYYY
+ * @param array|null $filters
+ * @param array|null $productFilter
+ * @param string $type
* @return array{
- * 'historicalWeekly' => array<int, array>, // суммарные суммы за каждый week
- * 'weeklyShare' => array<int, array> // доли недель относительно исторического месяца
+ * 'historicalWeekly' => array<int, array>,
+ * 'weeklyShare' => array<int, array>
* }
*/
public function getHistoricalWeeklySpeciesShare(
?array $productFilter = null,
string $type = 'sales'
): array {
+
[$monthStr, $yearStr] = explode('-', $monthYear);
$month = (int)$monthStr;
$year = (int)$yearStr;
$historical = [];
for ($yr = 2020; $yr < $year; $yr++) {
$mYear = sprintf('%02d-%d', $month, $yr);
- $weekData = $this->getWeeklySpeciesDataForMonth($mYear, $filters, $productFilter, $type);
- foreach ($weekData as $row) {
- $idx = $row['week'];
- $sid = $row['store_id'];
- $cat = $row['category'];
- $sub = $row['subcategory'];
+ $weeklyData = $this->getWeeklySpeciesDataForMonth($mYear, $filters, $productFilter, $type);
+ foreach ($weeklyData as $row) {
+ $idx = $row['week'];
+ $historical[$idx] ??= [];
+ $cat = $row['category'];
+ $sub = $row['subcategory'];
$spec = $row['species'];
- $historical[$idx][$sid][$cat][$sub][$spec] =
- ($historical[$idx][$sid][$cat][$sub][$spec] ?? 0)
- + $row['sum'];
+
+ $historical[$idx][$cat][$sub][$spec] =
+ ($historical[$idx][$cat][$sub][$spec] ?? 0) + $row['sum'];
}
}
+
$dateFrom = sprintf('%04d-%02d-01 00:00:00', $year, $month);
$dateTo = date('Y-m-d H:i:s', strtotime($dateFrom . ' +1 month -1 second'));
$monthWeighted = $this->getMonthSpeciesShareOrWriteOffWeighted(
$dateFrom, $dateTo, $filters, $productFilter, $type
);
+
$monthMap = [];
foreach ($monthWeighted as $m) {
- $monthMap[
- $m['store_id']
- ][
- $m['category']
- ][
- $m['subcategory']
- ][
- $m['species']
- ] = $m['total_sum'];
+ $cat = $m['category'];
+ $sub = $m['subcategory'];
+ $spec = $m['species'];
+ $monthMap[$cat][$sub][$spec] = ($monthMap[$cat][$sub][$spec] ?? 0) + $m['total_sum'];
}
- $flat = $this->flattenHistorical($historical);
- $weeksShare = [];
- foreach ($flat as $row) {
- $w = $row['week'];
- $sid = $row['store_id'];
- $cat = $row['category'];
- $sub = $row['subcategory'];
- $spec = $row['species'];
- $sum = $row['sum'];
-
- $monthSum = $monthMap[$sid][$cat][$sub][$spec] ?? 0;
- if ($monthSum > 0) {
- $weeksShare[$w][$sid][$cat][$sub][$spec] = round($sum / $monthSum, 4);
+ $flatRows = [];
+ foreach ($historical as $week => $byCat) {
+ foreach ($byCat as $cat => $bySub) {
+ foreach ($bySub as $sub => $bySpec) {
+ foreach ($bySpec as $spec => $sumWeek) {
+ $sumMonth = $monthMap[$cat][$sub][$spec] ?? 0;
+ if ($sumMonth <= 0) {
+ continue;
+ }
+ $flatRows[] = [
+ 'week' => $week,
+ 'category' => $cat,
+ 'subcategory' => $sub,
+ 'species' => $spec,
+ 'percent' => round($sumWeek / $sumMonth, 4),
+ ];
+ }
+ }
}
}
+ usort($flatRows, function(array $a, array $b): int {
+ $cmp = strcmp($a['category'], $b['category']);
+ if ($cmp !== 0) {
+ return $cmp;
+ }
+ $cmp = strcmp($a['subcategory'], $b['subcategory']);
+ if ($cmp !== 0) {
+ return $cmp;
+ }
+ $cmp = strcmp($a['species'], $b['species']);
+ if ($cmp !== 0) {
+ return $cmp;
+ }
+ return $a['week'] <=> $b['week'];
+ });
return [
- 'historicalWeekly' => $historical,
- 'weeklyShare' => $weeksShare,
+ 'weeksData' => $flatRows,
];
}
<?php endif; ?>
<?php if (!empty($weeksData)): ?>
<h2>Результаты по неделям</h2>
- <?php foreach ($weeksData as $weekNum => $weekRows): ?>
- <h3>Неделя <?= $weekNum ?></h3>
- <?php if (empty($weekRows)): ?>
- <p>Нет данных за эту неделю.</p>
- <?php else: ?>
- <table class="table table-striped table-bordered">
- <thead>
- <tr>
- <th>Категория</th>
- <th>Подкатегория</th>
- <th>Вид товара</th>
- <th>Сумма</th>
- <th>Доля недели</th>
- <th>Цель недели</th>
- </tr>
- </thead>
- <tbody>
- <?php foreach ($weekRows as $row): ?>
- <tr>
- <td><?= Html::encode($row['category']) ?></td>
- <td><?= Html::encode($row['subcategory']) ?></td>
- <td><?= Html::encode($row['species']) ?></td>
- <td><?= Yii::$app->formatter->asDecimal($row['total_sum'], 2) ?></td>
- <td>
- <?= isset($weeksShareResult[$weekNum])
- ? Yii::$app->formatter->asPercent(
- $weeksShareResult[$weekNum][$row['category']][$row['subcategory']][$row['species']],
- 2
- )
- : '-' ?>
- </td>
- <td>
- <?= isset($weeksGoalResult[$weekNum])
- ? Yii::$app->formatter->asPercent(
- $weeksGoalResult[$weekNum][$row['category']][$row['subcategory']][$row['species']],
- 2
- )
- : '-' ?>
- </td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- <?php endif; ?>
- <?php endforeach; ?>
+ <table class="table table-striped table-bordered">
+ <thead>
+ <tr>
+ <th>Категория</th>
+ <th>Подкатегория</th>
+ <th>Вид</th>
+ <th>Неделя</th>
+ <th>Доля (%)</th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($weeksData as $r): ?>
+ <tr>
+ <td><?= Html::encode($r['category']) ?></td>
+ <td><?= Html::encode($r['subcategory']) ?></td>
+ <td><?= Html::encode($r['species']) ?></td>
+ <td><?= $r['week'] ?></td>
+ <td><?= Yii::$app->formatter->asPercent($r['percent'], 1) ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
<?php endif; ?>
</div>