mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -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 }])
|
||||
|
||||
Reference in New Issue
Block a user