256 lines
6.8 KiB
PHP
256 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories;
|
|
|
|
use App\Models\AnalyticsProductVisit;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class AnalyticsProductVisitRepository
|
|
{
|
|
/**
|
|
* Get all product visits with optional filtering
|
|
*/
|
|
public function getAll(array $filters = []): Collection
|
|
{
|
|
$query = AnalyticsProductVisit::query();
|
|
|
|
// Filter by product ID
|
|
if (isset($filters['item_id'])) {
|
|
$query->where('item_id', $filters['item_id']);
|
|
}
|
|
|
|
// Filter by user ID
|
|
if (isset($filters['user_id'])) {
|
|
$query->where('user_id', $filters['user_id']);
|
|
}
|
|
|
|
// Filter by date range
|
|
if (isset($filters['date_from'])) {
|
|
$query->where('started_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (isset($filters['date_to'])) {
|
|
$query->where('started_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
// Filter by IP address
|
|
if (isset($filters['ip_address'])) {
|
|
$query->where('ip_address', $filters['ip_address']);
|
|
}
|
|
|
|
return $query->orderBy('started_at', 'desc')->get();
|
|
}
|
|
|
|
/**
|
|
* Get product visits with pagination
|
|
*/
|
|
public function getPaginated(array $filters = [], int $perPage = 20): LengthAwarePaginator
|
|
{
|
|
$query = AnalyticsProductVisit::query();
|
|
|
|
// Apply same filters as getAll method
|
|
if (isset($filters['item_id'])) {
|
|
$query->where('item_id', $filters['item_id']);
|
|
}
|
|
|
|
if (isset($filters['user_id'])) {
|
|
$query->where('user_id', $filters['user_id']);
|
|
}
|
|
|
|
if (isset($filters['date_from'])) {
|
|
$query->where('started_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (isset($filters['date_to'])) {
|
|
$query->where('started_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
return $query->orderBy('started_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Create a new product visit record
|
|
*/
|
|
public function create(array $data): AnalyticsProductVisit
|
|
{
|
|
return AnalyticsProductVisit::create($data);
|
|
}
|
|
|
|
/**
|
|
* Update existing product visit
|
|
*/
|
|
public function update(int $id, array $data): bool
|
|
{
|
|
$visit = AnalyticsProductVisit::find($id);
|
|
|
|
if (!$visit) {
|
|
return false;
|
|
}
|
|
|
|
return $visit->update($data);
|
|
}
|
|
|
|
/**
|
|
* Delete a product visit record
|
|
*/
|
|
public function delete(int $id): bool
|
|
{
|
|
$visit = AnalyticsProductVisit::find($id);
|
|
|
|
if (!$visit) {
|
|
return false;
|
|
}
|
|
|
|
return $visit->delete();
|
|
}
|
|
|
|
/**
|
|
* Get visit statistics
|
|
*/
|
|
public function getStatistics(array $filters = []): array
|
|
{
|
|
$query = AnalyticsProductVisit::query();
|
|
|
|
// Apply date filters
|
|
if (isset($filters['date_from'])) {
|
|
$query->where('started_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (isset($filters['date_to'])) {
|
|
$query->where('started_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
$totalVisits = $query->count();
|
|
|
|
$uniqueVisitors = $query->distinct('user_id')->count('user_id');
|
|
|
|
$averageDuration = $query->avg('duration_seconds');
|
|
|
|
$totalDuration = $query->sum('duration_seconds');
|
|
|
|
return [
|
|
'total_visits' => $totalVisits,
|
|
'unique_visitors' => $uniqueVisitors,
|
|
'average_duration_seconds' => round($averageDuration, 2),
|
|
'total_duration_seconds' => $totalDuration,
|
|
'average_duration_formatted' => $this->formatDuration($averageDuration),
|
|
'total_duration_formatted' => $this->formatDuration($totalDuration),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get most visited products
|
|
*/
|
|
public function getMostVisitedProducts(int $limit = 10): array
|
|
{
|
|
return AnalyticsProductVisit::query()
|
|
->selectRaw('item_id, COUNT(*) as visit_count, AVG(duration_seconds) as avg_duration')
|
|
->groupBy('item_id')
|
|
->orderBy('visit_count', 'desc')
|
|
->limit($limit)
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Get visits by device type
|
|
*/
|
|
public function getVisitsByDeviceType(array $filters = []): array
|
|
{
|
|
$query = AnalyticsProductVisit::query();
|
|
|
|
if (isset($filters['date_from'])) {
|
|
$query->where('started_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (isset($filters['date_to'])) {
|
|
$query->where('started_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
return $query->selectRaw('device_type, COUNT(*) as count')
|
|
->groupBy('device_type')
|
|
->orderBy('count', 'desc')
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Get daily visit statistics
|
|
*/
|
|
public function getDailyStatistics(array $filters = []): array
|
|
{
|
|
$query = AnalyticsProductVisit::query();
|
|
|
|
if (isset($filters['date_from'])) {
|
|
$query->where('started_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (isset($filters['date_to'])) {
|
|
$query->where('started_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
return $query->selectRaw('DATE(started_at) as date, COUNT(*) as visits, COUNT(DISTINCT user_id) as unique_visitors')
|
|
->groupBy('date')
|
|
->orderBy('date', 'desc')
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Format duration in human readable format
|
|
*/
|
|
private function formatDuration(float $seconds): string
|
|
{
|
|
if ($seconds < 60) {
|
|
return round($seconds) . 's';
|
|
}
|
|
|
|
if ($seconds < 3600) {
|
|
$minutes = floor($seconds / 60);
|
|
$remainingSeconds = $seconds % 60;
|
|
return $minutes . 'm ' . round($remainingSeconds) . 's';
|
|
}
|
|
|
|
$hours = floor($seconds / 3600);
|
|
$remainingSeconds = $seconds % 3600;
|
|
$minutes = floor($remainingSeconds / 60);
|
|
$remainingSeconds = $remainingSeconds % 60;
|
|
|
|
return $hours . 'h ' . $minutes . 'm ' . round($remainingSeconds) . 's';
|
|
}
|
|
|
|
/**
|
|
* Get product visit by ID
|
|
*/
|
|
public function findById(int $id): ?AnalyticsProductVisit
|
|
{
|
|
return AnalyticsProductVisit::find($id);
|
|
}
|
|
|
|
/**
|
|
* Get visits by session ID
|
|
*/
|
|
public function getBySessionId(string $sessionId): Collection
|
|
{
|
|
return AnalyticsProductVisit::where('session_id', $sessionId)
|
|
->orderBy('started_at', 'desc')
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Bulk insert visits
|
|
*/
|
|
public function bulkInsert(array $visits): bool
|
|
{
|
|
try {
|
|
AnalyticsProductVisit::insert($visits);
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|