Initial commit
This commit is contained in:
130
app/Http/Controllers/IssueReportsController.php
Normal file
130
app/Http/Controllers/IssueReportsController.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Issue;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class IssueReportsController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
// Date range filter (default: last 30 days)
|
||||
$startDate = $request->date('start_date', now()->subDays(30));
|
||||
$endDate = $request->date('end_date', now());
|
||||
|
||||
// Overview Statistics
|
||||
$stats = [
|
||||
'total_issues' => Issue::count(),
|
||||
'open_issues' => Issue::open()->count(),
|
||||
'closed_issues' => Issue::closed()->count(),
|
||||
'overdue_issues' => Issue::overdue()->count(),
|
||||
];
|
||||
|
||||
// Issues by Status
|
||||
$issuesByStatus = Issue::select('status', DB::raw('count(*) as count'))
|
||||
->groupBy('status')
|
||||
->get()
|
||||
->mapWithKeys(fn($item) => [$item->status => $item->count]);
|
||||
|
||||
// Issues by Priority
|
||||
$issuesByPriority = Issue::select('priority', DB::raw('count(*) as count'))
|
||||
->groupBy('priority')
|
||||
->get()
|
||||
->mapWithKeys(fn($item) => [$item->priority => $item->count]);
|
||||
|
||||
// Issues by Type
|
||||
$issuesByType = Issue::select('issue_type', DB::raw('count(*) as count'))
|
||||
->groupBy('issue_type')
|
||||
->get()
|
||||
->mapWithKeys(fn($item) => [$item->issue_type => $item->count]);
|
||||
|
||||
// Issues Created Over Time (last 30 days)
|
||||
$issuesCreatedOverTime = Issue::select(
|
||||
DB::raw('DATE(created_at) as date'),
|
||||
DB::raw('count(*) as count')
|
||||
)
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->groupBy('date')
|
||||
->orderBy('date')
|
||||
->get();
|
||||
|
||||
// Issues Closed Over Time (last 30 days)
|
||||
$issuesClosedOverTime = Issue::select(
|
||||
DB::raw('DATE(closed_at) as date'),
|
||||
DB::raw('count(*) as count')
|
||||
)
|
||||
->whereNotNull('closed_at')
|
||||
->whereBetween('closed_at', [$startDate, $endDate])
|
||||
->groupBy('date')
|
||||
->orderBy('date')
|
||||
->get();
|
||||
|
||||
// Assignee Performance
|
||||
$assigneePerformance = User::select('users.id', 'users.name')
|
||||
->leftJoin('issues', 'users.id', '=', 'issues.assigned_to_user_id')
|
||||
->selectRaw('count(issues.id) as total_assigned')
|
||||
->selectRaw('sum(case when issues.status = ? then 1 else 0 end) as completed', [Issue::STATUS_CLOSED])
|
||||
->selectRaw('sum(case when issues.due_date < NOW() and issues.status != ? then 1 else 0 end) as overdue', [Issue::STATUS_CLOSED])
|
||||
->groupBy('users.id', 'users.name')
|
||||
->having('total_assigned', '>', 0)
|
||||
->orderByDesc('total_assigned')
|
||||
->limit(10)
|
||||
->get()
|
||||
->map(function ($user) {
|
||||
$user->completion_rate = $user->total_assigned > 0
|
||||
? round(($user->completed / $user->total_assigned) * 100, 1)
|
||||
: 0;
|
||||
return $user;
|
||||
});
|
||||
|
||||
// Time Tracking Metrics
|
||||
$timeTrackingMetrics = Issue::selectRaw('
|
||||
sum(estimated_hours) as total_estimated,
|
||||
sum(actual_hours) as total_actual,
|
||||
avg(estimated_hours) as avg_estimated,
|
||||
avg(actual_hours) as avg_actual
|
||||
')
|
||||
->whereNotNull('estimated_hours')
|
||||
->first();
|
||||
|
||||
// Top Labels Used
|
||||
$topLabels = DB::table('issue_labels')
|
||||
->select('issue_labels.id', 'issue_labels.name', 'issue_labels.color', DB::raw('count(issue_label_pivot.issue_id) as usage_count'))
|
||||
->leftJoin('issue_label_pivot', 'issue_labels.id', '=', 'issue_label_pivot.issue_label_id')
|
||||
->groupBy('issue_labels.id', 'issue_labels.name', 'issue_labels.color')
|
||||
->having('usage_count', '>', 0)
|
||||
->orderByDesc('usage_count')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
// Average Resolution Time (days)
|
||||
$avgResolutionTime = Issue::whereNotNull('closed_at')
|
||||
->selectRaw('avg(TIMESTAMPDIFF(DAY, created_at, closed_at)) as avg_days')
|
||||
->value('avg_days');
|
||||
|
||||
// Recent Activity (last 10 issues)
|
||||
$recentIssues = Issue::with(['creator', 'assignee'])
|
||||
->latest()
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
return view('admin.issue-reports.index', compact(
|
||||
'stats',
|
||||
'issuesByStatus',
|
||||
'issuesByPriority',
|
||||
'issuesByType',
|
||||
'issuesCreatedOverTime',
|
||||
'issuesClosedOverTime',
|
||||
'assigneePerformance',
|
||||
'timeTrackingMetrics',
|
||||
'topLabels',
|
||||
'avgResolutionTime',
|
||||
'recentIssues',
|
||||
'startDate',
|
||||
'endDate'
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user