withTrashed(); // 테넌트 필터링 (user_tenants pivot을 통한 필터링) if ($tenantId) { $query->whereHas('tenants', function ($q) use ($tenantId) { $q->where('tenants.id', $tenantId); }); } // Soft Delete 필터 if (isset($filters['trashed'])) { if ($filters['trashed'] === 'only') { $query->onlyTrashed(); } elseif ($filters['trashed'] === 'with') { $query->withTrashed(); } } // 검색 필터 if (! empty($filters['search'])) { $search = $filters['search']; $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%") ->orWhere('phone', 'like', "%{$search}%") ->orWhere('user_id', 'like', "%{$search}%"); }); } // 활성 상태 필터 if (isset($filters['is_active'])) { $query->where('is_active', $filters['is_active']); } return $query->orderBy('created_at', 'desc')->paginate($perPage); } /** * 사용자 상세 조회 */ public function getUserById(int $id): ?User { return User::find($id); } /** * 사용자 생성 */ public function createUser(array $data): User { $tenantId = session('selected_tenant_id'); // 비밀번호 해싱 if (isset($data['password'])) { $data['password'] = Hash::make($data['password']); } // is_active 처리 $data['is_active'] = isset($data['is_active']) && $data['is_active'] == '1'; // 생성자 정보 $data['created_by'] = auth()->id(); // 사용자 생성 $user = User::create($data); // user_tenants pivot에 관계 추가 if ($tenantId) { $user->tenants()->attach($tenantId, [ 'is_active' => true, 'is_default' => true, 'joined_at' => now(), ]); // 역할/부서 동기화 $roleIds = $data['role_ids'] ?? []; $departmentIds = $data['department_ids'] ?? []; $this->syncRoles($user, $tenantId, $roleIds); $this->syncDepartments($user, $tenantId, $departmentIds); } return $user; } /** * 사용자 수정 */ public function updateUser(int $id, array $data): bool { $user = $this->getUserById($id); if (! $user) { return false; } $tenantId = session('selected_tenant_id'); // 비밀번호가 입력된 경우만 업데이트 if (! empty($data['password'])) { $data['password'] = Hash::make($data['password']); } else { unset($data['password']); } // is_active 처리 $data['is_active'] = isset($data['is_active']) && $data['is_active'] == '1'; // 수정자 정보 $data['updated_by'] = auth()->id(); // 역할/부서 동기화 (테넌트가 선택된 경우) if ($tenantId) { $roleIds = $data['role_ids'] ?? []; $departmentIds = $data['department_ids'] ?? []; $this->syncRoles($user, $tenantId, $roleIds); $this->syncDepartments($user, $tenantId, $departmentIds); } // role_ids, department_ids는 User 모델의 fillable이 아니므로 제거 unset($data['role_ids'], $data['department_ids']); return $user->update($data); } /** * 사용자 역할 동기화 (특정 테넌트) */ public function syncRoles(User $user, int $tenantId, array $roleIds): void { // 기존 역할 삭제 (해당 테넌트만) - forceDelete로 실제 삭제 UserRole::withTrashed() ->where('user_id', $user->id) ->where('tenant_id', $tenantId) ->forceDelete(); // 새 역할 추가 foreach ($roleIds as $roleId) { UserRole::create([ 'user_id' => $user->id, 'tenant_id' => $tenantId, 'role_id' => $roleId, 'assigned_at' => now(), ]); } } /** * 사용자 부서 동기화 (특정 테넌트) */ public function syncDepartments(User $user, int $tenantId, array $departmentIds): void { // 기존 부서 삭제 (해당 테넌트만) - forceDelete로 실제 삭제 DepartmentUser::withTrashed() ->where('user_id', $user->id) ->where('tenant_id', $tenantId) ->forceDelete(); // 새 부서 추가 (첫 번째를 primary로) foreach ($departmentIds as $index => $departmentId) { DepartmentUser::create([ 'user_id' => $user->id, 'tenant_id' => $tenantId, 'department_id' => $departmentId, 'is_primary' => $index === 0, 'joined_at' => now(), 'created_by' => auth()->id(), ]); } } /** * 사용자 삭제 (Soft Delete) */ public function deleteUser(int $id): bool { $user = $this->getUserById($id); if (! $user) { return false; } $user->deleted_by = auth()->id(); $user->save(); return $user->delete(); } /** * 사용자 복원 */ public function restoreUser(int $id): bool { $user = User::onlyTrashed()->findOrFail($id); return $user->restore(); } /** * 사용자 영구 삭제 (슈퍼관리자 전용) */ public function forceDeleteUser(int $id): bool { $user = User::withTrashed()->findOrFail($id); // 관련 데이터 먼저 삭제 $user->tenants()->detach(); // user_tenants 관계 삭제 return $user->forceDelete(); } /** * 활성 사용자 목록 조회 (드롭다운용) */ public function getActiveUsers() { $tenantId = session('selected_tenant_id'); $query = User::query()->where('is_active', true); // 테넌트 필터링 (user_tenants pivot을 통한 필터링) if ($tenantId) { $query->whereHas('tenants', function ($q) use ($tenantId) { $q->where('tenants.id', $tenantId); }); } return $query->orderBy('name')->get(); } }