Fixes bug when changing the location of a booking (#3585)

* use correct booking

* delete calendar event and update booking reference

* use middleware to get booking

* updating event instad of deleting and creating a new one

* fix issue with google hangout link

* remove unsed imports

* Apply suggestions from code review

* Update bookings.tsx

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Carina Wollendorfer
2022-08-08 19:38:02 +00:00
committed by GitHub
co-authored by CarinaWolli Omar López Syed Ali Shahbaz Peer Richelsen kodiakhq[bot]
parent f036f0fb64
commit 88384192f8
3 changed files with 114 additions and 28 deletions
@@ -191,26 +191,62 @@ export default class GoogleCalendarService implements Calendar {
payload["location"] = getLocation(event);
}
if (event.conferenceData && event.location === "integrations:google:meet") {
payload["conferenceData"] = event.conferenceData;
}
const calendar = google.calendar({
version: "v3",
auth: myGoogleAuth,
});
const selectedCalendar = externalCalendarId
? externalCalendarId
: event.destinationCalendar?.externalId;
calendar.events.update(
{
auth: myGoogleAuth,
calendarId: externalCalendarId ? externalCalendarId : event.destinationCalendar?.externalId,
calendarId: selectedCalendar,
eventId: uid,
sendNotifications: true,
sendUpdates: "all",
requestBody: payload,
conferenceDataVersion: 1,
},
function (err, event) {
function (err, evt) {
if (err) {
console.error("There was an error contacting google calendar service: ", err);
return reject(err);
}
return resolve(event?.data);
if (evt && evt.data.id && evt.data.hangoutLink && event.location === "integrations:google:meet") {
calendar.events.patch({
// Update the same event but this time we know the hangout link
calendarId: selectedCalendar,
auth: myGoogleAuth,
eventId: evt.data.id || "",
requestBody: {
description: getRichDescription({
...event,
additionalInformation: { hangoutLink: evt.data.hangoutLink },
}),
},
});
return resolve({
uid: "",
...evt.data,
id: evt.data.id || "",
additionalInfo: {
hangoutLink: evt.data.hangoutLink || "",
},
type: "google_calendar",
password: "",
url: "",
});
}
return resolve(evt?.data);
}
);
});
+36
View File
@@ -156,6 +156,42 @@ export default class EventManager {
};
}
public async updateLocation(event: CalendarEvent, booking: PartialBooking): Promise<CreateUpdateResult> {
const evt = processLocation(event);
const isDedicated = evt.location ? isDedicatedIntegration(evt.location) : null;
const results: Array<EventResult<Exclude<Event, AdditionalInformation>>> = [];
// If and only if event type is a dedicated meeting, create a dedicated video meeting.
if (isDedicated) {
const result = await this.createVideoEvent(evt);
if (result.createdEvent) {
evt.videoCallData = result.createdEvent;
}
results.push(result);
}
// Update the calendar event with the proper video call data
results.push(...(await this.updateAllCalendarEvents(evt, booking)));
const referencesToCreate = results.map((result) => {
return {
type: result.type,
uid: result.createdEvent?.id?.toString() ?? "",
meetingId: result.createdEvent?.id?.toString(),
meetingPassword: result.createdEvent?.password,
meetingUrl: result.createdEvent?.url,
externalCalendarId: evt.destinationCalendar?.externalId,
credentialId: evt.destinationCalendar?.credentialId,
};
});
return {
results,
referencesToCreate,
};
}
/**
* Takes a calendarEvent and a rescheduleUid and updates the event that has the
* given uid using the data delivered in the given CalendarEvent.
@@ -23,36 +23,44 @@ export const bookingsRouter = createProtectedRouter()
.middleware(async ({ ctx, rawInput, next }) => {
// Endpoints that just read the logged in user's data - like 'list' don't necessary have any input
if (!rawInput) return next({ ctx: { ...ctx, booking: null } });
const webhookIdAndEventTypeId = commonBookingSchema.safeParse(rawInput);
if (!webhookIdAndEventTypeId.success) throw new TRPCError({ code: "PARSE_ERROR" });
const { bookingId } = webhookIdAndEventTypeId.data;
const booking = await ctx.prisma.booking.findFirst({
where: {
OR: [
/* If user is organizer */
{ userId: ctx.user.id, id: bookingId },
/* Or part of a collective booking */
id: bookingId,
AND: [
{
eventType: {
schedulingType: SchedulingType.COLLECTIVE,
users: {
some: {
id: ctx.user.id,
OR: [
/* If user is organizer */
{ userId: ctx.user.id },
/* Or part of a collective booking */
{
eventType: {
schedulingType: SchedulingType.COLLECTIVE,
users: {
some: {
id: ctx.user.id,
},
},
},
},
},
],
},
],
},
include: {
attendees: true,
eventType: true,
user: {
include: { destinationCalendar: true },
},
destinationCalendar: true,
references: true,
user: {
include: {
destinationCalendar: true,
credentials: true,
},
},
},
});
return next({ ctx: { ...ctx, booking } });
@@ -73,11 +81,6 @@ export const bookingsRouter = createProtectedRouter()
const { booking } = ctx;
try {
await ctx.prisma.booking.update({
where: { id: bookingId },
data: { location },
});
const organizer = await ctx.prisma.user.findFirst({
where: {
id: booking.userId || 0,
@@ -127,10 +130,9 @@ export const bookingsRouter = createProtectedRouter()
};
const eventManager = new EventManager(ctx.user);
// TODO: This is causing duplicate calendar events when updating location
const scheduleResult = await eventManager.create(evt);
const results = scheduleResult.results;
const updatedResult = await eventManager.updateLocation(evt, booking);
const results = updatedResult.results;
if (results.length > 0 && results.every((res) => !res.success)) {
const error = {
errorCode: "BookingUpdateLocationFailed",
@@ -138,11 +140,23 @@ export const bookingsRouter = createProtectedRouter()
};
logger.error(`Booking ${ctx.user.username} failed`, error, results);
} else {
await ctx.prisma.booking.update({
where: {
id: bookingId,
},
data: {
location,
references: {
create: updatedResult.referencesToCreate,
},
},
});
const metadata: AdditionalInformation = {};
if (results.length) {
metadata.hangoutLink = results[0].createdEvent?.hangoutLink;
metadata.conferenceData = results[0].createdEvent?.conferenceData;
metadata.entryPoints = results[0].createdEvent?.entryPoints;
metadata.hangoutLink = results[0].updatedEvent?.hangoutLink;
metadata.conferenceData = results[0].updatedEvent?.conferenceData;
metadata.entryPoints = results[0].updatedEvent?.entryPoints;
}
try {
await sendLocationChangeEmails({ ...evt, additionalInformation: metadata });