mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
perform test
test to courses Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -11,13 +11,10 @@
|
||||
***********************************************************************************************************************************************************************/
|
||||
'use strict';
|
||||
|
||||
const R = require('../../utils/response.util');
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const mdl_Achievements = require('../../models/users/achievements.mdl');
|
||||
const { generateCertificate } = require('../../services/certificate.service');
|
||||
const { formatDuration } = require('../../utils/duration.util');
|
||||
const UserNotification = require('../../models/notifications/user_notification.mdl');
|
||||
const { NOTIFICATION_REGISTRY } = require('../../data/notifications.data');
|
||||
const R = require('../../utils/response.util');
|
||||
const mdl_Users = require('../../models/users/users.mdl');
|
||||
const { generateCertificate } = require('../../services/certificate.service');
|
||||
const { formatDuration } = require('../../utils/duration.util');
|
||||
|
||||
const {
|
||||
Course,
|
||||
@@ -113,17 +110,20 @@ exports.getCertificate = async (req, res) => {
|
||||
const fullName = user?.personal_info?.name?.full_name?.trim() || 'Participant';
|
||||
|
||||
// ── 4. Resolve or create the certificate record ────────────────────────────
|
||||
const [cert, created] = await Certificate.findOrCreate({
|
||||
where: { user_id, course_id: course.course_id },
|
||||
defaults: {
|
||||
// CockroachDB does not support findOrCreate (uses temp PL/pgSQL functions).
|
||||
let cert = await Certificate.findOne({ where: { user_id, course_id: course.course_id } });
|
||||
if (!cert) {
|
||||
cert = await Certificate.create({
|
||||
user_id,
|
||||
course_id: course.course_id,
|
||||
cert_no: await buildCertNo(user_id),
|
||||
ref_no: await buildRefNo(),
|
||||
instructors: formatInstructors(course.instructors ?? []),
|
||||
score: passedAttempt.score ?? null,
|
||||
length_str: formatDuration(course.duration_seconds),
|
||||
issued_at: passedAttempt.createdAt,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Always use live instructors from course_instructors table for the PDF.
|
||||
// Keep the snapshot in sync so it reflects the current state.
|
||||
@@ -132,57 +132,15 @@ exports.getCertificate = async (req, res) => {
|
||||
await cert.update({ instructors: liveInstructors });
|
||||
}
|
||||
|
||||
// ── 5. On first issue: fire notification + achievements ────────────────────
|
||||
if (created) {
|
||||
// Certificate issued notification
|
||||
UserNotification.create({
|
||||
user_id,
|
||||
...NOTIFICATION_REGISTRY.certificate_issued.build({
|
||||
courseTitle: course.title,
|
||||
courseUuid,
|
||||
}),
|
||||
}).catch(err => console.error('[CERTIFICATE] Failed to emit notification:', err));
|
||||
|
||||
// Per-course completion achievement
|
||||
mdl_Achievements.findOrCreate({
|
||||
where: { user_id, key: `course_completed_${courseUuid}` },
|
||||
defaults: {
|
||||
type: 'milestone',
|
||||
label: 'Certificate of Completion',
|
||||
description: course.title,
|
||||
granted_at: passedAttempt.createdAt,
|
||||
metadata: { courseTitle: course.title, courseUuid },
|
||||
},
|
||||
}).catch(err => console.error('[CERTIFICATE] Failed to grant course achievement:', err));
|
||||
|
||||
// First-course achievement (only if this is their very first certificate)
|
||||
const totalCerts = await Certificate.count({ where: { user_id } });
|
||||
if (totalCerts === 1) {
|
||||
mdl_Achievements.findOrCreate({
|
||||
where: { user_id, key: 'first_course_completed' },
|
||||
defaults: {
|
||||
type: 'milestone',
|
||||
label: 'First Course Completed',
|
||||
description: 'Completed your very first course on Philproperties.',
|
||||
granted_at: passedAttempt.createdAt,
|
||||
metadata: { courseTitle: course.title, courseUuid },
|
||||
},
|
||||
}).catch(err => console.error('[CERTIFICATE] Failed to grant first-course achievement:', err));
|
||||
}
|
||||
}
|
||||
|
||||
// ── 6. Format issued date as MM/DD/YY HH:MM AM/PM ────────────────────────
|
||||
// ── 5. Format issued date as MM/DD/YY HH:MM AM/PM ───────────────────────────
|
||||
const issuedDate = new Date(cert.issued_at);
|
||||
const dateStr = new Intl.DateTimeFormat('en-US', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
year: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: true,
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(issuedDate);
|
||||
|
||||
// ── 7. Generate PDF ────────────────────────────────────────────────────────
|
||||
// ── 6. Generate PDF ────────────────────────────────────────────────────────
|
||||
const pdf = await generateCertificate({
|
||||
name: fullName,
|
||||
course: course.title,
|
||||
@@ -193,7 +151,7 @@ exports.getCertificate = async (req, res) => {
|
||||
length: cert.length_str ?? '',
|
||||
});
|
||||
|
||||
// ── 8. Stream response ─────────────────────────────────────────────────────
|
||||
// ── 7. Stream response ─────────────────────────────────────────────────────
|
||||
const nameParts = fullName.trim().split(/\s+/);
|
||||
const lastName = nameParts.length > 1 ? nameParts[nameParts.length - 1] : nameParts[0];
|
||||
const firstName = nameParts.length > 1 ? nameParts.slice(0, -1).join(' ') : '';
|
||||
|
||||
Reference in New Issue
Block a user