diff --git a/package.json b/package.json index 34ad321..e3f3bde 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "lint": "next lint", "create-test-user": "npx ts-node -P tsconfig.scripts.json src/scripts/create-test-user.ts", "reset-database": "npx ts-node -P tsconfig.scripts.json src/scripts/reset-database.ts", - "import-customers": "npx ts-node -P tsconfig.scripts.json src/scripts/import-customers.ts" + "import-customers": "npx ts-node -P tsconfig.scripts.json src/scripts/import-customers.ts", + "send-emails": "npx ts-node -P tsconfig.scripts.json src/scripts/send-emails-to-customers.ts" }, "dependencies": { "@editorjs/code": "^2.9.3", @@ -50,4 +51,4 @@ "ts-node": "^10.9.2", "typescript": "^5" } -} +} \ No newline at end of file diff --git a/src/scripts/send-emails-to-customers.ts b/src/scripts/send-emails-to-customers.ts new file mode 100644 index 0000000..0cb2a50 --- /dev/null +++ b/src/scripts/send-emails-to-customers.ts @@ -0,0 +1,126 @@ +import 'reflect-metadata'; +import { getDataSource } from '../lib/database'; +import { Customer } from '../lib/database/entities/Customer'; +import { ContactRecord } from '../lib/database/entities/ContactRecord'; +import { sendEmail } from '../lib/email'; + +// Get command line arguments +const args = process.argv.slice(2); +const emailCountArg = args.find(arg => arg.startsWith('--count=')); +const defaultEmailCount = 0; +const emailCount = emailCountArg + ? parseInt(emailCountArg.split('=')[1], 10) + : defaultEmailCount; + +if (isNaN(emailCount) || emailCount < 0) { + console.error('Error: Email count must be a non-negative number'); + process.exit(1); +} + +async function main() { + try { + console.log('Initializing database connection...'); + const dataSource = await getDataSource(); + + console.log(`Finding customers with exactly ${emailCount} email contact records...`); + + let customersQuery = dataSource + .getRepository(Customer) + .createQueryBuilder('customer'); + + if (emailCount === 0) { + // Find customers with no email contact records + customersQuery = customersQuery + .leftJoin( + ContactRecord, + 'contact', + 'contact.customerId = customer.id AND contact.contactType = :contactType', + { contactType: 'EMAIL' } + ) + .where('contact.id IS NULL'); + } else { + // Find customers with exactly N email contact records + customersQuery = customersQuery + .leftJoin( + ContactRecord, + 'contact', + 'contact.customerId = customer.id AND contact.contactType = :contactType', + { contactType: 'EMAIL' } + ) + .groupBy('customer.id') + .having('COUNT(contact.id) = :count', { count: emailCount }); + } + + const filteredCustomers = await customersQuery.getMany(); + + console.log(`Found ${filteredCustomers.length} customers with exactly ${emailCount} email contact records.`); + + // Exit if no customers found + if (filteredCustomers.length === 0) { + console.log(`No customers with exactly ${emailCount} email contact records found. Exiting.`); + await dataSource.destroy(); + return; + } + + // Ask for confirmation before sending emails + console.log('The following customers will receive emails:'); + filteredCustomers.forEach((customer, index) => { + console.log(`${index + 1}. ${customer.name} (${customer.email})`); + }); + + console.log('\nSending emails to customers...'); + + // Send emails to each customer + let emailSubject = 'Welcome to Our Service'; + let emailBody = 'Thank you for your interest in our services. We look forward to working with you!'; + + // Customize email based on email count + if (emailCount === 0) { + emailSubject = 'Welcome to Our Service'; + emailBody = 'Thank you for your interest in our services. We look forward to working with you!'; + } else if (emailCount === 1) { + emailSubject = 'Follow-up on Our Services'; + emailBody = 'We hope you found our previous information helpful. Here are some additional details about our services.'; + } else { + emailSubject = `Important Update - Contact #${emailCount + 1}`; + emailBody = 'We wanted to share some important updates about our services that might interest you.'; + } + + for (const customer of filteredCustomers) { + console.log(`Sending email to ${customer.name} (${customer.email})...`); + + try { + const result = await sendEmail( + customer.id, + emailSubject, + emailBody, + `

Hello ${customer.name}!

${emailBody}

