add all controllers logic

This commit is contained in:
root
2026-03-11 17:53:15 -04:00
parent 3e6c577085
commit 2ef71cc92b
421 changed files with 12009 additions and 5211 deletions
@@ -0,0 +1,126 @@
<?php
namespace App\Services\Messaging;
use App\Models\Message;
use App\Services\System\GlobalConfigService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use RuntimeException;
class MessageCommandService
{
public function __construct(private GlobalConfigService $configService)
{
}
public function create(int $senderId, array $payload, ?UploadedFile $attachment = null): Message
{
$recipientId = $payload['recipient_id'] ?? null;
if (!$recipientId && !empty($payload['recipient_role'])) {
$recipientId = $this->recipientIdFromRole($payload['recipient_role']);
}
if (!$recipientId) {
throw new RuntimeException('Recipient is required.');
}
if ((int) $recipientId === $senderId) {
throw new RuntimeException('Cannot send a message to yourself.');
}
return DB::transaction(function () use ($senderId, $payload, $recipientId, $attachment) {
$path = null;
if ($attachment) {
$path = $attachment->store('messages', ['disk' => 'public']);
}
$message = Message::query()->create([
'sender_id' => $senderId,
'recipient_id' => (int) $recipientId,
'subject' => (string) $payload['subject'],
'message' => (string) $payload['message'],
'sent_datetime' => now(),
'read_status' => 0,
'message_number' => 'MSG-' . now()->format('YmdHis'),
'priority' => $payload['priority'] ?? 'normal',
'attachment' => $path,
'status' => $payload['status'] ?? 'sent',
'semester' => $payload['semester'] ?? $this->configService->getSemester() ?? '',
'school_year' => $payload['school_year'] ?? $this->configService->getSchoolYear() ?? '',
]);
if (!$message) {
throw new RuntimeException('Failed to send message.');
}
return $message;
});
}
public function update(Message $message, array $payload): Message
{
return DB::transaction(function () use ($message, $payload) {
$updates = [];
if (array_key_exists('status', $payload)) {
$updates['status'] = $payload['status'];
}
if (array_key_exists('priority', $payload)) {
$updates['priority'] = $payload['priority'];
}
if (array_key_exists('read_status', $payload)) {
$read = (int) $payload['read_status'];
$updates['read_status'] = $read;
if ($read === 1) {
$updates['read_datetime'] = now();
}
}
if (!empty($updates)) {
$message->fill($updates);
$message->save();
}
return $message->fresh();
});
}
public function trash(Message $message): bool
{
return DB::transaction(function () use ($message) {
$message->status = 'trashed';
return (bool) $message->save();
});
}
public function markRead(Message $message): bool
{
if ($message->read_status) {
return true;
}
$message->read_status = 1;
$message->read_datetime = now();
return (bool) $message->save();
}
private function recipientIdFromRole(string $roleName): int
{
$map = [
'teacher' => 1,
'parent' => 2,
'admin' => 3,
'student' => 4,
'guest' => 5,
'administrator' => 6,
];
$key = strtolower(trim($roleName));
if (!isset($map[$key])) {
throw new RuntimeException('Invalid recipient role.');
}
return $map[$key];
}
}
@@ -0,0 +1,115 @@
<?php
namespace App\Services\Messaging;
use App\Models\Message;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
class MessageQueryService
{
public function getUserRoleName(int $userId): ?string
{
$user = User::query()->with('roles')->find($userId);
if (!$user) {
return null;
}
$role = $user->roles->sortBy('id')->first();
return $role ? (string) $role->name : null;
}
public function inbox(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
{
return $this->baseQuery($filters)
->where('recipient_id', $userId)
->whereIn('status', ['sent', 'received'])
->paginate($perPage, ['*'], 'page', $page);
}
public function sent(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
{
return $this->baseQuery($filters)
->where('sender_id', $userId)
->where('status', 'sent')
->paginate($perPage, ['*'], 'page', $page);
}
public function drafts(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
{
return $this->baseQuery($filters)
->where('sender_id', $userId)
->where('status', 'draft')
->paginate($perPage, ['*'], 'page', $page);
}
public function trash(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
{
return $this->baseQuery($filters)
->where('status', 'trashed')
->where(function ($q) use ($userId) {
$q->where('sender_id', $userId)
->orWhere('recipient_id', $userId);
})
->paginate($perPage, ['*'], 'page', $page);
}
public function receivedAndMarkRead(int $userId): array
{
$messages = Message::query()
->with(['sender', 'recipient'])
->where('recipient_id', $userId)
->orderByDesc('sent_datetime')
->get();
$ids = $messages
->where('read_status', false)
->pluck('id')
->all();
if (!empty($ids)) {
Message::query()
->whereIn('id', $ids)
->update([
'read_status' => 1,
'read_datetime' => now(),
]);
}
return $messages->all();
}
public function findForUser(int $messageId): ?Message
{
return Message::query()
->with(['sender', 'recipient'])
->find($messageId);
}
private function baseQuery(array $filters)
{
$query = Message::query()->with(['sender', 'recipient']);
if (!empty($filters['priority'])) {
$query->where('priority', $filters['priority']);
}
if (isset($filters['read_status'])) {
$query->where('read_status', (int) $filters['read_status']);
}
if (!empty($filters['search'])) {
$term = '%' . $filters['search'] . '%';
$query->where(function ($q) use ($term) {
$q->where('subject', 'like', $term)
->orWhere('message', 'like', $term);
});
}
$sortBy = $filters['sort_by'] ?? 'sent_datetime';
$sortDir = strtolower((string) ($filters['sort_dir'] ?? 'desc')) === 'asc' ? 'asc' : 'desc';
$query->orderBy($sortBy, $sortDir);
return $query;
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Services\Messaging;
use App\Models\ParentModel;
use App\Models\Student;
use App\Models\StudentClass;
use App\Models\TeacherClass;
use App\Models\User;
class MessageRecipientService
{
public function teachers(): array
{
$rows = TeacherClass::query()
->select('teacher_class.teacher_id', 'users.firstname', 'users.lastname')
->join('users', 'users.id', '=', 'teacher_class.teacher_id')
->orderBy('users.firstname')
->orderBy('users.lastname')
->get();
return $rows
->map(fn ($row) => [
'id' => (int) $row->teacher_id,
'name' => trim($row->firstname . ' ' . $row->lastname),
])
->unique('id')
->values()
->all();
}
public function parents(): array
{
$sectionIds = TeacherClass::query()->pluck('class_section_id')->filter()->unique()->values()->all();
if (empty($sectionIds)) {
return [];
}
$studentIds = StudentClass::query()
->active()
->whereIn('student_class.class_section_id', $sectionIds)
->pluck('student_class.student_id')
->filter()
->unique()
->values()
->all();
if (empty($studentIds)) {
return [];
}
$parentIds = Student::query()
->whereIn('id', $studentIds)
->where('is_active', 1)
->pluck('parent_id')
->filter()
->unique()
->values()
->all();
if (empty($parentIds)) {
return [];
}
$secondParentIds = ParentModel::query()
->whereIn('firstparent_id', $parentIds)
->pluck('secondparent_id')
->filter()
->unique()
->values()
->all();
$allIds = collect($parentIds)->merge($secondParentIds)->unique()->values()->all();
$users = User::query()
->whereIn('id', $allIds)
->orderBy('firstname')
->orderBy('lastname')
->get();
return $users
->map(fn ($row) => [
'id' => (int) $row->id,
'name' => trim($row->firstname . ' ' . $row->lastname),
])
->unique('id')
->values()
->all();
}
}