with(['profile', 'employee', 'roles']) ->whereDoesntHave('roles', fn ($query) => $query->where('name', Role::DEVELOPER->value)) ->when($tableQuery['search'] !== '', function ($query) use ($tableQuery): void { $search = $tableQuery['search']; $query->where(function ($query) use ($search): void { $query->where('email', 'like', "%{$search}%") ->orWhere('username', 'like', "%{$search}%") ->orWhereHas('profile', function ($query) use ($search): void { $query->where('full_name', 'like', "%{$search}%") ->orWhere('phone_number', 'like', "%{$search}%"); }); }); }) ->when($role !== '', fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', $role))) ->when($gender !== '', fn ($query) => $query->whereHas('profile', fn ($query) => $query->where('gender', $gender))) ->when($employmentStatus !== '', function ($query) use ($employmentStatus): void { $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus)); }) ->when($isActive !== '', fn ($query) => $query->where('is_active', $isActive === '1')); $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); return $query ->paginate(10) ->withQueryString(); } public function assignableRoleOptions(): array { return Role::assignableSelectOptions(); } public function findForEdit(User $user): array { $user->load(['profile', 'employee', 'roles']); return [ 'employee' => $user, 'profilePhoto' => $user->profile ? MediaPresenter::first($user->profile, 'profile_photo') : null, ]; } /** * @param array $validated */ public function create(array $validated): void { try { DB::transaction(function () use ($validated): void { $user = User::create([ 'email' => $validated['email'], 'username' => $validated['username'], 'password' => Hash::make(config('auth.password_default')), ]); $profile = UserProfile::create([ 'user_id' => $user->id, 'full_name' => $validated['full_name'], 'phone_number' => $validated['phone_number'], 'gender' => $validated['gender'], 'birth_date' => $validated['birth_date'], 'address' => $validated['address'], ]); $this->syncProfilePhoto($profile, $validated); if ($validated['role'] !== Role::OWNER->value) { Employee::create([ 'user_id' => $user->id, 'join_date' => $validated['join_date'], 'employment_status' => $validated['employment_status'], 'base_salary' => $validated['base_salary'], ]); } $user->syncRoles([$validated['role']]); }); } catch (ValidationException $e) { throw $e; } catch (\Throwable $e) { Log::error('Gagal membuat karyawan: '.$e->getMessage(), [ 'trace' => $e->getTraceAsString(), ]); throw ValidationException::withMessages([ 'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.', ]); } } /** * @param array $validated */ public function update(User $user, array $validated): void { $employee = $user->employee; try { DB::transaction(function () use ($validated, $user, $employee): void { $user->update([ 'email' => $validated['email'], 'username' => $validated['username'], ]); /** @var UserProfile $profile */ $profile = $user->profile()->updateOrCreate( ['user_id' => $user->id], [ 'full_name' => $validated['full_name'], 'phone_number' => $validated['phone_number'], 'gender' => $validated['gender'], 'birth_date' => $validated['birth_date'], 'address' => $validated['address'], ], ); $this->syncProfilePhoto($profile, $validated); $hasEmployee = ! empty($validated['join_date']) && ! empty($validated['employment_status']) && ! empty($validated['base_salary']); if ($hasEmployee) { if ($employee) { $employee->update([ 'join_date' => $validated['join_date'], 'employment_status' => $validated['employment_status'], 'base_salary' => $validated['base_salary'], ]); } else { Employee::create([ 'user_id' => $user->id, 'join_date' => $validated['join_date'], 'employment_status' => $validated['employment_status'], 'base_salary' => $validated['base_salary'], ]); } } else { if ($employee) { $employee->delete(); } } $user->syncRoles([$validated['role']]); }); } catch (ValidationException $e) { throw $e; } catch (\Throwable $e) { Log::error('Gagal memperbarui karyawan: '.$e->getMessage(), [ 'trace' => $e->getTraceAsString(), ]); throw ValidationException::withMessages([ 'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.', ]); } } public function toggleStatus(User $user, array $validated): void { $user->update([ 'is_active' => $validated['is_active'], ]); if (! $validated['is_active']) { DB::table('sessions')->where('user_id', $user->id)->delete(); } } public function resetPassword(User $user): void { $user->update([ 'password' => config('auth.password_default'), ]); DB::table('sessions')->where('user_id', $user->id)->delete(); } public function delete(User $user): void { try { DB::transaction(function () use ($user): void { $user->employee?->delete(); $user->profile?->delete(); $user->delete(); }); } catch (ValidationException $e) { throw $e; } catch (\Throwable $e) { Log::error('Gagal menghapus karyawan: '.$e->getMessage(), [ 'trace' => $e->getTraceAsString(), ]); throw ValidationException::withMessages([ 'system' => 'Terjadi kesalahan pada server. Silakan laporkan masalah ini ke pihak terkait.', ]); } } /** * @param array $validated */ private function syncProfilePhoto(UserProfile $profile, array $validated): void { $newFiles = ! empty($validated['profile_photo']) ? [$validated['profile_photo']] : []; $removeIds = $validated['remove_profile_photo_ids'] ?? []; $this->mediaService->syncCollection($profile, 'profile_photo', $newFiles, $removeIds, 1); } private function applySorting(Builder $query, string $sort, string $direction): void { $employeeSorts = [ 'join_date', 'base_salary', 'employment_status', ]; if (in_array($sort, $employeeSorts, true)) { $query->orderBy( Employee::select($sort) ->whereColumn('employees.user_id', 'users.id') ->limit(1), $direction ); return; } if ($sort === 'full_name') { $query->orderBy( UserProfile::select('full_name') ->whereColumn('user_profiles.user_id', 'users.id') ->limit(1), $direction ); return; } if ($sort === 'email') { $query->orderBy('email', $direction); return; } $query->latest(); } }