Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
forbidals
/
admin_panel
/
app
/
Http
/
Controllers
:
ClassSchoolController.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php namespace App\Http\Controllers; use App\Models\Fee; use App\Models\Exam; use App\Models\Syllabus; use App\Repositories\ClassSchool\ClassSchoolInterface; use App\Repositories\ClassSection\ClassSectionInterface; use App\Repositories\ClassSubject\ClassSubjectInterface; use App\Repositories\ElectiveSubjectGroup\ElectiveSubjectGroupInterface; use App\Repositories\Medium\MediumInterface; use App\Repositories\Section\SectionInterface; use App\Repositories\Semester\SemesterInterface; use App\Repositories\SessionYear\SessionYearInterface; use App\Repositories\Shift\ShiftInterface; use App\Repositories\Stream\StreamInterface; use App\Repositories\Subject\SubjectInterface; use App\Repositories\Timetable\TimetableInterface; use App\Rules\uniqueForSchool; use App\Services\BootstrapTableService; use App\Services\CachingService; use App\Services\ResponseService; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Validator; use Throwable; class ClassSchoolController extends Controller { private MediumInterface $medium; private SectionInterface $section; private ClassSchoolInterface $class; private ClassSectionInterface $classSection; private SubjectInterface $subject; private ClassSubjectInterface $classSubject; private ElectiveSubjectGroupInterface $electiveSubjectGroup; private CachingService $cache; private SemesterInterface $semester; private ShiftInterface $shift; private StreamInterface $stream; private TimetableInterface $timetable; public function __construct(MediumInterface $medium, SectionInterface $section, ClassSchoolInterface $class, ClassSectionInterface $classSection, SubjectInterface $subject, ClassSubjectInterface $classSubject, ElectiveSubjectGroupInterface $electiveSubjectGroup, SemesterInterface $semester, CachingService $cache, ShiftInterface $shift, StreamInterface $stream, TimetableInterface $timetable) { $this->medium = $medium; $this->section = $section; $this->class = $class; $this->classSection = $classSection; $this->subject = $subject; $this->classSubject = $classSubject; $this->electiveSubjectGroup = $electiveSubjectGroup; $this->semester = $semester; $this->cache = $cache; $this->shift = $shift; $this->stream = $stream; $this->timetable = $timetable; } public function index() { ResponseService::noPermissionThenRedirect('class-list'); $classes = $this->class->builder()->orderBy('id', 'DESC')->with('stream', 'medium', 'sections')->get(); $sections = $this->section->builder()->orderBy('id', 'ASC')->get(); $mediums = $this->medium->builder()->orderBy('id', 'ASC')->get(); $subjects = $this->subject->builder()->orderBy('id', 'ASC')->get(); $semesters = $this->semester->all(); $shifts = $this->shift->active(); $streams = $this->stream->all(); return response(view('class.index', compact('classes', 'sections', 'mediums', 'subjects', 'semesters', 'shifts', 'streams'))); } public function store(Request $request) { ResponseService::noPermissionThenSendJson('class-create'); $validator = Validator::make($request->all(), [ 'medium_id' => 'required|numeric', 'name' => [ 'required', new uniqueForSchool('classes', ['name' => $request->name, 'medium_id' => $request->medium_id, 'stream_id' => $request->stream_id, 'shift_id' => $request->shift_id]) ], 'stream_id' => 'nullable|array', 'shift_id' => 'nullable|numeric', 'stream_id.*' => 'nullable|numeric', 'section_id' => 'nullable|array', 'section_id.*.*' => 'nullable|numeric', ]); if ($validator->fails()) { ResponseService::errorResponse($validator->errors()->first()); } try { DB::beginTransaction(); // $request->stream_id = $request->stream_id ?? [0]; /* Create Class */ if (!empty($request->stream_id) && $request->stream_id[0] != null) { foreach ($request->stream_id as $stream) { $classDetails = [ ...$request->all(), 'stream_id' => ($stream != 0) ? $stream : null, 'include_semesters' => $request->include_semesters[$stream] ?? 0, ]; $class = $this->class->create($classDetails); /* Create Class Sections */ $class_section = array(); if (!empty($request->section_id[$stream])) { foreach ($request->section_id[$stream] as $section_id) { $class_section[] = array('class_id' => $class->id, 'section_id' => $section_id, 'medium_id' => $request->medium_id); } } else { $class_section[] = array('class_id' => $class->id, 'medium_id' => $request->medium_id); } $this->classSection->createBulk($class_section); } } else { $classDetails = [ ...$request->all(), 'stream_id' => null, 'include_semesters' => $request->include_semesters[0] ?? 0, ]; $class = $this->class->create($classDetails); /* Create Class Sections */ $class_section = array(); if (!empty($request->section_id[0])) { foreach ($request->section_id[0] as $section_id) { $class_section[] = array('class_id' => $class->id, 'section_id' => $section_id, 'medium_id' => $request->medium_id); } } else { $class_section[] = array('class_id' => $class->id, 'medium_id' => $request->medium_id); } $this->classSection->createBulk($class_section); } DB::commit(); ResponseService::successResponse('Data Stored Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function edit($id) { ResponseService::noPermissionThenRedirect('class-edit'); $class = $this->class->findById($id, ['*'], ['stream', 'sections', 'core_subjects:id', 'elective_subject_groups.subjects:id']); $class_section = $class->sections->pluck('id'); $subjects = $this->subject->builder()->where('medium_id', $class->medium_id)->orderBy('id', 'ASC')->get(); $sections = $this->section->builder()->orderBy('id', 'ASC')->get(); $semesters = $this->semester->all(); $shifts = $this->shift->active(); $streams = $this->stream->all(); return response(view('class.edit', compact('class', 'subjects', 'sections', 'class_section', 'id', 'semesters', 'shifts', 'streams'))); } public function update(Request $request, $id) { ResponseService::noPermissionThenRedirect('class-edit'); $validator = Validator::make($request->all(), [ 'name' => [ 'required', new uniqueForSchool('classes', ['name' => $request->name, 'medium_id' => $request->medium_id, 'stream_id' => $request->stream_id, 'shift_id' => $request->shift_id], $id) ], 'stream_id' => 'nullable|numeric', 'shift_id' => 'nullable|numeric', ]); if ($validator->fails()) { ResponseService::errorResponse($validator->errors()->first()); } try { DB::beginTransaction(); $sessionYearId = $this->cache->getSessionYear()->id; // Class Update $class = $this->class->findById($id, ['*'], ['class_sections']); $semesterIncluded = $request->include_semesters[0] ?? 0; if ($class->include_semesters != $semesterIncluded) { //If include_semester is changed then delete the class subjects $this->electiveSubjectGroup->builder()->where('class_id', $class->id)->where('session_year_id', $sessionYearId)->delete(); $this->classSubject->builder()->where('class_id', $class->id)->where('session_year_id', $sessionYearId)->delete(); } // if (count($class->class_sections ?? []) == 0 && count($request->section_id ?? []) == 0) { // ResponseService::errorResponse("Class Section is Required"); // } $this->class->update($id, [...$request->all(), 'include_semesters' => $semesterIncluded]); // Section Update if (!empty($request->section_id)) { $class_section = array(); foreach ($request->section_id ?? [] as $section_id) { $class_section[] = array( 'class_id' => $id, 'section_id' => $section_id, 'medium_id' => $class->medium_id, 'deleted_at' => null ); } $this->classSection->upsert($class_section, ['class_id', 'section_id'], ['deleted_at']); } // Subjects Update $coreSubjects = array(); if (!empty($request->core_subject)) { foreach ($request->core_subject as $row) { $coreSubjects[] = array('class_id' => $id, 'type' => "Compulsory", 'subject_id' => $row['id'], "elective_subject_group_id" => null, "semester_id" => $row['semester_id'] ?? null); } } // Upsert Elective Subjects $electiveSubject = []; if (!empty($request->elective_subject_group)) { foreach ($request->elective_subject_group as $subjectGroup) { $electiveSubjectGroup = $this->electiveSubjectGroup->updateOrCreate( ['id' => $subjectGroup['id'],], [ 'total_subjects' => count($subjectGroup['subject']), 'total_selectable_subjects' => $subjectGroup['total_selectable_subjects'], 'class_id' => $id, "semester_id" => $subjectGroup['semester_id'] ?? null ] ); foreach ($subjectGroup['subject'] as $subject) { $electiveSubject[] = array('class_id' => $id, 'type' => "Elective", 'subject_id' => $subject['id'], 'elective_subject_group_id' => $electiveSubjectGroup->id, "semester_id" => $subjectGroup['semester_id'] ?? null); } } } // Check that If Elective Subjects exists then merge or else store only Core Subjects $classSubjects = array_merge($coreSubjects, $electiveSubject); $this->classSubject->upsert($classSubjects, ['class_id', 'subject_id', 'semester_id'], ['type']); $sessionYearId = $this->cache->getSessionYear()->id; $this->timetable->builder()->where('session_year_id', $sessionYearId)->whereHas('class_section', function ($q) use ($id) { $q->where('class_id', $id); })->delete(); DB::commit(); ResponseService::successResponse('Data Updated Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function show(Request $request) { ResponseService::noPermissionThenRedirect('class-list'); $offset = request('offset', 0); $limit = request('limit', 10); $sort = request('sort', 'id'); $order = request('order', 'DESC'); $search = $request->search; $showDeleted = $request->show_deleted; // $currentSemester = $this->cache->getDefaultSemesterData(); $semesters = $this->semester->all(); $sql = $this->class->builder()->with('stream', 'sections', 'medium', 'stream:id,name', 'shift:id,name') ->where(function ($query) use ($search) { $query->when($search, function ($q) use ($search) { $q->where('id', 'LIKE', "%$search%")->orwhere('name', 'LIKE', "%$search%")->orWhereHas('sections', function ($q) use ($search) { $q->where('name', 'LIKE', "%$search%"); })->orWhereHas('medium', function ($q) use ($search) { $q->where('name', 'LIKE', "%$search%"); })->orWhereHas('shift', function ($q) use ($search) { $q->where('name', 'LIKE', "%$search%"); })->Owner(); }); }) ->when(!empty($showDeleted), function ($q) { $q->onlyTrashed()->Owner()->with('section'); }); if (!empty($request->medium_id)) { $sql = $sql->where('medium_id', $request->medium_id); } if (!empty($request->shift_id)) { $sql = $sql->where('shift_id', $request->shift_id); } $total = $sql->count(); if ($offset >= $total && $total > 0) { $lastPage = floor(($total - 1) / $limit) * $limit; // calculate last page offset $offset = $lastPage; } $sql->orderBy($sort, $order)->skip($offset)->take($limit); $res = $sql->get(); $bulkData = array(); $bulkData['total'] = $total; $rows = array(); $no = 1; foreach ($res as $row) { if ($request->show_deleted) { //Show Restore and Hard Delete Buttons $operate = BootstrapTableService::restoreButton(route('class.restore', $row->id)); $operate .= BootstrapTableService::trashButton(route('class.trash', $row->id)); } else { //Show Edit and Soft Delete Buttons $operate = BootstrapTableService::editButton(route('class.edit', $row->id), false); $operate .= BootstrapTableService::deleteButton(route('class.destroy', $row->id)); } $tempRow = $row->toArray(); $tempRow['no'] = $no++; if (empty($showDeleted)) { $tempRow['section_names'] = $row->sections->pluck('name'); } else { $tempRow['section_names'] = $row->section->pluck('name'); } $tempRow['semesters'] = $semesters; $tempRow['operate'] = $operate; $tempRow['created_at'] = $row->created_at; $tempRow['updated_at'] = $row->updated_at; $rows[] = $tempRow; } $bulkData['rows'] = $rows; return response()->json($bulkData); } public function destroy($id) { ResponseService::noPermissionThenSendJson('class-delete'); try { DB::beginTransaction(); $class = $this->class->findById($id, ['*'], ['class_sections']); // Safety Check: Prevent deletion if any historical data exists across any session $hasSubjects = $this->classSubject->builder()->where('class_id', $id)->exists(); $hasFees = Fee::where('class_id', $id)->exists(); $hasExams = Exam::where('class_id', $id)->exists(); $hasSectionsWithData = false; if ($class->class_sections) { foreach ($class->class_sections as $section) { // Check if students are assigned to this class section in any session if ($section->students()->exists()) { $hasSectionsWithData = true; break; } } } if ($hasSubjects || $hasFees || $hasExams || $hasSectionsWithData) { return ResponseService::errorResponse("Cannot delete this class because it is associated with records (subjects, fees, exams, or students) in one or more academic sessions. Please remove those associations first."); } if (!empty($class->class_sections)) { foreach ($class->class_sections as $section) { $section->delete(); } } $this->class->deleteById($id); DB::commit(); ResponseService::successResponse('Data Deleted Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function restore(int $id) { ResponseService::noPermissionThenSendJson('class-delete'); try { $this->class->findOnlyTrashedById($id)->restore(); $this->classSection->builder()->where('class_id', $id)->restore(); ResponseService::successResponse("Data Restored Successfully"); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function trash($id) { ResponseService::noPermissionThenSendJson('class-delete'); try { // Safety Check: Prevent permanent deletion if any historical data exists $hasSubjects = $this->classSubject->builder()->where('class_id', $id)->exists(); $hasFees = Fee::where('class_id', $id)->exists(); $hasExams = Exam::where('class_id', $id)->exists(); if ($hasSubjects || $hasFees || $hasExams) { return ResponseService::errorResponse("Cannot delete this class permanently because it is associated with subjects, fees, or exams in academic sessions."); } $this->class->findOnlyTrashedById($id)->forceDelete(); ResponseService::successResponse("Data Deleted Permanently"); } catch (Throwable $e) { ResponseService::logErrorResponse($e, "ClassSchool Controller -> Trash Method", 'cannot_delete_because_data_is_associated_with_other_data'); ResponseService::errorResponse(); } } public function classSubjectIndex() { ResponseService::noPermissionThenRedirect('class-list'); $classes = $this->class->builder()->orderBy('id', 'DESC')->with('stream', 'medium', 'sections')->get(); $sections = $this->section->builder()->orderBy('id', 'ASC')->get(); $mediums = $this->medium->builder()->orderBy('id', 'ASC')->get(); $subjects = $this->subject->builder()->orderBy('id', 'ASC')->get(); $semesters = $this->semester->all(); $shifts = $this->shift->active(); $streams = $this->stream->all(); return response(view('class-subject.index', compact('classes', 'sections', 'mediums', 'subjects', 'semesters', 'shifts', 'streams'))); } public function classSubjectEdit($id) { ResponseService::noPermissionThenRedirect('class-edit'); $sessionYearId = $this->cache->getSessionYear()->id; $class = $this->class->findById($id, ['*'], [ 'stream', 'sections', 'medium', 'shift', 'core_subjects' => function ($query) use ($sessionYearId) { $query->wherePivot('session_year_id', $sessionYearId); }, 'elective_subject_groups' => function ($query) use ($sessionYearId) { $query->where('session_year_id', $sessionYearId)->with(['subjects' => function ($q) use ($sessionYearId) { $q->where('class_subjects.session_year_id', $sessionYearId); }]); } ]); $subjects = $this->subject->builder()->where('medium_id', $class->medium_id)->orderBy('id', 'ASC')->get(); $semesters = $class->include_semesters ? $this->semester->all() : []; $syllabus = Syllabus::where('status', 'active')->where('class_id', $id)->get(); return response(view('class-subject.edit', compact('class', 'subjects', 'id', 'semesters', 'syllabus'))); } public function classSubjectUpdate(Request $request, $id) { ResponseService::noPermissionThenRedirect('class-edit'); $validator = Validator::make($request->all(), [ 'core_subject' => 'nullable|array', 'core_subject.*.id' => 'required|numeric', 'elective_subject_group' => 'array|nullable', 'elective_subjects.*.subject.*.id' => 'required|array', 'elective_subjects.*.total_selectable_subjects' => 'required|numeric' ]); if ($validator->fails()) { ResponseService::errorResponse($validator->errors()->first()); } try { $sessionYearId = $this->cache->getSessionYear()->id; $schoolId = Auth::user()->school_id; $coreSubjects = array(); if (!empty($request->core_subject)) { foreach ($request->core_subject as $row) { $coreSubjects[] = array( 'class_id' => $id, 'type' => "Compulsory", 'subject_id' => $row['id'], "elective_subject_group_id" => null, "semester_id" => $row['semester_id'] ?? null, "session_year_id" => $sessionYearId, "school_id" => $schoolId, 'syllabus_id' => $row['syllabus_id'] ?? null, ); } } // Scope deletion only to the current session year $this->classSubject->builder()->where('class_id', $id)->where('session_year_id', $sessionYearId)->delete(); // Upsert Elective Subjects $electiveSubject = []; if (!empty($request->elective_subject_group)) { foreach ($request->elective_subject_group as $subjectGroup) { $electiveSubjectGroup = $this->electiveSubjectGroup->updateOrCreate( ['id' => $subjectGroup['id'],], [ 'total_subjects' => count($subjectGroup['subject']), 'total_selectable_subjects' => $subjectGroup['total_selectable_subjects'], 'class_id' => $id, "semester_id" => $subjectGroup['semester_id'] ?? null, "session_year_id" => $sessionYearId, "school_id" => $schoolId ] ); foreach ($subjectGroup['subject'] as $subject) { $electiveSubject[] = array( 'class_id' => $id, 'type' => "Elective", 'subject_id' => $subject['id'], 'elective_subject_group_id' => $electiveSubjectGroup->id, "semester_id" => $subjectGroup['semester_id'] ?? null, "session_year_id" => $sessionYearId, "school_id" => $schoolId, 'syllabus_id' => $subject['syllabus_id'] ?? null, ); } } } // Check that If Elective Subjects exists then merge or else store only Core Subjects $classSubjects = array_merge($coreSubjects, $electiveSubject); foreach ($classSubjects as $subject) { // Check if the subject exists in the database and is soft-deleted FOR THIS SESSION YEAR $existingSubject = $this->classSubject->builder()->onlyTrashed() ->where('class_id', $subject['class_id']) ->where('subject_id', $subject['subject_id']) ->where('semester_id', $subject['semester_id']) ->where('session_year_id', $sessionYearId) ->first(); // If the subject exists and is soft-deleted, restore it if ($existingSubject && $existingSubject->trashed()) { $existingSubject->restore(); } } // Using model's query builder directly to bypass the broken SaaSRepository::upsert loop. // Unique keys now include session_year_id to match the database's updated unique index. $this->classSubject->builder()->upsert( $classSubjects, ['class_id', 'subject_id', 'semester_id', 'session_year_id'], ['type', 'elective_subject_group_id', 'school_id', 'syllabus_id'] ); DB::commit(); ResponseService::successResponse('Data Updated Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function classSubjectList(Request $request) { ResponseService::noPermissionThenRedirect('class-list'); $offset = request('offset', 0); $limit = request('limit', 10); $sort = request('sort', 'id'); $order = request('order', 'DESC'); $search = $request->search; $showDeleted = $request->show_deleted; $currentSemester = $this->cache->getDefaultSemesterData(); $semesters = $this->semester->all(); $sessionYearId = $this->cache->getSessionYear()->id; $sql = $this->class->builder()->with([ 'stream', 'sections', 'medium', 'stream:id,name', 'shift:id,name', 'core_subjects' => function ($query) use ($sessionYearId) { $query->wherePivot('session_year_id', $sessionYearId); }, 'elective_subject_groups' => function ($query) use ($sessionYearId) { $query->where('session_year_id', $sessionYearId)->with([ 'subjects' => function ($q) use ($sessionYearId) { $q->where('class_subjects.session_year_id', $sessionYearId); } ]); }, ])->where(function ($query) use ($search) { $query->when($search, function ($q) use ($search) { $q->where('id', 'LIKE', "%$search%")->orwhere('name', 'LIKE', "%$search%")->orWhereHas('sections', function ($q) use ($search) { $q->where('name', 'LIKE', "%$search%"); })->orWhereHas('medium', function ($q) use ($search) { $q->where('name', 'LIKE', "%$search%"); })->Owner(); }); }) ->when(!empty($showDeleted), function ($q) { $q->onlyTrashed()->Owner(); }); if (!empty($request->medium_id)) { $sql = $sql->where('medium_id', $request->medium_id); } if (!empty($request->shift_id)) { $sql = $sql->where('shift_id', $request->shift_id); } if (!empty($request->stream_id)) { $sql = $sql->where('stream_id', $request->stream_id); } if (!empty($request->core_subject_id)) { $sql = $sql->whereHas('core_subjects', function ($q) use ($request) { $q->where('id', $request->core_subject_id); }); } if (!empty($request->elective_subject_group_id)) { $sql = $sql->whereHas('elective_subject_groups.subjects', function ($q) use ($request) { $q->where('id', $request->elective_subject_group_id); }); } $total = $sql->count(); if ($offset >= $total && $total > 0) { $lastPage = floor(($total - 1) / $limit) * $limit; // calculate last page offset $offset = $lastPage; } $sql->orderBy($sort, $order)->skip($offset)->take($limit); $res = $sql->get(); $bulkData = array(); $bulkData['total'] = $total; $rows = array(); $no = 1; foreach ($res as $row) { $operate = ''; if ($showDeleted) { $operate = BootstrapTableService::restoreButton(route('class.restore', $row->id)); } else { $operate = BootstrapTableService::editButton(route('class.subject.edit', $row->id), false); } $tempRow = $row->toArray(); $tempRow['no'] = $no++; $tempRow['section_names'] = $row->sections->pluck('name'); $tempRow['semesters'] = $semesters; $tempRow['semester_wise_core_subjects'] = array(); // Explicitly filter core subjects by session year $coreSubjects = $row->core_subjects->filter(function ($data) use ($sessionYearId) { return $data->pivot->session_year_id == $sessionYearId; }); // Explicitly filter elective subject groups by session year $electiveSubjectGroups = $row->elective_subject_groups->filter(function ($data) use ($sessionYearId) { return $data->session_year_id == $sessionYearId; }); if ($row->include_semesters && $currentSemester->id) { $tempRow['core_subjects'] = array_values($coreSubjects->filter(function ($data) use ($currentSemester) { return $data->pivot->semester_id == $currentSemester->id; })->toArray()); $tempRow['elective_subject_groups'] = array_values($electiveSubjectGroups->filter(function ($data) use ($currentSemester) { return $data->semester_id == $currentSemester->id; })->toArray()); $tempRow['semester_wise_core_subjects'] = $coreSubjects->values()->toArray(); $tempRow['semester_wise_elective_subject_groups'] = $electiveSubjectGroups->values()->toArray(); } else { $tempRow['core_subjects'] = $coreSubjects->values()->toArray(); $tempRow['elective_subject_groups'] = $electiveSubjectGroups->values()->toArray(); } $tempRow['operate'] = $operate; $tempRow['created_at'] = $row->created_at; $tempRow['updated_at'] = $row->updated_at; $rows[] = $tempRow; } $bulkData['rows'] = $rows; return response()->json($bulkData); } public function deleteClassSubject($id) { // TODO : Set Permission try { DB::beginTransaction(); $class_subject = $this->classSubject->findById($id); if ($class_subject->type == "Elective") { $this->electiveSubjectGroup->findById($class_subject->elective_subject_group_id)->decrement('total_subjects'); } $class_subject->delete(); DB::commit(); ResponseService::successResponse('Data Deleted Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e, "ClassSchool Controller ->deleteClassSubject Method", 'cannot_delete_because_data_is_associated_with_other_data'); ResponseService::errorResponse(); } } public function deleteClassSubjectGroup($id) { // TODO : Set Permission try { // Delete Subject Group will automatically delete ClassSubject $this->electiveSubjectGroup->deleteById($id); ResponseService::successResponse('Data Deleted Successfully'); } catch (Throwable $e) { ResponseService::logErrorResponse($e, "ClassSchool Controller ->deleteClassSubjectGroup Method", 'cannot_delete_because_data_is_associated_with_other_data'); ResponseService::errorResponse(); } } public function classAttendance($id = null) { ResponseService::noPermissionThenSendJson('attendance-list'); try { $sessionYear = $this->cache->getDefaultSessionYear(); $sql = $this->classSection->builder()->select('id', 'section_id', 'class_id')->where('class_id', $id)->with('section', 'class', 'class.medium') ->withCount([ 'attendance as present' => function ($q) use ($sessionYear) { $q->where('type', 1)->where('session_year_id', $sessionYear->id); } ]) ->withCount([ 'attendance as absent' => function ($q) use ($sessionYear) { $q->where('type', 0)->where('session_year_id', $sessionYear->id); } ]) ->withCount([ 'attendance' => function ($q) use ($sessionYear) { $q->where('session_year_id', $sessionYear->id); } ]) ->get(); $data = $sql->map(function ($q) { if ($q->attendance_count) { return [ optional($q->section)->name ?? $q->class->full_name, number_format(($q->present * 100) / $q->attendance_count, 2) ]; } })->toArray(); $data = array_filter($data); if (count($data)) { $attendance = [ 'section' => $this->pluck($data, 0), 'data' => $this->pluck($data, 1) ]; } else { $attendance = [ 'section' => ['A', 'B', 'C', 'D'], 'data' => [0, 0, 0, 0] ]; } ResponseService::successResponse('Data Fetched Successfully', $attendance); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function pluck($array, $key) { return array_map(function ($item) use ($key) { return $item[$key]; }, $array); } }