` + ); + + if (result.success) { + console.log(`✅ Email sent successfully to ${customer.email}`); + } else { + console.error(`❌ Failed to send email to ${customer.email}: ${result.error}`); + } + } catch (error) { + console.error(`❌ Error sending email to ${customer.email}:`, error); + } + + // Add a small delay between emails to avoid rate limiting + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + console.log('Email sending process completed.'); + await dataSource.destroy(); + + } catch (error) { + console.error('An error occurred:', error); + process.exit(1); + } +} + +// Run the main function +main().catch(error => { + console.error('Unhandled error:', error); + process.exit(1); +}); diff --git a/src/scripts/send-emails-to-new-customers.ts b/src/scripts/send-emails-to-new-customers.ts new file mode 100644 index 0000000..5f7d03c --- /dev/null +++ b/src/scripts/send-emails-to-new-customers.ts @@ -0,0 +1,126 @@ +import 'reflect-metadata'; +import { getDataSource } from '../lib/database'; +import { Customer } from '../lib/database/entities/Customer'; +import { ContactRecord } from '../lib/database/entities/ContactRecord'; +import { sendEmail } from '../lib/email'; + +// Get command line arguments +const args = process.argv.slice(2); +const emailCountArg = args.find(arg => arg.startsWith('--count=')); +const defaultEmailCount = 0; +const emailCount = emailCountArg + ? parseInt(emailCountArg.split('=')[1], 10) + : defaultEmailCount; + +if (isNaN(emailCount) || emailCount < 0) { + console.error('Error: Email count must be a non-negative number'); + process.exit(1); +} + +async function main() { + try { + console.log('Initializing database connection...'); + const dataSource = await getDataSource(); + + console.log(`Finding customers with exactly ${emailCount} email contact records...`); + + let customersQuery = dataSource + .getRepository(Customer) + .createQueryBuilder('customer'); + + if (emailCount === 0) { + // Find customers with no email contact records + customersQuery = customersQuery + .leftJoin( + ContactRecord, + 'contact', + 'contact.customerId = customer.id AND contact.contactType = :contactType', + { contactType: 'EMAIL' } + ) + .where('contact.id IS NULL'); + } else { + // Find customers with exactly N email contact records + customersQuery = customersQuery + .leftJoin( + ContactRecord, + 'contact', + 'contact.customerId = customer.id AND contact.contactType = :contactType', + { contactType: 'EMAIL' } + ) + .groupBy('customer.id') + .having('COUNT(contact.id) = :count', { count: emailCount }); + } + + const filteredCustomers = await customersQuery.getMany(); + + console.log(`Found ${filteredCustomers.length} customers with exactly ${emailCount} email contact records.`); + + // Exit if no customers found + if (filteredCustomers.length === 0) { + console.log(`No customers with exactly ${emailCount} email contact records found. Exiting.`); + await dataSource.destroy(); + return; + } + + // Ask for confirmation before sending emails + console.log('The following customers will receive emails:'); + filteredCustomers.forEach((customer, index) => { + console.log(`${index + 1}. ${customer.name} (${customer.email})`); + }); + + console.log('\nSending emails to customers...'); + + // Send emails to each customer + let emailSubject = 'Welcome to Our Service'; + let emailBody = 'Thank you for your interest in our services. We look forward to working with you!'; + + // Customize email based on email count + if (emailCount === 0) { + emailSubject = 'Welcome to Our Service'; + emailBody = 'Thank you for your interest in our services. We look forward to working with you!'; + } else if (emailCount === 1) { + emailSubject = 'Follow-up on Our Services'; + emailBody = 'We hope you found our previous information helpful. Here are some additional details about our services.'; + } else { + emailSubject = `Important Update - Contact #${emailCount + 1}`; + emailBody = 'We wanted to share some important updates about our services that might interest you.'; + } + + for (const customer of filteredCustomers) { + console.log(`Sending email to ${customer.name} (${customer.email})...`); + + try { + const result = await sendEmail( + customer.id, + emailSubject, + emailBody, + `

Welcome ${customer.name}!

${emailBody}

` + ); + + if (result.success) { + console.log(`✅ Email sent successfully to ${customer.email}`); + } else { + console.error(`❌ Failed to send email to ${customer.email}: ${result.error}`); + } + } catch (error) { + console.error(`❌ Error sending email to ${customer.email}:`, error); + } + + // Add a small delay between emails to avoid rate limiting + await new Promise(resolve => setTimeout(resolve, 1000)); + } + + console.log('Email sending process completed.'); + await dataSource.destroy(); + + } catch (error) { + console.error('An error occurred:', error); + process.exit(1); + } +} + +// Run the main function +main().catch(error => { + console.error('Unhandled error:', error); + process.exit(1); +});