///
//
// 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');
}
);