/** * Seed script for Helix Engage — populates the platform with realistic demo data. * * Field name mapping (SDK → Platform): * Campaign: campaignType→typeCustom, campaignStatus→status, impressionCount→impressions, * clickCount→clicks, contactedCount→contacted, convertedCount→converted, leadCount→leadsGenerated * Lead: leadSource→source, leadStatus→status, landingPageUrl→landingPage, * firstContactedAt→firstContacted, lastContactedAt→lastContacted * Call: callDirection→direction, durationSeconds→durationSec, recordingUrl→recording * Appointment: durationMinutes→durationMin, appointmentStatus→status, roomNumber→room * LeadActivity: durationSeconds→durationSec, activityNotes→notes * FollowUp: followUpType→typeCustom, followUpStatus→status, followUpNotes→notes * * Run: cd helix-engage && npx tsx scripts/seed-data.ts */ const GRAPHQL_URL = 'http://localhost:4000/graphql'; const WORKSPACE_SUBDOMAIN = 'fortytwo-dev'; const ORIGIN = 'http://fortytwo-dev.localhost:4010'; const EMAIL = 'dev@fortytwo.dev'; const PASSWORD = 'tim@apple.dev'; function daysAgo(n: number): string { const d = new Date(); d.setDate(d.getDate() - n); return d.toISOString(); } function daysFromNow(n: number, hour = 10): string { const d = new Date(); d.setDate(d.getDate() + n); d.setHours(hour, 0, 0, 0); return d.toISOString(); } function hoursAgo(n: number): string { const d = new Date(); d.setHours(d.getHours() - n); return d.toISOString(); } let token = ''; async function gql(query: string, variables?: Record): Promise { const headers: Record = { 'Content-Type': 'application/json', 'X-Workspace-Subdomain': WORKSPACE_SUBDOMAIN, }; if (token) headers['Authorization'] = `Bearer ${token}`; const res = await fetch(GRAPHQL_URL, { method: 'POST', headers, body: JSON.stringify({ query, variables }) }); const data = await res.json(); if (data.errors) { console.error('GraphQL error:', JSON.stringify(data.errors[0], null, 2)); throw new Error(data.errors[0]?.message ?? 'GraphQL error'); } return data.data; } async function refreshToken() { const d1 = await gql(`mutation { getLoginTokenFromCredentials(email: "${EMAIL}", password: "${PASSWORD}", origin: "${ORIGIN}") { loginToken { token } } }`); const lt = d1.getLoginTokenFromCredentials.loginToken.token; const d2 = await gql(`mutation { getAuthTokensFromLoginToken(loginToken: "${lt}", origin: "${ORIGIN}") { tokens { accessOrWorkspaceAgnosticToken { token } } } }`); token = d2.getAuthTokensFromLoginToken.tokens.accessOrWorkspaceAgnosticToken.token; } async function create(entity: string, data: Record): Promise { const cap = entity.charAt(0).toUpperCase() + entity.slice(1); const result = await gql(`mutation Create($data: ${cap}CreateInput!) { create${cap}(data: $data) { id } }`, { data }); return result[`create${cap}`].id; } async function main() { console.log('🌱 Starting Helix Engage data seed...\n'); await refreshToken(); console.log('✅ Authenticated\n'); // === CAMPAIGNS === console.log('📢 Campaigns...'); const wdId = await create('campaign', { campaignName: "Women's Day Health Checkup", status: 'ACTIVE', platform: 'FACEBOOK', startDate: daysAgo(14), endDate: daysFromNow(16), budget: { amountMicros: 200000000000, currencyCode: 'INR' }, amountSpent: { amountMicros: 130000000000, currencyCode: 'INR' }, impressions: 82000, clicks: 2100, targetCount: 500, contacted: 89, converted: 24, leadsGenerated: 148, externalCampaignId: 'fb_camp_28491', }); console.log(` ✅ Women's Day: ${wdId}`); const csId = await create('campaign', { campaignName: 'Cervical Cancer Screening Drive', status: 'ACTIVE', platform: 'GOOGLE', startDate: daysAgo(10), endDate: daysFromNow(28), budget: { amountMicros: 150000000000, currencyCode: 'INR' }, amountSpent: { amountMicros: 57500000000, currencyCode: 'INR' }, impressions: 45000, clicks: 1300, targetCount: 300, contacted: 31, converted: 8, leadsGenerated: 56, externalCampaignId: 'ggl_camp_44102', }); console.log(` ✅ Cervical Screening: ${csId}`); const ivfId = await create('campaign', { campaignName: 'IVF Consultation — Free First Visit', status: 'ACTIVE', platform: 'FACEBOOK', startDate: daysAgo(23), endDate: daysFromNow(13), budget: { amountMicros: 300000000000, currencyCode: 'INR' }, amountSpent: { amountMicros: 246000000000, currencyCode: 'INR' }, impressions: 156000, clicks: 4200, targetCount: 500, contacted: 198, converted: 52, leadsGenerated: 312, externalCampaignId: 'fb_camp_28555', }); console.log(` ✅ IVF: ${ivfId}\n`); // Refresh token (short-lived JWT) await refreshToken(); // === LEADS === console.log('👥 Leads...'); const priyaId = await create('lead', { contactName: { firstName: 'Priya', lastName: 'Sharma' }, contactPhone: { primaryPhoneNumber: '9876543210', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN' }, contactEmail: { primaryEmail: 'priya.sharma@gmail.com' }, source: 'FACEBOOK_AD', status: 'APPOINTMENT_SET', interestedService: 'IVF Consultation', assignedAgent: 'Rekha CC', spamScore: 5, isSpam: false, isDuplicate: false, firstContacted: daysAgo(12), lastContacted: daysAgo(2), contactAttempts: 3, leadScore: 92, aiSummary: 'Returning IVF patient. Had first consultation with Dr. Patel last week. Next appointment scheduled in 3 days. Very responsive — all calls answered.', aiSuggestedAction: 'Confirm upcoming appointment and discuss treatment timeline', campaignId: ivfId, utmSource: 'facebook', utmMedium: 'paid', utmCampaign: 'ivf-free-consult', }); console.log(` ✅ Priya Sharma: ${priyaId}`); const raviId = await create('lead', { contactName: { firstName: 'Ravi', lastName: 'Kumar' }, contactPhone: { primaryPhoneNumber: '8765432109', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN' }, contactEmail: { primaryEmail: 'ravi.k@yahoo.com' }, source: 'GOOGLE_AD', status: 'NEW', interestedService: 'Cervical Screening', assignedAgent: 'Rekha CC', spamScore: 8, isSpam: false, contactAttempts: 0, leadScore: 75, aiSummary: 'New lead from Google Ads cervical screening campaign. Missed call yesterday — no callback yet. SLA breached.', aiSuggestedAction: 'Urgent callback — missed call SLA breached', campaignId: csId, utmSource: 'google', utmMedium: 'paid', }); console.log(` ✅ Ravi Kumar: ${raviId}`); const deepaId = await create('lead', { contactName: { firstName: 'Deepa', lastName: 'Rao' }, contactPhone: { primaryPhoneNumber: '7654321098', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN' }, source: 'WALK_IN', status: 'CONVERTED', interestedService: 'IVF Package', assignedAgent: 'Rekha CC', convertedAt: daysAgo(2), firstContacted: daysAgo(7), lastContacted: daysAgo(2), contactAttempts: 2, leadScore: 88, aiSummary: 'Walk-in converted to IVF patient. Completed first consultation with Dr. Patel 2 days ago.', aiSuggestedAction: 'Follow up on treatment plan discussion', campaignId: ivfId, }); console.log(` ✅ Deepa Rao: ${deepaId}`); const vijayId = await create('lead', { contactName: { firstName: 'Vijay', lastName: 'Nair' }, contactPhone: { primaryPhoneNumber: '6543210987', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN' }, contactEmail: { primaryEmail: 'vijay.n@gmail.com' }, source: 'REFERRAL', status: 'APPOINTMENT_SET', interestedService: 'Cardiology Consultation', assignedAgent: 'Rekha CC', firstContacted: daysAgo(20), lastContacted: daysAgo(3), contactAttempts: 4, leadScore: 85, aiSummary: 'Regular cardiology patient under Dr. Sharma. 2 completed visits. Has upcoming appointment. Cancelled once before.', aiSuggestedAction: 'Confirm upcoming appointment — previous cancellation history', }); console.log(` ✅ Vijay Nair: ${vijayId}`); const kavithaId = await create('lead', { contactName: { firstName: 'Kavitha', lastName: 'S' }, contactPhone: { primaryPhoneNumber: '9949879837', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN' }, source: 'FACEBOOK_AD', status: 'NEW', interestedService: "Women's Health Checkup", spamScore: 3, isSpam: false, contactAttempts: 0, leadScore: 80, aiSummary: "Brand new lead from today's Women's Day campaign. No contact yet.", aiSuggestedAction: 'Send WhatsApp template and assign to call center', campaignId: wdId, utmSource: 'facebook', utmMedium: 'paid', }); console.log(` ✅ Kavitha S: ${kavithaId}\n`); await refreshToken(); // === APPOINTMENTS === console.log('📅 Appointments...'); await create('appointment', { scheduledAt: daysAgo(5), durationMin: 30, appointmentType: 'CONSULTATION', status: 'COMPLETED', doctorName: 'Dr. Patel', department: 'Gynecology', reasonForVisit: 'IVF initial consultation' }); console.log(' ✅ Priya completed'); await create('appointment', { scheduledAt: daysFromNow(3, 10), durationMin: 45, appointmentType: 'FOLLOW_UP', status: 'SCHEDULED', doctorName: 'Dr. Patel', department: 'Gynecology', reasonForVisit: 'IVF follow-up — treatment plan' }); console.log(' ✅ Priya upcoming'); await create('appointment', { scheduledAt: daysAgo(2), durationMin: 30, appointmentType: 'CONSULTATION', status: 'COMPLETED', doctorName: 'Dr. Patel', department: 'Gynecology', reasonForVisit: 'IVF package consultation — walk-in' }); console.log(' ✅ Deepa completed'); await create('appointment', { scheduledAt: daysAgo(14), durationMin: 30, appointmentType: 'CONSULTATION', status: 'COMPLETED', doctorName: 'Dr. Sharma', department: 'Cardiology', reasonForVisit: 'Initial cardiology assessment' }); console.log(' ✅ Vijay initial'); await create('appointment', { scheduledAt: daysAgo(7), durationMin: 30, appointmentType: 'FOLLOW_UP', status: 'COMPLETED', doctorName: 'Dr. Sharma', department: 'Cardiology', reasonForVisit: 'Echocardiogram review' }); console.log(' ✅ Vijay follow-up'); await create('appointment', { scheduledAt: daysFromNow(5, 11), durationMin: 30, appointmentType: 'FOLLOW_UP', status: 'SCHEDULED', doctorName: 'Dr. Sharma', department: 'Cardiology', reasonForVisit: 'Quarterly check-up' }); console.log(' ✅ Vijay upcoming\n'); await refreshToken(); // === CALLS === console.log('📞 Calls...'); await create('call', { direction: 'INBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(12), endedAt: daysAgo(12), durationSec: 240, disposition: 'INFO_PROVIDED', leadId: priyaId }); console.log(' ✅ Priya enquiry'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(6), endedAt: daysAgo(6), durationSec: 180, disposition: 'APPOINTMENT_BOOKED', leadId: priyaId }); console.log(' ✅ Priya booked'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(2), endedAt: daysAgo(2), durationSec: 120, disposition: 'FOLLOW_UP_SCHEDULED', leadId: priyaId }); console.log(' ✅ Priya reminder'); await create('call', { direction: 'INBOUND', callStatus: 'MISSED', agentName: 'Rekha CC', startedAt: hoursAgo(18), durationSec: 0, leadId: raviId }); console.log(' ✅ Ravi missed'); await create('call', { direction: 'INBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(7), endedAt: daysAgo(7), durationSec: 300, disposition: 'INFO_PROVIDED', leadId: deepaId }); console.log(' ✅ Deepa enquiry'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(3), endedAt: daysAgo(3), durationSec: 150, disposition: 'APPOINTMENT_BOOKED', leadId: deepaId }); console.log(' ✅ Deepa booked'); await create('call', { direction: 'INBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(20), endedAt: daysAgo(20), durationSec: 210, disposition: 'APPOINTMENT_BOOKED', leadId: vijayId }); console.log(' ✅ Vijay initial'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(10), endedAt: daysAgo(10), durationSec: 90, disposition: 'FOLLOW_UP_SCHEDULED', leadId: vijayId }); console.log(' ✅ Vijay follow-up'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(5), endedAt: daysAgo(5), durationSec: 0, disposition: 'NO_ANSWER', leadId: vijayId }); console.log(' ✅ Vijay no-answer'); await create('call', { direction: 'OUTBOUND', callStatus: 'COMPLETED', agentName: 'Rekha CC', startedAt: daysAgo(3), endedAt: daysAgo(3), durationSec: 180, disposition: 'APPOINTMENT_BOOKED', leadId: vijayId }); console.log(' ✅ Vijay confirmed\n'); await refreshToken(); // === LEAD ACTIVITIES === console.log('📋 Activities...'); const acts = [ { activityType: 'STATUS_CHANGE', summary: 'Lead created from Facebook Ad — IVF campaign', occurredAt: daysAgo(14), performedBy: 'System', channel: 'SYSTEM', leadId: priyaId }, { activityType: 'ASSIGNED', summary: 'Auto-assigned to Rekha CC', occurredAt: daysAgo(14), performedBy: 'System', channel: 'SYSTEM', newValue: 'Rekha CC', leadId: priyaId }, { activityType: 'WHATSAPP_SENT', summary: 'IVF consultation template sent', occurredAt: daysAgo(13), performedBy: 'Sanjay Marketing', channel: 'WHATSAPP', leadId: priyaId }, { activityType: 'CALL_RECEIVED', summary: 'Enquired about IVF costs and process', occurredAt: daysAgo(12), performedBy: 'Rekha CC', channel: 'PHONE', leadId: priyaId }, { activityType: 'STATUS_CHANGE', summary: 'NEW → CONTACTED', occurredAt: daysAgo(12), performedBy: 'System', channel: 'SYSTEM', previousValue: 'NEW', newValue: 'CONTACTED', leadId: priyaId }, { activityType: 'APPOINTMENT_BOOKED', summary: 'Booked with Dr. Patel — IVF consultation', occurredAt: daysAgo(6), performedBy: 'Rekha CC', channel: 'PHONE', leadId: priyaId }, { activityType: 'STATUS_CHANGE', summary: 'CONTACTED → APPOINTMENT_SET', occurredAt: daysAgo(6), performedBy: 'System', channel: 'SYSTEM', previousValue: 'CONTACTED', newValue: 'APPOINTMENT_SET', leadId: priyaId }, { activityType: 'NOTE_ADDED', summary: 'Patient confirmed follow-up attendance', occurredAt: daysAgo(2), performedBy: 'Rekha CC', channel: 'PHONE', leadId: priyaId }, { activityType: 'STATUS_CHANGE', summary: 'Lead from Google Ad — cervical screening', occurredAt: daysAgo(3), performedBy: 'System', channel: 'SYSTEM', leadId: raviId }, { activityType: 'ASSIGNED', summary: 'Assigned to Rekha CC', occurredAt: daysAgo(3), performedBy: 'System', channel: 'SYSTEM', leadId: raviId }, { activityType: 'CALL_RECEIVED', summary: 'Missed call — all agents busy', occurredAt: hoursAgo(18), performedBy: 'System', channel: 'PHONE', leadId: raviId }, { activityType: 'STATUS_CHANGE', summary: 'Walk-in enquiry created', occurredAt: daysAgo(7), performedBy: 'System', channel: 'IN_PERSON', leadId: deepaId }, { activityType: 'CALL_RECEIVED', summary: 'IVF package enquiry', occurredAt: daysAgo(7), performedBy: 'Rekha CC', channel: 'PHONE', leadId: deepaId }, { activityType: 'APPOINTMENT_BOOKED', summary: 'Booked IVF consultation with Dr. Patel', occurredAt: daysAgo(3), performedBy: 'Rekha CC', channel: 'PHONE', leadId: deepaId }, { activityType: 'CONVERTED', summary: 'Completed first IVF consultation', occurredAt: daysAgo(2), performedBy: 'System', channel: 'SYSTEM', leadId: deepaId }, { activityType: 'STATUS_CHANGE', summary: 'Referral lead — family doctor', occurredAt: daysAgo(21), performedBy: 'System', channel: 'SYSTEM', leadId: vijayId }, { activityType: 'APPOINTMENT_BOOKED', summary: 'Cardiology consultation with Dr. Sharma', occurredAt: daysAgo(20), performedBy: 'Rekha CC', channel: 'PHONE', leadId: vijayId }, { activityType: 'NOTE_ADDED', summary: 'Family history of cardiac issues. Echo ordered.', occurredAt: daysAgo(14), performedBy: 'Rekha CC', channel: 'SYSTEM', leadId: vijayId }, { activityType: 'NOTE_ADDED', summary: 'Cancelled once — rescheduled', occurredAt: daysAgo(8), performedBy: 'Rekha CC', channel: 'PHONE', leadId: vijayId }, { activityType: 'STATUS_CHANGE', summary: "New from Women's Day FB campaign", occurredAt: hoursAgo(2), performedBy: 'System', channel: 'SYSTEM', leadId: kavithaId }, ]; for (const a of acts) { await create('leadActivity', a); } console.log(` ✅ ${acts.length} activities\n`); await refreshToken(); // === FOLLOW-UPS === console.log('🔔 Follow-ups...'); await create('followUp', { typeCustom: 'CALLBACK', status: 'OVERDUE', scheduledAt: hoursAgo(6), assignedAgent: 'Rekha CC', priority: 'URGENT' }); console.log(' ✅ Ravi overdue callback'); await create('followUp', { typeCustom: 'APPOINTMENT_REMINDER', status: 'PENDING', scheduledAt: daysFromNow(1, 9), assignedAgent: 'Rekha CC', priority: 'HIGH' }); console.log(' ✅ Vijay appointment reminder\n'); console.log('🎉 Seed complete!'); console.log(' 3 campaigns, 5 leads, 6 appointments, 10 calls, 20 activities, 2 follow-ups'); } main().catch(e => { console.error('❌', e.message); process.exit(1); });