'integer', 'school_id' => 'integer', 'class_section_id' => 'integer', 'updated_by' => 'integer', // score is numeric; change to 'integer' if it is whole number 'score' => 'decimal:2', 'max_points' => 'decimal:2', 'locked_by' => 'integer', 'locked_at' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; /* Optional relationships */ public function student() { return $this->belongsTo(Student::class, 'student_id'); } public function classSection() { return $this->belongsTo(ClassSection::class, 'class_section_id'); } /** * Equivalent of legacy getParticipationScore() * Returns null if missing/blank/non-numeric. */ public static function getParticipationScore( int $studentId, string $semester, string $schoolYear, ?int $classSectionId = null ): ?float { $q = static::query() ->select('score') ->where('student_id', $studentId) ->where('semester', $semester) ->where('school_year', $schoolYear); if ($classSectionId !== null) { $q->where('class_section_id', $classSectionId); } $row = $q->first(); if (!$row) return null; $score = $row->score; if ($score === null) return null; if (is_string($score) && trim($score) === '') return null; if ($score === '') return null; if (!is_numeric($score)) return null; return (float) $score; } }