Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions public/main/gradebook/lib/be/attendancelink.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,32 @@ public function calc_score(?int $studentId = null, ?string $type = null): array

// Load attendance settings (qualify max + require unique mode)
$sql = 'SELECT attendance_qualify_max, require_unique
FROM '.$this->get_attendance_table().'
WHERE iid = '.$attendanceId;
FROM '.$this->get_attendance_table().'
WHERE iid = '.(int) $attendanceId;
$query = Database::query($sql);
$attendance = Database::fetch_assoc($query);

$qualifyMax = (float) ($attendance['attendance_qualify_max'] ?? 0);
$requireUnique = !empty($attendance['require_unique']);

// Avoid gradebook showing 0/0 in require-unique mode when qualify max was never set.
if ($requireUnique && $qualifyMax <= 0) {
if ($requireUnique && $qualifyMax <= 0.0) {
// Using 100 matches the UI expectation ("100% when present at least once").
$qualifyMax = 100.0;
}

if (!$requireUnique && $qualifyMax <= 0.0) {
$sqlTotal = 'SELECT COUNT(*) AS total
FROM '.$tbl_calendar.'
WHERE attendance_id = '.(int) $attendanceId;
$rowTotal = Database::fetch_assoc(Database::query($sqlTotal));
$totalDates = (int) ($rowTotal['total'] ?? 0);

if ($totalDates > 0) {
$qualifyMax = (float) $totalDates;
}
}

// ------------------------------------------------------------
// Require-unique mode: 100% score if present at least once
// This is calculated from attendance sheets to avoid relying on
Expand All @@ -130,8 +142,8 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
$sqlHasPresence = 'SELECT 1
FROM '.$tbl_sheet.' s
INNER JOIN '.$tbl_calendar.' c ON c.iid = s.attendance_calendar_id
WHERE c.attendance_id = '.$attendanceId.'
AND s.user_id = '.$studentId.'
WHERE c.attendance_id = '.(int) $attendanceId.'
AND s.user_id = '.(int) $studentId.'
AND s.presence IN (1, 2, 3)
LIMIT 1';

Expand All @@ -156,7 +168,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
MAX(CASE WHEN s.presence IN (1, 2, 3) THEN 1 ELSE 0 END) AS has_presence
FROM '.$tbl_sheet.' s
INNER JOIN '.$tbl_calendar.' c ON c.iid = s.attendance_calendar_id
WHERE c.attendance_id = '.$attendanceId.'
WHERE c.attendance_id = '.(int) $attendanceId.'
GROUP BY s.user_id';

$rs = Database::query($sqlAll);
Expand All @@ -173,7 +185,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array

// Compute stats (keep legacy behavior when qualifyMax is 0)
foreach ($students as $uid => $finalScore) {
if (0 != $qualifyMax) {
if (0.0 != $qualifyMax) {
$resultCount++;
$sumRatio += $finalScore / $qualifyMax;
$sumScore += $finalScore;
Expand Down Expand Up @@ -205,8 +217,8 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
}

$sql = 'SELECT user_id, score
FROM '.$tbl_attendance_result.'
WHERE attendance_id = '.$attendanceId;
FROM '.$tbl_attendance_result.'
WHERE attendance_id = '.(int) $attendanceId;

if (null !== $studentId) {
$sql .= ' AND user_id = '.(int) $studentId;
Expand All @@ -219,7 +231,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
if ($row = Database::fetch_assoc($scores)) {
$score = (float) ($row['score'] ?? 0);
if ('default' === $type) {
return [$qualifyMax > 0 ? ($score / $qualifyMax) : 0.0, 1];
return [$qualifyMax > 0.0 ? ($score / $qualifyMax) : 0.0, 1];
}

return [$score, $qualifyMax];
Expand Down Expand Up @@ -256,7 +268,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array

// Compute stats
foreach ($students as $uid => $finalScore) {
if (0 != $qualifyMax) {
if (0.0 != $qualifyMax) {
$resultCount++;
$sumRatio += $finalScore / $qualifyMax;
$sumScore += $finalScore;
Expand Down
Loading