Просмотр исходного кода

feat: enhance FranchisorDashboardService to include attendance and ticket details in overview

ebagabee 1 неделя назад
Родитель
Сommit
b086d58703
1 измененных файлов с 96 добавлено и 3 удалено
  1. 96 3
      app/Services/FranchisorDashboardService.php

+ 96 - 3
app/Services/FranchisorDashboardService.php

@@ -41,10 +41,13 @@ public function overview(array $unitIds = [], ?Carbon $startDate = null, ?Carbon
         return [
             'enrollments'     => $this->enrollments($unitIds),
             'birthdays'       => $this->birthdays($unitIds),
+            'attendance'      => $this->attendance($unitIds, $startDate, $endDate),
             'open_tickets'    => $this->openTickets($unitIds),
+            'tickets'         => $this->tickets($unitIds),
             'pending_tasks'   => $this->pendingTasks($unitIds),
             'general_revenue' => $this->generalRevenue($unitIds),
             'product_stock'   => $this->productStock(),
+            'products'        => $this->products(),
             'units_summary'   => $this->unitsSummary($unitIds, $startDate, $endDate),
         ];
     }
@@ -143,11 +146,81 @@ private function birthdays(array $unitIds): array
 
     private function openTickets(array $unitIds): int
     {
-        return (int) DB::table('support_tickets')
+        return (int) $this->openTicketsQuery($unitIds)->count();
+    }
+
+    private function tickets(array $unitIds): array
+    {
+        return $this->openTicketsQuery($unitIds)
+            ->orderByDesc('created_at')
+            ->get(['id', 'severity', 'created_at', 'sector', 'status', 'title'])
+            ->map(fn ($ticket) => [
+                'id'       => (int) $ticket->id,
+                'number'   => '#' . $ticket->id,
+                'title'    => $ticket->title,
+                'priority' => $ticket->severity,
+                'date'     => Carbon::parse($ticket->created_at)->format('d/m/Y'),
+                'sector'   => $ticket->sector ?: 'Não informado',
+                'status'   => $ticket->status,
+            ])
+            ->all();
+    }
+
+    private function openTicketsQuery(array $unitIds)
+    {
+        return DB::table('support_tickets')
             ->whereNull('deleted_at')
             ->where('status', 'in_progress')
-            ->when(!empty($unitIds), fn ($q) => $q->whereIn('unit_id', $unitIds))
-            ->count();
+            ->when(!empty($unitIds), fn ($q) => $q->where(function ($units) use ($unitIds) {
+                $units->whereIn('applicant_unit_id', $unitIds)
+                    ->orWhereIn('target_unit_id', $unitIds)
+                    ->orWhereIn('unit_id', $unitIds);
+            }));
+    }
+
+    private function attendance(array $unitIds, Carbon $startDate, Carbon $endDate): array
+    {
+        $rows = DB::table('units as u')
+            ->leftJoin('classes as c', function ($join) use ($startDate, $endDate) {
+                $join->on('c.unit_id', '=', 'u.id')
+                    ->whereNull('c.deleted_at')
+                    ->whereBetween('c.date_time_start', [$startDate, $endDate]);
+            })
+            ->leftJoin('class_attendances as ca', function ($join) {
+                $join->on('ca.class_id', '=', 'c.id')->whereNull('ca.deleted_at');
+            })
+            ->whereNull('u.deleted_at')
+            ->when(!empty($unitIds), fn ($q) => $q->whereIn('u.id', $unitIds))
+            ->groupBy('u.id', 'u.fantasy_name')
+            ->orderBy('u.fantasy_name')
+            ->get([
+                'u.id',
+                'u.fantasy_name',
+                DB::raw('COUNT(ca.id) as attendance_count'),
+                DB::raw('SUM(CASE WHEN ca.in_class = 1 THEN 1 ELSE 0 END) as present_count'),
+            ]);
+
+        $total = (int) $rows->sum('attendance_count');
+        $present = (int) $rows->sum('present_count');
+
+        return [
+            'average' => $total > 0 ? round(($present / $total) * 100, 1) : 0,
+            'units'   => $rows->map(function ($row) {
+                $count = (int) $row->attendance_count;
+                $average = $count > 0
+                    ? round(((int) $row->present_count / $count) * 100, 1)
+                    : 0;
+
+                return [
+                    'id'        => (int) $row->id,
+                    'unit'      => $row->fantasy_name,
+                    'frequency' => $average,
+                    'status'    => $count === 0
+                        ? 'Sem dados'
+                        : ($average >= 70 ? 'Alto' : 'Baixa'),
+                ];
+            })->all(),
+        ];
     }
 
     private function pendingTasks(array $unitIds): int
@@ -184,4 +257,24 @@ private function productStock(): int
             ->whereNull('deleted_at')
             ->sum('quantity');
     }
+
+    private function products(): array
+    {
+        return DB::table('products')
+            ->whereNull('deleted_at')
+            ->orderBy('name')
+            ->get(['id', 'name', 'quantity'])
+            ->map(function ($product) {
+                $quantity = (int) $product->quantity;
+
+                return [
+                    'id'       => (int) $product->id,
+                    'name'     => $product->name,
+                    'quantity' => $quantity,
+                    'status'   => $quantity <= 15
+                        ? 'Baixo'
+                        : ($quantity <= 30 ? 'Limitado' : 'Alto'),
+                ];
+            })->all();
+    }
 }