From 956fd6ae2f4534072afaff31af1280ec157e88b5 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 08:11:08 +0100 Subject: [PATCH] feat: add attendee data to CSV export with seated event support (#21842) * feat: add attendee data to CSV export with seated event support - Add up to 3 attendees to CSV export in 'name (email)' format - Use booking.seatsReferences for seated events, booking.attendees for regular events - Maintain backward compatibility with existing bookerEmail/bookerName fields - Add attendee1, attendee2, attendee3 columns to CSV output Co-Authored-By: eunjae@cal.com * fix: restore missing comment as requested in PR review Co-Authored-By: eunjae@cal.com * Update packages/features/insights/server/events.ts * feat: remove duplicate booker columns from CSV export - Remove bookerEmail and bookerName columns as they duplicate attendee data - Remove noShowGuest field which was based on booker data - Remove unused booker field from bookingMap - Keep only attendee1, attendee2, attendee3 columns with name (email) format Co-Authored-By: eunjae@cal.com * feat: restore noShowGuest field to CSV export - Add noShowGuest field mapping from first attendee's noShow property - Maintain existing attendee1, attendee2, attendee3 columns - Default to false when no attendees exist - Works with both seated events and regular events Co-Authored-By: eunjae@cal.com * rename column --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: eunjae@cal.com --- packages/features/insights/server/events.ts | 61 ++++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/features/insights/server/events.ts b/packages/features/insights/server/events.ts index 57c3b6bc69..f32d86903e 100644 --- a/packages/features/insights/server/events.ts +++ b/packages/features/insights/server/events.ts @@ -462,28 +462,73 @@ class EventsInsights { noShow: true, }, }, + seatsReferences: { + select: { + attendee: { + select: { + name: true, + email: true, + noShow: true, + }, + }, + }, + }, }, }); - const bookingMap = new Map(bookings.map((booking) => [booking.uid, booking.attendees[0] || null])); + const bookingMap = new Map( + bookings.map((booking) => { + const attendeeList = + booking.seatsReferences.length > 0 + ? booking.seatsReferences.map((ref) => ref.attendee) + : booking.attendees; + + const formattedAttendees = attendeeList + .slice(0, 3) + .map((attendee) => (attendee ? `${attendee.name} (${attendee.email})` : null)); + + return [ + booking.uid, + { + noShowGuest: attendeeList[0]?.noShow || false, + attendee1: formattedAttendees[0] || null, + attendee2: formattedAttendees[1] || null, + attendee3: formattedAttendees[2] || null, + }, + ]; + }) + ); const data = csvData.map((bookingTimeStatus) => { if (!bookingTimeStatus.uid) { // should not be reached because we filtered above - return bookingTimeStatus; + return { + ...bookingTimeStatus, + noShowGuest: false, + attendee1: null, + attendee2: null, + attendee3: null, + }; } - const booker = bookingMap.get(bookingTimeStatus.uid); + const attendeeData = bookingMap.get(bookingTimeStatus.uid); - if (!booker) { - return bookingTimeStatus; + if (!attendeeData) { + return { + ...bookingTimeStatus, + noShowGuest: false, + attendee1: null, + attendee2: null, + attendee3: null, + }; } return { ...bookingTimeStatus, - noShowGuest: booker.noShow, - bookerEmail: booker.email, - bookerName: booker.name, + noShowGuest: attendeeData.noShowGuest, + attendee1: attendeeData.attendee1, + attendee2: attendeeData.attendee2, + attendee3: attendeeData.attendee3, }; });