good morning

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-08-06 08:11:05 +08:00
parent 141b7ab592
commit dcae93eb35
15 changed files with 81 additions and 204 deletions
+6 -24
View File
@@ -17,7 +17,6 @@ const { TaskCompletion, TaskCompletionFile } = require('../../models/task/task_c
const { TaskLinkVisit, TaskProgress } = require('../../models/task/task_progress.mdl');
const { mdl_UserGroups, mdl_UserGroupMembers } = require('../../models/users/user_groups.mdl');
const mdl_Users = require('../../models/users/users.mdl');
const { QuizAttempt } = require('../../models/courses/courses.associations');
const { userExclude } = require('../../models/task/task.attributes');
const { clientExclude } = require('../../models/task/task_completion.attributes');
@@ -135,15 +134,9 @@ const isMember = async (userId, groupId) => {
// ─── Helper: per-user completion signals for a batch of tasks ─────────────────
// Shared by getGroupTaskList/getGroupTaskLists. upload_file/submit_text share
// one TaskCompletion per task (resubmit-anytime — latest by submitted_at wins);
// pass_quiz is computed live from QuizAttempt, same as unit-quiz has_passed
// (courses.controller.js) rather than a separately-synced TaskProgress row.
const getTaskCompletionSignals = async (userId, taskIds, requirements) => {
const quizIds = [...new Set(
requirements.filter((r) => r.type === 'pass_quiz' && r.reference_id).map((r) => r.reference_id)
)];
const [completions, linkVisits, progressRows, passedAttempts] = await Promise.all([
// one TaskCompletion per task (resubmit-anytime — latest by submitted_at wins).
const getTaskCompletionSignals = async (userId, taskIds) => {
const [completions, linkVisits, progressRows] = await Promise.all([
taskIds.length
? TaskCompletion.findAll({
where: { task_id: { [Op.in]: taskIds }, user_id: userId },
@@ -163,12 +156,6 @@ const getTaskCompletionSignals = async (userId, taskIds, requirements) => {
attributes: ['task_id', 'requirement_id', 'reference_id'],
})
: [],
quizIds.length
? QuizAttempt.findAll({
where: { quiz_id: { [Op.in]: quizIds }, user_id: userId, passed: true },
attributes: ['quiz_id'],
})
: [],
]);
// First row per task_id wins — completions are ordered submitted_at DESC.
@@ -181,7 +168,6 @@ const getTaskCompletionSignals = async (userId, taskIds, requirements) => {
latestCompletionByTask,
visitedRequirementIds: new Set(linkVisits.map((v) => v.requirement_id)),
completedProgressKeys: new Set(progressRows.map((p) => `${p.requirement_id}:${p.reference_id}`)),
passedQuizIds: new Set(passedAttempts.map((a) => String(a.quiz_id))),
};
};
@@ -200,8 +186,6 @@ const isRequirementDone = (r, signals) => {
case 'read_unit':
case 'read_lesson':
return signals.completedProgressKeys.has(`${r.requirement_id}:${r.reference_id}`);
case 'pass_quiz':
return signals.passedQuizIds.has(String(r.reference_id));
default:
return true; // unknown requirement types don't block completion
}
@@ -241,7 +225,7 @@ const checkTaskCompletion = async (userId, taskId) => {
const reqs = await TaskRequirement.findAll({ where: { task_id: taskId } });
if (!reqs.length) return false;
const plainReqs = reqs.map((r) => r.toJSON());
const signals = await getTaskCompletionSignals(userId, [taskId], plainReqs);
const signals = await getTaskCompletionSignals(userId, [taskId]);
return plainReqs.every((r) => isRequirementDone(r, signals));
};
@@ -359,8 +343,7 @@ exports.getGroupTaskList = async (req, res) => {
await hydrateReadTaskProgress(userId, readRequirements);
// ── Fetch user's completion signals for these tasks ────────────────────
const allRequirements = tasks.flatMap((task) => task.requirements ?? []);
const signals = await getTaskCompletionSignals(userId, taskIds, allRequirements);
const signals = await getTaskCompletionSignals(userId, taskIds);
const now = Date.now();
@@ -490,8 +473,7 @@ exports.getGroupTaskLists = async (req, res) => {
await hydrateReadTaskProgress(userId, readRequirements);
// ── Fetch user's completion signals for these tasks ────────────────────
const allRequirements = allTasks.flatMap((task) => task.requirements ?? []);
const signals = await getTaskCompletionSignals(userId, taskIds, allRequirements);
const signals = await getTaskCompletionSignals(userId, taskIds);
const now = Date.now();