| import { prisma } from './prisma'; |
| import { logger } from '../logger'; |
|
|
| export interface ContactImportRow { |
| [key: string]: any; |
| } |
|
|
| export interface BulkImportResult { |
| created: number; |
| updated: number; |
| errors: number; |
| } |
|
|
| export class ContactService { |
| |
| |
| |
| static findPhoneKey(row: ContactImportRow): string | undefined { |
| return Object.keys(row).find(k => |
| k.toLowerCase().includes('phone') || |
| k.toLowerCase().includes('téléphone') || |
| k.toLowerCase().includes('tel') || |
| k.toLowerCase().includes('num') || |
| k.toLowerCase().includes('whatsapp') |
| ); |
| } |
|
|
| |
| |
| |
| static findNameKey(row: ContactImportRow): string | undefined { |
| return Object.keys(row).find(k => |
| k.toLowerCase().includes('name') || |
| k.toLowerCase().includes('nom') || |
| k.toLowerCase().includes('contact') || |
| k.toLowerCase().includes('client') |
| ); |
| } |
|
|
| |
| |
| |
| static normalizePhone(rawPhone: any): string | null { |
| if (!rawPhone) return null; |
| |
| let phoneNumber = String(rawPhone) |
| .replace(/\s+/g, '') |
| .replace(/^\+/, '') |
| .replace(/\D/g, ''); |
|
|
| if (phoneNumber.length < 7) return null; |
|
|
| |
| if (phoneNumber.length === 9) { |
| phoneNumber = `221${phoneNumber}`; |
| } |
|
|
| return phoneNumber; |
| } |
|
|
| |
| |
| |
| static async bulkImport(organizationId: string, contacts: ContactImportRow[], listId: string): Promise<BulkImportResult> { |
| const results = { created: 0, updated: 0, errors: 0 }; |
|
|
| for (const row of contacts) { |
| try { |
| const phoneKey = this.findPhoneKey(row); |
| const nameKey = this.findNameKey(row); |
|
|
| const phoneNumber = this.normalizePhone(phoneKey ? row[phoneKey] : null); |
| const name = nameKey ? String(row[nameKey]).trim() : null; |
|
|
| if (!phoneNumber) { |
| results.errors++; |
| continue; |
| } |
|
|
| const attributes: any = { ...row }; |
| if (phoneKey) delete attributes[phoneKey]; |
| if (nameKey) delete attributes[nameKey]; |
|
|
| await prisma.contact.upsert({ |
| where: { |
| phoneNumber_organizationId: { phoneNumber, organizationId } |
| }, |
| update: { |
| name, |
| attributes, |
| broadcastLists: { connect: { id: listId } } |
| }, |
| create: { |
| phoneNumber, |
| name, |
| attributes, |
| organizationId, |
| broadcastLists: { connect: { id: listId } } |
| } |
| }); |
|
|
| results.created++; |
| } catch (err) { |
| logger.error({ err, row }, '[ContactService] Failed to import row'); |
| results.errors++; |
| } |
| } |
|
|
| return results; |
| } |
| } |
|
|