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
/
Api
:
ApiController.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php namespace App\Http\Controllers\Api; use App\Events\MessageSent; use App\Http\Controllers\Controller; use App\Models\Chat; use App\Models\ClassTeacher; use App\Models\Role; use App\Models\Students; use App\Models\SubjectTeacher; use App\Models\User; use App\Models\TransportationPayment; use App\Models\RouteVehicle; use App\Models\TransportationFee; use App\Repositories\Attachment\AttachmentInterface; use App\Repositories\Chat\ChatInterface; use App\Repositories\ClassSection\ClassSectionInterface; use App\Repositories\ExamResult\ExamResultInterface; use App\Repositories\Gallery\GalleryInterface; use App\Repositories\Grades\GradesInterface; use App\Repositories\Holiday\HolidayInterface; use App\Repositories\Leave\LeaveInterface; use App\Repositories\LeaveDetail\LeaveDetailInterface; use App\Repositories\LeaveMaster\LeaveMasterInterface; use App\Repositories\Medium\MediumInterface; use App\Repositories\PaymentConfiguration\PaymentConfigurationInterface; use App\Repositories\PaymentTransaction\PaymentTransactionInterface; use App\Repositories\SchoolSetting\SchoolSettingInterface; use App\Repositories\SessionYear\SessionYearInterface; use App\Repositories\Student\StudentInterface; use App\Repositories\User\UserInterface; use App\Services\CachingService; use App\Services\FcmTokenService; use App\Services\Payment\PaymentService; use App\Services\ResponseService; use App\Repositories\Fees\FeesInterface; use App\Repositories\ExtraFormField\ExtraFormFieldsInterface; use Auth; use DB; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use PDF; use Stripe\Exception\ApiErrorException; use Throwable; use App\Repositories\Files\FilesInterface; use App\Repositories\Message\MessageInterface; use App\Repositories\Transportation\PickupPointRepositoryInterface; use App\Rules\MaxFileSize; use App\Services\GeneralFunctionService; use Laravel\Sanctum\PersonalAccessToken; use App\Models\School; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Log; use App\Models\Notification; use App\Models\UserNotification; use App\Models\ClassSubject; use App\Models\Message; use App\Models\Subject; use Exception; use GuzzleHttp\Psr7\UploadedFile; class ApiController extends Controller { private CachingService $cache; private HolidayInterface $holiday; private StudentInterface $student; private PaymentConfigurationInterface $paymentConfiguration; private PaymentTransactionInterface $paymentTransaction; private GalleryInterface $gallery; private SessionYearInterface $sessionYear; private LeaveDetailInterface $leaveDetail; private LeaveMasterInterface $leaveMaster; private LeaveInterface $leave; private UserInterface $user; private MediumInterface $medium; private ClassSectionInterface $classSection; private FilesInterface $files; private ExamResultInterface $examResult; private GradesInterface $grade; private ChatInterface $chat; private MessageInterface $message; private AttachmentInterface $attachment; private SchoolSettingInterface $schoolSettings; private FeesInterface $fees; private PickupPointRepositoryInterface $pickupPoint; private ExtraFormFieldsInterface $extraFormFields; public function __construct(CachingService $cache, HolidayInterface $holiday, StudentInterface $student, PaymentConfigurationInterface $paymentConfiguration, PaymentTransactionInterface $paymentTransaction, GalleryInterface $gallery, SessionYearInterface $sessionYear, LeaveDetailInterface $leaveDetail, LeaveMasterInterface $leaveMaster, LeaveInterface $leave, UserInterface $user, MediumInterface $medium, ClassSectionInterface $classSection, ExamResultInterface $examResult, GradesInterface $grade, FilesInterface $files, ChatInterface $chat, MessageInterface $message, AttachmentInterface $attachment, SchoolSettingInterface $schoolSettings, FeesInterface $fees, PickupPointRepositoryInterface $pickupPoint, ExtraFormFieldsInterface $extraFormFields) { $this->cache = $cache; $this->holiday = $holiday; $this->student = $student; $this->paymentConfiguration = $paymentConfiguration; $this->paymentTransaction = $paymentTransaction; $this->gallery = $gallery; $this->sessionYear = $sessionYear; $this->leaveDetail = $leaveDetail; $this->leaveMaster = $leaveMaster; $this->leave = $leave; $this->user = $user; $this->medium = $medium; $this->classSection = $classSection; $this->files = $files; $this->examResult = $examResult; $this->grade = $grade; $this->chat = $chat; $this->message = $message; $this->attachment = $attachment; $this->schoolSettings = $schoolSettings; $this->fees = $fees; $this->pickupPoint = $pickupPoint; $this->extraFormFields = $extraFormFields; } public function logout(Request $request) { try { $user = $request->user(); // Remove FCM token for the specific device (if device_id or fcm_token provided) // Otherwise, remove all tokens for the user (full logout) $fcmTokenService = app(FcmTokenService::class); if ($request->device_id) { // Remove token for specific device $fcmTokenService->removeToken($user, null, $request->device_id); } elseif ($request->fcm_id) { // Remove specific FCM token $fcmTokenService->removeToken($user, $request->fcm_id); } else { // Remove all tokens for the user (full logout) $fcmTokenService->removeToken($user); } // Backward compatibility: Clear old fcm_id column $user->fcm_id = ''; if (isset($user->web_fcm)) { $user->web_fcm = ''; } $user->save(); // Delete the access token $token = $request->bearerToken(); if ($token) { $accessToken = PersonalAccessToken::findToken($token); if ($accessToken) { $accessToken->delete(); } } ResponseService::successResponse('Logout Successfully done'); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getHolidays(Request $request) { try { // $query->whereDate('date', '>=',$sessionYear->start_date) // ->whereDate('date', '<=',$sessionYear->end_date); $sessionYear = $this->cache->getDefaultSessionYear(); $settings = $this->cache->getSchoolSettings(); if ($request->child_id) { $child = $this->student->findById($request->child_id); $data = $this->holiday->builder()->where('school_id', $child->user->school_id); } else { $data = $this->holiday->builder(); } $sessionyearStartDate = carbon::createFromFormat($settings['date_format'], $sessionYear->start_date)->format('Y-m-d'); $sessionyearEndDate = carbon::createFromFormat($settings['date_format'], $sessionYear->end_date)->format('Y-m-d'); $data = $data->whereDate('date', '>=', $sessionyearStartDate) ->whereDate('date', '<=', $sessionyearEndDate)->get(); ResponseService::successResponse("Holidays Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getSettings(Request $request) { $validator = Validator::make($request->all(), [ 'type' => 'required|in:student_parent_privacy_policy,teacher_staff_privacy_policy,student_terms_condition,teacher_terms_condition,contact_us,about_us,app_settings,fees_settings,terms_condition,privacy_policy' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $systemSettings = $this->cache->getSystemSettings(); if ($request->type == "app_settings") { $data = array( 'app_link' => $systemSettings['app_link'] ?? "", 'ios_app_link' => $systemSettings['ios_app_link'] ?? "", 'app_version' => $systemSettings['app_version'] ?? "", 'ios_app_version' => $systemSettings['ios_app_version'] ?? "", 'force_app_update' => $systemSettings['force_app_update'] ?? "", 'app_maintenance' => $systemSettings['app_maintenance'] ?? "", 'teacher_app_link' => $systemSettings['teacher_app_link'] ?? "", 'teacher_ios_app_link' => $systemSettings['teacher_ios_app_link'] ?? "", 'teacher_app_version' => $systemSettings['teacher_app_version'] ?? "", 'teacher_ios_app_version' => $systemSettings['teacher_ios_app_version'] ?? "", 'teacher_force_app_update' => $systemSettings['teacher_force_app_update'] ?? "", 'teacher_app_maintenance' => $systemSettings['teacher_app_maintenance'] ?? "", 'tagline' => $systemSettings['tag_line'] ?? "", 'title' => $systemSettings['system_name'] ?? "", ); } else { $data = isset($systemSettings[$request->type]) ? htmlspecialchars_decode($systemSettings[$request->type]) : ""; } ResponseService::successResponse("Data Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } protected function forgotPassword(Request $request) { $request->validate([ 'email' => "required|email", 'school_code' => 'required' ]); try { $schoolCode = $request->school_code; if ($schoolCode) { $school = School::on('mysql')->where('code', $schoolCode)->first(); if ($school) { DB::setDefaultConnection('school'); Config::set('database.connections.school.database', $school->database_name); DB::purge('school'); DB::connection('school')->reconnect(); DB::setDefaultConnection('school'); $response = Password::sendResetLink(['email' => $request->email]); if ($response == Password::RESET_LINK_SENT) { ResponseService::successResponse("Forgot Password email send successfully"); } else { ResponseService::errorResponse("Cannot send Reset Password Link.Try again later", null, config('constants.RESPONSE_CODE.RESET_PASSWORD_FAILED')); } } else { return response()->json(['error' => true, 'message' => 'Invalid school code'], 200); } } else { return response()->json(['error' => true, 'message' => 'Unauthenticated'], 200); } } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } protected function changePassword(Request $request) { $validator = Validator::make($request->all(), [ 'current_password' => 'required', 'new_password' => 'required|min:6', 'new_confirm_password' => 'same:new_password', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $user = $request->user(); if (Hash::check($request->current_password, $user->password)) { $user->update(['password' => Hash::make($request->new_password)]); ResponseService::successResponse("Password Changed successfully."); } else { ResponseService::errorResponse("Invalid Password", null, config('constants.RESPONSE_CODE.INVALID_PASSWORD')); } } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getPaymentMethod(Request $request) { if (Auth::user()->hasRole('Guardian')) { $validator = Validator::make($request->all(), [ 'child_id' => 'required|numeric', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } } try { $response = $this->paymentConfiguration->builder()->select('payment_method', 'status')->pluck('status', 'payment_method'); ResponseService::successResponse("Payment Details Fetched", $response); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getPaymentConfirmation(Request $request) { $validator = Validator::make($request->all(), [ 'id' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $paymentTransaction = app(PaymentTransactionInterface::class)->builder()->where('id', $request->id)->first(); if (empty($paymentTransaction)) { ResponseService::errorResponse("No Data Found"); } $data = PaymentService::create($paymentTransaction->payment_gateway, $paymentTransaction->school_id)->retrievePaymentIntent($paymentTransaction->order_id); $data = PaymentService::formatPaymentIntent($paymentTransaction->payment_gateway, $data); // Success ResponseService::successResponse("Payment Details Fetched", $data, ['payment_transaction' => $paymentTransaction]); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getPaymentTransactions(Request $request) { $validator = Validator::make($request->all(), [ 'latest_only' => 'nullable|boolean' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { if (!Auth::user()->hasRole('School Admin') || Auth::user()->hasRole('Super Admin')) { $user_id = Auth::user()->id; } $paymentTransactions = app(PaymentTransactionInterface::class)->builder(); if ($request->latest_only) { $paymentTransactions->where('created_at', '>', Carbon::now()->subMinutes(30)->toDateTimeString()); } $paymentTransactions = $paymentTransactions->with('school')->orderBy('id', 'DESC'); if (isset($user_id)) { if (Auth::user()->hasRole('Guardian')) { $childIds = Students::where('guardian_id', $user_id)->pluck('user_id')->toArray(); $paymentTransactions->whereIn('user_id', $childIds); $paymentTransactions->orWhere('user_id', $user_id); } else { $paymentTransactions->where('user_id', $user_id); } } $paymentTransactions = $paymentTransactions->get(); $schoolSettings = app(SchoolSettingInterface::class)->builder() ->where(function ($q) { $q->where('name', 'currency_code')->orWhere('name', 'currency_symbol'); })->whereIn('school_id', $paymentTransactions->pluck('school_id'))->get(); $paymentTransactions = $paymentTransactions->map(function ($data) use ($schoolSettings) { $getSchoolSettings = $schoolSettings->filter(function ($settings) use ($data) { return $settings->school_id == $data->school_id; })->where('status', 1)->pluck('data', 'name'); $data->currency_code = $getSchoolSettings['currency_code'] ?? ''; $data->currency_symbol = $getSchoolSettings['currency_symbol'] ?? ''; if ($data->payment_status == "pending") { try { if ($data->order_id) { // For Flutterwave, use tx_ref for verification if ($data->payment_gateway == "Flutterwave") { $paymentIntent = PaymentService::create($data->payment_gateway, $data->school_id) ->retrievePaymentIntent($data->order_id); $paymentIntent = PaymentService::formatPaymentIntent($data->payment_gateway, $paymentIntent); // Update transaction status based on verification if (isset($paymentIntent['status'])) { $status = match (strtolower($paymentIntent['status'])) { 'successful', 'completed', 'success' => 'succeed', 'failed', 'cancelled' => 'failed', default => 'pending' }; if ($status !== 'pending') { $this->paymentTransaction->update($data->id, [ 'payment_status' => $status, 'payment_id' => $paymentIntent['transaction_id'] ?? null, 'school_id' => $data->school_id ]); $data->payment_status = $status; if ($status === 'succeed') { $fee_id = Transportationpayment::where('payment_transaction_id', $data->id)->first(); $transportationFee = TransportationFee::where('id', $fee_id->transportation_fee_id)->first(); $expiryDate = null; if ($transportationFee) { if (!empty($transportationFee->duration)) { $expiryDate = now()->addDays($transportationFee->duration); } } TransportationPayment::where('payment_transaction_id', $data->id) ->update([ 'status' => "paid", 'paid_at' => Carbon::now()->format('Y-m-d H:i:s'), 'expiry_date' => $expiryDate ]); } } } } else { // For other payment gateways $paymentIntent = PaymentService::create($data->payment_gateway, $data->school_id) ->retrievePaymentIntent($data->order_id); $paymentIntent = PaymentService::formatPaymentIntent($data->payment_gateway, $paymentIntent); if ($paymentIntent['status'] != "pending") { $this->paymentTransaction->update($data->id, [ 'payment_status' => $paymentIntent['status'], 'school_id' => $data->school_id ]); if ($paymentIntent['status'] == "succeed") { $transportationFee = TransportationFee::where('id', $paymentIntent['metadata']['fees_id'])->first(); $expiryDate = null; if ($transportationFee) { if (!empty($transportationFee->duration)) { $expiryDate = now()->addDays($transportationFee->duration); } } TransportationPayment::where('payment_transaction_id', $data->id) ->update([ 'status' => "paid", 'paid_at' => Carbon::now()->format('Y-m-d H:i:s'), 'expiry_date' => $expiryDate ]); } else { TransportationPayment::where('payment_transaction_id', $data->id) ->update([ 'status' => "canceled" ]); } $data->payment_status = $paymentIntent['status']; } } } } catch (Exception $e) { Log::error('Payment verification error:', [ 'payment_id' => $data->id, 'order_id' => $data->order_id, 'error' => $e->getMessage() ]); // Don't update status on verification error } } return $data; }); ResponseService::successResponse("Payment Transactions Fetched", $paymentTransactions); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getGallery(Request $request) { try { $limit = $request->limit ?? 10; // default limit $offset = $request->offset ?? 0; // default offset 0 if ($request->gallery_id) { $data = $this->gallery->builder() ->with('file') ->where('id', $request->gallery_id) ->first(); // Organize files into videos and photos with limit/offset if ($data) { $data = $this->organizeGalleryFiles($data, $limit, $offset); } } else { if ($request->child_id) { // $child = $this->student->findById($request->child_id); $query = $this->gallery->builder() ->with('file'); // ->where('school_id', $child->user->school_id); if ($request->session_year_id) { $query = $query->where('session_year_id', $request->session_year_id); } $data = $query->offset($offset)->limit($limit)->get(); // Organize files for each gallery with limit/offset $data = $data->map(function ($gallery) use ($limit, $offset) { return $this->organizeGalleryFiles($gallery, $limit, $offset); }); } else { if ($request->session_year_id) { $query = $this->gallery->builder() ->with('file') ->where('session_year_id', $request->session_year_id); } else { $query = $this->gallery->builder() ->with('file'); } $data = $query->offset($offset)->limit($limit)->get(); // Count total photos and videos for each gallery $data = $data->map(function ($gallery) { $total_photos = 0; $total_videos = 0; if ($gallery->file && $gallery->file->count() > 0) { foreach ($gallery->file as $file) { if ($file->type_detail == 'Youtube Link') { $total_videos++; } elseif ($file->type_detail == 'File Upload') { $total_photos++; } } } // Add count params to the gallery object (as attributes for response) $gallery->total_photos = $total_photos; $gallery->total_videos = $total_videos; return $gallery; }); // Organize files for each gallery with limit/offset $data = $data->map(function ($gallery) use ($limit, $offset) { return $this->organizeGalleryFiles($gallery, $limit, $offset); }); } } ResponseService::successResponse("Gallery Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } /** * Organize gallery files into videos and photos arrays based on type_detail * Apply limit and offset separately to each array */ private function organizeGalleryFiles($gallery, $limit = 10, $offset = 0) { $videos = []; $photos = []; if ($gallery->file && $gallery->file->count() > 0) { foreach ($gallery->file as $file) { $fileArray = $file->toArray(); if ($file->type_detail == 'Youtube Link') { $videos[] = $fileArray; } elseif ($file->type_detail == 'File Upload') { $photos[] = $fileArray; } } } // Apply limit and offset to videos array $videos = array_slice($videos, $offset, $limit); // Apply limit and offset to photos array $photos = array_slice($photos, $offset, $limit); // Convert to array if it's a model instance $galleryArray = $gallery->toArray(); $galleryArray['videos'] = $videos; $galleryArray['photos'] = $photos; // Remove the original file relation unset($galleryArray['file']); return $galleryArray; } public function getSessionYear(Request $request) { try { if ($request->filled('child_id')) { $child = $this->student->findById($request->child_id); if (!$child) { return ResponseService::validationError('Invalid child selected.'); } $sessionYears = $this->sessionYear ->builder() ->where('school_id', $child->user->school_id) ->get(); } else { $sessionYears = $this->sessionYear->builder()->get(); } $data = $sessionYears->map(function ($item) { return [ "id" => $item->id, "name" => $item->name, "default" => $item->default, "start_date" => Carbon::parse($item->original_start_date)->format('d-m-Y'), "end_date" => Carbon::parse($item->original_end_date)->format('d-m-Y'), "school_id" => $item->school_id, "created_at" => $item->created_at, "updated_at" => $item->updated_at, "deleted_at" => $item->deleted_at, ]; }); return ResponseService::successResponse( "Session Year Fetched Successfully", $data ); } catch (\Throwable $e) { ResponseService::logErrorResponse($e); return ResponseService::errorResponse(); } } public function getLeaves(Request $request) { ResponseService::noFeatureThenSendJson('Staff Leave Management'); try { $leave = $this->leaveDetail->builder()->with('leave:id,user_id', 'leave.user:id,first_name,last_name,image', 'leave.user.roles') ->whereHas('leave', function ($q) { $q->where('status', 1); }); if ($request->type == 0 || $request->type == null) { $leave->whereDate('date', '<=', Carbon::now()->format('Y-m-d'))->whereDate('date', '>=', Carbon::now()->format('Y-m-d')); } if ($request->type == 1) { $tomorrow_date = Carbon::now()->addDay()->format('Y-m-d'); $leave->whereDate('date', '<=', $tomorrow_date)->whereDate('date', '>=', $tomorrow_date); } if ($request->type == 2) { $upcoming_date = Carbon::now()->addDays(1)->format('Y-m-d'); $leave->whereDate('date', '>', $upcoming_date); } $leave = $leave->orderBy('date', 'ASC')->get()->append(['leave_date']); ResponseService::successResponse("Data Fetched Successfully", $leave); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function applyLeaves(Request $request) { $file_upload_size_limit = $this->cache->getSystemSettings('file_upload_size_limit'); $validator = Validator::make($request->all(), [ 'reason' => 'required', 'files' => 'nullable|array', 'files.*' => ['nullable', 'mimes:jpg,jpeg,png,pdf,doc,docx', new MaxFileSize($file_upload_size_limit)] ], [ 'files.*.max_file_size' => trans('The file Uploaded must be less than :file_upload_size_limit MB.', [ 'file_upload_size_limit' => $file_upload_size_limit, ]), 'files.*.mimes' => 'Only JPG, JPEG, PNG, PDF, DOC, and DOCX files are allowed.', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { DB::beginTransaction(); $sessionYear = $this->cache->getDefaultSessionYear(); $leaveMaster = $this->leaveMaster->builder()->where('session_year_id', $sessionYear->id)->first(); if (!$leaveMaster) { ResponseService::errorResponse("Kindly contact the school admin to update settings for continued access."); } $public_holiday = $this->holiday->builder()->whereDate('date', '>=', $sessionYear->start_date)->whereDate('date', '<=', $sessionYear->end_date)->get()->pluck('dmyFormat')->toArray(); $dates = collect($request->leave_details) ->pluck('date') ->map(fn($d) => \Carbon\Carbon::parse($d)); if ($dates->isEmpty()) { ResponseService::validationError('Leave dates cannot be empty.'); } $from_date = $dates->min()->toDateString(); $to_date = $dates->max()->toDateString(); $exists = $this->leave->builder() ->where('user_id', Auth::user()->id) ->where(function ($q) use ($from_date, $to_date) { $q->where('from_date', '<=', $to_date) ->where('to_date', '>=', $from_date); }) ->exists(); if ($exists) { ResponseService::errorResponse('You already have a leave request during this period.'); } $leave_data = [ 'user_id' => Auth::user()->id, 'reason' => $request->reason, 'from_date' => $from_date, 'to_date' => $to_date, 'status' => 0, 'leave_master_id' => $leaveMaster->id ]; $holidays = explode(',', $leaveMaster->holiday); $leave = $this->leave->create($leave_data); foreach ($request->leave_details as $key => $leaves) { $date = date('d-m-Y', strtotime($leaves['date'])); $day = date('l', strtotime($leaves['date'])); if (!in_array($day, $holidays) && !in_array($date, $public_holiday)) { $data[] = [ 'leave_id' => $leave->id, 'date' => $leaves['date'], 'type' => $leaves['type'] ]; } else { ResponseService::errorResponse("Kindly select different dates as the ones mentioned are already allocated as holidays."); } } if ($request->hasFile('files')) { $fileData = []; // Empty FileData Array // Create A File Model Instance $leaveModelAssociate = $this->files->model()->modal()->associate($leave); foreach ($request->file('files') as $file_upload) { // Create Temp File Data Array $tempFileData = [ 'modal_type' => $leaveModelAssociate->modal_type, 'modal_id' => $leaveModelAssociate->modal_id, 'file_name' => $file_upload->getClientOriginalName(), 'type' => 1, 'file_url' => $file_upload->store('files', 'public') // Store file and get the file path ]; $fileData[] = $tempFileData; // Store Temp File Data in Multi-Dimensional File Data Array } $this->files->createBulk($fileData); // Store File Data } $this->leaveDetail->createBulk($data); $user = $this->user->builder()->whereHas('roles.permissions', function ($q) { $q->where('name', 'approve-leave'); })->pluck('id')->toArray(); $type = "Leave"; $title = Auth::user()->full_name . ' has submitted a new leave request.'; $body = $request->reason; DB::commit(); send_notification($user, $title, $body, $type); ResponseService::successResponse("Data Stored Successfully"); } catch (Throwable $e) { if ( Str::contains($e->getMessage(), [ 'does not exist', 'file_get_contents' ]) ) { DB::commit(); ResponseService::warningResponse("Data Stored successfully. But App push notification not send."); } else { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } } public function getMyLeaves(Request $request) { ResponseService::noFeatureThenSendJson('Staff Leave Management'); $validator = Validator::make($request->all(), [ 'month' => 'in:1,2,3,4,5,6,7,8,9,10,11,12', 'status' => 'in:0,1,2' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $sessionYear = $this->cache->getDefaultSessionYear(); $leaveMaster = $this->leaveMaster->builder(); $sql = $this->leave->builder()->with('leave_detail')->where('user_id', Auth::user()->id)->withCount([ 'leave_detail as full_leave' => function ($q) { $q->where('type', 'Full'); } ])->withCount([ 'leave_detail as half_leave' => function ($q) { $q->whereNot('type', 'Full'); } ]); if ($request->session_year_id) { $sql->whereHas('leave_master', function ($q) use ($request) { $q->where('session_year_id', $request->session_year_id); }); $leaveMaster->where('session_year_id', $request->session_year_id); } else { $sql->whereHas('leave_master', function ($q) use ($sessionYear) { $q->where('session_year_id', $sessionYear->id); }); $leaveMaster->where('session_year_id', $sessionYear->id); } if (isset($request->status)) { $sql->where('status', $request->status); } if ($request->month) { $sql->whereHas('leave_detail', function ($q) use ($request) { $q->whereMonth('date', $request->month); }); } $leaveMaster = $leaveMaster->first(); $sql = $sql->get(); $sql = $sql->map(function ($sql) { $total_leaves = ($sql->half_leave / 2) + $sql->full_leave; $sql->days = $total_leaves; return $sql; }); $data = [ 'monthly_allowed_leaves' => $leaveMaster->leaves, 'taken_leaves' => $sql->sum('days'), 'leave_details' => $sql ]; ResponseService::successResponse("Data Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function deleteLeaves(Request $request) { ResponseService::noFeatureThenSendJson('Staff Leave Management'); $validator = Validator::make($request->all(), [ 'leave_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { DB::beginTransaction(); $leave = $this->leave->findById($request->leave_id); if ($leave->status != 0) { ResponseService::errorResponse("You cannot delete this leave"); } $this->leave->deleteById($request->leave_id); DB::commit(); ResponseService::successResponse("Data Deleted Successfully"); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getStaffLeaveDetail(Request $request) { ResponseService::noFeatureThenSendJson('Staff Leave Management'); $validator = Validator::make($request->all(), [ 'staff_id' => 'required', 'month' => 'in:1,2,3,4,5,6,7,8,9,10,11,12', 'status' => 'in:0,1,2' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $sessionYear = $this->cache->getDefaultSessionYear(); $leaveMaster = $this->leaveMaster->builder(); $sql = $this->leave->builder()->with('leave_detail', 'file')->withCount([ 'leave_detail as full_leave' => function ($q) { $q->where('type', 'Full'); } ])->withCount([ 'leave_detail as half_leave' => function ($q) { $q->whereNot('type', 'Full'); } ])->where('user_id', $request->staff_id); if ($request->session_year_id) { $sql->whereHas('leave_master', function ($q) use ($request) { $q->where('session_year_id', $request->session_year_id); }); $leaveMaster->where('session_year_id', $request->session_year_id); } else { $sql->whereHas('leave_master', function ($q) use ($sessionYear) { $q->where('session_year_id', $sessionYear->id); }); $leaveMaster->where('session_year_id', $sessionYear->id); } if (isset($request->status)) { $sql->where('status', $request->status); } if ($request->month) { $sql->whereHas('leave_detail', function ($q) use ($request) { $q->whereMonth('date', $request->month); }); } $leaveMaster = $leaveMaster->first(); if (!$leaveMaster) { ResponseService::errorResponse("Leave settings not found"); } $sql = $sql->get(); $sql = $sql->map(function ($sql) { $total_leaves = ($sql->half_leave / 2) + $sql->full_leave; $sql->days = $total_leaves; if ($sql->status == 1) { $sql->taken_leaves = $total_leaves; } return $sql; }); $data = [ 'monthly_allowed_leaves' => $leaveMaster->leaves, 'total_leaves' => $sql->sum('days'), 'taken_leaves' => $sql->sum('taken_leaves'), 'leave_details' => $sql ]; ResponseService::successResponse("Data Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getMedium() { try { $sql = $this->medium->builder()->get(); ResponseService::successResponse("Data Fetched Successfully", $sql); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getClass(Request $request) { try { $currentSemester = $this->cache->getDefaultSemesterData(); $defaultSessionYear = $this->cache->getDefaultSessionYear(); // Teacher if (Auth::user()->hasRole('Teacher')) { $user = $request->user()->teacher; //Find the class in which teacher is assigns as Class Teacher $class_section_ids = []; if ($user->class_teacher) { // $class_teacher = $user->class_teacher; // $class_teacher = $class_teacher->load('class_section.class.stream', 'class_section.class.shift', 'class_section.section', 'class_section.medium'); $class_teacher = $user->class_teacher() ->where('session_year_id', $defaultSessionYear->id) ->with([ 'class_section.class.stream', 'class_section.class.shift', 'class_section.section', 'class_section.medium' ]) ->get(); $class_section_ids = $class_teacher->pluck('class_section_id'); } //Find the Classes in which teacher is taking subjects $class_section = $this->classSection->builder()->with('class.stream', 'class.shift', 'section', 'medium')->whereNotIn('id', $class_section_ids); $class_section = $class_section->whereHas('subject_teachers.class_subject', function ($q) use ($currentSemester) { (!empty($currentSemester)) ? $q->where('semester_id', $currentSemester->id)->orWhereNull('semester_id') : $q->orWhereNull('semester_id'); })->get(); } else { // Staff $class_section = $this->classSection->builder()->with('class', 'class.shift', 'section', 'medium', 'class.stream')->get(); } ResponseService::successResponse('Data Fetched Successfully', null, [ 'class_teacher' => $class_teacher ?? [], 'other' => $class_section, 'semester' => $currentSemester ?? null ]); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function updateProfile(Request $request) { $validator = Validator::make($request->all(), [ 'first_name' => 'required', 'last_name' => 'required', 'mobile' => 'required', 'email' => 'required|unique:users,email,' . Auth::user()->id, 'dob' => 'required', 'current_address' => 'required', 'permanent_address' => 'required', 'gender' => 'required|in:male,female', 'image' => 'nullable|image|mimes:jpeg,png,jpg,svg|max:5120', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } if (Auth::user()->school_id) { $schoolSettings = $this->cache->getSchoolSettings(); } else { $schoolSettings = $this->cache->getSystemSettings(); } try { $user_data = [ 'first_name' => $request->first_name, 'last_name' => $request->last_name, 'mobile' => $request->mobile, 'email' => $request->email, 'dob' => Carbon::parse($request->dob)->format('Y-m-d'), 'current_address' => $request->current_address, 'permanent_address' => $request->permanent_address, 'gender' => $request->gender, ]; if ($request->hasFile('image')) { $user_data['image'] = $request->file('image'); } $user = $this->user->update(Auth::user()->id, $user_data); $extraDetails = []; foreach ($request->custom_fields ?? [] as $fields) { if ($fields['input_type'] == 'file' && $fields['data'] instanceof UploadedFile) { if (isset($fields['data'])) { $extraDetails[] = array( 'id' => $fields['id'], 'user_id' => $user->id, 'form_field_id' => $fields['form_field_id'], 'data' => $fields['data'] ); } } else { $data = null; if (isset($fields['data'])) { $data = (is_array($fields['data']) ? json_encode($fields['data'], JSON_THROW_ON_ERROR) : $fields['data']); } $extraDetails[] = array( 'id' => $fields['id'], 'user_id' => $user->id, 'form_field_id' => $fields['form_field_id'], 'data' => $data, ); } } $this->extraFormFields->upsert($extraDetails, ['id'], ['data']); $user = User::where('id', Auth::id()) ->with(['extra_user_details.form_field']) ->first(); $customFields = $user->extra_user_details->map(function ($row) { $field = $row->form_field; $value = $row->data; if ($field->type === 'file' && !empty($value)) { $raw = $row->getRawOriginal('data'); $value = url('storage/' . ltrim($raw, '/')); } return [ 'id' => $row->id, 'form_field_id' => $field->id, 'name' => $field->name, 'type' => $field->type, 'is_required' => (bool) $field->is_required, 'default_value' => $field->default_values, 'value' => $value, 'user_type' => $field->user_type == 1 ? 'student' : 'teacher/staff', 'rank' => $field->rank, ]; }); $user->custom_fields = $customFields; unset($user->extra_user_details); ResponseService::successResponse('Data Updated Successfully', $user); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function getExamResultPdf(Request $request) { ResponseService::noFeatureThenSendJson('Exam Management'); try { $validator = Validator::make($request->all(), [ 'exam_id' => 'required', 'student_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $exam_id = $request->exam_id; $student_id = $request->student_id; $results = $this->examResult->builder() ->with([ 'exam', 'session_year', 'class_section.class.stream', 'class_section.class.shift', 'class_section.section', 'class_section.medium', 'user' => function ($q) use ($exam_id) { $q->with([ 'student.guardian', 'exam_marks' => function ($q) use ($exam_id) { $q->whereHas('timetable', function ($q) use ($exam_id) { $q->where('exam_id', $exam_id); })->with([ 'class_subject' => function ($q) { $q->withTrashed()->with('subject:id,name,type'); }, 'timetable' ]); } ]); } ]) ->where('exam_id', $exam_id) ->select('exam_results.*') ->get(); // Convert the results to a collection $results = collect($results); // Add rank calculation to each item in the collection $results = $results->map(function ($result) { $rank = DB::table('exam_results as er2') ->where('er2.class_section_id', $result->class_section_id) ->where('er2.obtained_marks', '>', $result->obtained_marks) ->where('er2.exam_id', $result->exam_id) ->where('er2.status', 1) ->distinct('er2.obtained_marks') ->count() + 1; $result->rank = $rank; return $result; }); // Filter the collection based on student ID $result = $results->where('student_id', $student_id)->first(); if (!$result) { return redirect()->back()->with('error', trans('no_records_found')); } $grades = $this->grade->builder()->orderBy('starting_range', 'ASC')->get(); $settings = $this->cache->getSchoolSettings(); $data = explode("storage/", $settings['horizontal_logo'] ?? ''); $settings['horizontal_logo'] = end($data); if ($settings['horizontal_logo'] == null) { $systemSettings = $this->cache->getSystemSettings(); $data = explode("storage/", $systemSettings['horizontal_logo'] ?? ''); $settings['horizontal_logo'] = end($data); } $pdf = PDF::loadView('exams.exam_result_pdf', compact('result', 'settings', 'grades'))->output(); return $response = array( 'error' => false, 'pdf' => base64_encode($pdf), ); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function leaveSettings(Request $request) { try { if ($request->session_year_id) { $session_year_id = $request->session_year_id; } else { $sessionYear = $this->cache->getDefaultSessionYear(); $session_year_id = $sessionYear->id; } $sql = $this->leaveMaster->builder()->where('session_year_id', $session_year_id)->get(); $public_holiday = $this->holiday->builder()->whereDate('date', '>=', $sessionYear->start_date)->whereDate('date', '<=', $sessionYear->end_date)->get(['date', 'title']); ResponseService::successResponse("Data Fetched Successfully", ['leave_settings' => $sql, 'public_holidays' => $public_holiday]); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getSchoolSettings(Request $request) { $validator = Validator::make($request->all(), [ 'type' => 'required|in:privacy_policy,terms_condition,refund_cancellation,about_us,contact_us' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { if ($request->child_id) { $child = $this->student->builder()->where('id', $request->child_id)->first(); if (!$child) { ResponseService::errorResponse("no_data_found"); } $schoolSettings = $this->cache->getSchoolSettings('*', $child->school_id); } else { $schoolSettings = $this->cache->getSchoolSettings(); } $data = isset($schoolSettings[$request->type]) ? htmlspecialchars_decode($schoolSettings[$request->type]) : ""; ResponseService::successResponse("Data Fetched Successfully", $data); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function sendMessage(Request $request) { $validator = Validator::make($request->all(), [ 'to' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $message = ''; try { DB::beginTransaction(); $chat = $this->chat->builder() ->where(function ($q) use ($request) { $q->where('sender_id', Auth::user()->id)->where('receiver_id', $request->to); }) ->orWhere(function ($q) use ($request) { $q->where('sender_id', $request->to)->where('receiver_id', Auth::user()->id); }) ->first(); if (!$chat) { $chat = $this->chat->create(['sender_id' => Auth::user()->id, 'receiver_id' => $request->to]); } $chat = $chat->load(['receiver']); $message = $this->message->create(['chat_id' => $chat->id, 'sender_id' => Auth::user()->id, 'message' => $request->message]); // $message = new Message(); // $message->chat_id = $chat->id; // $message->sender_id = Auth::user()->id; // $message->message = $request->message; // $message->save(); $message = $message->refresh(); $data = []; $subjectName = ''; // Prepare customData if Teacher is messaging Student $customData = []; $receiverUser = User::find($request->to); if (Auth::user()->hasRole('Teacher') && $receiverUser && $receiverUser->hasRole('Student')) { // Get student's class_section_id $student = $receiverUser->student; if ($student && $student->class_section_id) { // Get teacher's subject teachers for the student's class section $teacherSubjectTeachers = SubjectTeacher::where('teacher_id', Auth::user()->id) ->where('class_section_id', $student->class_section_id) ->with('class_subject.subject') ->get(); // Get student's subjects (student_id in StudentSubject references Students.user_id) $studentSubjects = \App\Models\StudentSubject::where('student_id', $student->user_id) ->where('class_section_id', $student->class_section_id) ->pluck('class_subject_id') ->toArray(); // Find common subject foreach ($teacherSubjectTeachers as $subjectTeacher) { if (in_array($subjectTeacher->class_subject_id, $studentSubjects)) { if ($subjectTeacher->class_subject && $subjectTeacher->class_subject->subject) { $subjectName = $subjectTeacher->class_subject->subject->name; if ($subjectTeacher->class_subject->subject->type) { $subjectName .= ' (' . $subjectTeacher->class_subject->subject->type . ')'; } } break; // Get first matching subject } } } } $customData = [ 'receiver_id' => Auth::user()->id, 'teacher_name' => Auth::user()->full_name ?? '', 'teacher_image' => Auth::user()->image ?? '', 'subject_name' => $subjectName, ]; if ($request->hasFile('files')) { foreach ($request->file('files') as $file) { $file_path = $file->store('chat_file', 'public'); $data[] = [ 'message_id' => $message->id, 'file' => $file_path, 'file_type' => $file->getClientOriginalExtension() ]; } $this->attachment->createBulk($data); // set attachment $message->load(['attachment']); $messageData = $message->toArray(); $messageData['created_at'] = $message->created_at; $messageData['updated_at'] = $message->updated_at; // send notification $user[] = $request->to; $title = 'New Message from ' . Auth::user()->full_name; $fileNames = array_map(function ($file) { return basename($file->getClientOriginalName()); }, $request->file('files')); $body = $request->message ? $request->message . ' (Files: ' . implode(', ', $fileNames) . ')' : 'Files attached: ' . implode(', ', $fileNames); $type = 'Message'; DB::commit(); broadcast(new MessageSent( channel: 'user.' . $request->to, event: 'NewMessage', message: $messageData, from: Auth::id(), to: $request->to, )); send_notification($user, $title, $body, $type, $customData); ResponseService::successResponse("Data Stored Successfully", $messageData); } else { // Only send notification if no files attached $user[] = $request->to; $title = 'New Message from ' . Auth::user()->full_name; $body = $request->message ?? 'No message'; $type = 'Message'; $messageData = $message->toArray(); $messageData['created_at'] = $message->created_at; $messageData['updated_at'] = $message->updated_at; DB::commit(); broadcast(new MessageSent( channel: 'user.' . $request->to, event: 'NewMessage', message: $messageData, from: Auth::id(), to: (int) $request->to, )); send_notification($user, $title, $body, $type, $customData); ResponseService::successResponse("Data Stored Successfully", $messageData); } } catch (\Throwable $th) { $notificationStatus = app(GeneralFunctionService::class)->wrongNotificationSetup($th); if ($notificationStatus) { DB::rollBack(); ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } else { DB::commit(); if (is_object($message)) { $messageData = $message->toArray(); $messageData['created_at'] = $message->created_at; $messageData['updated_at'] = $message->updated_at; } else { $messageData = $message; } ResponseService::warningResponse("Data Stored successfully. But App push notification not send.", $messageData); } } } public function getMessage(Request $request) { $validator = Validator::make($request->all(), [ 'receiver_id' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $data = []; $data = $this->message->builder()->whereHas('chat', function ($q) use ($request) { $q->where(function ($q) use ($request) { $q->where('sender_id', Auth::user()->id)->where('receiver_id', $request->receiver_id); }) ->orWhere(function ($q) use ($request) { $q->where('sender_id', $request->receiver_id)->where('receiver_id', Auth::user()->id); }); }) ->with('attachment')->orderBy('id', 'DESC') ->paginate(10); ResponseService::successResponse("data_fetch_successfully", $data); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function deleteMessage(Request $request) { $validator = Validator::make($request->all(), [ 'id' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $this->message->builder()->whereIn('id', $request->id)->delete(); ResponseService::successResponse("Data Deleted Successfully"); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function readMessage(Request $request) { $validator = Validator::make($request->all(), [ 'message_id' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $read_at = Carbon::now(); $this->message->builder()->whereIn('id', $request->message_id)->update(['read_at' => $read_at]); ResponseService::successResponse("Data Updated Successfully"); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function getUsers(Request $request) { if (Auth::user()->hasRole('Teacher')) { $validator = Validator::make($request->all(), [ 'role' => 'required|in:Guardian,Staff,Student,Teacher', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } } try { $users = []; $currentSemester = $this->cache->getDefaultSemesterData(Auth::user()->school_id); $sessionYear = $this->cache->getDefaultSessionYear(); $sessionYearId = $sessionYear->id; if (Auth::user()) { $searchTerm = $request->search; DB::enableQueryLog(); $users = User::select('id', 'first_name', 'last_name', 'image', 'school_id')->whereNot('id', Auth::user()->id)->where('status', 1); if ($request->search) { $search = $request->search; $users->where(function ($query) use ($search) { $query->where('first_name', 'LIKE', "%$search%") ->orWhere('last_name', 'LIKE', "%$search%"); }); } if (Auth::user()->hasRole('Student')) { $userId = Auth::user()->id; $student = Auth::user()->student; $classId = $student->class_section->class_id; $class_subject_ids = ClassSubject::where('class_id', $classId) ->where(function ($q) use ($currentSemester) { if ($currentSemester) { $q->where('semester_id', $currentSemester->id) ->orWhereNull('semester_id'); } else { $q->whereNull('semester_id'); } }) ->pluck('id') ->toArray(); $class_teachers = ClassTeacher::where('class_section_id', $student->class_section_id) ->pluck('teacher_id') ->toArray(); // Transportation (optional) $allowedUserIds = []; $transportationPayment = TransportationPayment::where('user_id', $userId) ->where('expiry_date', '>=', now()) ->whereNotNull('route_vehicle_id') ->first(); if ($transportationPayment) { $routeVehicle = RouteVehicle::find($transportationPayment->route_vehicle_id); $allowedUserIds = array_filter([ $routeVehicle?->driver_id, $routeVehicle?->helper_id, ]); } $users = $users ->with([ 'subjectTeachers' => function ($q) use ($class_teachers, $class_subject_ids) { $q->whereIn('class_subject_id', $class_subject_ids) ->whereNotIn('teacher_id', $class_teachers) ->with('subject:id,name'); }, 'class_teacher.class_section.class.stream', 'class_teacher.class_section.class.shift', 'class_teacher.class_section.section', 'class_teacher.class_section.medium', 'roles' ]) ->where(function ($query) use ($class_subject_ids, $class_teachers, $allowedUserIds, $searchTerm, $sessionYearId) { // 🎓 Academic teachers $query->whereHas('subjectTeachers', function ($q) use ($class_subject_ids, $class_teachers) { $q->whereIn('class_subject_id', $class_subject_ids) ->whereNotIn('teacher_id', $class_teachers); }) ->orWhereHas('class_teacher', function ($q) use ($class_teachers) { $q->whereIn('teacher_id', $class_teachers); }); // 🚌 Transportation staff if (!empty($allowedUserIds)) { $query->orWhereIn('id', $allowedUserIds); } $query->orWhereHas('roles', function ($q) { $q->where('custom_role', 1); }); $query->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); }); $query->WhereHas('roles', function ($r) { $r->whereNot('name', 'School Admin'); }); }) ->where(function ($q) use ($searchTerm) { if ($searchTerm) { $q->where('first_name', 'like', "%{$searchTerm}%") ->orWhere('last_name', 'like', "%{$searchTerm}%"); } }); } else if (Auth::user()->hasRole('Teacher')) { // Teacher login // Get guardian list if ($request->role == 'Guardian') { $validator = Validator::make($request->all(), [ 'class_section_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $users = $users->role(['Guardian'])->whereHas('child', function ($q) use ($request, $sessionYearId) { $q->where('school_id', Auth::user()->school_id) ->where('session_year_id', $sessionYearId) ->where('class_section_id', $request->class_section_id); })->with('child:id,user_id,guardian_id,class_section_id', 'child.user:id,first_name,last_name,image'); } else if ($request->role == 'Staff') { $userId = Auth::user()->id; $allowedUserIds = []; if ($userId) { $transportationPayment = TransportationPayment::where('user_id', $userId) ->where('expiry_date', '>=', Carbon::now()) ->whereNotNull('route_vehicle_id') ->first(); if ($transportationPayment) { $routeVehicle = RouteVehicle::find($transportationPayment->route_vehicle_id); // ✅ driver_id & helper_id are USER IDs $allowedUserIds = array_filter([ $routeVehicle?->driver_id, $routeVehicle?->helper_id, ]); } } // Get staff list $users = $users ->where('school_id', Auth::user()->school_id) ->where(function ($q) use ($allowedUserIds, $sessionYearId) { // (staff AND custom_role) $q->where(function ($q2) use ($sessionYearId) { $q2->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); }) ->orWhereHas('roles', function ($r) { $r->where('custom_role', 1); }); }); // OR School Admin $q->orWhereHas('roles', function ($r) { $r->where('name', 'School Admin'); }); if (!empty($allowedUserIds)) { $q->orWhereIn('id', $allowedUserIds); } }); } } else if (Auth::user()->hasRole('Guardian')) { // Guardian login $users = $users ->where('school_id', Auth::user()->school_id) ->where(function ($q) use ($sessionYearId) { // Staff users $q->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); }); // OR School Admins (even without staff record) $q->orWhereHas('roles', function ($r) { $r->where('name', 'School Admin'); }); }); $driverId = null; $helperId = null; if ($request->role === 'Staff') { // Always initialize $allowedUserIds = []; if ($request->child_id) { // ✅ FIX: get scalar, not collection $userId = Students::where('id', $request->child_id)->where('session_year_id', $sessionYearId)->value('user_id'); if ($userId) { $transportationPayment = TransportationPayment::where('user_id', $userId) ->where('expiry_date', '>=', Carbon::now()) ->whereNotNull('route_vehicle_id') ->first(); if ($transportationPayment) { $routeVehicle = RouteVehicle::find($transportationPayment->route_vehicle_id); // ✅ driver_id & helper_id are USER IDs $allowedUserIds = array_filter([ $routeVehicle?->driver_id, $routeVehicle?->helper_id, ]); } } } $users = $users ->with('roles') ->where(function ($query) use ($allowedUserIds) { // Custom staff $query->whereHas('roles', function ($q) { $q->where('custom_role', 1); }); // OR School Admin $query->orWhereHas('roles', function ($q) { $q->where('name', 'School Admin'); }); // OR assigned Driver / Helper if (!empty($allowedUserIds)) { $query->orWhereIn('id', $allowedUserIds); } }); } else { if ($request->child_id) { $class_sections = Students::where('id', $request->child_id)->where('session_year_id', $sessionYearId)->pluck('class_section_id')->toArray(); } else { $child_ids = Auth::user()->load('child.user')->child->pluck('id')->toArray(); $class_sections = Students::whereIn('id', $child_ids)->where('session_year_id', $sessionYearId)->pluck('class_section_id')->toArray(); } $class_sections = array_filter($class_sections); $class_teachers = ClassTeacher::whereIn('class_section_id', $class_sections)->pluck('teacher_id')->toArray(); $class_teachers = array_unique($class_teachers); $class_teachers = array_values($class_teachers); $subject_teachers = SubjectTeacher::whereIn('class_section_id', $class_sections)->pluck('teacher_id')->toArray(); $subject_teachers = array_unique($subject_teachers); $subject_teachers = array_values($subject_teachers); $teacher_ids = array_merge($class_teachers, $subject_teachers); $teacher_ids = array_unique($teacher_ids); $teacher_ids = array_values($teacher_ids); $users = $users->whereIn('id', $teacher_ids)->with([ 'subjectTeachers' => function ($q) use ($class_sections) { $q->whereIn('class_section_id', $class_sections) ->with('subject:id,name'); } ]) ->where(function ($query) use ($searchTerm) { $query->where('first_name', 'like', '%' . $searchTerm . '%') ->orWhere('last_name', 'like', '%' . $searchTerm . '%'); }) ->with([ 'class_teacher' => function ($q) use ($class_sections) { $q->whereIn('class_section_id', $class_sections) ->with('class_section.class.stream', 'class_section.class.shift', 'class_section.section', 'class_section.medium'); } ]); // ->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); // }); } // ===================== // $users = $users->whereHas('subjectTeachers', function($q) use($class_sections) { // $q->whereIn('class_section_id', $class_sections); // }) // ->with(['subjectTeachers' => function($q) use($class_sections){ // $q->whereIn('class_section_id', $class_sections) // ->with('subject:id,name'); // }]) // ->where(function($query) use ($searchTerm) { // $query->where('first_name', 'like', '%' . $searchTerm . '%') // ->orWhere('last_name', 'like', '%' . $searchTerm . '%'); // }) // ->orWhereHas('class_teacher',function($q) use($class_sections) { // $q->whereIn('class_section_id', $class_sections); // }) // ->with(['class_teacher' => function($q) use($class_sections) { // $q->whereIn('class_section_id',$class_sections) // ->with('class_section.class.stream','class_section.section','class_section.medium'); // }]) // ->has('staff'); } else if (Auth::user()->hasRole('School Admin')) { // Admin or Super Admin login if ($request->role == 'Guardian') { $validator = Validator::make($request->all(), [ 'class_section_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $users = $users->role(['Guardian'])->whereHas('child', function ($q) use ($request, $sessionYearId) { $q->where('school_id', Auth::user()->school_id) ->where('session_year_id', $sessionYearId) ->where('class_section_id', $request->class_section_id); })->with('child:id,user_id,guardian_id,class_section_id', 'child.user:id,first_name,last_name,image'); } else if ($request->role == 'Staff') { // Get staff list $users = $users ->where('school_id', Auth::user()->school_id) ->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); }) ->where(function ($q) { // custom staff $q->whereHas('roles', function ($r) { $r->where('custom_role', 1); }); // OR Driver / Helper (custom_role = 0) $q->orWhereHas('roles', function ($r) { $r->where('custom_role', 0) ->whereIn('name', ['Driver', 'Helper']); }); }); } } else if (Auth::user()->hasRole('Staff') || Auth::user()->roles->first()->custom_role == 1 || Auth::user()->hasRole('Driver') || Auth::user()->hasRole('Helper')) { // Staff login if ($request->role == 'Guardian') { $validator = Validator::make($request->all(), [ 'class_section_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $users = $users->role(['Guardian'])->whereHas('child', function ($q) use ($request, $sessionYearId) { $q->where('school_id', Auth::user()->school_id) ->where('session_year_id', $sessionYearId) ->where('class_section_id', $request->class_section_id); })->with('child:id,user_id,guardian_id,class_section_id', 'child.user:id,first_name,last_name,image'); } else if ($request->role == 'Staff') { // Get staff list $users = $users->where('school_id', Auth::user()->school_id) ->whereHas('staff', function ($q) use ($sessionYearId) { // $q->where('join_session_year_id', $sessionYearId); }) ->whereHas('roles', function ($q) { $q->where('custom_role', 1); })->orWhereHas('roles', function ($q) { $q->where('name', 'School Admin'); }); } else if ($request->role == 'Student') { $validator = Validator::make($request->all(), [ 'class_section_id' => 'required', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } $users = $users->role(['Student'])->whereHas('student', function ($q) use ($request, $sessionYearId) { $q->where('school_id', Auth::user()->school_id) ->where('session_year_id', $sessionYearId) ->where('class_section_id', $request->class_section_id); })->with('student:id,user_id,class_section_id', 'student.class_section:id,class_id,section_id,medium_id', 'student.class_section.class:id,name,shift_id', 'student.class_section.class.shift:id,name', 'student.class_section.section:id,name', 'student.class_section.medium:id,name'); } } else { // Staff login $users = $users->where('school_id', Auth::user()->school_id); } if ($request->role == 'Staff') { $users = $users->whereHas('roles', function ($q) use ($request) { $q->whereNotIn('name', ['Student', 'Guardian']); })->orderBy('first_name', 'ASC')->with('roles')->paginate(10); } else { $users = $users->whereHas('roles', function ($q) use ($request) { $q->where('name', $request->role); })->orderBy('first_name', 'ASC')->with('roles')->paginate(10); } } ResponseService::successResponse("Data Fetched Successfully", $users); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function getUsersByRoles(Request $request) { $validator = Validator::make($request->all(), [ 'roles' => 'required', ]); if ($validator->fails()) { return ResponseService::validationError($validator->errors()->first()); } try { $roles = is_array($request->roles) ? $request->roles : explode(',', $request->roles); $type = $request->type ?? null; $users = User::select('id', 'first_name', 'last_name', 'image') ->where('school_id', Auth::user()->school_id) ->where('status', 1); if ($request->search) { $search = $request->search; $users = $users->where(function ($query) use ($search) { $query->where('first_name', 'LIKE', "%$search%") ->orWhere('last_name', 'LIKE', "%$search%") ->orWhereRaw("concat(first_name,' ',last_name) LIKE '%" . $search . "%'"); }); } $users = $users->where(function ($query) use ($roles) { foreach ($roles as $role) { // STAFF umbrella if ($role === 'Staff') { $query->orWhereHas('roles', function ($q) { $q->where(function ($r) { $r->where('custom_role', 1); }) ->orWhere(function ($r) { $r->where('custom_role', 0) ->whereIn('name', ['Driver', 'Helper']); }) ->orWhere(function ($r) { $r->where('name', 'School Admin'); }); }); } else { // Normal roles $query->orWhereHas('roles', function ($q) use ($role) { $q->where('name', $role); }); } } }); if ($type == 'Over Due Fees') { $today = Carbon::now()->format('Y-m-d'); $users_ids = []; $fees = $this->fees->builder()->whereDate('due_date', '<', $today)->get(); if ($fees->isNotEmpty()) { foreach ($fees as $fee) { $overdueStudents = $this->user->builder() ->role('Student') ->select('id', 'first_name', 'last_name') ->with([ 'fees_paid' => function ($q) use ($fee) { $q->where('fees_id', $fee->id); }, 'student:id,guardian_id,user_id', 'student.guardian:id' ]) ->whereHas('student.class_section', function ($q) use ($fee) { $q->where('class_id', $fee->class_id); }) ->whereDoesntHave('fees_paid', function ($q) use ($fee) { $q->where('fees_id', $fee->id); }) ->orWhereHas('fees_paid', function ($q) use ($fee) { $q->where(['fees_id' => $fee->id, 'is_fully_paid' => 0]); }) ->get(); $users_ids = array_unique(array_merge($overdueStudents->pluck('id')->toArray() ?? [], $overdueStudents->pluck('student.guardian.id')->toArray() ?? [])); $users = $this->user->builder()->whereIn("id", $users_ids); if (is_array($roles)) { $users->whereHas('roles', function ($q) use ($roles) { $q->whereIn('name', $roles); }); } } } else { $users = $this->user->builder()->whereIn("id", $users_ids); } } $users = $users->with('roles') ->orderBy('first_name', 'ASC') ->paginate(10); return ResponseService::successResponse( 'Users fetched successfully', $users ); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); return ResponseService::errorResponse(); } } public function usersChatHistory(Request $request) { $validator = Validator::make($request->all(), [ 'role' => 'required|in:Guardian,Staff,Student,Teacher', ], [ 'role.required' => 'The role field is mandatory. Please select a role.', 'role.in' => 'The selected role is invalid. Valid roles are: Guardian, Staff, Student, Teacher.', ]); if ($validator->fails()) { return ResponseService::validationError($validator->errors()->first()); } try { $data = []; $userId = Auth::id(); $search = $request->search; if (Auth::user()) { $data = Chat::where(function ($q) use ($userId) { $q->where('sender_id', $userId) ->orWhere('receiver_id', $userId); }) ->where(function ($q) use ($request, $userId) { switch ($request->role) { case 'Staff': $roleNames = ['Driver', 'Helper', 'Teacher']; if (Auth::user()->hasRole('Guardian')) { $roleNames = ['Driver', 'Helper']; } $q->whereHas('receiver', function ($receiverQ) use ($userId, $roleNames) { $receiverQ->where('id', '!=', $userId) ->whereHas('roles', function ($roleQ) use ($roleNames) { $roleQ->where('custom_role', 1) ->orWhere(function ($q2) use ($roleNames) { $q2->where('custom_role', 0) ->whereIn('name', $roleNames); }); }); }) ->orWhereHas('sender', function ($senderQ) use ($userId, $roleNames) { $senderQ->where('id', '!=', $userId) ->whereHas('roles', function ($roleQ) use ($roleNames) { $roleQ->where('custom_role', 1) ->orWhere(function ($q2) use ($roleNames) { $q2->where('custom_role', 0) ->whereIn('name', $roleNames); }); }); }); break; case 'Teacher': $q->whereHas('receiver', function ($receiverQ) use ($userId) { $receiverQ->where('id', '!=', $userId) ->whereHas('roles', fn($roleQ) => $roleQ->where('name', 'Teacher')); }) ->orWhereHas('sender', function ($senderQ) use ($userId) { $senderQ->where('id', '!=', $userId) ->whereHas('roles', fn($roleQ) => $roleQ->where('name', 'Teacher')); }); break; case 'Student': case 'Guardian': $role = $request->role; $q->whereHas('receiver', function ($receiverQ) use ($role, $userId) { $receiverQ->where('id', '!=', $userId) ->role([$role]); }) ->orWhereHas('sender', function ($senderQ) use ($role, $userId) { $senderQ->where('id', '!=', $userId) ->role([$role]); }); break; } }) ->withCount([ 'message as unread_count' => function ($q) use ($userId) { $q->where('read_at', null) ->where('sender_id', '!=', $userId); } ]) ->when($search, function ($q) use ($search, $userId) { $q->where(function ($query) use ($search, $userId) { // Search in receiver's name $query->whereHas('receiver', function ($receiverQ) use ($search, $userId) { $receiverQ->where('id', '!=', $userId) ->where(function ($nameQ) use ($search) { $nameQ->where('first_name', 'LIKE', "%$search%") ->orWhere('last_name', 'LIKE', "%$search%") ->orWhereRaw("concat(first_name,' ',last_name) LIKE ?", ["%$search%"]); }); }) // Search in sender's name ->orWhereHas('sender', function ($senderQ) use ($search, $userId) { $senderQ->where('id', '!=', $userId) ->where(function ($nameQ) use ($search) { $nameQ->where('first_name', 'LIKE', "%$search%") ->orWhere('last_name', 'LIKE', "%$search%") ->orWhereRaw("concat(first_name,' ',last_name) LIKE ?", ["%$search%"]); }); }); }); }) ->paginate(10); } ResponseService::successResponse("Data Fetched Successfully", $data); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function classSectionTeachers(Request $request) { $validator = Validator::make($request->all(), [ 'class_section_id' => 'required' ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { $users = $this->user->builder()->role(['Teacher'])->select('id', 'first_name', 'last_name', 'image') ->whereHas('class_teacher', function ($q) use ($request) { $q->where('class_section_id', $request->class_section_id); }) ->orWhereHas('subjectTeachers', function ($q) use ($request) { $q->where('class_section_id', $request->class_section_id); }) // ->with(['class_teacher' => function($q) use($request) { // $q->where('class_section_id', $request->class_section_id); // }]) // ->with(['subjectTeachers' => function($q) use($request) { // $q->where('class_section_id', $request->class_section_id); // }]) ->get(); ResponseService::successResponse("Data Fetched Successfully", $users); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function schoolDetails(Request $request) { try { $gallery_images = []; $school_code = $request->header('school-code'); if ($school_code) { $school = School::on('mysql')->where('code', $school_code)->first(); if ($school) { DB::setDefaultConnection('school'); Config::set('database.connections.school.database', $school->database_name); DB::purge('school'); DB::connection('school')->reconnect(); DB::setDefaultConnection('school'); $names = array('school_name', 'school_tagline', 'horizontal_logo'); $settings = $this->schoolSettings->getBulkData($names); $gallery = $this->gallery->builder()->with('file')->first(); if ($gallery) { $gallery_images = $gallery->file->where('file_name', '!=', 'YouTube Link')->pluck('file_url')->toArray(); } $schoolDetails = array( 'school_name' => $settings['school_name'], 'school_tagline' => $settings['school_tagline'], 'school_logo' => $settings['horizontal_logo'], 'school_images' => $gallery_images ?? [] ); } else { return response()->json(['message' => 'Invalid school code'], 400); } } else { return response()->json(['message' => 'Unauthenticated'], 400); } ResponseService::successResponse("Data Fetched Successfully", $schoolDetails); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); ResponseService::errorResponse(); } } public function sendFeeNotification(Request $request) { try { $school_code = $request->header('school-code'); if ($school_code) { $school = School::on('mysql')->where('code', $school_code)->first(); if ($school) { DB::setDefaultConnection('school'); Config::set('database.connections.school.database', $school->database_name); DB::purge('school'); DB::connection('school')->reconnect(); DB::setDefaultConnection('school'); $feesRemainderDuration = $this->schoolSettings->builder()->where('name', 'fees_remainder_duration')->value('data') ?? 2; $feesRemainderDuration = (int) $feesRemainderDuration; if (!$feesRemainderDuration) { return response()->json(['message' => 'Remainder duration not found in settings'], 400); } $classesWithDueDates = $this->fees->builder()->with('installments')->get(); $today = Carbon::now(); foreach ($classesWithDueDates as $classFee) { $dueDate = Carbon::parse($classFee->due_date); $class_section_id = $this->classSection->builder()->where('class_id', $classFee->class_id)->first(); $daysUntilDue = $today->diffInDays($dueDate, false); if ($daysUntilDue <= $feesRemainderDuration && $daysUntilDue >= 0) { $user = $this->student->builder()->whereIn('class_section_id', $class_section_id)->pluck('guardian_id')->toArray(); $title = 'Fees Due Reminder'; $body = "Pay fees if you didn't paid !!"; $type = "fee-reminder"; send_notification($user, $title, $body, $type); } } } else { return response()->json(['message' => 'Invalid school code'], 400); } } else { return response()->json(['message' => 'Unauthenticated'], 400); } ResponseService::successResponse("Notification Sent Successfully",); } catch (\Throwable $e) { ResponseService::logErrorResponse($e); return ResponseService::errorResponse(); } } public function paymentStatus(Request $request) { Log::info('Payment Status Callback:', $request->all()); ResponseService::successResponse("Payment Status Callback.", $request->all()); } public function flutterwaveFeesWebhook(Request $request) { Log::info('Flutterwave Fees Webhook:', $request->all()); ResponseService::successResponse("Flutterwave Fees Webhook received."); } public function flutterwaveSuccessCallback() { Log::info('Flutterwave Successfully.'); ResponseService::successResponse("Flutterwave Successfully."); } public function flutterwaveCancelCallback() { Log::info('Flutterwave Payment Canceled.'); ResponseService::successResponse("Flutterwave Payment Canceled."); } public function getStudentDetails(Request $request) { try { if (!$request->has('student_id') || empty($request->student_id)) { return ResponseService::errorResponse("Student ID is required"); } $user = $this->student->builder() ->where('user_id', $request->student_id) ->with([ 'user', 'class_section.class', 'class_section.class.shift', 'class_section.section', 'class_section.medium' ])->first(); if (!$user) { return ResponseService::errorResponse("Student not found"); } // Add semester subjects as a property $user->subjects = $user->currentSemesterSubjects(); ResponseService::successResponse("Student Class Details Fetched Successfully", $user); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function pickupPoints(Request $request) { try { $school_code = $request->header('school-code'); if (!$school_code) { return response()->json(['message' => 'Unauthenticated'], 400); } $school = School::on('mysql')->where('code', $school_code)->first(); if (!$school) { return response()->json(['message' => 'Invalid school code'], 400); } // Switch DB DB::setDefaultConnection('school'); Config::set('database.connections.school.database', $school->database_name); DB::purge('school'); DB::connection('school')->reconnect(); DB::setDefaultConnection('school'); $pickupPoints = $this->pickupPoint->builder()->select('id', 'name', 'latitude', 'longitude')->where('status', 1)->get(); return ResponseService::successResponse("Pickup points fetched successfully", $pickupPoints); } catch (\Throwable $th) { ResponseService::logErrorResponse($th); return ResponseService::errorResponse(); } } public function getStudentDiaries(Request $request) { $validator = Validator::make($request->all(), [ 'student_id' => 'required', ]); if ($validator->fails()) { return ResponseService::validationError($validator->errors()->first()); } try { /* ------------------------------------------------- | 1. Fetch student → class_section → class_id -------------------------------------------------*/ $student = $this->user->builder() ->where('id', $request->student_id) ->with('student.class_section') // student → class_section ->first(); if ( !$student || !$student->student || !$student->student->class_section || !$student->student->class_section->class_id ) { return ResponseService::errorResponse('Invalid student or class not found'); } $classId = $student->student->class_section->class_id; $sortType = strtolower($request->get('sort', 'new')); /* ------------------------------------------------- | 2. Resolve allowed class_subject_ids -------------------------------------------------*/ $allowedClassSubjectIds = DB::table('class_subjects') ->where('class_id', $classId) ->where(function ($q) use ($request) { // Compulsory subjects → always allowed $q->where('type', 'Compulsory') // Elective subjects → must be assigned ->orWhere(function ($q) use ($request) { $q->where('type', 'Elective') ->whereExists(function ($sub) use ($request) { $sub->select(DB::raw(1)) ->from('student_subjects') ->whereColumn( 'student_subjects.class_subject_id', 'class_subjects.id' ) ->where('student_subjects.student_id', $request->student_id); }); }); }) ->pluck('id'); /* ------------------------------------------------- | 3. Base student query -------------------------------------------------*/ $users = $this->user->builder() ->select('id', 'first_name', 'last_name', 'mobile', 'email', 'image', 'dob') ->where('id', $request->student_id) ->whereHas('roles', function ($q) { $q->where('name', 'Student'); }); // Search if ($request->search) { $users->where(function ($q) use ($request) { $q->where('first_name', 'like', "%{$request->search}%") ->orWhere('last_name', 'like', "%{$request->search}%") ->orWhere('mobile', 'like', "%{$request->search}%") ->orWhere('email', 'like', "%{$request->search}%"); }); } /* ------------------------------------------------- | 4. Diary student filter -------------------------------------------------*/ $diaryStudentFilter = function ($q) use ($request, $sortType, $allowedClassSubjectIds) { // Diary category if ($request->diary_category_id) { $q->whereHas('diary', function ($dq) use ($request) { $dq->where('diary_category_id', $request->diary_category_id); }); } // Positive / Negative if ($sortType === 'positive') { $q->whereHas('diary.diary_category', function ($dq) { $dq->where('type', 'positive'); }); } if ($sortType === 'negative') { $q->whereHas('diary.diary_category', function ($dq) { $dq->where('type', 'negative'); }); } // SUBJECT FILTER (class_subject based) $q->where(function ($subjectFilter) use ($allowedClassSubjectIds) { // Case 1: Diary has NO subject (subject_id IS NULL) $subjectFilter->whereDoesntHave('diary.subject') // Case 2: Diary has subject AND it is allowed ->orWhereHas('diary.subject.class_subjects', function ($cs) use ($allowedClassSubjectIds) { $cs->whereIn('id', $allowedClassSubjectIds); }); }); // Optional subject filter if ($request->subject_id) { $q->whereHas('diary.subject', function ($sq) use ($request) { $sq->where('subjects.id', $request->subject_id); }); } // Sorting if ($sortType === 'new') { $q->orderBy('created_at', 'DESC'); } if ($sortType === 'old') { $q->orderBy('created_at', 'ASC'); } }; /* ------------------------------------------------- | 5. Apply filters + eager loading -------------------------------------------------*/ $users->whereHas('diary_student', $diaryStudentFilter); $users->with([ 'diary_student' => $diaryStudentFilter, 'diary_student.diary.subject', 'diary_student.diary.diary_category' => function ($q) { $q->withTrashed(); } ]); /* ------------------------------------------------- | 6. Response -------------------------------------------------*/ $result = $users ->orderBy('id', 'DESC') ->paginate(10); ResponseService::successResponse( 'Student Diaries Fetched Successfully', $result ); } catch (\Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getTeachers(Request $request) { $validator = Validator::make($request->all(), [ 'student_id' => 'required|numeric', ]); if ($validator->fails()) { ResponseService::validationError($validator->errors()->first()); } try { // Get student by user_id (student_id is the user_id) $student = $this->student->builder() ->where('user_id', $request->student_id) ->whereHas('user', function ($q) { $q->whereNull('deleted_at'); }) ->first(); if (empty($student)) { ResponseService::errorResponse("Student Account is not Active. Contact School Support", NULL, config('constants.RESPONSE_CODE.INACTIVE_CHILD')); } $defaultSessionYear = $this->cache->getDefaultSessionYear(); // Get class subject IDs for the student $class_subject_id = $student->selectedStudentSubjects()->pluck('class_subject_id'); // Get subject teachers for the student's class section and subjects $subjectTeachers = SubjectTeacher::select('id', 'subject_id', 'teacher_id', 'school_id') ->whereIn('class_subject_id', $class_subject_id) ->where('class_section_id', $student->class_section_id) ->whereHas('teacher', fn($q) => $q->where('status', 1)) ->where('session_year_id', $defaultSessionYear->id) ->with([ 'subject:id,name,type', 'teacher:id,first_name,last_name,image,mobile' ]) ->get(); ResponseService::successResponse("Teacher Details Fetched Successfully", $subjectTeachers); } catch (Throwable $e) { ResponseService::logErrorResponse($e); ResponseService::errorResponse(); } } public function getNotifications(Request $request) { try { $offset = $request->offset ?? 0; $limit = $request->limit ?? 10; $user = Auth::user(); if (!$user) { return ResponseService::errorResponse("User not authenticated"); } // Only notifications belonging to this user (directly attached) $user_notifications = UserNotification::where('user_id', $user->id)->pluck('notification_id')->toArray(); $notifications = Notification::whereIn('id', $user_notifications)->orderBy('id', 'DESC')->offset($offset)->limit($limit)->get(); return ResponseService::successResponse("Notifications Fetched Successfully", $notifications); } catch (Throwable $e) { ResponseService::logErrorResponse($e); return ResponseService::errorResponse(); } } public function getFirebaseConfig() { try { // Fetch Firebase configuration fields individually and decode HTML entities $firebaseConfig = [ 'firebase_api_key' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_api_key') ?? ''), 'firebase_auth_domain' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_auth_domain') ?? ''), 'firebase_storage_bucket' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_storage_bucket') ?? ''), 'firebase_messaging_sender_id' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_messaging_sender_id') ?? ''), 'firebase_app_id' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_app_id') ?? ''), 'firebase_measurement_id' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_measurement_id') ?? ''), 'firebase_service_file' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_service_file') ?? ''), 'firebase_project_id' => htmlspecialchars_decode($this->cache->getSystemSettings('firebase_project_id') ?? '') ]; return ResponseService::successResponse("Data Fetched Successfully", $firebaseConfig); } catch (Throwable $e) { ResponseService::logErrorResponse($e); return ResponseService::errorResponse(); } } public function getSystemSettings(Request $request) { try { $school_code = $request->school_code; if ($school_code) { $school = School::on('mysql')->where('code', $school_code)->first(); if ($school) { // // Switch DB DB::setDefaultConnection('school'); Config::set('database.connections.school.database', $school->database_name); DB::purge('school'); DB::connection('school')->reconnect(); DB::setDefaultConnection('school'); $data = [ 'vertical_logo' => $this->cache->getSchoolSettings('vertical_logo', $school->id) ?? '', 'horizontal_logo' => $this->cache->getSchoolSettings('horizontal_logo', $school->id) ?? '', 'favicon' => $this->cache->getSchoolSettings('favicon', $school->id) ?? '', 'student_web_background_image' => $this->cache->getSystemSettings('student_web_background_image') ?? '', 'system_name' => $this->cache->getSchoolSettings('system_name', $school->id) ?? '', 'address' => $this->cache->getSystemSettings('address', $school->id) ?? '', 'tag_line' => $this->cache->getSchoolSettings('tag_line', $school->id) ?? '', 'theme_color' => $this->cache->getSchoolSettings('theme_color', $school->id) ?? '', 'mobile' => $this->cache->getSchoolSettings('mobile', $school->id) ?? '', 'student_parent_privacy_policy' => url('page/student-parent-privacy-policy') ?? '', 'student_terms_condition' => url('page/student-terms-conditions') ?? '', 'student_web_maintenance' => $this->cache->getSystemSettings('student_web_maintenance') ?? '0', ]; return ResponseService::successResponse("System Settings Fetched Successfully", $data); } else { return ResponseService::errorResponse("School not found"); } } else { $data = [ 'vertical_logo' => $this->cache->getSystemSettings('vertical_logo') ?? '', 'horizontal_logo' => $this->cache->getSystemSettings('horizontal_logo') ?? '', 'favicon' => $this->cache->getSystemSettings('favicon') ?? '', 'student_web_background_image' => $this->cache->getSystemSettings('student_web_background_image') ?? '', 'system_name' => $this->cache->getSystemSettings('system_name') ?? '', 'address' => $this->cache->getSystemSettings('address') ?? '', 'tag_line' => $this->cache->getSystemSettings('tag_line') ?? '', 'theme_color' => $this->cache->getSystemSettings('theme_color') ?? '', 'mobile' => $this->cache->getSystemSettings('mobile') ?? '', 'student_parent_privacy_policy' => url('page/student-parent-privacy-policy') ?? '', 'student_terms_condition' => url('page/student-terms-conditions') ?? '', 'student_web_maintenance' => $this->cache->getSystemSettings('student_web_maintenance') ?? '1', ]; return ResponseService::successResponse("System Settings Fetched Successfully", $data); } } catch (Throwable $e) { ResponseService::logErrorResponse($e); return ResponseService::errorResponse(); } } }