Learn how to create scheduled background tasks in EverShop
Cron jobs allow you to schedule background tasks to run automatically at specified intervals. They’re perfect for maintenance tasks, data synchronization, sending scheduled emails, generating reports, and cleaning up old data.
import { pool } from '@evershop/evershop/lib/postgres/connection';import { sendEmail } from '../services/emailService';export default async function WeeklySalesReport() { console.log('Generating weekly sales report...'); try { // Get sales data for the past week const result = await pool.query( `SELECT COUNT(*) as total_orders, SUM(grand_total) as total_revenue, AVG(grand_total) as average_order_value FROM orders WHERE created_at >= NOW() - INTERVAL '7 days' AND status = 'completed'` ); const stats = result.rows[0]; // Get top selling products const topProducts = await pool.query( `SELECT p.name, SUM(oi.quantity) as quantity_sold, SUM(oi.total) as revenue FROM order_items oi JOIN products p ON oi.product_id = p.product_id JOIN orders o ON oi.order_id = o.order_id WHERE o.created_at >= NOW() - INTERVAL '7 days' AND o.status = 'completed' GROUP BY p.product_id, p.name ORDER BY quantity_sold DESC LIMIT 10` ); // Send email report await sendEmail({ to: 'admin@mystore.com', subject: 'Weekly Sales Report', template: 'weekly-report', data: { totalOrders: stats.total_orders, totalRevenue: stats.total_revenue, averageOrderValue: stats.average_order_value, topProducts: topProducts.rows } }); console.log('Weekly sales report sent successfully'); } catch (error) { console.error('Failed to generate weekly report:', error); }}
src/bootstrap.ts
registerJob({ name: 'weeklySalesReport', schedule: '0 9 * * 1', // Every Monday at 9 AM resolve: path.resolve(import.meta.dirname, 'crons', 'weeklySalesReport.js'), enabled: true});
import { pool } from '@evershop/evershop/lib/postgres/connection';import { sendEmail } from '../services/emailService';export default async function AbandonedCartReminder() { console.log('Checking for abandoned carts...'); try { // Find carts abandoned 24 hours ago const result = await pool.query( `SELECT c.cart_id, c.customer_email, c.items, c.total FROM carts c WHERE c.status = 'active' AND c.updated_at BETWEEN NOW() - INTERVAL '25 hours' AND NOW() - INTERVAL '24 hours' AND c.customer_email IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM cart_recovery_emails WHERE cart_id = c.cart_id )` ); for (const cart of result.rows) { // Send recovery email await sendEmail({ to: cart.customer_email, subject: 'You left items in your cart!', template: 'cart-recovery', data: { items: cart.items, total: cart.total, cartLink: `https://mystore.com/cart/${cart.cart_id}` } }); // Log that we sent the email await pool.query( `INSERT INTO cart_recovery_emails (cart_id, sent_at) VALUES ($1, NOW())`, [cart.cart_id] ); } console.log(`Sent ${result.rows.length} cart recovery emails`); } catch (error) { console.error('Cart recovery failed:', error); }}