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
+2 -28
View File
@@ -33,8 +33,6 @@ const LessonReadingProgress = require('../../models/courses/lesson_reading_progr
const UnitReadingProgress = require('../../models/courses/unit_reading_progress.mdl');
const Lesson = require('../../models/courses/lessons.mdl');
const Unit = require('../../models/courses/units.mdl');
const QuizAttempt = require('../../models/courses/quiz_attempt.mdl');
const UnitQuiz = require('../../models/courses/unit_quiz.mdl');
// ─── URL normalizer — ensures protocol prefix so link_url is never a relative path ──
const normalizeUrl = (url) => {
@@ -679,14 +677,14 @@ const PREREQUISITE_INCLUDE = {
class TaskValidationError extends Error {}
// ─── Pre-completed assignees check ────────────────────────────────────────────
// A read_course/read_unit/read_lesson/pass_quiz requirement can reference content
// A read_course/read_unit/read_lesson requirement can reference content
// that a task list's assignees already finished BEFORE this requirement existed.
// That's not an error — task_reading_progress_sync.service.js's hydrateReadTaskProgress
// (client-side, on task list load) already auto-marks it done for them — but the
// admin creating/editing the task has no visibility into it otherwise. This is a
// heads-up, not a validator: it never blocks create/update, only informs.
const READ_TYPE_TO_PROGRESS_TYPE = { read_course: 'course', read_unit: 'unit', read_lesson: 'lesson' };
const progressKeyType = (reqType) => (reqType === 'pass_quiz' ? 'pass_quiz' : READ_TYPE_TO_PROGRESS_TYPE[reqType]);
const progressKeyType = (reqType) => READ_TYPE_TO_PROGRESS_TYPE[reqType];
async function getPreCompletedAssignees(taskListId, requirements, transaction) {
const contentReqs = (requirements ?? []).filter(
@@ -772,30 +770,6 @@ async function getPreCompletedAssignees(taskListId, requirements, transaction) {
}
}
// ── pass_quiz ────────────────────────────────────────────────────────────
const quizReqs = contentReqs.filter((r) => r.type === 'pass_quiz');
if (quizReqs.length) {
const quizUuids = [...new Set(quizReqs.map((r) => r.reference_id))];
const quizzes = await UnitQuiz.findAll({
where: { uuid: { [Op.in]: quizUuids } },
attributes: ['quiz_id', 'uuid'],
transaction,
});
const uuidByQuizId = new Map(quizzes.map((q) => [q.quiz_id, q.uuid]));
const quizIds = quizzes.map((q) => q.quiz_id);
if (quizIds.length) {
const rows = await QuizAttempt.findAll({
where: { quiz_id: { [Op.in]: quizIds }, user_id: { [Op.in]: userIds }, passed: true },
attributes: ['user_id', 'quiz_id'],
transaction,
});
for (const row of rows) {
const uuid = uuidByQuizId.get(row.quiz_id);
if (uuid) markCompleted('pass_quiz', uuid, row.user_id);
}
}
}
// ── One entry per requirement that has at least one already-completed assignee ──
const results = [];
for (const r of contentReqs) {