Add CSV import script for Customer model with unique name and email validation
This commit is contained in:
108
src/scripts/import-customers.ts
Normal file
108
src/scripts/import-customers.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import 'reflect-metadata';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { parse } from 'csv-parse/sync';
|
||||
import { getDataSource } from '../lib/database';
|
||||
import { Customer } from '../lib/database/entities/Customer';
|
||||
|
||||
interface CustomerCSVRow {
|
||||
City: string;
|
||||
Name: string;
|
||||
'Website URL': string;
|
||||
Email: string;
|
||||
}
|
||||
|
||||
async function importCustomers(csvFilePath: string): Promise<void> {
|
||||
try {
|
||||
// Initialize database connection
|
||||
const dataSource = await getDataSource();
|
||||
const customerRepository = dataSource.getRepository(Customer);
|
||||
|
||||
// Read and parse CSV file
|
||||
const fileContent = fs.readFileSync(csvFilePath, 'utf-8');
|
||||
const records = parse(fileContent, {
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
trim: true,
|
||||
}) as CustomerCSVRow[];
|
||||
|
||||
console.log(`Found ${records.length} records in CSV file`);
|
||||
|
||||
// Track processed emails to skip duplicates
|
||||
const processedEmails = new Set<string>();
|
||||
// Track existing names to ensure uniqueness
|
||||
const existingNames = new Set<string>(
|
||||
(await customerRepository.find()).map(customer => customer.name)
|
||||
);
|
||||
|
||||
let importedCount = 0;
|
||||
let skippedDuplicateEmail = 0;
|
||||
let skippedDuplicateName = 0;
|
||||
|
||||
for (const record of records) {
|
||||
const email = record.Email === 'null' ? '' : record.Email;
|
||||
const name = record.Name;
|
||||
|
||||
// Skip if email is already processed (not empty and already seen)
|
||||
if (email && processedEmails.has(email)) {
|
||||
console.log(`Skipping record with duplicate email: ${email}`);
|
||||
skippedDuplicateEmail++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if name already exists in database
|
||||
if (existingNames.has(name)) {
|
||||
console.log(`Skipping record with duplicate name: ${name}`);
|
||||
skippedDuplicateName++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add to processed sets
|
||||
if (email) {
|
||||
processedEmails.add(email);
|
||||
}
|
||||
existingNames.add(name);
|
||||
|
||||
// Create new customer
|
||||
const customer = new Customer();
|
||||
customer.name = name;
|
||||
customer.url = record['Website URL'] === 'null' ? '' : record['Website URL'];
|
||||
customer.email = email;
|
||||
|
||||
// Save to database
|
||||
await customerRepository.save(customer);
|
||||
importedCount++;
|
||||
|
||||
console.log(`Imported customer: ${name}`);
|
||||
}
|
||||
|
||||
console.log('Import summary:');
|
||||
console.log(`- Total records in CSV: ${records.length}`);
|
||||
console.log(`- Successfully imported: ${importedCount}`);
|
||||
console.log(`- Skipped (duplicate email): ${skippedDuplicateEmail}`);
|
||||
console.log(`- Skipped (duplicate name): ${skippedDuplicateName}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error importing customers:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if file path is provided as command line argument
|
||||
const csvFilePath = process.argv[2];
|
||||
if (!csvFilePath) {
|
||||
console.error('Please provide the path to the CSV file as a command line argument');
|
||||
console.error('Example: npm run import-customers -- ./data/customers.csv');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Run the import function
|
||||
importCustomers(csvFilePath)
|
||||
.then(() => {
|
||||
console.log('Import completed successfully');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Import failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user