Dealer_Onboarding_Backend/src/scripts/seed-missing-templates.ts

317 lines
16 KiB
TypeScript

/**
* @file seed-missing-templates.ts
* @description Seeds the 6 email templates that are referenced in workflow code
* but were missing from the DB and the allowed-email-template-codes list.
*
* Run with: npx ts-node src/scripts/seed-missing-templates.ts
*/
import db from '../database/models/index.js';
const seedMissingTemplates = async () => {
try {
console.log('--- Seeding Missing Workflow Email Templates ---');
const templates = [
// ── 1. Workflow Action Required ────────────────────────────────────────
// Used in: workflow-email-notifications.ts (next-actor, send-back notifications)
// constitutional.controller.ts
// Recipients: DD-ZM, RBM, ZBH, DD-Lead, DD-Head, NBH, Legal, Finance, FDD
// Channels: system + email + whatsapp (when phone available)
{
templateCode: 'WORKFLOW_ACTION_REQUIRED',
description: 'Sent to the next actor in any workflow when their action is required. Used across Onboarding, Resignation, Termination, Constitutional, and Relocation.',
subject: 'Action Required: {{requestId}} — {{targetStage}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#c8102e;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">Action Required</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Hi,</p>
<p>
The request <strong>{{requestId}}</strong>
{{#if dealerName}}(Dealer: <strong>{{dealerName}}</strong>){{/if}}
has reached the <strong>{{targetStage}}</strong> stage and requires your review and action.
</p>
{{#if remarks}}
<div style="background:#fff8e1;border-left:4px solid #fb8c00;padding:12px 16px;margin:16px 0;">
<strong>Remarks:</strong><br/>{{remarks}}
</div>
{{/if}}
<p>Please log in to the RE Dealer Management Portal to review and act:</p>
<div style="text-align:center;margin:24px 0;">
<a href="{{link}}" style="background:#c8102e;color:#fff;padding:12px 28px;border-radius:6px;text-decoration:none;font-weight:bold;">
{{#if ctaLabel}}{{ctaLabel}}{{else}}Review & Take Action{{/if}}
</a>
</div>
<p style="color:#888;font-size:12px;">This is an automated notification. Do not reply to this email.</p>
</div>
</div>`,
placeholders: ['requestId', 'dealerName', 'targetStage', 'link', 'remarks', 'ctaLabel']
},
// ── 2. Workflow Status Update — Dealer ─────────────────────────────────
// Used in: workflow-email-notifications.ts (dealer on interim + terminal events)
// Recipients: Dealer / Applicant
// Channels: system always; email+whatsapp on terminal (rejection/completion)
{
templateCode: 'WORKFLOW_STATUS_UPDATE_DEALER',
description: 'Milestone/status update sent to the dealer or applicant when their request moves to a new stage.',
subject: 'Update on Your Request — {{requestId}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#c8102e;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">Request Status Update</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Dear {{dealerName}},</p>
<p>
Your request <strong>{{requestId}}</strong> has been updated.
Current status: <strong>{{targetStage}}</strong>.
</p>
{{#if remarks}}
<div style="background:#f0f4ff;border-left:4px solid #3d6be8;padding:12px 16px;margin:16px 0;">
<strong>Note:</strong> {{remarks}}
</div>
{{/if}}
<p>Track the live progress of your request:</p>
<div style="text-align:center;margin:24px 0;">
<a href="{{link}}" style="background:#c8102e;color:#fff;padding:12px 28px;border-radius:6px;text-decoration:none;font-weight:bold;">
View Request
</a>
</div>
<p style="color:#888;font-size:12px;">
For queries, contact your assigned Area Sales Manager.
</p>
</div>
</div>`,
placeholders: ['requestId', 'dealerName', 'targetStage', 'link', 'remarks']
},
// ── 3. F&F Initiated ───────────────────────────────────────────────────
// Used in: resignation.controller.ts (when F&F is triggered on LWD)
// termination.controller.ts (post-termination F&F)
// Recipients: Finance team, Department heads, DD-Admin
// Channels: system + email
{
templateCode: 'FNF_INITIATED',
description: 'Notifies Finance and department heads when Full & Final (F&F) settlement is triggered on the Last Working Day.',
subject: 'F&F Settlement Initiated — {{requestId}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#c8102e;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">Full &amp; Final Settlement Initiated</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Dear {{recipientName}},</p>
<p>
The Full &amp; Final (F&amp;F) settlement process has been initiated for dealer
<strong>{{dealerName}}</strong> (Request: <strong>{{requestId}}</strong>).
</p>
<table style="width:100%;border-collapse:collapse;margin:16px 0;">
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Request ID</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{requestId}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Dealer Name</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{dealerName}}</td>
</tr>
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Last Working Day</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{lwd}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Initiated By</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{initiatedBy}}</td>
</tr>
</table>
<p>Please update your department clearance status promptly.</p>
<div style="text-align:center;margin:24px 0;">
<a href="{{link}}" style="background:#c8102e;color:#fff;padding:12px 28px;border-radius:6px;text-decoration:none;font-weight:bold;">
View F&amp;F Settlement
</a>
</div>
<p style="color:#888;font-size:12px;">
Per Royal Enfield policy, F&amp;F settlement is initiated only on or after the Last Working Day.
</p>
</div>
</div>`,
placeholders: ['recipientName', 'dealerName', 'requestId', 'lwd', 'initiatedBy', 'link']
},
// ── 4. EOR Completed ───────────────────────────────────────────────────
// Used in: eor.controller.ts (when all EOR checklist items are complete)
// Recipients: DD-Head, NBH
// Channels: system (alert only — no email per SRS §6.19.3.4 design choice)
// Adding email template so Admin can optionally enable
{
templateCode: 'EOR_COMPLETED',
description: 'Alert to DD-Head and NBH when 100% of EOR (Essential Operating Requirements) checklist items are verified. Signals readiness for Inauguration stage.',
subject: 'EOR Checklist Complete — Ready for Inauguration: {{requestId}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#2e7d32;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">✓ EOR Checklist — 100% Complete</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Dear {{recipientName}},</p>
<p>
All <strong>Essential Operating Requirements (EOR)</strong> for dealer application
<strong>{{requestId}}</strong> (Applicant: <strong>{{applicantName}}</strong>)
have been completed and verified.
</p>
<div style="background:#e8f5e9;border-left:4px solid #43a047;padding:12px 16px;margin:16px 0;">
<strong>EOR Status: 100% Complete</strong><br/>
The dealership is now ready for Inauguration review.
</div>
<table style="width:100%;border-collapse:collapse;margin:16px 0;">
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Application ID</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{requestId}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Applicant</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{applicantName}}</td>
</tr>
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Location</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{location}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Completed On</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{completedOn}}</td>
</tr>
</table>
<p>Please review and authorize the <strong>Inauguration</strong> stage to mark this dealership as Live.</p>
<div style="text-align:center;margin:24px 0;">
<a href="{{link}}" style="background:#2e7d32;color:#fff;padding:12px 28px;border-radius:6px;text-decoration:none;font-weight:bold;">
Authorize Inauguration
</a>
</div>
</div>
</div>`,
placeholders: ['recipientName', 'applicantName', 'requestId', 'location', 'completedOn', 'link']
},
// ── 5. Applicant Rejected ──────────────────────────────────────────────
// Used in: WorkflowService.transitionApplication (any rejection)
// Recipients: Applicant (external)
// Channels: email (SRS §6.12.3 — rejection via email)
// WhatsApp if mobileNumber present
{
templateCode: 'APPLICANT_REJECTED',
description: 'Sent to the applicant/dealer when their application is rejected at any stage of the onboarding process.',
subject: 'Update on Your Dealership Application — {{applicationId}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#b71c1c;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">Application Status Update</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Dear {{applicantName}},</p>
<p>
We regret to inform you that your Royal Enfield Dealership Application
(<strong>{{applicationId}}</strong>) for location <strong>{{location}}</strong>
has been <strong>rejected</strong> after careful evaluation.
</p>
{{#if rejectionReason}}
<div style="background:#fff3f3;border-left:4px solid #e53935;padding:12px 16px;margin:16px 0;">
<strong>Reason:</strong><br/>{{rejectionReason}}
</div>
{{/if}}
<p>
We appreciate your interest in partnering with Royal Enfield. You may reapply
when opportunities are available in your area in the future.
</p>
<p>
For any queries, contact us at
<a href="mailto:dealer-support@royalenfield.com">dealer-support@royalenfield.com</a>.
</p>
<p>Best Regards,<br/><strong>Royal Enfield Dealer Development Team</strong></p>
</div>
</div>`,
placeholders: ['applicantName', 'applicationId', 'location', 'rejectionReason']
},
// ── 6. Termination Initiated ───────────────────────────────────────────
// Used in: termination.controller.ts (case creation)
// Recipients: RBM, DD-ZM, ZBH, DD-Lead, Legal, NBH
// Channels: system + email + whatsapp
{
templateCode: 'TERMINATION_INITIATED',
description: 'Notifies internal stakeholders (RBM, DD-ZM, ZBH, Legal, NBH) when a dealer termination case is formally initiated by ASM.',
subject: 'Dealer Termination Case Initiated — {{requestId}}',
body: `
<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;padding:20px;">
<div style="background:#4a148c;padding:20px;border-radius:8px 8px 0 0;">
<h2 style="color:#fff;margin:0;font-size:20px;">Dealer Termination Case Initiated</h2>
</div>
<div style="background:#f9f9f9;padding:24px;border-radius:0 0 8px 8px;border:1px solid #eee;">
<p>Dear {{recipientName}},</p>
<p>
A formal termination process has been initiated for dealer
<strong>{{dealerName}}</strong> (Request ID: <strong>{{requestId}}</strong>).
</p>
<table style="width:100%;border-collapse:collapse;margin:16px 0;">
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Request ID</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{requestId}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Dealer Name</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{dealerName}}</td>
</tr>
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Termination Category</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{category}}</td>
</tr>
<tr>
<td style="padding:8px;border:1px solid #ddd;"><strong>Initiated By</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{initiatedBy}}</td>
</tr>
<tr style="background:#f0f0f0;">
<td style="padding:8px;border:1px solid #ddd;"><strong>Current Stage</strong></td>
<td style="padding:8px;border:1px solid #ddd;">{{currentStage}}</td>
</tr>
</table>
{{#if remarks}}
<div style="background:#fff8e1;border-left:4px solid #fb8c00;padding:12px 16px;margin:16px 0;">
<strong>Remarks:</strong><br/>{{remarks}}
</div>
{{/if}}
<p>Please review the case and provide your evaluation with mandatory work notes.</p>
<div style="text-align:center;margin:24px 0;">
<a href="{{link}}" style="background:#4a148c;color:#fff;padding:12px 28px;border-radius:6px;text-decoration:none;font-weight:bold;">
Review Termination Case
</a>
</div>
<p style="color:#888;font-size:12px;">
This notification is confidential. Do not share externally without authorization.
</p>
</div>
</div>`,
placeholders: ['recipientName', 'dealerName', 'requestId', 'category', 'initiatedBy', 'currentStage', 'remarks', 'link']
}
];
for (const t of templates) {
const [, created] = await db.EmailTemplate.upsert({
...t,
isActive: true
});
console.log(`${created ? 'Created' : 'Updated'}: ${t.templateCode}`);
}
console.log('\n--- Missing Templates Seeded Successfully ---');
console.log(`Total: ${templates.length} templates seeded.`);
process.exit(0);
} catch (error) {
console.error('Error seeding missing templates:', error);
process.exit(1);
}
};
seedMissingTemplates();