select(['id', 'employee_id', 'start_date', 'end_date', 'total_days', 'status', 'created_at']) ->with(['employee.user.userProfile']) ->when($highlight, fn ($q) => $q->where('id', $highlight)) ->when(! self::hasAnyRole([Role::DEVELOPER, Role::OWNER, Role::DIREKTUR, Role::ADMIN_TOKO]), fn ($q) => $q->whereHas('employee', fn ($eq) => $eq->where('user_id', auth()->id()))) ->when($search, fn ($q) => $q->whereHas('employee.user.userProfile', fn ($uq) => $uq->where('full_name', 'like', "%{$search}%"))) ->when($filters['status'] ?? null, function ($query, $status) { $query->where('status', $status); }) ->orderBy($sort, $direction) ->paginate($perPage); } public function store(array $data): LeaveRequest { $leaveRequest = DB::transaction(function () use ($data) { $employee = auth()->user()->employee; if (! $employee) { throw ValidationException::withMessages([ 'employee' => 'Anda tidak terdaftar sebagai karyawan.', ]); } $startDate = new Carbon($data['start_date']); $endDate = new Carbon($data['end_date']); $totalDays = $startDate->diffInDays($endDate) + 1; return LeaveRequest::create([ 'employee_id' => $employee->id, 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'total_days' => $totalDays, 'status' => LeaveRequestStatus::PENDING, ]); }); $leaveRequest->load('employee.user'); NotificationService::notify( roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Pengajuan Cuti Baru', body: "Pengajuan cuti {$leaveRequest->total_days} hari oleh ".auth()->user()->full_name.'.', url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $leaveRequest->employee->user ?? null, ); return $leaveRequest; } public function update(LeaveRequest $leaveRequest, array $data): LeaveRequest { if (! $this->canModify($leaveRequest)) { throw ValidationException::withMessages([ 'employee' => 'Anda tidak memiliki akses untuk mengubah cuti ini.', ]); } return DB::transaction(function () use ($leaveRequest, $data) { $startDate = new Carbon($data['start_date']); $endDate = new Carbon($data['end_date']); $totalDays = $startDate->diffInDays($endDate) + 1; $leaveRequest->update([ 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'total_days' => $totalDays, ]); return $leaveRequest; }); } public function destroy(LeaveRequest $leaveRequest): bool { if (! $this->canModify($leaveRequest)) { throw ValidationException::withMessages([ 'employee' => 'Anda tidak memiliki akses untuk menghapus cuti ini.', ]); } return $leaveRequest->delete(); } public function approve(LeaveRequest $leaveRequest): LeaveRequest { $leaveRequest->update([ 'status' => LeaveRequestStatus::APPROVED, 'verified_by_id' => auth()->id(), 'verified_at' => now(), ]); $employeeUser = $leaveRequest->employee->user ?? null; NotificationService::notify( roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Cuti Disetujui', body: "Cuti {$leaveRequest->employee->name} telah disetujui oleh ".auth()->user()->full_name.'.', url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $employeeUser, ); return $leaveRequest; } public function reject(LeaveRequest $leaveRequest): LeaveRequest { $leaveRequest->update([ 'status' => LeaveRequestStatus::REJECTED, 'verified_by_id' => auth()->id(), 'verified_at' => now(), ]); $employeeUser = $leaveRequest->employee->user ?? null; NotificationService::notify( roles: [Role::OWNER, Role::DEVELOPER, Role::DIREKTUR, Role::ADMIN_TOKO], title: 'Cuti Ditolak', body: "Cuti {$leaveRequest->employee->name} telah ditolak oleh ".auth()->user()->full_name.'.', url: route('admin.hr.leave-requests.index', ['highlight' => $leaveRequest->id]), additionalUser: $employeeUser, ); return $leaveRequest; } private function canModify(LeaveRequest $leaveRequest): bool { if (self::hasAnyRole([Role::DEVELOPER, Role::OWNER])) { return true; } return $leaveRequest->employee->user_id === auth()->id(); } }