/// // // M23 — Quote Approval Notifications. // // Sends an email to the shop owner when a customer approves or declines // a quote via the public share-token path. // // Uses onRecordUpdateRequest (fires before update) to inspect old vs new // status, then sends the email fire-and-forget. // migrate( (app) => { app.onRecordUpdateRequest((e) => { if (e.collection.name !== 'quotes') return; const record = e.record; const oldRecord = e.oldRecord; if (!oldRecord) return; const oldStatus = oldRecord.get('status') ?? ''; const newStatus = record.get('status') ?? ''; if (oldStatus !== 'sent') return; if (newStatus !== 'approved' && newStatus !== 'declined') return; const userId = record.get('userId'); if (!userId) return; let user; try { user = e.dao.findRecordById('users', userId); } catch { return; } const email = user.get('email'); if (!email) return; const shopName = record.get('customerInfo')?.name || ''; const vehicleInfo = record.get('customerInfo')?.vehicleInfo || ''; const statusLabel = newStatus === 'approved' ? 'Approved' : 'Declined'; const subject = `Quote ${statusLabel} — ${shopName} (${vehicleInfo})`; const html = [ '

Quote ', statusLabel.toLowerCase(), '

', '

Customer: ', shopName, '

', '

Vehicle: ', vehicleInfo, '

', '

Status: ', statusLabel, '

', '

Sent from ShopProQuote

', ].join(''); try { app.getMailer().send({ to: [{ address: email }], subject, html, }); console.log('[M23] quote ' + newStatus + ' notification sent to ' + email); } catch (mailErr) { console.error('[M23] failed to send notification email', mailErr); } }); }, (app) => { console.log('[M23] rollback — restart PocketBase to remove the hook'); } );