uawdijnntqw1x1x1
IP : 216.73.216.130
Hostname : it-staging-server
Kernel : Linux it-staging-server 5.15.0-131-generic #141-Ubuntu SMP Fri Jan 10 21:18:28 UTC 2025 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
forge
/
stage.herta-bht.smartcon-survey.com
/
app
/
Services
/
FunnelService.php
/
/
<?php namespace App\Services; use App\Models\Brand; use App\Models\DataAggregation; use App\Models\DataUpload; use App\Models\Product; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Support\Collection; /** * Class FunnelService * * This service class handles the funnel data processing for a given country, wave, and row ID. */ class FunnelService { /** @var array Total number of interviews for the current wave */ public array $quarters; /** @var array Cached funnel data to avoid duplicated database queries */ private array $funnelData = []; private Collection|EloquentCollection $aggregatedInterviews; private Brand|Product $model; private Collection|EloquentCollection $models; private bool $getAllQuarters = false; private array $currentQuarter; private array $lastQuarter; /** * FunnelService constructor. */ public function __construct(private readonly int $countryId) { $this->quarters = DataUpload::getCountsByYearAndQuarter($this->countryId)->toArray(); $this->aggregatedInterviews = DataAggregation::where('country_id', $this->countryId)->get(); $this->currentQuarter = [ 'year' => 2025, 'quarter' => 1, ]; $this->lastQuarter = [ 'year' => 2024, 'quarter' => 4, ]; } public function getQuarters(): array { return $this->quarters; } private function getTotal(array $quarters): int { $sum = 0; foreach ($this->quarters as $item) { if ($item['year'] === $quarters['year'] && $item['quarter'] === $quarters['quarter']) { $sum += $item['aggregate']; } } return $sum; } /** * Get the funnel data for a specific question. * * @param string $title The title of the funnel step * @param string $question The question identifier * @param int $conversionN The conversion number (optional) * @param int|array $value The value(s) to filter by (optional) * @return array The funnel data */ private function getFunnelData( string $title, string $question, int $conversionN = 0, int|array $value = 1 ): array { $totalN = $this->getTotal($this->currentQuarter); $n = $this->calculateN($question, $value, $this->currentQuarter); $valueInPercent = $totalN === 0 ? 0 : $n * 100 / $totalN; return [ 'label' => $title, 'n' => $n, 'value' => round($valueInPercent), 'conversion' => round($conversionN === 0 ? 0 : ($n * 100 / $conversionN)), 'delta' => $this->calculateDelta($valueInPercent, $question, $value), ]; } private function calculateN(string $question, int|array $value, array $quarter): int { $questions = [$question, "{$question}a"]; if (str_contains($question, 'Q1')) { $questions = [$question]; } $n = $this->aggregatedInterviews ->where('model_id', $this->model->sid) ->where('year', $quarter['year']) ->where('quarter', $quarter['quarter']) ->whereIn('question_name', $questions); if (is_array($value)) { $n = $n->whereIn('value', $value); } else { $n = $n->where('value', $value); } return $n->sum('aggregate'); } /** * Calculate the delta between the current and last wave values. * * @param float $currentValue The current value in percent * @param string $question The question identifier * @param int|array $value The value(s) to filter by * @return float The delta value */ private function calculateDelta(float $currentValue, string $question, int|array $value): float { $lastTotalN = $this->getTotal($this->lastQuarter); $lastN = $this->calculateN($question, $value, $this->lastQuarter); $lastValue = $lastTotalN === 0 ? 0 : $lastN * 100 / $lastTotalN; return number_format($currentValue - $lastValue); } /** * Get the awareness funnel data. * * @return array The awareness data */ public function awareness(): array { if (isset($this->funnelData['awareness'])) { return $this->funnelData['awareness']; } $this->funnelData['awareness'] = $this->getFunnelData('Awareness', 'Q2'); return $this->funnelData['awareness']; } /** * Get the consideration funnel data. * * @return array The consideration data */ public function consideration(): array { if (isset($this->funnelData['consideration'])) { return $this->funnelData['consideration']; } $this->funnelData['consideration'] = $this->getFunnelData( 'Consideration', 'Q8', $this->awareness()['n'], [1, 2, 3] ); return $this->funnelData['consideration']; } /** * Get the trial funnel data. * * @return array The trial data */ public function trial(): array { if (isset($this->funnelData['trial'])) { return $this->funnelData['trial']; } $this->funnelData['trial'] = $this->getFunnelData('Trial', 'Q4', $this->consideration()['n']); return $this->funnelData['trial']; } /** * Get the purchase funnel data. * * @return array The purchase data */ public function purchase(): array { if (isset($this->funnelData['purchase'])) { return $this->funnelData['purchase']; } $this->funnelData['purchase'] = $this->getFunnelData('Repurchase', 'Q5', $this->trial()['n']); return $this->funnelData['purchase']; } /** * Get the loyalty funnel data. * * @return array The loyalty data */ public function loyalty(): array { if (isset($this->funnelData['loyalty'])) { return $this->funnelData['loyalty']; } $this->funnelData['loyalty'] = $this->getFunnelData( 'Loyalty', 'Q7', $this->purchase()['n'], $this->model->sid ); return $this->funnelData['loyalty']; } /** * Get the spontaneous awareness funnel data. * * @return array The spontaneous awareness data */ public function spontaneousAwareness(): array { return $this->getFunnelData('Spontaneous Awareness', 'Q1B_BRAND'); } /** * Retrieves the funnel data specifically for the 'Top of mind' category. */ public function topOfMind(): array { return $this->getFunnelData('Top of mind', 'Q1A_BRAND'); } public function setModel(Brand|Product $model): self { $this->model = $model; return $this; } public function setModels(Collection|EloquentCollection $models): self { $this->models = $models; return $this; } public function allQuarters(bool $getAllQuarters): self { $this->getAllQuarters = $getAllQuarters; return $this; } /** * Get all funnel data. * * @return array The total number of interviews and the funnel data * $*/ public function getData(): array { if (isset($this->model)) { return $this->getDataForModel(); } elseif (isset($this->models)) { return $this->getDataForAllModels(); } return []; } public function getDataForModel(): array { if ($this->getAllQuarters) { $data = []; foreach ($this->quarters as $key => $quarter) { $this->currentQuarter = $quarter; $this->lastQuarter = $this->quarters[$key - 1] ?? $quarter; $data[] = $this->getDataArray($quarter); } return $data; } return $this->getDataArray($this->currentQuarter); } private function getDataArray(array $quarter): array { return [ 'totalN' => $this->getTotal($quarter), 'title' => 'KPI Funnel', 'quarterYear' => "Q{$quarter['quarter']} {$quarter['year']}", 'topOfMind' => $this->topOfMind(), 'spontaneousAwareness' => $this->spontaneousAwareness(), 'data' => [ $this->awareness(), $this->consideration(), $this->trial(), $this->purchase(), $this->loyalty(), ], ]; } private function getDataForAllModels(): array { $data = []; foreach ($this->models as $model) { $this->model = $model; $data[] = [ 'model' => $model->name, 'data' => $this->getDataForModel(), ]; } return $data; } }
/home/forge/stage.herta-bht.smartcon-survey.com/app/Services/FunnelService.php