*/ public function summaryFor(QrCode $qrCode): array { $now = now(); $events = QrScanEvent::query()->where('qr_code_id', $qrCode->id); return [ 'total_scans' => (int) $qrCode->scans_total, 'unique_scans' => (int) $qrCode->unique_scans_total, 'scans_7d' => (clone $events)->where('scanned_at', '>=', $now->copy()->subDays(7))->count(), 'scans_30d' => (clone $events)->where('scanned_at', '>=', $now->copy()->subDays(30))->count(), 'last_scanned_at' => $qrCode->last_scanned_at, ]; } /** * @return Collection */ public function dailyScans(QrCode $qrCode, int $days = 30): Collection { $start = now()->subDays($days - 1)->startOfDay(); $rows = QrScanEvent::query() ->selectRaw('DATE(scanned_at) as scan_date, COUNT(*) as total') ->where('qr_code_id', $qrCode->id) ->where('scanned_at', '>=', $start) ->groupBy('scan_date') ->orderBy('scan_date') ->get() ->keyBy('scan_date'); $series = collect(); for ($i = 0; $i < $days; $i++) { $date = $start->copy()->addDays($i)->toDateString(); $series->push((object) [ 'date' => $date, 'total' => (int) ($rows->get($date)?->total ?? 0), ]); } return $series; } /** * @return array */ public function breakdown(QrCode $qrCode, string $column, int $limit = 5): array { return QrScanEvent::query() ->select($column, DB::raw('COUNT(*) as total')) ->where('qr_code_id', $qrCode->id) ->whereNotNull($column) ->groupBy($column) ->orderByDesc('total') ->limit($limit) ->get() ->map(fn ($row) => [ 'label' => (string) $row->{$column}, 'total' => (int) $row->total, ]) ->all(); } /** * @return \Illuminate\Database\Eloquent\Collection */ public function recentScans(QrCode $qrCode, int $limit = 20) { return QrScanEvent::query() ->where('qr_code_id', $qrCode->id) ->latest('scanned_at') ->limit($limit) ->get(); } }