fix(crm): self-heal missing CRM email templates at boot + recover queue
The CRM template seeders (crmEmailTemplates / contractEmailTemplates / eventReminderTemplates) were idempotent and ready, but only contractEmailTemplates was actually called (lazily, by contractService sends). crmEmailTemplates had no caller anywhere — every install that didn't pre-exist its templates failed every quote_sent / invoice_sent / storno_issued / invoice_reminder_* send with "Email template '<key>' not found". The queue processor retries 3 times then leaves the row in status='pending', retry_count=3, silently dead with no admin surface (see project_crm_backlog for the eventual System Health page). Fix: wire all three seeders into server.js startServer() right before startEmailQueueProcessor. The new _emailTemplateBoot.js orchestrates all three and then, for any template_key it just inserted, resets retry_count on stuck email_queue rows of that email_type so the queue processor's next tick picks them back up. Recovery is targeted: unrelated retry-exhausted rows (e.g. SMTP-timeout failures) are not touched. Integration test boots a fresh CRM DB, pre-seeds a stuck quote_sent row plus an unrelated stuck row, runs the boot helper, and asserts: templates landed, stuck quote_sent row was reset, unrelated row was left alone. Already-deployed installs heal automatically on the next backend restart after this lands.
This commit is contained in:
@@ -777,6 +777,16 @@ async function startServer() {
|
||||
|
||||
// Initialize email transporter and start queue processor
|
||||
await initializeTransporter();
|
||||
// Seed CRM / contract / event-reminder email templates and recover
|
||||
// any queue rows that exhausted retries because their template
|
||||
// didn't exist yet. Runs once per boot via module-level caches in
|
||||
// each seeder. See _emailTemplateBoot.js for the full rationale.
|
||||
try {
|
||||
const { seedEmailTemplatesAndRecoverQueue } = require('./src/services/_emailTemplateBoot');
|
||||
await seedEmailTemplatesAndRecoverQueue(db, logger);
|
||||
} catch (err) {
|
||||
logger.warn('Email template self-heal failed at boot:', err.message);
|
||||
}
|
||||
startEmailQueueProcessor();
|
||||
|
||||
// Start webhook delivery worker (#327)
|
||||
|
||||
Reference in New Issue
Block a user