entityManager = $entityManager; $this->cache = $cache; } public function updateTimeSerisCache(): void { $this->cache->delete('time_series'); } public function updateBartChartCache($input): void { $cacheKey = 'bar-chart' . $input; if ($this->cache->has($cacheKey)) { $this->cache->delete($cacheKey); } } public function updateDonutChartCache($year): void { $cacheKey = 'donut-chart' . $year; if ($this->cache->has($cacheKey)) { $this->cache->delete($cacheKey); } } public function getTimeSeries(): array { return $this->cache->get('time_series', function (ItemInterface $item) { try { $queryBuilder = $this->entityManager->createQueryBuilder(); $result = $queryBuilder ->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'AVG(CASE WHEN s.surface <> 0 THEN s.amount / s.surface ELSE 0 END) as average_price') #->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'SUM(s.amount) as total_price', 'SUM(s.surface) as total_surface') #->select('MONTH(s.date) as month', 'YEAR(s.date) as year', 'AVG(s.amount) as total_price', 'AVG(s.surface) as total_surface') ->from(Sale::class, 's') ->groupBy('year, month') ->orderBy('year, month') ->getQuery() ->getResult(Query::HYDRATE_ARRAY); $monthlyAveragePriceEvolutions = []; foreach ($result as $row) { #$row['average_price'] = $row['total_surface'] != 0 ? $row['total_price'] / $row['total_surface'] : 0; $monthlyAveragePriceEvolutions[] = new MonthlyAveragePriceEvolution( (int)$row['month'], (int)$row['year'], (float)$row['average_price'] ); } $item->expiresAfter(600); return $monthlyAveragePriceEvolutions; } catch (\Exception $exception){ throw $exception; } }); } private function generateCacheKey(BarChartInput $input): string { $inputArray = [ 'start' => $input->start, 'end' => $input->end, 'granularity' => $input->granularity, ]; $jsonEncodedInput = json_encode($inputArray); $cleanedKey = preg_replace('/[^A-Za-z0-9]/', '_', $jsonEncodedInput); return $cleanedKey; } public function getBarChartData(BarChartInput $input): array { $cacheKey = 'bar-chart' . $this->generateCacheKey($input); return $this->cache->get($cacheKey, function (ItemInterface $item) use ($input) { try { $startDate = new \DateTime($input->start); $endDate = new \DateTime($input->end); $queryBuilder = $this->entityManager->createQueryBuilder(); $output = []; if ($input->granularity == 'month') { $result = $queryBuilder ->select('YEAR(s.date) as year', 'MONTH(s.date) as month', 'COUNT(s.id) as occurrences') ->from(Sale::class, 's') ->where('s.date BETWEEN :start AND :end') ->setParameter('start', $startDate) ->setParameter('end', $endDate) ->groupBy('year', 'month') ->orderBy('year') ->getQuery() ->getResult(Query::HYDRATE_ARRAY); } else { switch ($input->granularity) { case 'day': $groupByExpression = 's.date'; $groupByAlias = 'date'; $dateFormat = 'Y-m-d'; break; case 'year': $groupByExpression = 'YEAR(s.date)'; $groupByAlias = 'year'; $dateFormat = 'Y'; break; default: throw new \InvalidArgumentException('Invalid granularity'); } $result = $queryBuilder ->select("{$groupByExpression} as {$groupByAlias}", 'COUNT(s.id) as occurrences') ->from(Sale::class, 's') ->where('s.date BETWEEN :start AND :end') ->setParameter('start', $startDate) ->setParameter('end', $endDate) ->groupBy("{$groupByAlias}") ->orderBy("{$groupByAlias}") ->getQuery() ->getResult(Query::HYDRATE_ARRAY); } foreach ($result as $row) { if ($input->granularity == 'month') { $month = $row['month']; $year = $row['year']; $dateString = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT); } else { $dateString = $row[$groupByAlias] instanceof \DateTimeInterface ? $row[$groupByAlias]->format($dateFormat) : $row[$groupByAlias]; } $output[] = new BarChartOutput($dateString, (int)$row['occurrences']); } $item->expiresAfter(600); return $output; } catch (\Exception $exception){ throw $exception; } }); } public function getDonutChartData(string $year): array { $cacheKey = 'donut-chart' . $year; return $this->cache->get($cacheKey, function (ItemInterface $item) use ($year) { try { $repository = $this->entityManager->getRepository(Sale::class); $result = $repository->createQueryBuilder('s') ->select('s.region', 'COUNT(s.id) as occurrences') ->andWhere('YEAR(s.date) = :year') ->setParameter('year', $year) ->groupBy('s.region') ->getQuery() ->getResult(Query::HYDRATE_ARRAY); $data = []; foreach ($result as $row) { $data[] = [ 'region' => $row['region'], 'occurrences' => (int)$row['occurrences'], ]; } $item->expiresAfter(600); return $data; }catch (\Exception $exception){ throw $exception; } }); } }