employeeService->getEmployees( $request->all(), $request->integer('per_page', 20) ); if ($request->header('HX-Request')) { return response(view('hr.employees.partials.table', compact('employees'))); } return response()->json([ 'success' => true, 'data' => $employees->items(), 'meta' => [ 'current_page' => $employees->currentPage(), 'last_page' => $employees->lastPage(), 'per_page' => $employees->perPage(), 'total' => $employees->total(), ], ]); } /** * 기존 사용자 검색 (사원 미등록, 테넌트 소속) */ public function searchUsers(Request $request): JsonResponse { $users = $this->employeeService->searchTenantUsers($request->get('q', '')); return response()->json([ 'success' => true, 'data' => $users, ]); } /** * 사원 통계 */ public function stats(): JsonResponse { $stats = $this->employeeService->getStats(); return response()->json([ 'success' => true, 'data' => $stats, ]); } /** * 사원 등록 */ public function store(Request $request): JsonResponse { $rules = [ 'existing_user_id' => 'nullable|integer|exists:users,id', 'name' => 'required|string|max:50', 'email' => 'nullable|email|max:100', 'phone' => 'nullable|string|max:20', 'password' => 'nullable|string|min:6', 'department_id' => 'nullable|integer|exists:departments,id', 'position_key' => 'nullable|string|max:50', 'job_title_key' => 'nullable|string|max:50', 'work_location_key' => 'nullable|string|max:50', 'employment_type_key' => 'nullable|string|max:50', 'employee_status' => 'nullable|string|in:active,leave,resigned', 'manager_user_id' => 'nullable|integer|exists:users,id', 'display_name' => 'nullable|string|max:50', 'employee_code' => 'nullable|string|max:30', 'hire_date' => 'nullable|date', 'address' => 'nullable|string|max:200', 'emergency_contact' => 'nullable|string|max:100', ]; // 신규 사용자일 때만 이메일 unique 검증 if (! $request->filled('existing_user_id')) { $rules['email'] = 'nullable|email|max:100|unique:users,email'; } $validated = $request->validate($rules); try { $employee = $this->employeeService->createEmployee($validated); return response()->json([ 'success' => true, 'message' => '사원이 등록되었습니다.', 'data' => $employee, ], 201); } catch (\Throwable $e) { report($e); return response()->json([ 'success' => false, 'message' => '사원 등록 중 오류가 발생했습니다.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * 사원 상세 조회 */ public function show(int $id): JsonResponse { $employee = $this->employeeService->getEmployeeById($id); if (! $employee) { return response()->json([ 'success' => false, 'message' => '사원 정보를 찾을 수 없습니다.', ], 404); } return response()->json([ 'success' => true, 'data' => $employee, ]); } /** * 사원 수정 */ public function update(Request $request, int $id): JsonResponse { $validated = $request->validate([ 'name' => 'sometimes|required|string|max:50', 'email' => 'nullable|email|max:100', 'phone' => 'nullable|string|max:20', 'department_id' => 'nullable|integer|exists:departments,id', 'position_key' => 'nullable|string|max:50', 'job_title_key' => 'nullable|string|max:50', 'work_location_key' => 'nullable|string|max:50', 'employment_type_key' => 'nullable|string|max:50', 'employee_status' => 'nullable|string|in:active,leave,resigned', 'manager_user_id' => 'nullable|integer|exists:users,id', 'display_name' => 'nullable|string|max:50', 'employee_code' => 'nullable|string|max:30', 'hire_date' => 'nullable|date', 'address' => 'nullable|string|max:200', 'emergency_contact' => 'nullable|string|max:100', ]); try { $employee = $this->employeeService->updateEmployee($id, $validated); if (! $employee) { return response()->json([ 'success' => false, 'message' => '사원 정보를 찾을 수 없습니다.', ], 404); } return response()->json([ 'success' => true, 'message' => '사원 정보가 수정되었습니다.', 'data' => $employee, ]); } catch (\Throwable $e) { report($e); return response()->json([ 'success' => false, 'message' => '사원 수정 중 오류가 발생했습니다.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * 사원 삭제 (퇴직 처리) */ public function destroy(Request $request, int $id): JsonResponse|Response { try { $result = $this->employeeService->deleteEmployee($id); if (! $result) { if ($request->header('HX-Request')) { return response()->json([ 'success' => false, 'message' => '사원 정보를 찾을 수 없습니다.', ], 404); } return response()->json([ 'success' => false, 'message' => '사원 정보를 찾을 수 없습니다.', ], 404); } if ($request->header('HX-Request')) { $employees = $this->employeeService->getEmployees($request->all(), $request->integer('per_page', 20)); return response(view('hr.employees.partials.table', compact('employees'))); } return response()->json([ 'success' => true, 'message' => '퇴직 처리되었습니다.', ]); } catch (\Throwable $e) { report($e); return response()->json([ 'success' => false, 'message' => '퇴직 처리 중 오류가 발생했습니다.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * 직급/직책 추가 */ public function storePosition(Request $request): JsonResponse { $validated = $request->validate([ 'type' => 'required|string|in:rank,title', 'name' => 'required|string|max:50', ]); $position = $this->employeeService->createPosition($validated['type'], $validated['name']); return response()->json([ 'success' => true, 'message' => ($validated['type'] === 'rank' ? '직급' : '직책').'이 추가되었습니다.', 'data' => [ 'id' => $position->id, 'key' => $position->key, 'name' => $position->name, ], ], 201); } }