validated(); $data = $this->overviewService->overview( isset($payload['class_id']) ? (int) $payload['class_id'] : null, $payload['semester'] ?? null, $payload['school_year'] ?? null ); return response()->json(['ok' => true] + $data); } public function show(GradingScoreShowRequest $request, string $type, int $classSectionId, int $studentId): JsonResponse { $payload = $request->validated(); $data = $this->scoreService->show( $type, $classSectionId, $studentId, (string) $payload['semester'], (string) $payload['school_year'] ); return response()->json([ 'ok' => true, 'student' => $data['student'], 'scores' => GradingScoreResource::collection($data['scores']), 'type' => $data['type'], 'class_section_id' => $data['class_section_id'], 'class_section_name' => $data['class_section_name'], 'semester' => $data['semester'], 'scores_locked' => $data['scores_locked'], ]); } public function update(GradingScoreUpdateRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->scoreService->update($payload, $userId); return response()->json(['ok' => true]); } public function toggleLock(GradingLockRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $locked = $this->lockService->toggle( (int) $payload['class_section_id'], (string) $payload['semester'], (string) $payload['school_year'], $userId ); return response()->json(['ok' => true, 'locked' => $locked]); } public function lockAll(GradingLockAllRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $count = $this->lockService->lockAll( (string) $payload['semester'], (string) $payload['school_year'], $userId ); return response()->json(['ok' => true, 'locked_count' => $count]); } public function refresh(GradingRefreshRequest $request): JsonResponse { $payload = $request->validated(); $this->refreshService->refreshSemesterScores( (int) $payload['class_section_id'], (string) $payload['semester'], (string) $payload['school_year'] ); return response()->json(['ok' => true]); } public function placement(PlacementRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->placementService->placementContext( isset($payload['class_section_id']) ? (int) $payload['class_section_id'] : null, (string) $payload['school_year'], $payload['placement_test'] ?? null, $payload['open'] ?? null ); return response()->json(['ok' => true] + $data); } public function updatePlacementLevel(PlacementLevelRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->placementService->updatePlacementLevel( (int) $payload['student_id'], (string) $payload['school_year'], $payload['placement_level'] ?? null, $userId ); return response()->json(['ok' => true]); } public function updatePlacementLevels(PlacementLevelsRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->placementService->updatePlacementLevels( (int) $payload['class_section_id'], (string) $payload['school_year'], $payload['placement_level'] ?? [], $userId ); return response()->json(['ok' => true]); } public function createPlacementBatch(PlacementBatchRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $batchId = $this->placementService->createPlacementBatch( (string) $payload['school_year'], (string) $payload['placement_test'], $payload['placement_level'] ?? [], $userId ); return response()->json(['ok' => true, 'batch_id' => $batchId]); } public function showPlacementBatch(int $batchId): JsonResponse { $data = $this->placementService->getPlacementBatch($batchId); return response()->json(['ok' => true] + $data); } public function updatePlacementBatch(PlacementBatchUpdateRequest $request, int $batchId): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->placementService->updatePlacementBatch( $batchId, (string) $payload['school_year'], $payload['placement_level'] ?? [], $userId ); return response()->json(['ok' => true]); } public function belowSixty(BelowSixtyListRequest $request): JsonResponse { $payload = $request->validated(); $rows = $this->belowSixtyService->listRows( (string) $payload['school_year'], (string) $payload['semester'] ); return response()->json([ 'ok' => true, 'rows' => BelowSixtyStudentResource::collection($rows), 'semester' => $payload['semester'], 'school_year' => $payload['school_year'], ]); } public function belowSixtyEmail(BelowSixtyEmailRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->emailContext( (int) $payload['student_id'], (string) $payload['school_year'], (string) $payload['semester'] ); return response()->json(['ok' => true] + $data); } public function sendBelowSixtyEmail(BelowSixtySendRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->emailContext( (int) $payload['student_id'], (string) $payload['school_year'], (string) $payload['semester'] ); $subject = trim((string) ($payload['subject'] ?? '')); if ($subject !== '') { $data['subject'] = $subject; } if (isset($payload['html']) && trim((string) $payload['html']) !== '') { $data['html'] = (string) $payload['html']; } $this->belowSixtyService->sendEmail($data); return response()->json(['ok' => true]); } public function updateBelowSixtyStatus(BelowSixtyStatusRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->belowSixtyService->updateStatus( (int) $payload['student_id'], (string) $payload['semester'], (string) $payload['school_year'], (string) $payload['status'], (string) ($payload['note'] ?? ''), $userId ); return response()->json(['ok' => true]); } public function belowSixtyMeeting(BelowSixtyMeetingRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->meetingContext( (int) $payload['student_id'], (string) $payload['school_year'], (string) $payload['semester'] ); return response()->json(['ok' => true] + $data); } public function allDecisions(AllDecisionsRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->listAllDecisions((string) $payload['school_year']); return response()->json(['ok' => true] + $data); } public function generateAllDecisions(GenerateAllDecisionsRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $count = $this->belowSixtyService->generateAllDecisions((string) $payload['school_year'], $userId); return response()->json(['ok' => true, 'saved_count' => $count]); } public function belowSixtyDecisions(BelowSixtyDecisionListRequest $request): JsonResponse { $payload = $request->validated(); $rows = $this->belowSixtyService->listDecisionRows((string) $payload['school_year']); return response()->json([ 'ok' => true, 'rows' => $rows, 'school_year' => $payload['school_year'], 'semester' => 'year', ]); } public function saveBelowSixtyDecision(BelowSixtyDecisionSaveRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $result = $this->belowSixtyService->saveDecision( (int) $payload['student_id'], (string) $payload['school_year'], (string) ($payload['decision'] ?? ''), (string) ($payload['notes'] ?? ''), $userId ); return response()->json(['ok' => true, 'decision' => $result]); } public function belowSixtyDecisionDetails(BelowSixtyDecisionDetailsRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->studentDecisionDetails( (int) $payload['student_id'], (string) $payload['school_year'] ); return response()->json(['ok' => true] + $data); } public function belowSixtyDecisionEmail(BelowSixtyDecisionDetailsRequest $request): JsonResponse { $payload = $request->validated(); $data = $this->belowSixtyService->decisionEmailContext( (int) $payload['student_id'], (string) $payload['school_year'] ); return response()->json(['ok' => true] + $data); } public function sendBelowSixtyDecisionEmail(BelowSixtyDecisionSendRequest $request): JsonResponse { $payload = $request->validated(); $this->belowSixtyService->sendDecisionEmail( (int) $payload['student_id'], (string) $payload['school_year'], isset($payload['subject']) ? (string) $payload['subject'] : null, isset($payload['html']) ? (string) $payload['html'] : null ); return response()->json(['ok' => true]); } public function saveBelowSixtyMeeting(BelowSixtyMeetingSaveRequest $request): JsonResponse { $userId = $this->authenticatedUserIdOrUnauthorized(); if ($userId instanceof JsonResponse) { return $userId; } $payload = $request->validated(); $this->belowSixtyService->saveMeeting($payload, $userId); return response()->json(['ok' => true]); } private function authenticatedUserIdOrUnauthorized(): int|JsonResponse { $userId = (int) (auth()->id() ?? 0); if ($userId <= 0) { return response()->json(['ok' => false, 'message' => 'Unauthorized.'], 401); } return $userId; } }