attendanceService->getAttendances( $request->all(), $request->integer('per_page', 20) ); if ($request->header('HX-Request')) { return response(view('hr.attendances.partials.table', compact('attendances'))); } return response()->json([ 'success' => true, 'data' => $attendances->items(), 'meta' => [ 'current_page' => $attendances->currentPage(), 'last_page' => $attendances->lastPage(), 'per_page' => $attendances->perPage(), 'total' => $attendances->total(), ], ]); } /** * 월간 통계 */ public function stats(Request $request): JsonResponse { $stats = $this->attendanceService->getMonthlyStats( $request->integer('year') ?: null, $request->integer('month') ?: null ); return response()->json([ 'success' => true, 'data' => $stats, ]); } /** * 근태 등록 */ public function store(Request $request): JsonResponse { $validated = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'base_date' => 'required|date', 'status' => 'required|string|in:onTime,late,absent,vacation,businessTrip,fieldWork,overtime,remote', 'check_in' => 'nullable|date_format:H:i', 'check_out' => 'nullable|date_format:H:i', 'remarks' => 'nullable|string|max:500', ]); try { $attendance = $this->attendanceService->storeAttendance($validated); return response()->json([ 'success' => true, 'message' => '근태가 등록되었습니다.', 'data' => $attendance, ], 201); } catch (\Throwable $e) { report($e); return response()->json([ 'success' => false, 'message' => '근태 등록 중 오류가 발생했습니다.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * 근태 수정 */ public function update(Request $request, int $id): JsonResponse { $validated = $request->validate([ 'status' => 'sometimes|required|string|in:onTime,late,absent,vacation,businessTrip,fieldWork,overtime,remote', 'check_in' => 'nullable|date_format:H:i', 'check_out' => 'nullable|date_format:H:i', 'remarks' => 'nullable|string|max:500', ]); try { $attendance = $this->attendanceService->updateAttendance($id, $validated); if (! $attendance) { return response()->json([ 'success' => false, 'message' => '근태 정보를 찾을 수 없습니다.', ], 404); } return response()->json([ 'success' => true, 'message' => '근태가 수정되었습니다.', 'data' => $attendance, ]); } 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->attendanceService->deleteAttendance($id); if (! $result) { return response()->json([ 'success' => false, 'message' => '근태 정보를 찾을 수 없습니다.', ], 404); } if ($request->header('HX-Request')) { $attendances = $this->attendanceService->getAttendances( $request->all(), $request->integer('per_page', 20) ); return response(view('hr.attendances.partials.table', compact('attendances'))); } 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); } } }