Explorar o código

absence_report - modificata logica generazione report

ferrari hai 1 mes
pai
achega
138a83a3b8

+ 218 - 45
app/Http/Livewire/AbsenceReport.php

@@ -2,13 +2,16 @@
 
 namespace App\Http\Livewire;
 
+use Illuminate\Support\Carbon;
 use Livewire\Component;
 
 class AbsenceReport extends Component
 {
 
     public $records;
-
+    public $record_assenze;
+    
+    public $fiscalStartMonth = 9;
     public $year;
 
     public function mount()
@@ -19,71 +22,241 @@ class AbsenceReport extends Component
     public function render()
     {
         setlocale(LC_ALL, 'it_IT');
+        
+        $this->record_assenze = [];
+
+        $today = now();
+        $this->year = ($today->month >= $this->fiscalStartMonth) ? $today->year : $today->year - 1;
+
+        $dayMap = [
+            'lun' => 1,
+            'mar' => 2,
+            'mer' => 3,
+            'gio' => 4,
+            'ven' => 5,
+            'sab' => 6,
+            'dom' => 0,
+        ];
+
+        try {
+            $courses = \App\Models\Course::whereDate('date_from', '<=', now())->whereDate('date_to', '>=', now())->where('active', true)->where('enabled', true)->get();
+            foreach ($courses as $course) {
+                $course_members = \App\Models\MemberCourse::where('course_id', $course->id)->get();
+                $this->record_assenze[$course->id] = [
+                    'course' => $course,
+                    'members' => []
+                ];
+
+                foreach ($course_members as $course_member) {
+                    $calendars_query = \App\Models\Calendar::where('course_id', $course->id);
+
+                    $calendars_query->where(function ($c_query) use ($course_member, $dayMap) {
+                        $months = array_column(array_filter(json_decode($course_member->months, true), function ($month) {
+                            return $month['status'] != 2;
+                        }), "m");
+                        sort($months);
 
-        $this->records = [];
+                        $when = json_decode($course_member->when, true);
+                        foreach ($when as $period) {
+                            $days = $period['day'];
+
+                            if ($days) {
+                                $from = $period['from'];
+                                $to = $period['to'];
+
+                                $ranges = $this->generateFiscalDateRanges($months, $days, $dayMap, $from, $to);
+
+                                foreach ($ranges as $range) {
+                                    $date_from = $range['from'];
+                                    $date_to   = $range['to'];
+
+                                    $c_query->orWhere(function ($query) use ($date_from, $date_to) {
+                                        $query->where('from', $date_from)
+                                            ->where('to',   $date_to);
+                                    });
+                                }
+                            }
+                        }
+                    });
+                    $calendars_query->orderBy('to', 'desc');
+                    $calendars = $calendars_query->get();
+
+                    $this->record_assenze[$course->id]['members'][$course_member->id] = [
+                        'member' => $course_member->member,
+                        'count' => 0,
+                        'dates' => []
+                    ];
+                    foreach ($calendars as $calendar) {
+                        $presence_query = \App\Models\Presence::where('calendar_id', $calendar->id)->where('member_id', $course_member->member_id);
+                        $presence = $presence_query->first();
+
+                        if (!$presence) {
+                            $this->record_assenze[$course->id]['members'][$course_member->id]['count']++;
+                            $this->record_assenze[$course->id]['members'][$course_member->id]['dates'][] = [
+                                'calendar_id' => $calendar->id, 
+                                'date' => Carbon::parse($calendar->from)->translatedFormat('d/m'),
+                            ];
+                        } else {
+                            break;
+                        }
+                    }
+
+                    if ($this->record_assenze[$course->id]['members'][$course_member->id]['count'] < 2) {
+                        unset($this->record_assenze[$course->id]['members'][$course_member->id]);
+                    }
+                }
+
+                if (empty($this->record_assenze[$course->id]['members'])) {
+                    unset($this->record_assenze[$course->id]);
+                } else {
+                    usort($this->record_assenze[$course->id]['members'], function($a, $b) {
+                        $result = $a['count'] < $b['count'];
+                        if ($a['count'] == $b['count']) {
+                            $result = strcmp($a['member']->last_name, $b['member']->last_name);
+                            if ($result == 0) {
+                                $result = strcmp($a['member']->first_name, $b['member']->first_name);
+                            }
+                        }
+                        return $result;
+                    });
+                }
+            }
+        } catch (\Throwable $e) {
+            dd($e->getMessage());
+        }
+
+        // $this->records = [];
 
         // $to = date("Y-m-d 23:59:59");
         // $calendars = \App\Models\Calendar::where('from', '<=', $to)->orderBy('from')->get();
 
-        $month = date("n");
-        $this->year = ($month >= 9) ? date("Y") : date("Y") - 1;
+        // $month = date("n");
+        // $this->year = ($month >= 9) ? date("Y") : date("Y") - 1;
+
+        // $start = date("Y-m-d H:i:s", mktime(0, 0, 0, 9, 1, $this->year));
+        // $end   = date("Y-m-d 23:59:59");
+
+        // $calendars = \App\Models\Calendar::whereBetween('from', [$start, $end])->orderBy('from')->get();
 
-        $start = date("Y-m-d H:i:s", mktime(0, 0, 0, 9, 1, $this->year));
-        $end   = date("Y-m-d 23:59:59");
+        // foreach ($calendars as $calendar) {
 
-        $calendars = \App\Models\Calendar::whereBetween('from', [$start, $end])->orderBy('from')->get();
+        //     $presences = \App\Models\Presence::where('calendar_id', $calendar->id)->where('status', '<>', 99);
+        //     $presences = $presences->pluck('member_id')->toArray();
+        //     $presences_annullate = \App\Models\Presence::where('calendar_id', $calendar->id)->where('status', 99)->pluck('member_id')->toArray();
 
-        foreach ($calendars as $calendar) {
+        //     $days = ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'];
+        //     $dow = date('w', strtotime($calendar->from));
+        //     $d = $days[$dow];
 
-            $presences = \App\Models\Presence::where('calendar_id', $calendar->id)->where('status', '<>', 99);
-            $presences = $presences->pluck('member_id')->toArray();
-            $presences_annullate = \App\Models\Presence::where('calendar_id', $calendar->id)->where('status', 99)->pluck('member_id')->toArray();
+        //     $h = date('H:i', strtotime($calendar->from));
 
-            $days = ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'];
-            $dow = date('w', strtotime($calendar->from));
-            $d = $days[$dow];
+        //     // Elenco corsi per tipologia in base al calendario
+        //     $courses = \App\Models\Course::where('name', $calendar->name)->where('date_from', '<=', $calendar->from)->where('date_to', '>=', $calendar->to);
+        //     $courses = $courses->pluck('id')->toArray();
 
-            $h = date('H:i', strtotime($calendar->from));
+        //     $months = date("n", strtotime($calendar->from));
 
-            // Elenco corsi per tipologia in base al calendario
-            $courses = \App\Models\Course::where('name', $calendar->name)->where('date_from', '<=', $calendar->from)->where('date_to', '>=', $calendar->to);
-            $courses = $courses->pluck('id')->toArray();
+        //     // Elenco utenti iscritti al corso "padre"
+        //     $members = \App\Models\MemberCourse::where('when', 'like', "%" . $d . "%")
+        //         ->where('when', 'like', '%"from":"' . $h . '"%')
+        //         ->whereNot('months', 'like', '%"m":' . $months . ',"status":2%')
+        //         ->whereDate('date_from', '<=', $calendar->from)
+        //         ->whereDate('date_to', '>=', $calendar->from)
+        //         ->whereIn('course_id', $courses)
+        //         ->orderBy('member_id')
+        //         ->get();
+        //     //$members = \App\Models\MemberCourse::where('when', 'like', "%" . $d . "%")->where('when', 'like', '%"from":"' . $h . '"%')->whereIn('member_id', $presences)->whereIn('course_id', $courses)->get();
+        //     foreach ($members as $member) {
 
-            $months = date("n", strtotime($calendar->from));
+        //         $presence = \App\Models\Presence::where('member_id', $member->member->id)->where('calendar_id', $calendar->id)->first();
 
-            // Elenco utenti iscritti al corso "padre"
-            $members = \App\Models\MemberCourse::where('when', 'like', "%" . $d . "%")
-                ->where('when', 'like', '%"from":"' . $h . '"%')
-                ->whereNot('months', 'like', '%"m":' . $months . ',"status":2%')
-                ->whereDate('date_from', '<=', $calendar->from)                                 
-                ->whereDate('date_to', '>=', $calendar->from)      
-                ->whereIn('course_id', $courses)
-                ->orderBy('member_id')
-                ->get();
-            //$members = \App\Models\MemberCourse::where('when', 'like', "%" . $d . "%")->where('when', 'like', '%"from":"' . $h . '"%')->whereIn('member_id', $presences)->whereIn('course_id', $courses)->get();
-            foreach ($members as $member) {
+        //         if (!in_array($member->member->id, $presences)) {
+        //             if (!in_array($member->member->id, $presences_annullate)) {
+        //                 if (array_key_exists($member->member->id, $this->records)) {
+        //                     $this->records[$member->member->id]['total'] += 1;
+        //                     $this->records[$member->member->id]['date'] .= " - " . date("d/m", strtotime($calendar->from));
+        //                 } else
+        //                     $this->records[$member->member->id] = array("last_name" => $member->member->last_name, "first_name" => $member->member->first_name, "course" => $calendar->name, "total" => 1, "date" => date("d/m", strtotime($calendar->from)));
+        //             }
+        //         } else {
+        //             if (array_key_exists($member->member->id, $this->records))
+        //                 unset($this->records[$member->member->id]);
+        //         }
+        //     }
+        // }
 
-                $presence = \App\Models\Presence::where('member_id', $member->member->id)->where('calendar_id', $calendar->id)->first();
+        // array_multisort(array_column($this->records, 'total'), SORT_DESC, $this->records);
 
-                if (!in_array($member->member->id, $presences)) {
-                    if (!in_array($member->member->id, $presences_annullate)) {
-                        if (array_key_exists($member->member->id, $this->records)) {
-                            $this->records[$member->member->id]['total'] += 1;
-                            $this->records[$member->member->id]['date'] .= " - " . date("d/m", strtotime($calendar->from));
-                        } else
-                            $this->records[$member->member->id] = array("last_name" => $member->member->last_name, "first_name" => $member->member->first_name, "course" => $calendar->name, "total" => 1, "date" => date("d/m", strtotime($calendar->from)));
+        return view('livewire.absence_report');
+    }
+
+    protected function generateFiscalDateRanges($months, $days, $dayMap, $fromTime, $toTime)
+    {
+        $limit = now()->endOfDay();
+
+        $today = $limit;
+
+        $startYear = ($today->month >= $this->fiscalStartMonth) ? $today->year : $today->year - 1;
+
+        $allowedDow = collect($days)
+            ->map(fn($d) => $dayMap[$d] ?? null)
+            ->filter(fn($v) => $v !== null)
+            ->unique()
+            ->values();
+
+        sort($months);
+
+        $fromCarbon = Carbon::parse($fromTime);
+        $toCarbon = Carbon::parse($toTime);
+
+        $fromHour = $fromCarbon->hour;
+        $fromMinute = $fromCarbon->minute;
+        $fromSecond = $fromCarbon->second;
+
+        $toHour = $toCarbon->hour;
+        $toMinute = $toCarbon->minute;
+        $toSecond = $toCarbon->second;
+
+        $ranges = [];
+
+        foreach ($months as $month) {
+            $yearForMonth = ($month >= $this->fiscalStartMonth)
+                ? $startYear
+                : $startYear + 1;
+
+            if (
+                $yearForMonth > $limit->year ||
+                ($yearForMonth === $limit->year && $month > $limit->month)
+            ) {
+                continue;
+            }
+
+            $firstOfMonth = Carbon::create($yearForMonth, $month, 1)->startOfDay();
+
+            foreach ($allowedDow as $dow) {
+                $offset  = ($dow - $firstOfMonth->dayOfWeek + 7) % 7;
+                $current = $firstOfMonth->copy()->addDays($offset);
+
+                while ($current->month === $month) {
+                    $fromDateTime = $current->copy()->setTime($fromHour, $fromMinute, $fromSecond);
+                    $toDateTime   = $current->copy()->setTime($toHour, $toMinute, $toSecond);
+
+                    if ($fromDateTime->gt($limit)) {
+                        break;
                     }
-                }
-                else
-                {
-                    if (array_key_exists($member->member->id, $this->records))
-                        unset($this->records[$member->member->id]);
+
+                    $ranges[] = [
+                        'from' => $fromDateTime,
+                        'to'   => $toDateTime,
+                    ];
+
+                    $current->addWeek();
                 }
             }
         }
 
-        array_multisort(array_column($this->records, 'total'), SORT_DESC, $this->records);
+        usort($ranges, fn($a, $b) => $a['from'] <=> $b['from']);
 
-        return view('livewire.absence_report');
+        return $ranges;
     }
 }

+ 11 - 0
app/Models/Course.php

@@ -129,4 +129,15 @@ class Course extends Model
         return \App\Models\MemberCourse::where('course_id', $this->id)->count();
     }
 
+    public function getDetailsName() {
+        $courseName = $this->name ?? 'Corso Sconosciuto';
+        $levelName = is_object($this->level) ? $this->level->name : '';
+        $frequencyName = is_object($this->frequency) ? $this->frequency->name : '';
+
+        $displayNameParts = [$courseName];
+        if ($levelName) $displayNameParts[] = $levelName;
+        if ($frequencyName) $displayNameParts[] = $frequencyName;
+
+        return implode(' - ', $displayNameParts);
+    }
 }

+ 4 - 0
resources/views/layouts/app.blade.php

@@ -208,6 +208,10 @@
                 print "Profilo utenti";
             if (Request::is('reports'))
                 print "Reports";
+            if (Request::is('presence_reports'))
+                print "Report presenze";
+            if (Request::is('absence_reports'))
+                print "Assenze";
             @endphp
             </h3>
 

+ 35 - 2
resources/views/livewire/absence_report.blade.php

@@ -11,7 +11,40 @@
 
     <br>
 
-    <div class="row">
+    @foreach ($record_assenze as $record_data)
+        <div class="row mb-5">
+            <div class="col-12 mb-2 sticky-top">
+                <h3 class="primary">{{$record_data['course']->getDetailsName()}}</h3>
+            </div>
+            <div class="col-12">
+                <table class="report-table">
+                    <thead>
+                        <tr>
+                            <td style="width: 20%">Cognome</td>
+                            <td style="width: 20%">Nome</td>
+                            <td style="width: 10%">N. assenze</td>
+                            <td>Date</td>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        @foreach($record_data['members'] as $member)
+                        <tr @if($loop->index % 2 == 1)style="background-color: rgba(12 97 151 / 0.05);"@endif>
+                            <td>{{$member['member']->last_name}}</td>
+                            <td>{{$member['member']->first_name}}</td>
+                            <td>{{$member["count"]}}</td>
+                            <td>
+                                @foreach ($member["dates"] as $calendar_date)
+                                    <a href="/presences?calendarId={{$calendar_date['calendar_id']}}" target="_blank">{{$calendar_date['date']}}</a>@if (!$loop->last) - @endif
+                                @endforeach
+                            </td>
+                        </tr>
+                        @endforeach
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    @endforeach
+    {{-- <div class="row">
         <div class="col-12 mb-3">
             <h3 class="primary">Assenze {{$year}}/{{$year+1}}</h3>
         </div>
@@ -39,7 +72,7 @@
                 </tbody>
             </table>
         </div>
-    </div>
+    </div> --}}
 </div>
 
 @push('css')