Compare commits

...

12 Commits

Author SHA1 Message Date
Joe Au-Yeung 16fffd6258 Map `iCalUID` to `VarChar` 2023-10-30 11:18:17 -04:00
Joe Au-Yeung 674c0e2b54 Clean up 2023-10-30 10:51:05 -04:00
Joe Au-Yeung 833d3a25bf Fix updating iCalUID 2023-10-27 16:35:08 -04:00
Joe Au-Yeung 83cb60b0cc Update iCalSequence on normal booking 2023-10-27 15:40:05 -04:00
Joe Au-Yeung 4813b34feb On reschedule update sequence 2023-10-27 14:59:00 -04:00
Joe Au-Yeung 757c878200 When rescheduling, keep same iCalUID as original booking 2023-10-27 13:54:49 -04:00
Joe Au-Yeung 25b83c3978 Update migration to include iCalSequence 2023-10-27 12:58:13 -04:00
Joe Au-Yeung f050f0c869 Request reschedule send correct ics file 2023-10-26 16:57:11 -04:00
Joe Au-Yeung 8371a311b1 GCal set iCalUID 2023-10-26 16:56:45 -04:00
Joe Au-Yeung e401431e60 Add iCalUID to seeder 2023-10-26 16:48:59 -04:00
Joe Au-Yeung 11e1d6fd00 Write iCalUID to booking 2023-10-26 16:48:42 -04:00
Joe Au-Yeung b045e996b4 Add iCalUID to booking 2023-10-26 16:48:15 -04:00
9 changed files with 51 additions and 2 deletions

View File

@ -200,6 +200,7 @@ export default class GoogleCalendarService implements Calendar {
useDefault: true,
},
guestsCanSeeOtherGuests: !!calEventRaw.seatsPerTimeSlot ? calEventRaw.seatsShowAttendees : true,
iCalUID: calEventRaw.iCalUID,
};
if (calEventRaw.location) {
@ -248,7 +249,6 @@ export default class GoogleCalendarService implements Calendar {
type: "google_calendar",
password: "",
url: "",
iCalUID: event.data.iCalUID,
};
} catch (error) {
console.error("There was an error contacting google calendar service: ", error);

View File

@ -23,6 +23,7 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
icalEvent: {
filename: "event.ics",
content: this.getiCalEventAsString(),
method: "request",
},
from: `${APP_NAME} <${this.getMailerOptions().from}>`,
to: toAddresses.join(","),
@ -42,6 +43,8 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
// @OVERRIDE
protected getiCalEventAsString(): string | undefined {
const icsEvent = createEvent({
uid: this.calEvent.iCalUID || this.calEvent.uid!,
sequence: 100,
start: dayjs(this.calEvent.startTime)
.utc()
.toArray()
@ -61,7 +64,7 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche
email: attendee.email,
})),
status: "CANCELLED",
method: "CANCEL",
method: "REQUEST",
});
if (icsEvent.error) {
throw icsEvent.error;

View File

@ -110,6 +110,8 @@ async function getBookingToDelete(id: number | undefined, uid: string | undefine
scheduledJobs: true,
seatsReferences: true,
responses: true,
iCalUID: true,
iCalSequence: true,
},
});
}
@ -261,6 +263,8 @@ async function handler(req: CustomRequest) {
...(teamMembers && { team: { name: "", members: teamMembers } }),
seatsPerTimeSlot: bookingToDelete.eventType?.seatsPerTimeSlot,
seatsShowAttendees: bookingToDelete.eventType?.seatsShowAttendees,
iCalUID: bookingToDelete.iCalUID,
iCalSequence: bookingToDelete.iCalSequence + 1,
};
const dataForWebhooks = { evt, webhooks, eventTypeInfo };
@ -387,6 +391,7 @@ async function handler(req: CustomRequest) {
data: {
status: BookingStatus.CANCELLED,
cancellationReason: cancellationReason,
iCalSequence: evt.iCalSequence,
},
select: {
startTime: true,

View File

@ -1099,6 +1099,14 @@ async function handler(
const calEventUserFieldsResponses =
"calEventUserFieldsResponses" in reqBody ? reqBody.calEventUserFieldsResponses : null;
const iCalUID = originalRescheduledBooking?.iCalUID ?? `${uid}@cal.com`;
// For bookings made before introducing iCalSequence, assume that the sequence should start at 1. For new bookings start at 0.
const iCalSequence = originalRescheduledBooking?.iCalSequence
? originalRescheduledBooking.iCalSequence + 1
: originalRescheduledBooking
? 1
: 0;
let evt: CalendarEvent = {
bookerUrl: await getBookerUrl(organizerUser),
type: eventType.title,
@ -1135,6 +1143,8 @@ async function handler(
seatsPerTimeSlot: eventType.seatsPerTimeSlot,
seatsShowAvailabilityCount: eventType.seatsPerTimeSlot ? eventType.seatsShowAvailabilityCount : true,
schedulingType: eventType.schedulingType,
iCalUID,
iCalSequence,
};
if (isTeamEventType && eventType.schedulingType === "COLLECTIVE") {
@ -1963,6 +1973,8 @@ async function handler(
connect: { id: evt.destinationCalendar[0].id },
}
: undefined,
iCalUID: evt.iCalUID ?? "",
iCalSequence: evt.iCalSequence ?? 0,
};
if (reqBody.recurringEventId) {
@ -2299,6 +2311,18 @@ async function handler(
evt.appsStatus = handleAppsStatus(results, booking);
videoCallUrl =
metadata.hangoutLink || organizerOrFirstDynamicGroupMemberDefaultLocationUrl || videoCallUrl;
if (evt.iCalUID !== booking.iCalUID) {
// The eventManager and handleAppsStatus could change the iCalUID. At this point we can update the DB record
await prisma.booking.update({
where: {
id: booking.id,
},
data: {
iCalUID: evt.iCalUID,
},
});
}
}
if (noEmail !== true) {
let isHostConfirmationEmailsDisabled = false;

View File

@ -0,0 +1,10 @@
/*
Warnings:
- Added the required column `iCalUID` to the `Booking` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Booking"
ADD COLUMN "iCalUID" VARCHAR NOT NULL ,
ADD COLUMN "iCalSequence" INTEGER NOT NULL DEFAULT 0;

View File

@ -417,6 +417,8 @@ model Booking {
/// @zod.custom(imports.bookingMetadataSchema)
metadata Json?
isRecorded Boolean @default(false)
iCalUID String @db.VarChar()
iCalSequence Int @default(0)
@@index([eventTypeId])
@@index([userId])

View File

@ -133,6 +133,7 @@ export async function createUserAndEventType({
},
},
status: bookingInput.status,
iCalUID: "",
},
});
console.log(

View File

@ -62,6 +62,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
scheduledJobs: true,
workflowReminders: true,
responses: true,
iCalUID: true,
},
where: {
uid: bookingId,
@ -176,6 +177,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
tAttendees
),
organizer: userAsPeopleType,
iCalUID: bookingToReschedule.iCalUID,
});
const director = new CalendarEventDirector();
@ -246,6 +248,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
? [bookingToReschedule?.destinationCalendar]
: [],
cancellationReason: `Please reschedule. ${cancellationReason}`, // TODO::Add i18-next for this
iCalUID: bookingToReschedule?.iCalUID,
};
// Send webhook

View File

@ -184,6 +184,7 @@ export interface CalendarEvent {
seatsPerTimeSlot?: number | null;
schedulingType?: SchedulingType | null;
iCalUID?: string | null;
iCalSequence?: number | null;
// It has responses to all the fields(system + user)
responses?: CalEventResponses | null;