add projet
This commit is contained in:
Executable
+656
@@ -0,0 +1,656 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use App\Models\Quiz;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use App\Models\User;
|
||||
use App\Services\SemesterScoreService;
|
||||
use RuntimeException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class QuizController extends BaseApiController
|
||||
{
|
||||
protected Quiz $quiz;
|
||||
protected Configuration $config;
|
||||
protected Student $student;
|
||||
protected StudentClass $studentClass;
|
||||
protected TeacherClass $teacherClass;
|
||||
protected User $user;
|
||||
protected SemesterScoreService $semesterScoreService;
|
||||
protected string $schoolYear;
|
||||
protected string $semester;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->quiz = model(Quiz::class);
|
||||
$this->config = model(Configuration::class);
|
||||
$this->student = model(Student::class);
|
||||
$this->studentClass = model(StudentClass::class);
|
||||
$this->teacherClass = model(TeacherClass::class);
|
||||
$this->user = model(User::class);
|
||||
$this->semesterScoreService = app(SemesterScoreService::class);
|
||||
|
||||
$this->schoolYear = (string) ($this->config->getConfig('school_year') ?? '');
|
||||
$this->semester = (string) ($this->config->getConfig('semester') ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/quizzes
|
||||
* List quizzes with optional filters
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
||||
$perPage = min(100, max(1, (int) ($this->request->getGet('per_page') ?? 20)));
|
||||
$studentId = $this->request->getGet('student_id');
|
||||
$classSectionId = $this->request->getGet('class_section_id');
|
||||
|
||||
$query = $this->quiz->newQuery()
|
||||
->where('school_year', $this->schoolYear)
|
||||
->where('semester', $this->semester);
|
||||
|
||||
if ($studentId) {
|
||||
$query->where('student_id', $studentId);
|
||||
}
|
||||
|
||||
if ($classSectionId) {
|
||||
$query->where('class_section_id', $classSectionId);
|
||||
}
|
||||
|
||||
$result = $this->paginate($query, $page, $perPage);
|
||||
|
||||
return $this->success($result, 'Quizzes retrieved successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/quizzes/{id}
|
||||
* Get a single quiz
|
||||
*/
|
||||
public function show($id = null)
|
||||
{
|
||||
$quiz = $this->quiz->find($id);
|
||||
if (!$quiz) {
|
||||
return $this->error('Quiz not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
return $this->success($quiz, 'Quiz retrieved successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/quizzes/student/{id}
|
||||
* Get quizzes for a specific student
|
||||
*/
|
||||
public function getByStudent($id = null)
|
||||
{
|
||||
$quizzes = $this->quiz->newQuery()
|
||||
->where('student_id', $id)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->where('semester', $this->semester)
|
||||
->orderBy('quiz_index', 'ASC')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
return $this->success($quizzes, 'Quizzes retrieved successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/v1/quizzes
|
||||
* Create a new quiz entry
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$data = $this->payloadData();
|
||||
if (empty($data)) {
|
||||
return $this->error('Invalid request data', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'student_id' => 'required|integer',
|
||||
'class_section_id' => 'required|integer',
|
||||
'quiz_index' => 'required|integer',
|
||||
];
|
||||
|
||||
$errors = $this->validateRequest($data, $rules);
|
||||
if (!empty($errors)) {
|
||||
return $this->respondValidationError($errors);
|
||||
}
|
||||
|
||||
$quizData = [
|
||||
'student_id' => $data['student_id'],
|
||||
'class_section_id' => $data['class_section_id'],
|
||||
'quiz_index' => $data['quiz_index'],
|
||||
'score' => $data['score'] ?? null,
|
||||
'comment' => $data['comment'] ?? null,
|
||||
'school_year' => $this->schoolYear,
|
||||
'semester' => $this->semester,
|
||||
'updated_by' => $user->id,
|
||||
];
|
||||
|
||||
try {
|
||||
$quiz = $this->quiz->create($quizData);
|
||||
return $this->success($quiz->toArray(), 'Quiz created successfully', Response::HTTP_CREATED);
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'Quiz creation error: ' . $e->getMessage());
|
||||
return $this->respondError('Failed to create quiz', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PATCH /api/v1/quizzes/{id}
|
||||
* Update a quiz entry
|
||||
*/
|
||||
public function update($id = null)
|
||||
{
|
||||
$quiz = $this->quiz->find($id);
|
||||
if (!$quiz) {
|
||||
return $this->error('Quiz not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$data = $this->payloadData();
|
||||
if (empty($data)) {
|
||||
return $this->error('Invalid request data', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$allowedFields = ['score', 'comment', 'quiz_index'];
|
||||
$updateData = [];
|
||||
foreach ($allowedFields as $field) {
|
||||
if (array_key_exists($field, $data)) {
|
||||
$updateData[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($updateData)) {
|
||||
return $this->error('No valid fields to update', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$updateData['updated_by'] = $user->id;
|
||||
$updateData['updated_at'] = utc_now();
|
||||
|
||||
try {
|
||||
$this->quiz->update($id, $updateData);
|
||||
$updatedQuiz = $this->quiz->find($id);
|
||||
return $this->success($updatedQuiz, 'Quiz updated successfully');
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'Quiz update error: ' . $e->getMessage());
|
||||
return $this->respondError('Failed to update quiz', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/quizzes/add-quiz
|
||||
* Get quiz data for teacher's class section (equivalent to addQuiz view)
|
||||
*/
|
||||
public function addQuiz()
|
||||
{
|
||||
// Get class_section_id from POST -> GET -> session
|
||||
$incoming = $this->request->getPost('class_section_id')
|
||||
?? $this->request->getGet('class_section_id')
|
||||
?? session()->get('class_section_id');
|
||||
|
||||
$classSectionId = (int) ($incoming ?: 0);
|
||||
|
||||
if ($classSectionId <= 0) {
|
||||
return $this->respondError('Missing class section.', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
session()->put('class_section_id', $classSectionId);
|
||||
|
||||
// Get distinct quiz_index values for this class/term
|
||||
$quizHeaderRows = $this->quiz
|
||||
->select('quiz_index')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->groupBy('quiz_index')
|
||||
->orderBy('quiz_index', 'ASC')
|
||||
->findAll();
|
||||
|
||||
$quizHeaders = array_map(static fn($r) => (int)$r['quiz_index'], $quizHeaderRows);
|
||||
|
||||
// Get roster (distinct students for this section/term)
|
||||
$roster = DB::table('student_class as sc')
|
||||
->select('s.id AS student_id', 's.firstname', 's.lastname', 's.school_id')
|
||||
->distinct()
|
||||
->join('students as s', 's.id', '=', 'sc.student_id')
|
||||
->where('sc.class_section_id', $classSectionId)
|
||||
->where('sc.school_year', $this->schoolYear)
|
||||
->orderBy('s.lastname', 'ASC')
|
||||
->orderBy('s.firstname', 'ASC')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
// Get all existing quiz scores
|
||||
$scoreRows = $this->quiz
|
||||
->select('id, student_id, quiz_index, score')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->findAll();
|
||||
|
||||
$scoresMap = []; // [student_id][quiz_index] => score
|
||||
$idMap = []; // [student_id][quiz_index] => id
|
||||
|
||||
foreach ($scoreRows as $r) {
|
||||
$sid = (int)$r['student_id'];
|
||||
$qi = (int)$r['quiz_index'];
|
||||
$scoresMap[$sid][$qi] = $r['score'];
|
||||
$idMap[$sid][$qi] = (int)$r['id'];
|
||||
}
|
||||
|
||||
// Build students array with per-quiz scores
|
||||
$students = [];
|
||||
foreach ($roster as $st) {
|
||||
$sid = (int)$st->student_id;
|
||||
$quizScores = [];
|
||||
|
||||
foreach ($quizHeaders as $qi) {
|
||||
$quizScores[$qi] = $scoresMap[$sid][$qi] ?? '';
|
||||
}
|
||||
|
||||
$students[] = [
|
||||
'student_id' => $sid,
|
||||
'firstname' => $st->firstname,
|
||||
'lastname' => $st->lastname,
|
||||
'school_id' => $st->school_id ?? null,
|
||||
'scores' => $quizScores,
|
||||
'existingIds' => $idMap[$sid] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'students' => $students,
|
||||
'quiz_headers' => $quizHeaders,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
'class_section_id' => $classSectionId
|
||||
], 'Quiz data retrieved successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/v1/quizzes/update-scores
|
||||
* Update quiz scores for multiple students
|
||||
*/
|
||||
public function updateQuizScores()
|
||||
{
|
||||
$updatedBy = $this->getCurrentUserId();
|
||||
if (!$updatedBy) {
|
||||
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$payload = $this->payloadData();
|
||||
$scores = $payload['scores'] ?? null;
|
||||
$classSectionId = (int) ($payload['class_section_id'] ?? session()->get('class_section_id') ?? 0);
|
||||
|
||||
if ($classSectionId <= 0) {
|
||||
return $this->respondError('Class section ID is required', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!is_array($scores)) {
|
||||
return $this->respondError('No quiz scores submitted.', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($scores as $studentId => $quizData) {
|
||||
if (!is_numeric($studentId) || $studentId <= 0) continue;
|
||||
|
||||
// Normalize: if single input submitted
|
||||
if (!is_array($quizData)) {
|
||||
$quizData = [1 => $quizData];
|
||||
}
|
||||
|
||||
foreach ($quizData as $quizNumber => $score) {
|
||||
if (!is_numeric($quizNumber) || !is_numeric($score)) continue;
|
||||
|
||||
$existing = $this->quiz->where([
|
||||
'student_id' => $studentId,
|
||||
'quiz_index' => $quizNumber,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $this->semester
|
||||
])->first();
|
||||
|
||||
if ($existing) {
|
||||
$this->quiz->update($existing['id'], [
|
||||
'score' => is_numeric($score) ? (float)$score : null,
|
||||
'updated_at' => utc_now()
|
||||
]);
|
||||
} else {
|
||||
$student = $this->student->find($studentId);
|
||||
$this->quiz->insert([
|
||||
'student_id' => $studentId,
|
||||
'school_id' => $student['school_id'] ?? '',
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_by' => $updatedBy,
|
||||
'quiz_index' => $quizNumber,
|
||||
'score' => is_numeric($score) ? (float)$score : null,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
'created_at' => utc_now(),
|
||||
'updated_at' => utc_now()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$studentTeacherInfo = $this->student->getStudentInfoByClassSectionId($classSectionId);
|
||||
|
||||
// Call the updateScoresForStudents method
|
||||
try {
|
||||
$this->semesterScoreService->updateScoresForStudents($studentTeacherInfo);
|
||||
} catch (RuntimeException $e) {
|
||||
log_message('error', 'Failed to update semester scores: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->success(null, 'Quiz scores updated successfully.');
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'Update quiz scores error: ' . $e->getMessage());
|
||||
return $this->respondError('Failed to update quiz scores: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/v1/quizzes/add-column
|
||||
* Add a new quiz column for all students in a class section
|
||||
*/
|
||||
public function addNextQuizColumn()
|
||||
{
|
||||
$updatedBy = $this->getCurrentUserId();
|
||||
if (!$updatedBy) {
|
||||
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$payload = $this->payloadData();
|
||||
$classSectionId = (int) ($payload['class_section_id'] ?? session()->get('class_section_id') ?? 0);
|
||||
|
||||
if ($classSectionId <= 0) {
|
||||
return $this->respondError('Class section ID is required', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$existingQuizNumbers = $this->quiz
|
||||
->select('quiz_index')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('updated_by', $updatedBy)
|
||||
->where('semester', $this->semester)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->groupBy('quiz_index')
|
||||
->orderBy('quiz_index', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$maxQuizNumber = 0;
|
||||
foreach ($existingQuizNumbers as $row) {
|
||||
if (is_numeric($row['quiz_index'])) {
|
||||
$maxQuizNumber = max($maxQuizNumber, (int)$row['quiz_index']);
|
||||
}
|
||||
}
|
||||
|
||||
$nextQuizNumber = $maxQuizNumber + 1;
|
||||
|
||||
if ($nextQuizNumber <= 0) {
|
||||
return $this->respondError('Invalid quiz number', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$students = $this->studentClass
|
||||
->where('class_section_id', $classSectionId)
|
||||
->findAll();
|
||||
|
||||
if (empty($students)) {
|
||||
return $this->respondError('No students found in this class section.', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$firstInsertedId = null;
|
||||
$insertedCount = 0;
|
||||
|
||||
foreach ($students as $i => $student) {
|
||||
$exists = $this->quiz->where([
|
||||
'student_id' => $student['student_id'],
|
||||
'quiz_index' => $nextQuizNumber,
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_by' => $updatedBy,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
])->first();
|
||||
|
||||
if ($exists) continue;
|
||||
|
||||
$studentRecord = $this->student->find($student['student_id']);
|
||||
$insertData = [
|
||||
'student_id' => $student['student_id'],
|
||||
'school_id' => $studentRecord['school_id'] ?? '',
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_by' => $updatedBy,
|
||||
'quiz_index' => $nextQuizNumber,
|
||||
'score' => null,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
'created_at' => utc_now(),
|
||||
'updated_at' => utc_now(),
|
||||
];
|
||||
|
||||
$id = $this->quiz->insert($insertData);
|
||||
if ($i === 0) {
|
||||
$firstInsertedId = $id;
|
||||
}
|
||||
$insertedCount++;
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'status' => 'success',
|
||||
'quiz_index' => $nextQuizNumber,
|
||||
'new_quiz_id' => $firstInsertedId,
|
||||
'students_processed' => $insertedCount
|
||||
], 'Quiz column added successfully');
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'Add quiz column error: ' . $e->getMessage());
|
||||
return $this->respondError('Failed to add quiz column: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/v1/quizzes/management
|
||||
* Get quiz management data for a class section
|
||||
*/
|
||||
public function showQuizMngt()
|
||||
{
|
||||
// Accept POST first, then GET (query string), then session fallback
|
||||
$incomingId = $this->request->getPost('class_section_id');
|
||||
if (!$incomingId) {
|
||||
$incomingId = $this->request->getGet('class_section_id');
|
||||
}
|
||||
|
||||
$classSectionId = (int) ($incomingId ?: (session()->get('class_section_id') ?? 0));
|
||||
|
||||
if ($classSectionId <= 0) {
|
||||
return $this->respondError('No class section found for the current teacher or selection.', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
session()->put('class_section_id', $classSectionId);
|
||||
|
||||
$quizScores = $this->getQuizScoresByStudent($classSectionId, $this->semester, $this->schoolYear);
|
||||
$students = $this->getStudentsByClassSectionAndYear($classSectionId, $this->schoolYear);
|
||||
$quizHeaders = $this->getQuizHeaders($classSectionId, $this->semester, $this->schoolYear);
|
||||
|
||||
return $this->success([
|
||||
'quiz_scores' => $quizScores,
|
||||
'students' => $students,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
'quiz_headers' => $quizHeaders,
|
||||
'class_section_id' => $classSectionId,
|
||||
], 'Quiz management data retrieved successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/v1/quizzes/update
|
||||
* Update quiz scores (management endpoint)
|
||||
*/
|
||||
public function updateQuiz()
|
||||
{
|
||||
$payload = $this->payloadData();
|
||||
$scores = $payload['scores'] ?? null;
|
||||
$studentIds = $payload['student_ids'] ?? null;
|
||||
$semester = $payload['semester'] ?? $this->semester;
|
||||
$schoolYear = $payload['school_year'] ?? $this->schoolYear;
|
||||
$updatedBy = $payload['teacher_id'] ?? $this->getCurrentUserId();
|
||||
$classSectionId = (int) ($payload['class_section_id'] ?? session()->get('class_section_id') ?? 0);
|
||||
|
||||
if (!$updatedBy) {
|
||||
return $this->respondError('Authentication required', Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if ($classSectionId <= 0) {
|
||||
return $this->respondError('Class section ID is required', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if ($scores && $studentIds && $semester && $schoolYear) {
|
||||
try {
|
||||
// Update scores using the same logic as updateQuizScores
|
||||
foreach ($scores as $studentId => $quizData) {
|
||||
if (!is_numeric($studentId) || $studentId <= 0) continue;
|
||||
|
||||
// Normalize: if single input submitted
|
||||
if (!is_array($quizData)) {
|
||||
$quizData = [1 => $quizData];
|
||||
}
|
||||
|
||||
foreach ($quizData as $quizNumber => $score) {
|
||||
if (!is_numeric($quizNumber) || !is_numeric($score)) continue;
|
||||
|
||||
$existing = $this->quiz->where([
|
||||
'student_id' => $studentId,
|
||||
'quiz_index' => $quizNumber,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $semester
|
||||
])->first();
|
||||
|
||||
if ($existing) {
|
||||
$this->quiz->update($existing['id'], [
|
||||
'score' => is_numeric($score) ? (float)$score : null,
|
||||
'updated_at' => utc_now()
|
||||
]);
|
||||
} else {
|
||||
$student = $this->student->find($studentId);
|
||||
$this->quiz->insert([
|
||||
'student_id' => $studentId,
|
||||
'school_id' => $student['school_id'] ?? '',
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_by' => $updatedBy,
|
||||
'quiz_index' => $quizNumber,
|
||||
'score' => is_numeric($score) ? (float)$score : null,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'created_at' => utc_now(),
|
||||
'updated_at' => utc_now()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$studentTeacherInfo = $this->student->getStudentInfoByClassSectionId($classSectionId);
|
||||
|
||||
// Call the updateScoresForStudents method
|
||||
try {
|
||||
$this->semesterScoreService->updateScoresForStudents($studentTeacherInfo);
|
||||
} catch (RuntimeException $e) {
|
||||
log_message('error', 'Failed to update semester scores: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->success(null, 'Quiz scores updated successfully.');
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'Update quiz error: ' . $e->getMessage());
|
||||
return $this->respondError('Failed to update scores: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondError('Failed to update scores. Missing required data.', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Get students by class section and year
|
||||
*/
|
||||
private function getStudentsByClassSectionAndYear($classSectionId, $schoolYear)
|
||||
{
|
||||
// Step 1: Get student IDs from student_class table
|
||||
$studentClassRows = $this->studentClass
|
||||
->select('student_id')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
$studentIds = array_column($studentClassRows, 'student_id');
|
||||
|
||||
if (empty($studentIds)) {
|
||||
return []; // No students found
|
||||
}
|
||||
|
||||
// Step 2: Get student data from students table
|
||||
$students = $this->student
|
||||
->whereIn('id', $studentIds)
|
||||
->orderBy('lastname', 'ASC')
|
||||
->findAll();
|
||||
|
||||
return $students;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Get quiz headers for a class section
|
||||
*/
|
||||
private function getQuizHeaders($classSectionId, $semester, $schoolYear)
|
||||
{
|
||||
$rows = $this->quiz
|
||||
->select('quiz_index')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->orderBy('quiz_index', 'ASC')
|
||||
->findAll();
|
||||
|
||||
$headers = [];
|
||||
foreach ($rows as $row) {
|
||||
$index = $row['quiz_index'];
|
||||
if (!is_array($index)) {
|
||||
$headers[$index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($headers);
|
||||
return array_keys($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Get quiz scores by student
|
||||
*/
|
||||
private function getQuizScoresByStudent($classSectionId, $semester, $schoolYear)
|
||||
{
|
||||
$rows = $this->quiz
|
||||
->select('student_id, quiz_index, score')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
$studentScores = [];
|
||||
foreach ($rows as $row) {
|
||||
$studentId = $row['student_id'];
|
||||
$index = $row['quiz_index'];
|
||||
$score = $row['score'];
|
||||
|
||||
$studentScores[$studentId]['scores'][$index] = $score;
|
||||
}
|
||||
|
||||
return $studentScores;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user