# 📧 Royal Enfield Workflow - Email Templates Professional, responsive, and dynamic email templates for the Royal Enfield Workflow System. --- ## 🎯 Key Features ✅ **Dynamic & Adaptive** - Templates adjust based on request data, priority, and workflow state ✅ **Single Action Button** - Only "View Request Details" button that redirects to request URL ✅ **Fully Responsive** - Mobile-friendly design that works across all devices ✅ **Professional Design** - Royal Enfield branded with color-coded scenarios ✅ **Email Client Compatible** - Table-based layout for maximum compatibility ✅ **Placeholder-Based** - Easy to integrate with backend templating engines --- ## 📁 Template Files (12 Templates) ### Core Workflow Templates 1. **RequestCreated.html** - Request submission confirmation 2. **ApprovalRequest.html** - Single approver notification 3. **MultiApproverRequest.html** - Multi-level approver notification with chain 4. **ApprovalConfirmation.html** - Approval confirmation notification 5. **RejectionNotification.html** - Rejection notification ### TAT Management Templates 6. **TATReminder.html** - TAT deadline reminder (80% threshold) 7. **TATBreached.html** - TAT breach escalation ### Workflow Control Templates 8. **WorkflowPaused.html** - Workflow pause notification 9. **WorkflowResumed.html** - Workflow resume notification ### Participant Management Templates 10. **ParticipantAdded.html** - New approver/spectator welcome 11. **ApproverSkipped.html** - Approver skip notification 12. **RequestClosed.html** - Request closure summary --- ## 🎨 Visual Design Each template uses color-coded gradients to indicate the scenario: | Template | Header Color | Purpose | |----------|-------------|---------| | RequestCreated | Purple (#667eea) | Information | | ApprovalRequest | Purple (#667eea) | Action Required | | MultiApproverRequest | Purple (#667eea) | Action Required | | ApprovalConfirmation | Green (#28a745) | Success | | RejectionNotification | Red (#dc3545) | Error/Rejection | | TATReminder | Orange (#ff9800) | Warning | | TATBreached | Red (#dc3545) | Critical | | WorkflowPaused | Gray (#6c757d) | Neutral | | WorkflowResumed | Green (#28a745) | Success | | ParticipantAdded | Purple (#667eea) | Information | | ApproverSkipped | Cyan (#17a2b8) | Information | | RequestClosed | Purple (#6f42c1) | Complete | --- ## 🔗 View Details Button All templates feature a single action button: - **Text:** "View Request Details" / "Review Request Now" / "Take Action Now" - **Link Format:** `{baseURL}/request/{requestNumber}` - **Example:** `https://workflow.royalenfield.com/request/REQ-2025-12-0013` No approval/rejection buttons in emails - all actions happen within the application. --- ## 📋 How to Use Templates ### 1. Load Template File ```javascript const fs = require('fs'); const template = fs.readFileSync('./emailtemplates/ApprovalRequest.html', 'utf8'); ``` ### 2. Replace Placeholders ```javascript let emailContent = template .replace(/\[ApproverName\]/g, approverName) .replace(/\[InitiatorName\]/g, initiatorName) .replace(/\[RequestId\]/g, requestId) .replace(/\[ViewDetailsLink\]/g, `${baseURL}/request/${requestNumber}`) .replace(/\[CompanyName\]/g, 'Royal Enfield'); ``` ### 3. Handle Dynamic Sections ```javascript // Priority Section Example if (priority === 'HIGH' || priority === 'CRITICAL') { const priorityHTML = `

High Priority

This request has been marked as ${priority} priority and requires prompt attention.

