query($params); return [ 'total' => (clone $query)->count(), 'pending' => (clone $query)->where('status', 0)->count(), 'processing' => (clone $query)->where('status', 1)->count(), 'completed' => (clone $query)->where('status', 2)->count(), 'by_type' => $this->group($params, 'type_code', 'type_name'), 'by_reason' => $this->group($params, 'reason_code', 'reason_name'), 'by_issue' => $this->group($params, 'issue_code', 'issue_name'), 'by_date' => $this->byDate($params), ]; } private function group(array $params, string $codeColumn, string $nameColumn): array { return $this->query($params) ->selectRaw("{$codeColumn} as code, {$nameColumn} as name, COUNT(*) as total") ->groupBy($codeColumn, $nameColumn) ->orderByDesc('total') ->orderBy($nameColumn) ->limit(20) ->get() ->map(static fn (object $item): array => [ 'code' => (string) $item->code, 'name' => (string) $item->name, 'total' => (int) $item->total, ]) ->all(); } private function byDate(array $params): array { $model = new ExceptionRecord(); $connection = $model->getConnection(); $table = $connection->getTablePrefix() . $model->getTable(); return $this->query($params) ->selectRaw("DATE_FORMAT(FROM_UNIXTIME({$table}.reported_at), '%Y-%m-%d') as date, COUNT(*) as total") ->groupBy('date') ->orderBy('date') ->get() ->map(static fn (object $item): array => [ 'date' => (string) $item->date, 'total' => (int) $item->total, ]) ->all(); } private function query(array $params): Builder { $model = new ExceptionRecord(); $query = $model->getConnection()->table($model->getTable())->whereNull('deleted_at'); foreach (['type_code', 'reason_code', 'issue_code', 'status'] as $field) { if (($params[$field] ?? '') !== '') { $query->where($field, $params[$field]); } } if (!empty($params['reported_at_range']) && is_array($params['reported_at_range']) && count($params['reported_at_range']) === 2) { $query->whereBetween('reported_at', [ strtotime((string) $params['reported_at_range'][0] . ' 00:00:00'), strtotime((string) $params['reported_at_range'][1] . ' 23:59:59'), ]); } else { $query->whereBetween('reported_at', [strtotime('-29 days 00:00:00'), time()]); } return $query; } }