save changes
This commit is contained in:
@ -9,7 +9,8 @@
|
|||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"create-test-user": "npx ts-node -P tsconfig.scripts.json src/scripts/create-test-user.ts",
|
"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",
|
"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": {
|
"dependencies": {
|
||||||
"@editorjs/code": "^2.9.3",
|
"@editorjs/code": "^2.9.3",
|
||||||
@ -50,4 +51,4 @@
|
|||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
126
src/scripts/send-emails-to-customers.ts
Normal file
126
src/scripts/send-emails-to-customers.ts
Normal file
@ -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,
|
||||||
|
`<h1>Hello ${customer.name}!</h1><p>${emailBody}</p>`
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
126
src/scripts/send-emails-to-new-customers.ts
Normal file
126
src/scripts/send-emails-to-new-customers.ts
Normal file
@ -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,
|
||||||
|
`<h1>Welcome ${customer.name}!</h1><p>${emailBody}</p>`
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user