fix(audit): wire 6 missing email subject overrides (R2-H14)
Admin-editable subject overrides at /admin/email-templates were no-ops for 6 of 8 templates — only portal_activation and portal_reset called loadSubjectOverride. Added a shared resolveSubject() helper and wired it into the missing senders: - crm_invite + portal_invite_resend (crm-invite.service.ts) - inquiry_client_confirmation (email worker via portId on job payload) - inquiry_sales_notification (email worker via portId on job payload) - residential_inquiry_client_confirmation (residential-inquiries route) - residential_inquiry_sales_alert (residential-inquiries route) The inquiry email worker payloads now carry portId + portName so the worker can resolve the per-port override; producers in inquiry- notifications.service.ts pass them through. 1175/1175 vitest passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
34
src/lib/email/resolve-subject.ts
Normal file
34
src/lib/email/resolve-subject.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Helper that turns a template key + per-port settings into a final
|
||||
* subject line. Centralises the override-resolution + token-substitution
|
||||
* pattern so every transactional email sender is one call away from
|
||||
* honoring the admin's `email_template_<key>_subject` override.
|
||||
*
|
||||
* Wire-up (per send site):
|
||||
* const subject = await resolveSubject({
|
||||
* key: 'crm_invite',
|
||||
* portId,
|
||||
* fallback: result.subject,
|
||||
* tokens: { portName, recipientName: data.recipientName, ttlHours: 48 },
|
||||
* });
|
||||
*
|
||||
* The override is read from `system_settings.email_template_<key>_subject`.
|
||||
* If unset / empty / non-string, the `fallback` is returned as-is.
|
||||
*/
|
||||
|
||||
import { loadSubjectOverride, applySubjectTokens } from '@/lib/email/template-overrides';
|
||||
import type { TemplateKey } from '@/lib/email/template-catalog';
|
||||
|
||||
export async function resolveSubject(args: {
|
||||
key: TemplateKey;
|
||||
/** Optional — when omitted (e.g. system-level emails with no port
|
||||
* context), only the fallback subject is returned. */
|
||||
portId?: string | null;
|
||||
fallback: string;
|
||||
tokens?: Record<string, string | number | undefined>;
|
||||
}): Promise<string> {
|
||||
if (!args.portId) return args.fallback;
|
||||
const override = await loadSubjectOverride(args.portId, args.key);
|
||||
if (!override) return args.fallback;
|
||||
return args.tokens ? applySubjectTokens(override, args.tokens) : override;
|
||||
}
|
||||
Reference in New Issue
Block a user