message = model(Message::class); $this->userRole = model(UserRole::class); $this->teacherClass = model(TeacherClass::class); $this->studentClass = model(StudentClass::class); $this->student = model(Student::class); $this->user = model(User::class); } public function inbox() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $messages = $this->message->getInboxMessages((int) $user->id); return $this->success($messages, 'Inbox messages retrieved'); } public function sent() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $messages = $this->message->getSentMessages((int) $user->id); return $this->success($messages, 'Sent messages retrieved'); } public function drafts() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $messages = $this->message->getDraftMessages((int) $user->id); return $this->success($messages, 'Draft messages retrieved'); } public function trash() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $messages = $this->message->getTrashedMessages((int) $user->id); return $this->success($messages, 'Trashed messages retrieved'); } public function index() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $role = $this->resolveRoleName((int) $user->id); return $this->success([ 'role' => $role, 'receivedMessages' => $this->getReceivedMessages((int) $user->id), ], 'Message overview retrieved'); } public function send() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $payload = $this->payloadData(); $recipientId = $payload['recipient_id'] ?? null; if (!$recipientId && !empty($payload['recipient_role'])) { $recipientId = $this->getRecipientId(['name' => $payload['recipient_role']]); } if (!$recipientId) { return $this->respondError('Recipient not provided', Response::HTTP_UNPROCESSABLE_ENTITY); } $attachmentPath = $this->storeAttachment(); $data = [ 'sender_id' => (int) $user->id, 'recipient_id' => (int) $recipientId, 'subject' => $payload['subject'] ?? null, 'message' => $payload['message'] ?? null, 'sent_datetime' => Carbon::now('UTC')->format('Y-m-d H:i:s'), 'message_number'=> $this->generateMessageNumber(), 'priority' => $payload['priority'] ?? 'normal', 'attachment' => $attachmentPath, 'status' => $payload['status'] ?? 'sent', 'semester' => $payload['semester'] ?? null, 'school_year' => $payload['school_year'] ?? null, ]; $message = $this->message->create($data); return $this->success($message->toArray(), 'Message sent successfully'); } public function receive() { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $messages = $this->getReceivedMessages((int) $user->id); foreach ($messages as $message) { $this->markAsRead((int) ($message['id'] ?? 0)); } return $this->success($messages, 'Received messages retrieved'); } /** * GET /api/v1/messages/recipients/{type} * Get recipients list (teachers or parents) */ public function getRecipients($type) { $user = $this->getCurrentUser(); if (!$user) { return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED); } $type = strtolower(trim((string) ($type ?? ''))); if (!in_array($type, ['teacher', 'parent'], true)) { return $this->respondError('Unsupported recipient type. Must be "teacher" or "parent"', Response::HTTP_UNPROCESSABLE_ENTITY); } $recipients = []; $teacherClasses = $this->teacherClass->findAll(); if ($type === 'teacher') { foreach ($teacherClasses as $teacher) { $userRow = $this->user->find($teacher['teacher_id'] ?? null); if (!$userRow) { continue; } $recipients[(int) $teacher['teacher_id']] = [ 'id' => (int) $teacher['teacher_id'], 'name' => trim(($userRow['firstname'] ?? '') . ' ' . ($userRow['lastname'] ?? '')), ]; } } elseif ($type === 'parent') { foreach ($teacherClasses as $class) { $students = $this->studentClass->where('class_section_id', $class['class_section_id'] ?? null)->findAll(); foreach ($students as $student) { $studentData = $this->student->find($student['student_id'] ?? null); if (!$studentData) { continue; } // Get first parent (primary parent) if (!empty($studentData['parent_id'])) { $firstParent = $this->user->find($studentData['parent_id']); if ($firstParent) { $parentName = trim(($firstParent['firstname'] ?? '') . ' ' . ($firstParent['lastname'] ?? '')); if ($parentName) { $recipients[(int) $studentData['parent_id']] = [ 'id' => (int) $studentData['parent_id'], 'name' => $parentName, ]; } } } // Get second parent if exists // Check if secondparent_user_id exists in students table if (!empty($studentData['secondparent_user_id'])) { $secondParent = $this->user->find($studentData['secondparent_user_id']); if ($secondParent) { $parentName = trim(($secondParent['firstname'] ?? '') . ' ' . ($secondParent['lastname'] ?? '')); if ($parentName) { $recipients[(int) $studentData['secondparent_user_id']] = [ 'id' => (int) $studentData['secondparent_user_id'], 'name' => $parentName, ]; } } } else { // Fallback: check parents table for second parent $parentRow = DB::table('parents') ->where('firstparent_id', $studentData['parent_id'] ?? 0) ->first(); if ($parentRow && !empty($parentRow->secondparent_user_id)) { $secondParent = $this->user->find($parentRow->secondparent_user_id); if ($secondParent) { $parentName = trim(($secondParent['firstname'] ?? '') . ' ' . ($secondParent['lastname'] ?? '')); if ($parentName) { $recipients[(int) $parentRow->secondparent_user_id] = [ 'id' => (int) $parentRow->secondparent_user_id, 'name' => $parentName, ]; } } } } } } } return $this->success(array_values($recipients), 'Recipients retrieved successfully'); } protected function resolveRoleName(int $userId): ?string { $role = $this->userRole->newQuery() ->select('roles.name') ->join('roles', 'roles.id', '=', 'user_roles.role_id') ->where('user_roles.user_id', $userId) ->first(); return $role['name'] ?? null; } protected function getReceivedMessages(int $userId): array { $rows = DB::table('messages') ->select('messages.*', 'users.firstname AS sender_name') ->join('users', 'messages.sender_id', '=', 'users.id') ->where('messages.recipient_id', $userId) ->orderBy('sent_datetime', 'DESC') ->get() ->toArray(); return array_map(fn($row) => (array) $row, $rows); } protected function markAsRead(int $messageId): void { if ($messageId <= 0) { return; } $this->message->markAsRead($messageId); } protected function generateMessageNumber(): string { return 'MSG-' . Carbon::now('UTC')->format('YmdHis'); } protected function getRecipientId(array $role): ?int { $roleName = strtolower($role['name'] ?? ''); return match ($roleName) { 'teacher' => 1, 'parent' => 2, 'admin' => 3, 'student' => 4, 'guest' => 5, 'administrator' => 6, default => null, }; } protected function storeAttachment(): ?string { /** @var UploadedFile|null $file */ $file = $this->laravelRequest->file('attachment'); if (!$file || !$file->isValid()) { return null; } return Storage::putFile('messages', $file); } }