141 lines
5.0 KiB
SQL
141 lines
5.0 KiB
SQL
-- Notification templates: HTML email bodies + placeholder metadata
|
|
|
|
CREATE TABLE IF NOT EXISTS notification_templates (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
code VARCHAR(80) NOT NULL UNIQUE,
|
|
name VARCHAR(200) NOT NULL,
|
|
channel VARCHAR(20) NOT NULL DEFAULT 'EMAIL',
|
|
subject VARCHAR(500) NOT NULL,
|
|
html_body TEXT NOT NULL,
|
|
placeholders JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
description TEXT,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_by BIGINT,
|
|
updated_by BIGINT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_notification_templates_channel ON notification_templates (channel);
|
|
CREATE INDEX IF NOT EXISTS idx_notification_templates_is_active ON notification_templates (is_active);
|
|
|
|
INSERT INTO notification_templates (
|
|
code,
|
|
name,
|
|
channel,
|
|
subject,
|
|
html_body,
|
|
placeholders,
|
|
description,
|
|
is_active
|
|
)
|
|
VALUES (
|
|
'PO_SUBMIT_APPROVAL',
|
|
'Purchase Order Submitted for Approval',
|
|
'EMAIL',
|
|
'PO {{po_number}} submitted for approval',
|
|
'<!DOCTYPE html>
|
|
<html>
|
|
<body style="font-family: Arial, sans-serif; color: #222; line-height: 1.5;">
|
|
<p>Hello {{approver_name}},</p>
|
|
<p>Purchase order <strong>{{po_number}}</strong> has been submitted and is waiting for your approval.</p>
|
|
<table style="border-collapse: collapse; margin: 16px 0;">
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>PO Number</strong></td>
|
|
<td style="padding: 4px 0;">{{po_number}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>PO Date</strong></td>
|
|
<td style="padding: 4px 0;">{{po_date}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>Vendor</strong></td>
|
|
<td style="padding: 4px 0;">{{vendor_name}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>Grand Total</strong></td>
|
|
<td style="padding: 4px 0;">{{grand_total}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>Submitted By</strong></td>
|
|
<td style="padding: 4px 0;">{{submitted_by}}</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding: 4px 12px 4px 0;"><strong>Remarks</strong></td>
|
|
<td style="padding: 4px 0;">{{remarks}}</td>
|
|
</tr>
|
|
</table>
|
|
<p><a href="{{po_link}}" style="display: inline-block; padding: 10px 16px; background: #1f4b99; color: #fff; text-decoration: none; border-radius: 4px;">Review Purchase Order</a></p>
|
|
<p style="color: #666; font-size: 12px;">If the button does not work, open this link:<br/>{{po_link}}</p>
|
|
</body>
|
|
</html>',
|
|
'[
|
|
{"key": "approver_name", "description": "Approver full name"},
|
|
{"key": "po_number", "description": "Purchase order number"},
|
|
{"key": "po_date", "description": "Purchase order date"},
|
|
{"key": "vendor_name", "description": "Vendor name"},
|
|
{"key": "grand_total", "description": "PO grand total"},
|
|
{"key": "submitted_by", "description": "User who submitted the PO"},
|
|
{"key": "remarks", "description": "PO remarks"},
|
|
{"key": "po_link", "description": "Frontend deep link to the PO"}
|
|
]'::jsonb,
|
|
'Sent to users with PURCHASE_ORDER approve permission when a PO is submitted',
|
|
true
|
|
)
|
|
ON CONFLICT (code) DO UPDATE SET
|
|
name = EXCLUDED.name,
|
|
channel = EXCLUDED.channel,
|
|
subject = EXCLUDED.subject,
|
|
html_body = EXCLUDED.html_body,
|
|
placeholders = EXCLUDED.placeholders,
|
|
description = EXCLUDED.description,
|
|
is_active = true,
|
|
deleted_at = NULL,
|
|
updated_at = NOW();
|
|
|
|
INSERT INTO notification_templates (
|
|
code,
|
|
name,
|
|
channel,
|
|
subject,
|
|
html_body,
|
|
placeholders,
|
|
description,
|
|
is_active
|
|
)
|
|
VALUES (
|
|
'FORGOT_PASSWORD',
|
|
'Forgot Password Reset',
|
|
'EMAIL',
|
|
'Reset your ERP password',
|
|
'<!DOCTYPE html>
|
|
<html>
|
|
<body style="font-family: Arial, sans-serif; color: #222; line-height: 1.5;">
|
|
<p>Hello {{user_name}},</p>
|
|
<p>We received a request to reset your password.</p>
|
|
<p><a href="{{reset_url}}" style="display: inline-block; padding: 10px 16px; background: #1f4b99; color: #fff; text-decoration: none; border-radius: 4px;">Click here to reset your password</a></p>
|
|
<p>This link expires in {{expiry_minutes}} minutes.</p>
|
|
<p style="color: #666; font-size: 12px;">If the button does not work, open this link:<br/>{{reset_url}}</p>
|
|
<p>If you did not request this, you can ignore this email.</p>
|
|
</body>
|
|
</html>',
|
|
'[
|
|
{"key": "user_name", "description": "User full name"},
|
|
{"key": "reset_url", "description": "Password reset frontend URL with token"},
|
|
{"key": "expiry_minutes", "description": "Reset link expiry in minutes"}
|
|
]'::jsonb,
|
|
'Sent when a user requests a password reset via forgot-password',
|
|
true
|
|
)
|
|
ON CONFLICT (code) DO UPDATE SET
|
|
name = EXCLUDED.name,
|
|
channel = EXCLUDED.channel,
|
|
subject = EXCLUDED.subject,
|
|
html_body = EXCLUDED.html_body,
|
|
placeholders = EXCLUDED.placeholders,
|
|
description = EXCLUDED.description,
|
|
is_active = true,
|
|
deleted_at = NULL,
|
|
updated_at = NOW();
|