From 7d594489912b4c67e704687404d3d841f1c73de5 Mon Sep 17 00:00:00 2001 From: Kavehhn174 Date: Sun, 16 Aug 2026 09:22:41 +0330 Subject: [PATCH] Improve attendance completion checks and expose recorded counts. Only count existing enrolled students when deciding if a session is fully recorded, and return per-session attendance totals for the dashboard list. --- components/sessions/sessionService.js | 55 +++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/components/sessions/sessionService.js b/components/sessions/sessionService.js index 881f64d..1b6b75d 100644 --- a/components/sessions/sessionService.js +++ b/components/sessions/sessionService.js @@ -3,6 +3,7 @@ const Session = require('./sessionModel'); const Course = require('../courses/courseModel'); const Class = require('../classes/classModel'); +const User = require('../users/userModel'); const Professor = require('../professors/professorModel'); const AppError = require('../../utils/AppError'); const eventEmitter = require('../../events/eventEmitter'); @@ -124,7 +125,31 @@ const buildStudentsByClassId = async (sessions) => { if (!classIds.length) return new Map(); const classes = await Class.find({ _id: { $in: classIds } }).select('students').lean(); - return new Map(classes.map((cls) => [String(cls._id), cls.students || []])); + const allStudentIds = [...new Set( + classes.flatMap((cls) => (cls.students || []).map(normalizeId)).filter(Boolean) + )]; + + let existingSet = new Set(); + if (allStudentIds.length) { + const existingUsers = await User.find({ _id: { $in: allStudentIds } }).select('_id').lean(); + existingSet = new Set(existingUsers.map((user) => normalizeId(user._id))); + } + + return new Map(classes.map((cls) => { + const validStudentIds = (cls.students || []) + .map(normalizeId) + .filter((id) => existingSet.has(id)); + return [String(cls._id), validStudentIds]; + })); +}; + +const getValidStudentIdsForClass = async (classItem) => { + if (!classItem) return []; + const rawIds = (classItem.students || []).map(normalizeId).filter(Boolean); + if (!rawIds.length) return []; + const existingUsers = await User.find({ _id: { $in: rawIds } }).select('_id').lean(); + const existingSet = new Set(existingUsers.map((user) => normalizeId(user._id))); + return rawIds.filter((id) => existingSet.has(id)); }; const isSessionDue = (session) => { @@ -156,12 +181,21 @@ const hasCompleteAttendance = (session, studentsByClassId = null) => { const isAttendancePending = (session, studentsByClassId = null) => isSessionDue(session) && !hasCompleteAttendance(session, studentsByClassId); -const enrichSessionAttendance = (session, studentsByClassId = null) => ({ - ...session, - isDue: isSessionDue(session), - attendanceComplete: hasCompleteAttendance(session, studentsByClassId), - attendancePending: isAttendancePending(session, studentsByClassId) -}); +const enrichSessionAttendance = (session, studentsByClassId = null) => { + const studentIds = getClassStudentIds(session, studentsByClassId); + const recordedIds = getRecordedUserIds(session); + const studentSet = new Set(studentIds); + const attendanceRecordedCount = recordedIds.filter((id) => studentSet.has(id)).length; + + return { + ...session, + isDue: isSessionDue(session), + attendanceTotalCount: studentIds.length, + attendanceRecordedCount, + attendanceComplete: hasCompleteAttendance(session, studentsByClassId), + attendancePending: isAttendancePending(session, studentsByClassId) + }; +}; const filterByAttendanceScope = (sessions, scope, studentsByClassId = null) => { const dueSessions = sessions.filter(isSessionDue); @@ -351,7 +385,12 @@ const updateSessionAttendance = async (sessionId, attendanceList, recordedBy = n await session.save(); const classItem = await Class.findById(session.class).select('students').lean(); - if (classItem && hasCompleteAttendance({ ...session.toObject(), class: classItem }) && session.status !== 'cancelled') { + const validStudentIds = await getValidStudentIdsForClass(classItem); + if ( + classItem + && hasCompleteAttendance({ ...session.toObject(), class: { ...classItem, students: validStudentIds } }) + && session.status !== 'cancelled' + ) { session.status = 'held'; await session.save(); }