Skip to content

Commit

Permalink
refactor bookingStatuses --> bookings
Browse files Browse the repository at this point in the history
  • Loading branch information
lucia-gomez committed Oct 24, 2024
1 parent 8e76687 commit 8ef8c2b
Show file tree
Hide file tree
Showing 18 changed files with 181 additions and 319 deletions.
39 changes: 5 additions & 34 deletions booking-app/app/api/bookings/export/route.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,17 @@
import { Booking, BookingStatus } from "@/components/src/types";
import { NextRequest, NextResponse } from "next/server";

import { Booking } from "@/components/src/types";
import { TableNames } from "@/components/src/policy";
import { parse } from "json2csv";
import { serverFetchAllDataFromCollection } from "@/lib/firebase/server/adminDb";

export async function GET(request: NextRequest) {
const bookings = await serverFetchAllDataFromCollection<Booking>(
TableNames.BOOKING,
);
const statuses = await serverFetchAllDataFromCollection<BookingStatus>(
TableNames.BOOKING_STATUS,
);

// need to find corresponding status row for booking row
const idsToData: {
[key: string]: {
booking: Booking;
status: BookingStatus;
};
} = {};

for (let booking of bookings) {
const calendarEventId = booking.calendarEventId;
const statusMatch = statuses.filter(
row => row.calendarEventId === calendarEventId,
)[0];
idsToData[calendarEventId] = {
booking,
status: statusMatch,
};
}

const rows = Object.entries(idsToData)
.map(([_, { booking, status }]) => {
const { requestNumber, ...otherBooking } = booking;
return { requestNumber, ...otherBooking, ...status };
})
.sort((a, b) => a.requestNumber - b.requestNumber);
const bookings = (
await serverFetchAllDataFromCollection<Booking>(TableNames.BOOKING)
).sort((a, b) => a.requestNumber - b.requestNumber);

try {
const csv = parse(rows);
const csv = parse(bookings);
return new NextResponse(csv, {
status: 200,
headers: {
Expand Down
26 changes: 9 additions & 17 deletions booking-app/app/api/bookings/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,17 @@ async function handleBookingApprovalEmails(
contents: BookingFormDetails,
) => {
const { equipmentCheckedOut, ...otherContents } = contents;
const otherContentsStrings = Object.fromEntries(
Object.entries(otherContents).map(([key, value]) => [
key,
value instanceof Timestamp ? value.toDate().toISOString() : value,
]),
);
const emailPromises = recipients.map(recipient =>
sendHTMLEmail({
templateName: "approval_email",
contents: {
...otherContents,
...otherContentsStrings,
roomId: selectedRoomIds,
startDate: serverFormatDate(bookingCalendarInfo?.startStr),
endDate: serverFormatDate(bookingCalendarInfo?.endStr),
Expand Down Expand Up @@ -160,12 +166,8 @@ export async function POST(request: NextRequest) {
endDate: toFirebaseTimestampFromString(bookingCalendarInfo.endStr),
requestNumber: sequentialId,
equipmentCheckedOut: false,
...data,
});
await serverSaveDataToFirestore(TableNames.BOOKING_STATUS, {
calendarEventId,
email,
requestedAt: Timestamp.now(),
...data,
});

await handleBookingApprovalEmails(
Expand Down Expand Up @@ -247,6 +249,7 @@ export async function PUT(request: NextRequest) {
endDate: toFirebaseTimestampFromString(bookingCalendarInfo.endStr),
calendarEventId: newCalendarEventId,
equipmentCheckedOut: false,
requestedAt: Timestamp.now(),
};

await serverUpdateDataByCalendarEventId(
Expand All @@ -255,17 +258,6 @@ export async function PUT(request: NextRequest) {
updatedData,
);

// update statuses
await serverDeleteDataByCalendarEventId(
TableNames.BOOKING_STATUS,
calendarEventId,
);
await serverSaveDataToFirestore(TableNames.BOOKING_STATUS, {
calendarEventId: newCalendarEventId,
email,
requestedAt: Timestamp.now(),
});

// handle auto-approval + send emails
await handleBookingApprovalEmails(
isAutoApproval,
Expand Down
115 changes: 72 additions & 43 deletions booking-app/app/api/syncCalendars/route.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import { toFirebaseTimestampFromString } from "@/components/src/client/utils/serverDate";
import { TableNames } from "@/components/src/policy";
import { Booking, MediaServices } from "@/components/src/types";

import { NextResponse } from "next/server";
import { TableNames } from "@/components/src/policy";
import { Timestamp } from "@firebase/firestore";
import admin from "@/lib/firebase/server/firebaseAdmin";
import { getCalendarClient } from "@/lib/googleClient";
import { Timestamp } from "@firebase/firestore";
import { NextResponse } from "next/server";
import { toFirebaseTimestampFromString } from "@/components/src/client/utils/serverDate";

const db = admin.firestore();
const areRoomIdsSame = (roomIds1: string, roomIds2: string): boolean => {

const toArray = (ids: string): string[] => {
return ids.includes(',') ? ids.split(',').map(id => id.trim()) : [ids.trim()];
return ids.includes(",")
? ids.split(",").map(id => id.trim())
: [ids.trim()];
};

const sortedRoomIds1 = toArray(String(roomIds1)).sort();
const sortedRoomIds2 = toArray(String(roomIds2)).sort();

console.log('Comparing room IDs:', { ids1: sortedRoomIds1, ids2: sortedRoomIds2 });

const areEqual = sortedRoomIds1.length === sortedRoomIds2.length &&
sortedRoomIds1.every((id, index) => id === sortedRoomIds2[index]);
console.log("Comparing room IDs:", {
ids1: sortedRoomIds1,
ids2: sortedRoomIds2,
});

const areEqual =
sortedRoomIds1.length === sortedRoomIds2.length &&
sortedRoomIds1.every((id, index) => id === sortedRoomIds2[index]);

console.log('Comparison result:', areEqual);
console.log("Comparison result:", areEqual);

return areEqual;
};
Expand Down Expand Up @@ -63,14 +69,32 @@ const createBookingWithDefaults = (
equipmentCheckedOut: false,
startDate: null,
endDate: null,
requestedAt: undefined,
firstApprovedAt: undefined,
firstApprovedBy: "",
finalApprovedAt: undefined,
finalApprovedBy: "",
declinedAt: undefined,
declinedBy: "",
declineReason: "",
canceledAt: undefined,
canceledBy: "",
checkedInAt: undefined,
checkedInBy: "",
checkedOutAt: undefined,
checkedOutBy: "",
noShowedAt: undefined,
noShowedBy: "",
walkedInAt: undefined,
...partialBooking,
};
};

const findGuestEmail = (event: any): string => {
const attendees = event.attendees || [];
const guestEmail = attendees.find((attendee: any) =>
attendee.email && !attendee.email.endsWith('@group.calendar.google.com')
const guestEmail = attendees.find(
(attendee: any) =>
attendee.email && !attendee.email.endsWith("@group.calendar.google.com"),
);
return guestEmail ? guestEmail.email : "";
};
Expand All @@ -79,7 +103,9 @@ const findRoomIds = (event: any, resources: any[]): string => {
const roomIds = new Set<string>();

// Add the roomId of the current resource
const currentResource = resources.find(r => r.calendarId === event.organizer.email);
const currentResource = resources.find(
r => r.calendarId === event.organizer.email,
);
if (currentResource) {
roomIds.add(currentResource.roomId);
}
Expand All @@ -95,7 +121,7 @@ const findRoomIds = (event: any, resources: any[]): string => {
// Convert to array, sort numerically, and join
return Array.from(roomIds)
.sort((a, b) => parseInt(a) - parseInt(b))
.join(',');
.join(",");
};

export async function POST(request: Request) {
Expand Down Expand Up @@ -150,69 +176,72 @@ export async function POST(request: Request) {
title: event.summary || "",
description: event.description || "",
email: guestEmail,
startDate: toFirebaseTimestampFromString(event.start?.dateTime) as Timestamp,
endDate: toFirebaseTimestampFromString(event.end?.dateTime) as Timestamp,
startDate: toFirebaseTimestampFromString(
event.start?.dateTime,
) as Timestamp,
endDate: toFirebaseTimestampFromString(
event.end?.dateTime,
) as Timestamp,
calendarEventId: calendarEventId || "",
roomId: roomIds,
mediaServices: MediaServices.CHECKOUT_EQUIPMENT,
});

console.log("newBooking", newBooking);
const bookingDocRef = await db
.collection(TableNames.BOOKING)
.add(newBooking);
.add({
...newBooking,
requestedAt: admin.firestore.FieldValue.serverTimestamp(),
firstApprovedAt: admin.firestore.FieldValue.serverTimestamp(),
finalApprovedAt: admin.firestore.FieldValue.serverTimestamp(),
});

console.log(`New Booking created with ID: ${bookingDocRef.id}`);

const newBookingStatus = {
calendarEventId: calendarEventId,
email: guestEmail,
requestedAt: admin.firestore.FieldValue.serverTimestamp(),
firstApprovedAt: admin.firestore.FieldValue.serverTimestamp(),
finalApprovedAt: admin.firestore.FieldValue.serverTimestamp(),
};
console.log("newBookingStatus", newBookingStatus);
const statusDocRef = await db
.collection(TableNames.BOOKING_STATUS)
.add(newBookingStatus);
console.log(`New BookingStatus created with ID: ${statusDocRef.id}`);

totalNewBookings++;
} else if (!bookingSnapshot.empty) {
// Update existing booking if roomIds contains multiple rooms and is different from the existing roomId
const existingBooking = bookingSnapshot.docs[0];
const existingData = existingBooking.data() as Booking;
console.log("roomIds",roomIds)
console.log("existingData.roomId",existingData.roomId)
if (roomIds.includes(',') && !areRoomIdsSame(roomIds, existingData.roomId)) {
console.log("roomIds", roomIds);
console.log("existingData.roomId", existingData.roomId);
if (
roomIds.includes(",") &&
!areRoomIdsSame(roomIds, existingData.roomId)
) {
await existingBooking.ref.update({ roomId: roomIds });
console.log(`Updated roomId for Booking ID: ${existingBooking.id}`);
console.log(
`Updated roomId for Booking ID: ${existingBooking.id}`,
);
totalUpdatedBookings++;
}
}
}
pageToken = events.data.nextPageToken;
} while (pageToken);
} catch (error) {
console.error(`Error processing calendar ${resource.calendarId}:`, error);
console.error(
`Error processing calendar ${resource.calendarId}:`,
error,
);
}
}

console.log("targetBookings", targetBookings);
console.log("totalNewBookings", totalNewBookings);
console.log("totalUpdatedBookings", totalUpdatedBookings);

return NextResponse.json(
{
message: `${totalNewBookings} new bookings have been synchronized. ${totalUpdatedBookings} existing bookings have been updated with multiple rooms.`
{
message: `${totalNewBookings} new bookings have been synchronized. ${totalUpdatedBookings} existing bookings have been updated with multiple rooms.`,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
console.error("Error syncing calendars:", error);
return NextResponse.json(
{ error: "An error occurred while syncing calendars." },
{ status: 500 }
{ status: 500 },
);
}
}
}
41 changes: 6 additions & 35 deletions booking-app/app/api/walkIn/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { BookingFormDetails, BookingStatusLabel } from "@/components/src/types";
import { NextRequest, NextResponse } from "next/server";
import { TableNames, getApprovalCcEmail } from "@/components/src/policy";
import {
serverGetRoomCalendarId,
serverApproveInstantBooking,
serverGetRoomCalendarId,
serverSendBookingDetailEmail,
} from "@/components/src/server/admin";
import { insertEvent } from "@/components/src/server/calendars";

import { Timestamp } from "firebase-admin/firestore";
import {
serverGetFinalApproverEmail,
serverGetNextSequentialId,
serverSaveDataToFirestore,
} from "@/lib/firebase/server/adminDb";

import { Timestamp } from "firebase-admin/firestore";
import { insertEvent } from "@/components/src/server/calendars";
import { toFirebaseTimestampFromString } from "@/components/src/client/utils/serverDate";

export async function POST(request: NextRequest) {
Expand Down Expand Up @@ -55,12 +55,8 @@ export async function POST(request: NextRequest) {
startDate: toFirebaseTimestampFromString(bookingCalendarInfo.startStr),
endDate: toFirebaseTimestampFromString(bookingCalendarInfo.endStr),
requestNumber: sequentialId,
...data,
});
await serverSaveDataToFirestore(TableNames.BOOKING_STATUS, {
calendarEventId,
email,
walkedInAt: Timestamp.now(),
...data,
});

const sendWalkInNofificationEmail = async (
Expand All @@ -75,21 +71,7 @@ export async function POST(request: NextRequest) {
BookingStatusLabel.WALK_IN,
),
);
// const emailPromises = recipients.map(recipient =>
// sendHTMLEmail({
// templateName: "booking_detail",
// contents: {
// ...contents,
// roomId: contents.roomId.toString(),
// startDate: formatDate(contents.startDate),
// endDate: formatDate(contents.endDate),
// },
// targetEmail: recipient,
// status: BookingStatusLabel.WALK_IN,
// eventTitle: contents.title,
// body: "",
// }),
// );

await Promise.all(emailPromises);
};

Expand All @@ -100,17 +82,6 @@ export async function POST(request: NextRequest) {
BookingStatusLabel.WALK_IN,
);

// const userEventInputs: BookingFormDetails = {
// calendarEventId,
// roomId: selectedRoomIds.join(", "),
// email,
// startDate: bookingCalendarInfo?.startStr,
// endDate: bookingCalendarInfo?.endStr,
// bookingToolUrl: getBookingToolDeployUrl(),
// headerMessage: "This is a request email for first approval.",
// ...data,
// };

const notifyEmails = [
data.sponsorEmail ?? null,
await serverGetFinalApproverEmail(),
Expand Down
Loading

0 comments on commit 8ef8c2b

Please sign in to comment.