/*********************************************************************************************************************************************************************** * File Name: notifications.data.js * Type of Program: Data * Description: Central registry of all notification types for both admin and * client (user) notifications. * * Each entry describes one notification type: * type {string} — stored in the DB 'type' column * scope {string} — 'admin' | 'user' | 'both' * trigger {string} — what fires it (cron | event | manual) * build {function} — takes a data payload, returns the object * ready to pass to AdminNotification.create() * or UserNotification.create() / bulkCreate() * * To add a new notification type: * 1. Add an entry in the relevant section below. * 2. Call NOTIFICATION_REGISTRY..build(data) at the trigger * site (controller, cron, service). * No other changes needed. * * Current types: * Admin : task_overdue, user_registration, nogrp_user_registered * User : task_requirements_updated, user_task_overdue, task_reminder, achievement, * course_unlocked, course_completed, certificate_issued, welcome, * nogrp_welcome, assessment_updated, announcement, tier_expired, * task_submission_reviewed, task_assigned, task_completed * Both : broadcast (admin-composed, sent via notification_broadcasts CRUD) * * Author: Kenneth Obsequio (@lash0000) * Date Created: Jun. 19, 2026 * Date Modified: Jul. 11, 2026 — reverted from notification_templates (DB-editable) back to hardcoded ***********************************************************************************************************************************************************************/ 'use strict'; const { fmtDate } = require('../utils/datetime.util'); const NOTIFICATION_REGISTRY = { // ───────────────────────────────────────────────────────────────────────── // ADMIN notifications (scope: 'admin') // ───────────────────────────────────────────────────────────────────────── // ── Task ────────────────────────────────────────────────────────────────── task_overdue: { type: 'task_overdue', scope: 'admin', trigger: 'cron', build({ count, task_list_ids = [] }) { return { type: 'task_overdue', title: 'Tasks Overdue', message: `${count} task${count === 1 ? ' was' : 's were'} automatically marked as overdue.`, data: { count, task_list_ids }, }; }, }, // ── User Registration ───────────────────────────────────────────────────── user_registration: { type: 'user_registration', scope: 'admin', trigger: 'event', build({ groupName, groupCode, userEmail }) { return { type: 'user_registration', title: 'New User Registered', message: `A new user registered in ${groupName}.`, data: { groupName, groupCode, userEmail }, }; }, }, // ── Unaffiliated User Registration ─────────────────────────────────────── nogrp_user_registered: { type: 'nogrp_user_registered', scope: 'admin', trigger: 'event', build({ userEmail, regType }) { return { type: 'nogrp_user_registered', title: 'New Unaffiliated User', message: `A new user (${userEmail}) registered via ${regType} without a group code and was placed in the default group.`, data: { userEmail, regType }, }; }, }, // ───────────────────────────────────────────────────────────────────────── // USER notifications (scope: 'user') // ───────────────────────────────────────────────────────────────────────── // ── Task ────────────────────────────────────────────────────────────────── task_requirements_updated: { type: 'task', scope: 'user', trigger: 'event', build({ taskName, taskListId = null, groupId = null }) { return { type: 'task', title: 'Task Updated', message: `The requirements for "${taskName}" have been updated by your administrator.`, data: { taskName, taskListId, groupId }, }; }, }, user_task_overdue: { type: 'task', scope: 'user', trigger: 'cron', build({ count, task_list_ids = [] }) { const label = count === 1 ? '1 task has' : `${count} tasks have`; return { type: 'task', title: 'Tasks Overdue', message: `${label} passed their deadline and been marked as overdue.`, data: { count, task_list_ids }, }; }, }, task_reminder: { type: 'task', scope: 'user', trigger: 'cron', build({ taskName, deadline, taskListId = null, groupId = null }) { return { type: 'task', title: 'Task Deadline Approaching', message: `"${taskName}" is due on ${fmtDate(deadline)}.`, data: { taskName, deadline, taskListId, groupId }, }; }, }, // ── Task submission review (approve/reject) ───────────────────────────── task_submission_reviewed: { type: 'task', scope: 'user', trigger: 'event', build({ taskName, status, review_note = null }) { const statusLabel = status === 'approved' ? 'approved' : 'rejected'; const reviewNoteSuffix = review_note ? ` Note: ${review_note}` : ''; return { type: 'task', title: 'Submission Reviewed', message: `Your submission for "${taskName}" was ${statusLabel}.${reviewNoteSuffix}`, data: { taskName, status, review_note }, }; }, }, // ── Task list assignment (group added to a task list) ─────────────────── task_assigned: { type: 'task', scope: 'user', trigger: 'event', build({ taskListName, taskCount }) { return { type: 'task', title: 'New Task Assigned', message: `You have been assigned "${taskListName}" — ${taskCount} task(s) to complete.`, data: { taskListName, taskCount }, }; }, }, // ── Per-task completion (0→1 transition) ───────────────────────────────── task_completed: { type: 'task', scope: 'user', trigger: 'event', build({ taskName }) { return { type: 'task', title: 'Task Completed', message: `You completed "${taskName}".`, data: { taskName }, }; }, }, // ── Achievement — title/message come from the achievement definition itself ─ achievement: { type: 'achievement', scope: 'user', trigger: 'event', build({ label, description, key }) { return { type: 'achievement', title: label, message: description, data: { key }, }; }, }, // ── Course ──────────────────────────────────────────────────────────────── course_unlocked: { type: 'course', scope: 'user', trigger: 'event', build({ courseTitle, courseUuid = null }) { return { type: 'course', title: 'New Course Available', message: `"${courseTitle}" has been added to your learning library.`, data: { courseTitle, courseUuid }, }; }, }, course_completed: { type: 'course', scope: 'user', trigger: 'event', build({ courseTitle, courseUuid = null }) { return { type: 'course', title: 'Course Completed', message: `Great job! You've completed "${courseTitle}". Your certificate will be issued within the next hour.`, data: { courseTitle, courseUuid }, }; }, }, certificate_issued: { type: 'course', scope: 'user', trigger: 'cron', build({ courseTitle, courseUuid }) { return { type: 'course', title: 'Certificate Issued', message: `Congratulations! Your certificate for "${courseTitle}" is ready.`, data: { courseTitle, courseUuid }, }; }, }, // ── Welcome ─────────────────────────────────────────────────────────────── welcome: { type: 'announcement', scope: 'user', trigger: 'event', build({ groupName, groupCode, accType, groupId = null }) { const greeting = accType === 'admin' ? 'Welcome, Administrator!' : accType === 'staff' ? 'Welcome to the Philproperties team!' : 'Welcome to Philproperties!'; return { type: 'announcement', title: 'Welcome to Philproperties', message: groupName ? `${greeting} You have been added to ${groupName}.` : greeting, data: { groupName, groupCode, accType, groupId }, }; }, }, // ── No-Group Welcome ────────────────────────────────────────────────────── nogrp_welcome: { type: 'announcement', scope: 'user', trigger: 'event', build() { return { type: 'announcement', title: "You're Not in a Group Yet", message: 'You are currently in the default group. Contact an administrator to be assigned to your team.', data: { groupCode: 'NOGRP' }, }; }, }, // ── Assessment ──────────────────────────────────────────────────────────── assessment_updated: { type: 'assessment', scope: 'user', trigger: 'event', build({ assessmentTitle, courseTitle, courseUuid = null }) { return { type: 'assessment', title: 'Assessment Updated', message: `The administrator has updated the "${assessmentTitle || 'Course Assessment'}" in "${courseTitle || 'your course'}". Your current session is still valid — continue where you left off.`, data: { assessmentTitle, courseTitle, courseUuid }, }; }, }, // ── Platform ────────────────────────────────────────────────────────────── announcement: { type: 'announcement', scope: 'user', trigger: 'manual', build({ title, body }) { return { type: 'announcement', title, message: body, data: {}, }; }, }, // ── Broadcast (admin-composed, manual) — title/message typed per-send via // the notification_broadcasts CRUD, not a fixed template ───────────────── broadcast: { type: 'announcement', scope: 'both', trigger: 'manual', build({ title, message, targetType = null, targetId = null, groupId = null, linkUrl = null, linkLabel = null }) { return { type: 'announcement', title, message, data: { targetType, targetId, groupId, linkUrl, linkLabel }, }; }, }, // ── Tier ────────────────────────────────────────────────────────────────── tier_expired: { type: 'tier_expired', scope: 'user', trigger: 'cron', build({ tier, label, planId = null }) { return { type: 'tier_expired', title: 'Subscription Expired', message: `Your ${label ?? tier} plan has expired. Renew to keep access.`, data: { tier, label, planId }, }; }, }, }; module.exports = { NOTIFICATION_REGISTRY };