diff --git a/package-lock.json b/package-lock.json index 0e0e628..5af1f35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@editorjs/paragraph": "^2.11.7", "@editorjs/quote": "^2.7.6", "bcrypt": "^5.1.1", + "csv-parse": "^5.6.0", "jsonwebtoken": "^9.0.2", "mysql2": "^3.13.0", "next": "15.2.2", @@ -2764,6 +2765,11 @@ "dev": true, "license": "MIT" }, + "node_modules/csv-parse": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.6.0.tgz", + "integrity": "sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", diff --git a/package.json b/package.json index a90f6b5..de2b705 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "start": "next start", "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" + "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" }, "dependencies": { "@editorjs/code": "^2.9.3", @@ -22,6 +23,7 @@ "@editorjs/paragraph": "^2.11.7", "@editorjs/quote": "^2.7.6", "bcrypt": "^5.1.1", + "csv-parse": "^5.6.0", "jsonwebtoken": "^9.0.2", "mysql2": "^3.13.0", "next": "15.2.2", diff --git a/src/scripts/import-customers.ts b/src/scripts/import-customers.ts new file mode 100644 index 0000000..21dfd92 --- /dev/null +++ b/src/scripts/import-customers.ts @@ -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 { + 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(); + // Track existing names to ensure uniqueness + const existingNames = new Set( + (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); + });