assets and tier plans revamp

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-08-01 17:44:25 +08:00
parent 39c3c4566b
commit cae958b5d5
41 changed files with 1271 additions and 165 deletions
+11 -9
View File
@@ -5,6 +5,7 @@ const sequelize = require("../../config/db.config");
const R = require("../../utils/response.util");
const { paginate } = require("../../utils/paginate.util");
const { recomputeDurations, recomputeUnitDuration, recomputeCourseDuration, formatDuration } = require("../../utils/duration.util");
const { resolveAvatarUrl } = require("../../utils/resolveAvatar.util");
const { syncObjectivesCreate, syncObjectivesUpdate } = require("../../utils/courses/objectives.util");
const { resolvePrerequisiteTitles } = require("../../utils/courses/resolvePrerequisiteTitles.util");
const { syncJunction } = require("../../utils/courses/junction.util");
@@ -2653,22 +2654,23 @@ exports.syncInstructors = async (req, res) => {
// ─── COMPLETIONS HELPERS ──────────────────────────────────────────────────────
function extractUserInfo(user) {
async function extractUserInfo(user) {
if (!user) return { full_name: null, email: null, avatar_url: null, deleted: false };
const avatar = await resolveAvatarUrl(user.personal_info?.avatar);
return {
full_name: user.personal_info?.name?.full_name ?? null,
email: user.email ?? null,
avatar_url: user.personal_info?.avatar?.url ?? null,
avatar_url: avatar?.url ?? null,
deleted: !!user.deletedAt,
};
}
function groupByUser(attempts) {
async function groupByUser(attempts) {
const map = new Map();
for (const a of attempts) {
const uid = String(a.user_id);
if (!map.has(uid)) {
const { full_name, email, avatar_url, deleted } = extractUserInfo(a.user);
const { full_name, email, avatar_url, deleted } = await extractUserInfo(a.user);
map.set(uid, {
user_id: a.user_id,
full_name,
@@ -2749,7 +2751,7 @@ exports.getQuizCompletions = async (req, res) => {
const plain = attempts.map((a) => a.toJSON());
return R.success(res, "Quiz completions retrieved.", {
summary: buildSummary(plain),
completions: groupByUser(plain),
completions: await groupByUser(plain),
});
} catch (err) {
console.error("[ADMIN][QUIZ][COMPLETIONS]", err);
@@ -2773,7 +2775,7 @@ exports.getAssessmentCompletions = async (req, res) => {
const plain = attempts.map((a) => a.toJSON());
return R.success(res, "Assessment completions retrieved.", {
summary: buildSummary(plain),
completions: groupByUser(plain),
completions: await groupByUser(plain),
});
} catch (err) {
console.error("[ADMIN][ASSESSMENT][COMPLETIONS]", err);
@@ -2794,9 +2796,9 @@ exports.getAssessmentSessions = async (req, res) => {
order: [["createdAt", "DESC"]],
});
const rows = sessions.map((s) => {
const rows = await Promise.all(sessions.map(async (s) => {
const j = s.toJSON();
const { full_name, email, avatar_url, deleted } = extractUserInfo(j.user);
const { full_name, email, avatar_url, deleted } = await extractUserInfo(j.user);
const time_spent_seconds = j.status !== 'in_progress' && j.started_at
? Math.round((new Date(j.updatedAt) - new Date(j.started_at)) / 1000)
: null;
@@ -2813,7 +2815,7 @@ exports.getAssessmentSessions = async (req, res) => {
time_spent_seconds,
attempt_id: j.attempt_id,
};
});
}));
const summary = {
total_sessions: rows.length,