/*********************************************************************************************************************************************************************** * File Name: notificationTemplate.service.js * Type of Program: Service * Description: Renders system-triggered notification title/message from the * notification_templates table (admin-editable, see * controllers/admin/notification_templates.controller.js). * Mirrors the template-loading half of services/email.service.js's * sendEmail() — same "only live columns count as published" rule, * same {{placeholder}} substitution via utils/renderTemplate.util.js. * Author: Kenneth Obsequio (@lash0000) * Date Created: Jul. 3, 2026 *********************************************************************************************************************************************************************** * HOW TO USE: * const { renderNotification } = require('../services/notificationTemplate.service'); * const notify = await renderNotification({ type: 'task_overdue', data: { count } }); * await AdminNotification.create(notify); * * // Bulk/loop use — fetch once, render per-row without re-querying the DB: * const { getNotificationTemplate, renderNotificationContent } = require('../services/notificationTemplate.service'); * const template = await getNotificationTemplate('tier_expired'); * const rows = expired.map((t) => ({ user_id: t.user_id, ...renderNotificationContent(template, { tier: t.tier, label: t.plan?.label ?? null }) })); ***********************************************************************************************************************************************************************/ const mdl_NotificationTemplate = require('../models/notifications/notification_template.mdl'); const { enrichNotificationData } = require('../data/notification_template_enrichers.data'); const { renderTemplate } = require('../utils/renderTemplate.util'); const getNotificationTemplate = async (type) => { const template = await mdl_NotificationTemplate.findOne({ where: { type } }); if (!template || !template.title || !template.message) { throw new Error(`Notification template "${type}" has no published version yet`); } return template; }; // Pure — no DB access. Use when a template has already been fetched once // (e.g. reused across a bulk-create loop) to avoid a query per row. const renderNotificationContent = (template, data = {}) => { const enriched = enrichNotificationData(template.type, data); return { type: template.notify_type, title: renderTemplate(template.title, enriched), message: renderTemplate(template.message, enriched), data, }; }; const renderNotification = async ({ type, data = {} }) => { const template = await getNotificationTemplate(type); return renderNotificationContent(template, data); }; module.exports = { getNotificationTemplate, renderNotificationContent, renderNotification };