add: ver()

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-08 11:31:40 +08:00
parent 0e4cd86119
commit bb7e8fde08
29 changed files with 2234 additions and 780 deletions
@@ -17,8 +17,9 @@
const { Op } = require('sequelize');
const R = require('../../utils/response.util');
const CourseReadingProgress = require('../../models/courses/course_reading_progress.mdl');
const { Course, Unit, Lesson } = require('../../models/courses/courses.associations');
const { Course, Unit, Lesson, CourseUnit } = require('../../models/courses/courses.associations');
const mdl_Users = require('../../models/users/users.mdl');
const { countCourseLessons, getCourseUnitIds, flattenUnits } = require('../../utils/courses/hierarchy.util');
const notDeleted = { deletedAt: null };
@@ -40,27 +41,13 @@ exports.getCourseReadingProgress = async (req, res) => {
});
if (!course) return R.error(res, 'Course not found.', 404);
// Count total lessons and units in the course (structure totals)
const [units, allLessons] = await Promise.all([
Unit.findAll({
where: { course_id: courseId, ...notDeleted },
attributes: ['unit_id', 'uuid'],
}),
Lesson.findAll({
include: [{
model: Unit,
as: 'unit',
where: { course_id: courseId, ...notDeleted },
attributes: [],
required: true,
}],
where: { ...notDeleted },
attributes: ['lesson_id', 'uuid'],
}),
// Count total lessons and units in the course (structure totals via junctions)
const [unitIds, lessons_total] = await Promise.all([
getCourseUnitIds(courseId),
countCourseLessons(courseId),
]);
const units_total = units.length;
const lessons_total = allLessons.length;
const units_total = unitIds.length;
// All progress rows for this course, grouped per user
const rows = await CourseReadingProgress.findAll({
@@ -147,20 +134,26 @@ exports.getUserReadingProgress = async (req, res) => {
try {
const { courseId, userId } = req.params;
const [units, progressRows] = await Promise.all([
const [unitRows, progressRows] = await Promise.all([
Unit.findAll({
where: { course_id: courseId, ...notDeleted },
attributes: ['unit_id', 'uuid', 'title', 'order_index'],
include: [{
model: Lesson,
as: 'lessons',
where: notDeleted,
required: false,
attributes: ['lesson_id', 'uuid', 'title', 'order_index'],
}],
order: [
['order_index', 'ASC'],
[{ model: Lesson, as: 'lessons' }, 'order_index', 'ASC'],
where: notDeleted,
attributes: ['unit_id', 'uuid', 'title'],
include: [
{
model: CourseUnit,
as: 'courseLinks',
where: { course_id: courseId },
required: true,
attributes: ['order_index'],
},
{
model: Lesson,
as: 'lessons',
where: notDeleted,
required: false,
attributes: ['lesson_id', 'uuid', 'title'],
through: { attributes: ['order_index'] },
},
],
}),
CourseReadingProgress.findAll({
@@ -169,6 +162,14 @@ exports.getUserReadingProgress = async (req, res) => {
}),
]);
// Sort by junction order (course-level, then unit-level for lessons)
const units = flattenUnits(unitRows.map((u) => {
const plain = u.toJSON();
plain.CourseUnit = { order_index: plain.courseLinks?.[0]?.order_index ?? 0 };
delete plain.courseLinks;
return plain;
}));
// Build a quick lookup: { [reference_id (uuid)]: status }
const progressMap = Object.fromEntries(
progressRows.map((r) => [r.reference_id, { status: r.status, completed_at: r.completed_at }])