// Test immediate booking confirmation when appointment is created const { PrismaClient } = require('@prisma/client'); const crypto = require('crypto'); const prisma = new PrismaClient(); async function testImmediateBookingConfirmation() { console.log('šŸ“‹ TESTING IMMEDIATE BOOKING CONFIRMATION WORKFLOW'); console.log('='.repeat(60)); console.log('šŸŽÆ This simulates exactly what happens when you create an appointment in the UI'); console.log(''); try { // 1. Get system components console.log('1ļøāƒ£ Setting up test environment...'); const clinic = await prisma.clinic.findFirst(); const obaidLead = await prisma.lead.findFirst({ where: { phone: '+201066544750' } }); const treatment = await prisma.treatment.findFirst({ where: { clinicId: clinic.id, isActive: true } }); if (!obaidLead) { console.log('āŒ Obaid lead not found!'); return; } console.log(` āœ… Clinic: ${clinic.name}`); console.log(` āœ… Patient: ${obaidLead.name} (${obaidLead.phone})`); console.log(` āœ… Treatment: ${treatment.name}`); console.log(` āœ… Quiet hours: ${clinic.quietHoursStart}:00 - ${clinic.quietHoursEnd}:00`); // 2. Check current time vs quiet hours const now = new Date(); const currentHour = parseInt( new Intl.DateTimeFormat("en-US", { timeZone: clinic.timezone, hour: "numeric", hour12: false }).format(now) ); const inQuietHours = currentHour >= clinic.quietHoursStart && currentHour < clinic.quietHoursEnd; console.log(` āœ… Current time: ${now.toLocaleTimeString()} (hour: ${currentHour})`); console.log(` āœ… In quiet hours: ${inQuietHours ? 'YES' : 'NO'} - ${inQuietHours ? 'messages will be delayed' : 'messages will send immediately'}`); // 3. Check booking confirmation template const bookingTemplate = await prisma.reminderTemplate.findFirst({ where: { clinicId: clinic.id, trigger: 'booking_confirmed', isActive: true } }); if (!bookingTemplate) { console.log('āŒ No active booking confirmation template found!'); return; } console.log(` āœ… Booking template found: "${bookingTemplate.message.substr(0, 50)}..."`); console.log(` āœ… Template offset: ${bookingTemplate.offsetMinutes} minutes (should be 0 for immediate)`); // 4. Get baseline counts const beforeCounts = { appointments: await prisma.appointment.count(), reminders: await prisma.scheduledReminder.count(), messages: await prisma.messageLog.count({ where: { phone: '+201066544750' } }) }; console.log('\n2ļøāƒ£ Baseline counts:'); console.log(` Appointments: ${beforeCounts.appointments}`); console.log(` Reminders: ${beforeCounts.reminders}`); console.log(` Messages to obaid: ${beforeCounts.messages}`); // 5. Simulate exact UI appointment creation workflow console.log('\n3ļøāƒ£ Creating appointment (simulating UI workflow)...'); // Create appointment exactly like the UI does const appointmentTime = new Date(); appointmentTime.setDate(appointmentTime.getDate() + 1); appointmentTime.setHours(14, 30, 0, 0); // Tomorrow 2:30 PM const appointmentData = { clinicId: clinic.id, leadId: obaidLead.id, treatmentId: treatment.id, dateTime: appointmentTime, status: 'scheduled', confirmToken: crypto.randomBytes(32).toString('hex'), notes: 'UI workflow test - booking confirmation should be immediate' }; console.log(` Creating appointment for: ${appointmentTime.toLocaleString()}`); const appointment = await prisma.appointment.create({ data: appointmentData, include: { lead: true, treatment: true, clinic: true } }); console.log(` āœ… Appointment created: ${appointment.id}`); // 6. Call scheduleReminders exactly like the API does console.log('\n4ļøāƒ£ Calling scheduleReminders function (like API does)...'); try { // Import and call the actual scheduleReminders function const { scheduleReminders } = require('./src/lib/reminders'); await scheduleReminders(appointment.id); console.log(' āœ… scheduleReminders completed successfully'); } catch (scheduleError) { console.log(` āŒ scheduleReminders failed: ${scheduleError.message}`); // Fallback: manually schedule booking confirmation console.log(' šŸ”§ Manually scheduling booking confirmation...'); let scheduledFor = new Date(Date.now() + 5000); // 5 seconds from now // Apply quiet hours logic manually if needed if (inQuietHours) { console.log(' āš ļø Adjusting for quiet hours...'); const nextDay = new Date(scheduledFor); nextDay.setDate(nextDay.getDate() + 1); nextDay.setHours(clinic.quietHoursEnd, 0, 0, 0); scheduledFor = nextDay; console.log(` šŸ“… Rescheduled to: ${scheduledFor.toLocaleString()}`); } await prisma.scheduledReminder.create({ data: { appointmentId: appointment.id, templateId: bookingTemplate.id, scheduledFor: scheduledFor, }, }); console.log(' āœ… Booking confirmation manually scheduled'); } // 7. Check what was created console.log('\n5ļøāƒ£ Checking scheduled reminders...'); const scheduledReminders = await prisma.scheduledReminder.findMany({ where: { appointmentId: appointment.id }, include: { template: true }, orderBy: { scheduledFor: 'asc' } }); console.log(` šŸ“… Reminders scheduled: ${scheduledReminders.length}`); const bookingReminder = scheduledReminders.find(r => r.template.trigger === 'booking_confirmed'); if (bookingReminder) { const timeDiff = new Date(bookingReminder.scheduledFor).getTime() - Date.now(); const secondsUntil = Math.round(timeDiff / 1000); console.log(` āœ… Booking confirmation found:`); console.log(` Template: ${bookingReminder.template.trigger}`); console.log(` Scheduled: ${bookingReminder.scheduledFor}`); console.log(` Status: ${bookingReminder.status}`); console.log(` Time until send: ${secondsUntil} seconds`); if (secondsUntil <= 60) { console.log(' šŸŽ‰ PERFECT! Booking confirmation will send within 1 minute'); } else { console.log(` āš ļø DELAYED: Booking confirmation delayed by ${Math.round(secondsUntil / 60)} minutes`); } // 8. Wait and trigger cron to send the reminder if (secondsUntil <= 120) { // Only wait if it's within 2 minutes console.log('\n6ļøāƒ£ Waiting for reminder to be due, then sending...'); const waitTime = Math.max(secondsUntil + 2, 5); // Wait until due + 2 seconds, minimum 5 seconds console.log(` ā³ Waiting ${waitTime} seconds...`); for (let i = waitTime; i > 0; i--) { process.stdout.write(`\r ā³ ${i}s remaining...`); await new Promise(resolve => setTimeout(resolve, 1000)); } console.log('\n šŸ“¤ Triggering cron to send reminder...'); const cronResponse = await fetch('http://localhost:3000/api/cron/send-reminders?key=dev-cron-key', { method: 'POST' }); if (cronResponse.ok) { const cronResult = await cronResponse.json(); console.log(` āœ… Cron result: sent=${cronResult.sent}, failed=${cronResult.failed}, skipped=${cronResult.skipped}`); if (cronResult.sent > 0) { console.log(' šŸŽ‰ BOOKING CONFIRMATION SENT SUCCESSFULLY!'); // Check the message log await new Promise(resolve => setTimeout(resolve, 2000)); const sentMessage = await prisma.messageLog.findFirst({ where: { appointmentId: appointment.id, phone: '+201066544750' }, orderBy: { createdAt: 'desc' } }); if (sentMessage) { console.log(' šŸ“± Message details:'); console.log(` Status: ${sentMessage.status}`); console.log(` Sent at: ${sentMessage.sentAt}`); console.log(` WAHA ID: ${sentMessage.wahaMessageId}`); console.log(` Preview: "${sentMessage.message.substr(0, 60)}..."`); } } else if (cronResult.failed > 0) { console.log(' āŒ BOOKING CONFIRMATION FAILED TO SEND'); } else { console.log(' āš ļø No reminders processed (not due yet or other issue)'); } } else { console.log(' āŒ Cron endpoint failed'); } } else { console.log('\n6ļøāƒ£ Booking confirmation is delayed too long to test now'); console.log(` ā° Will be sent at: ${bookingReminder.scheduledFor}`); } } else { console.log(' āŒ NO BOOKING CONFIRMATION REMINDER SCHEDULED!'); console.log(' šŸ”§ This is the problem - the scheduleReminders function is not working'); } // 9. Final verification console.log('\n7ļøāƒ£ Final verification...'); const afterCounts = { appointments: await prisma.appointment.count(), reminders: await prisma.scheduledReminder.count(), messages: await prisma.messageLog.count({ where: { phone: '+201066544750' } }) }; console.log(` Appointments: ${beforeCounts.appointments} → ${afterCounts.appointments} (+${afterCounts.appointments - beforeCounts.appointments})`); console.log(` Reminders: ${beforeCounts.reminders} → ${afterCounts.reminders} (+${afterCounts.reminders - beforeCounts.reminders})`); console.log(` Messages to obaid: ${beforeCounts.messages} → ${afterCounts.messages} (+${afterCounts.messages - beforeCounts.messages})`); console.log('\nšŸŽÆ TEST RESULTS:'); console.log('='.repeat(40)); if (afterCounts.appointments > beforeCounts.appointments && afterCounts.reminders > beforeCounts.reminders && afterCounts.messages > beforeCounts.messages) { console.log('šŸŽ‰ SUCCESS! Complete workflow working:'); console.log(' āœ… Appointment created'); console.log(' āœ… Reminder scheduled'); console.log(' āœ… Message sent'); console.log(''); console.log('šŸ“± OBAID - Check your WhatsApp (+201066544750)!'); console.log(' You should see the booking confirmation message'); console.log(''); console.log('šŸš€ The system will work the same when you create appointments in the UI!'); } else if (afterCounts.appointments > beforeCounts.appointments && afterCounts.reminders > beforeCounts.reminders) { console.log('🟔 PARTIAL SUCCESS:'); console.log(' āœ… Appointment created'); console.log(' āœ… Reminder scheduled'); console.log(' āš ļø Message not sent yet (timing or quiet hours)'); console.log(''); console.log(' The message will be sent when the cron runs next'); } else { console.log('āŒ ISSUE DETECTED:'); console.log(' āœ… Appointment created'); if (afterCounts.reminders <= beforeCounts.reminders) { console.log(' āŒ Reminder NOT scheduled - scheduleReminders function issue'); } if (afterCounts.messages <= beforeCounts.messages) { console.log(' āŒ Message NOT sent - cron or WAHA issue'); } } } catch (error) { console.error('āŒ Test failed:', error); } finally { await prisma.$disconnect(); } } testImmediateBookingConfirmation().catch(console.error);