`; emailContent = emailContent.replace('[PrioritySection]', priorityHTML); } else { emailContent = emailContent.replace('[PrioritySection]', ''); } ``` ### 4. Send Email ```javascript await sendEmail({ to: recipientEmail, subject: `[${requestId}] New Approval Request`, html: emailContent }); ``` --- ## 📖 Complete Documentation See **TEMPLATE_MAPPING.md** for: - Complete list of all placeholders for each template - Dynamic section handling instructions - Priority-based sending strategy - Usage scenarios and triggers - Security considerations - Implementation examples --- ## 🚀 Integration Steps ### Step 1: Email Service Setup ```typescript // services/email.service.ts import nodemailer from 'nodemailer'; import fs from 'fs'; import path from 'path'; class EmailService { private transporter; constructor() { this.transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: process.env.SMTP_PORT, secure: process.env.SMTP_SECURE === 'true', auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD } }); } async sendEmail(to: string, subject: string, html: string) { return await this.transporter.sendMail({ from: process.env.EMAIL_FROM, to, subject, html }); } loadTemplate(templateName: string): string { const templatePath = path.join(__dirname, '../emailtemplates', `${templateName}.html`); return fs.readFileSync(templatePath, 'utf8'); } replaceplaceholders(template: string, data: Record): string { let result = template; for (const [key, value] of Object.entries(data)) { const regex = new RegExp(`\\[${key}\\]`, 'g'); result = result.replace(regex, value); } return result; } } export const emailService = new EmailService(); ``` ### Step 2: Create Email Handlers ```typescript // services/emailNotification.service.ts export async function sendApprovalRequest(approverEmail: string, requestData: any) { const template = emailService.loadTemplate('ApprovalRequest'); const placeholders = { ApproverName: approverEmail.split('@')[0], InitiatorName: requestData.initiatorName, RequestId: requestData.requestNumber, RequestDate: formatDate(requestData.createdAt), RequestTime: formatTime(requestData.createdAt), RequestType: requestData.requestType, RequestDescription: requestData.description, PrioritySection: getPrioritySection(requestData.priority), ViewDetailsLink: `${process.env.BASE_URL}/request/${requestData.requestNumber}`, CompanyName: 'Royal Enfield' }; const html = emailService.replaceplaceholders(template, placeholders); await emailService.sendEmail( approverEmail, `[${requestData.requestNumber}] New Approval Request`, html ); } ``` ### Step 3: Add to Workflow Events ```typescript // In workflow.service.ts await sendApprovalRequest(approverEmail, requestData); ``` --- ## 🔧 Environment Variables Required Add to your `.env` file: ```env # SMTP Configuration SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_SECURE=false SMTP_USER=your-email@domain.com SMTP_PASSWORD=your-app-password # Email Settings EMAIL_FROM=RE Workflow System BASE_URL=https://workflow.royalenfield.com COMPANY_NAME=Royal Enfield ``` --- ## ✅ Testing Templates ### Preview in Browser Open any `.html` file directly in a browser to see the design. Placeholders will be visible as `[PlaceholderName]`. ### Test Email Sending ```typescript // test/email.test.ts import { emailService } from '../services/email.service'; describe('Email Templates', () => { it('should send approval request email', async () => { const template = emailService.loadTemplate('ApprovalRequest'); const testData = { ApproverName: 'John Doe', InitiatorName: 'Jane Smith', RequestId: 'REQ-2025-12-0013', // ... other test data }; const html = emailService.replaceplaceholders(template, testData); // Send to test email await emailService.sendEmail('test@example.com', 'Test Email', html); }); }); ``` --- ## 📊 Template Selection Logic ```typescript function getTemplateForScenario(scenario: string, hasMultipleApprovers: boolean): string { switch(scenario) { case 'request_created': return 'RequestCreated'; case 'approval_required': return hasMultipleApprovers ? 'MultiApproverRequest' : 'ApprovalRequest'; case 'request_approved': return 'ApprovalConfirmation'; case 'request_rejected': return 'RejectionNotification'; case 'tat_reminder': return 'TATReminder'; case 'tat_breached': return 'TATBreached'; case 'workflow_paused': return 'WorkflowPaused'; case 'workflow_resumed': return 'WorkflowResumed'; case 'participant_added': return 'ParticipantAdded'; case 'approver_skipped': return 'ApproverSkipped'; case 'request_closed': return 'RequestClosed'; default: throw new Error(`Unknown scenario: ${scenario}`); } } ``` --- ## 🎯 Priority Queue Implementation Use Bull/BullMQ for reliable email delivery: ```typescript import Queue from 'bull'; const emailQueue = new Queue('email-notifications', { redis: { host: process.env.REDIS_HOST, port: process.env.REDIS_PORT } }); // Add email to queue with priority export async function queueEmail(emailData: any, priority: 'critical' | 'high' | 'medium' | 'low') { const priorityMap = { critical: 1, high: 2, medium: 3, low: 4 }; await emailQueue.add('send-email', emailData, { priority: priorityMap[priority], attempts: 3, backoff: { type: 'exponential', delay: 5000 } }); } // Process email queue emailQueue.process('send-email', async (job) => { const { to, subject, html } = job.data; await emailService.sendEmail(to, subject, html); }); ``` --- ## 📞 Support & Customization For template customization or issues: 1. Check **TEMPLATE_MAPPING.md** for complete documentation 2. Test templates in email clients (Gmail, Outlook, Apple Mail) 3. Validate HTML using online validators 4. Use email testing services (Litmus, Email on Acid) --- ## 📝 Change Log **Version 2.0** (Dec 4, 2025) - ✅ Removed all action buttons (Approve/Reject) - ✅ Added single "View Request Details" button - ✅ Made templates fully dynamic with conditional sections - ✅ Added 12 templates for all scenarios - ✅ Improved mobile responsiveness - ✅ Professional design without emojis - ✅ Added comprehensive documentation **Version 1.0** (Initial Release) - Basic templates with action buttons - 4 templates (Approval, Rejection, Multi-Approver, Confirmation) --- **Maintained by:** Royal Enfield Development Team **Last Updated:** December 4, 2025 **Email Template Version:** 2.0