add: more commits

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-03 21:40:24 +08:00
parent 1d12f04967
commit a572c1e25f
17 changed files with 476 additions and 302 deletions
@@ -0,0 +1,129 @@
'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('notification_templates', {
notification_template_id: { type: Sequelize.BIGINT, primaryKey: true, autoIncrement: true },
type: { type: Sequelize.STRING(100), allowNull: false, unique: true },
notify_type: { type: Sequelize.STRING(64), allowNull: false },
scope: { type: Sequelize.ENUM('admin', 'user', 'both'), allowNull: false },
label: { type: Sequelize.STRING(150), allowNull: false },
status: { type: Sequelize.ENUM('draft', 'sent'), allowNull: false, defaultValue: 'draft' },
title: { type: Sequelize.STRING(255), allowNull: true },
message: { type: Sequelize.TEXT, allowNull: true },
draft_title: { type: Sequelize.STRING(255), allowNull: true },
draft_message: { type: Sequelize.TEXT, allowNull: true },
last_sent_at: { type: Sequelize.DATE, allowNull: true },
is_system: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false },
createdAt: { type: Sequelize.DATE, allowNull: false },
updatedAt: { type: Sequelize.DATE, allowNull: false },
});
const now = new Date();
// Ported straight from data/notifications.data.js's NOTIFICATION_REGISTRY —
// seeded already-published (status: 'sent', content in the live title/message
// columns) because these types fire in production right now via cron/event
// triggers. Seeding them as drafts would make every trigger site throw
// "no published version yet" the moment this migration lands.
await queryInterface.bulkInsert('notification_templates', [
{
type: 'task_overdue', notify_type: 'task_overdue', scope: 'admin', is_system: true,
label: 'Tasks Overdue (Admin)', status: 'sent',
title: 'Tasks Overdue',
message: '{{count}} {{task_word}} automatically marked as overdue.',
createdAt: now, updatedAt: now,
},
{
type: 'user_registration', notify_type: 'user_registration', scope: 'admin', is_system: true,
label: 'New User Registered', status: 'sent',
title: 'New User Registered',
message: 'A new user registered in {{groupName}}.',
createdAt: now, updatedAt: now,
},
{
type: 'nogrp_user_registered', notify_type: 'nogrp_user_registered', scope: 'admin', is_system: true,
label: 'New Unaffiliated User', status: 'sent',
title: 'New Unaffiliated User',
message: 'A new user ({{userEmail}}) registered via {{regType}} without a group code and was placed in the default group.',
createdAt: now, updatedAt: now,
},
{
type: 'task_requirements_updated', notify_type: 'task', scope: 'user', is_system: true,
label: 'Task Requirements Updated', status: 'sent',
title: 'Task Updated',
message: 'The requirements for "{{taskName}}" have been updated by your administrator.',
createdAt: now, updatedAt: now,
},
{
type: 'user_task_overdue', notify_type: 'task', scope: 'user', is_system: true,
label: 'Tasks Overdue (User)', status: 'sent',
title: 'Tasks Overdue',
message: '{{task_label}} passed their deadline and been marked as overdue.',
createdAt: now, updatedAt: now,
},
{
type: 'task_reminder', notify_type: 'task', scope: 'user', is_system: true,
label: 'Task Deadline Approaching', status: 'sent',
title: 'Task Deadline Approaching',
message: '"{{taskName}}" is due on {{deadline}}.',
createdAt: now, updatedAt: now,
},
{
type: 'course_unlocked', notify_type: 'course', scope: 'user', is_system: true,
label: 'New Course Available', status: 'sent',
title: 'New Course Available',
message: '"{{courseTitle}}" has been added to your learning library.',
createdAt: now, updatedAt: now,
},
{
type: 'course_completed', notify_type: 'course', scope: 'user', is_system: true,
label: 'Course Completed', status: 'sent',
title: 'Course Completed',
message: 'Great job! You\'ve completed "{{courseTitle}}". Your certificate will be issued within the next hour.',
createdAt: now, updatedAt: now,
},
{
type: 'certificate_issued', notify_type: 'course', scope: 'user', is_system: true,
label: 'Certificate Issued', status: 'sent',
title: 'Certificate Issued',
message: 'Congratulations! Your certificate for "{{courseTitle}}" is ready.',
createdAt: now, updatedAt: now,
},
{
type: 'welcome', notify_type: 'announcement', scope: 'user', is_system: true,
label: 'Welcome Message', status: 'sent',
title: 'Welcome to Philproperties',
message: '{{greeting}}{{group_suffix}}',
createdAt: now, updatedAt: now,
},
{
type: 'nogrp_welcome', notify_type: 'announcement', scope: 'user', is_system: true,
label: "Not in a Group Yet", status: 'sent',
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.',
createdAt: now, updatedAt: now,
},
{
type: 'assessment_updated', notify_type: 'assessment', scope: 'user', is_system: true,
label: 'Assessment Updated', status: 'sent',
title: 'Assessment Updated',
message: 'The administrator has updated the "{{assessmentTitle}}" in "{{courseTitle}}". Your current session is still valid — continue where you left off.',
createdAt: now, updatedAt: now,
},
{
type: 'tier_expired', notify_type: 'tier_expired', scope: 'user', is_system: true,
label: 'Subscription Expired', status: 'sent',
title: 'Subscription Expired',
message: 'Your {{planLabel}} plan has expired. Renew to keep access.',
createdAt: now, updatedAt: now,
},
]);
},
async down(queryInterface) {
await queryInterface.dropTable('notification_templates');
await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_notification_templates_scope";`);
await queryInterface.sequelize.query(`DROP TYPE IF EXISTS "enum_notification_templates_status";`);
},
};