/// // // M24 — Quote Expiry Enforcement. // // Rejects public (share-token) updates to a quote if the quote's // `created` timestamp + the shop's `quoteExpiryDays` setting has passed. // The frontend (QuoteApprove.tsx) shows an "expired" UI state. // migrate( (app) => { app.onRecordUpdateRequest((e) => { if (e.collection.name !== 'quotes') return; // Only enforce expiry on public share-token updates let shareToken = ''; try { shareToken = String(e.httpContext.request.query.get('shareToken') || ''); } catch (_) { return; } if (!shareToken) return; const record = e.record; const created = record.get('created'); if (!created) return; const userId = record.get('userId'); if (!userId) return; let settings = null; try { settings = e.dao.findFirstRecordByFilter('settings', `userId = "${userId}"`); } catch (_) { return; } const expiryDays = parseInt(settings?.get('quoteExpiryDays') ?? '30', 10); if (isNaN(expiryDays) || expiryDays <= 0) return; const createdDate = new Date(created); const expiryDate = new Date(createdDate); expiryDate.setDate(expiryDate.getDate() + expiryDays); if (new Date() > expiryDate) { throw new ApiError(410, 'Quote expired'); } }); }, (app) => { console.log('[M24] rollback — restart PocketBase to remove the hook'); } );