Untitled
unknown
plain_text
a year ago
11 kB
14
Indexable
import { Response } from "express";
import { v4 as uuid } from "uuid";
import redis from "../../controllers/redis";
import { find, findOne, remove, update } from "../../db/operations";
import secondsToDhms from "../../utils/secondsToDhms";
import { BookingPayload, Req } from "../../utils/types";
import Booking from "./model";
const CREATE_ALLOWED = new Set([
"name",
"phone",
"email",
"numberOfPerson",
"totalPrice",
"paid",
"startDate",
"endDate",
"note",
"rooms",
"status",
"trackingId"
]);
const ALLOWED_QUERY = new Set([
"name",
"phone",
"email",
"startDate",
"endDate",
"status",
"page",
"limit",
"paginate",
"sortBy",
"trackingId",
"$in"
]);
const populate = { path: "rooms approvedBy", populate: { path: "room", select: "name" } };
export const createBooking = async (req: Req, res: Response) => {
try {
const isValid = Object.keys(req.body).every(k => CREATE_ALLOWED.has(k));
if (!isValid) return res.status(400).send({ status: 400, messae: "Invalid parameters provided" });
req.body.trackingId = uuid();
let data = req.body as BookingPayload;
const { startDate, endDate, rooms } = data;
const start = new Date(startDate);
const end = new Date(endDate);
const today = new Date().setHours(0, 0, 0, 0);
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
return res.status(400).send({ status: 400, message: "Invalid date format" });
}
if (start.getTime() < today) {
return res.status(400).send({ message: "Start date cannot be in the past date" });
}
if (end < start) {
return res.status(400).send({ message: "End date cannot be before start date" });
}
const overlappingBooking = await Booking.find({
startDate: { $lte: end },
endDate: { $gte: start }
})
.populate({ path: "rooms", populate: { path: "room", select: "name" } })
.lean();
// console.log(JSON.stringify());
return res.status(200).send("OK");
if (overlappingBooking.length > 0) {
const unavailableRooms = overlappingBooking.flatMap(booking => booking.rooms).map(room => room);
return res.status(400).send({ status: 400, message: "Some rooms are not available in the given date range", unavailableRooms });
}
const roomDocs = await find({
table: Room,
key: { query: { $in: rooms.map(room => room.room), paginate: "false" }, allowedQuery: ALLOWED_QUERY }
});
data.totalPrice = calculatePrice(roomDocs, data.rooms);
data.numberOfPerson = data.rooms.reduce((total, room) => room.guests + total, 0);
const booking = new Booking(data);
await booking.save();
await booking.populate({ path: "rooms", populate: { path: "room" } });
if (!booking) return res.status(503).send({ status: 503, message: "Failed to save booking, please try again later" });
return res.status(201).send({
status: 201,
message: "Booking created successfully",
data: { booking, trackingUrl: `${process.env.TRACKING_URL!}?trackingId=${booking.trackingId}` }
});
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const updateBooking = async (req: Req, res: Response) => {
try {
console.log(req.body);
const isValid = Object.keys(req.body).every(k => CREATE_ALLOWED.has(k));
if (!isValid) return res.status(400).send({ status: 400, message: "Invalid Parameters provided" });
const { id } = req.params;
if (id === "undefined" || !id || id.trim().length === 0) return res.status(400).send({ status: 400, message: "ID is required" });
let booking = await findOne({ table: Booking, key: { id } });
if (!booking) return res.status(404).send({ status: 404, message: "Booking not found" });
req.body.approvedBy = req?.user?.id;
booking = await update({ table: Booking, key: { id, body: req.body, populate } });
if (!booking) return res.status(503).send({ status: 503, message: "Failed to update booking,please try again later." });
return res.status(200).send({ status: 200, message: "Booking updated successfully", data: booking });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const getOneBooking = async (req: Req, res: Response) => {
try {
const { id } = req.params;
if (id === "undefined" || !id || id.trim().length === 0) return res.status(400).send({ status: 400, message: "ID is required" });
const booking = await findOne({ table: Booking, key: { id, populate } });
if (!booking) return res.status(404).send({ status: 404, message: "Booking not found" });
return res.status(200).send({ status: 200, message: "Booking retrieved successfully", data: booking });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const getAllBookings = async (req: Req, res: Response) => {
try {
const isValidQuery = Object.keys(req.query).every(k => ALLOWED_QUERY.has(k));
if (!isValidQuery) return res.status(400).send({ status: 400, message: "Query Validation Failed" });
const bookings = await find({ table: Booking, key: { query: req.query, allowedQuery: ALLOWED_QUERY, populate } });
return res.status(200).send({ status: 200, message: "Bookings retrieved successfully", data: bookings });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const deleteBooking = async (req: Req, res: Response) => {
try {
const { id } = req.params;
if (id === "undefined" || !id || id.trim().length === 0) return res.status(400).send({ status: 400, message: "ID is required" });
const booking = await findOne({ table: Booking, key: { id } });
if (!booking) return res.status(404).send({ status: 404, message: "Booking not found" });
await remove({ table: Booking, key: { id } });
return res.status(200).send({ status: 200, message: "Booking deleted successfully", data: booking });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const trackBooking = async (req: Req, res: Response) => {
try {
const { trackingId } = req.params;
if (!trackingId || trackingId === "") return res.status(400).send({ status: 400, message: "Tracking Id is required" });
const booking = await findOne({ table: Booking, key: { trackingId, populate } });
if (!booking) return res.status(404).send({ status: 404, message: "Booking not found" });
return res.status(200).send({ status: 200, message: "Booking retrieved successfully", data: booking });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const tempHold = async (req: Req, res: Response) => {
try {
if (!req?.body?.date) return res.status(400).send({ status: 400, message: "Date is required" });
const key = req.session;
if (Object.keys(req.body).length === 0) return res.status(400).send({ status: 400, message: "Body is empty" });
let rooms = req.body.rooms;
if (rooms.length === 0) return res.status(400).send({ status: 400, message: "No room id provided" });
const dateKey = new Date(new Date(req.body.date as string).setUTCHours(0, 0, 0, 0)).toISOString();
let roomsByDate = await redis.getValue(dateKey);
if (roomsByDate && JSON.parse(roomsByDate).length > 0) {
roomsByDate = Array.from(new Set([...JSON.parse(roomsByDate), ...rooms]));
await redis.setValue(dateKey, JSON.stringify(roomsByDate), 24 * 60 * 60);
} else await redis.setValue(dateKey, JSON.stringify(rooms), 24 * 60 * 60);
let holded = await redis.getValue(key!);
if (holded && JSON.parse(holded).length > 0) {
holded = JSON.parse(holded);
holded.forEach(async (h: string, index: number) => {
if (rooms.includes(h)) {
await redis.removeValue(h);
rooms = [];
holded.splice(index, 1);
}
});
if (rooms.length === 0 && holded.length === 0)
return res.status(200).send({ status: 200, message: "Holded room updated successfully", data: [] });
const holdExpirations = await Promise.all(
holded.map(async (hold: string) => ({
id: hold,
expiration: await redis.getExpirationTime(hold)
}))
);
holded = holdExpirations.filter(h => h.expiration > 0).map(h => h.id);
holded = Array.from(new Set([...holded, ...rooms]));
} else holded = [...rooms];
await redis.setValue(key!, JSON.stringify(holded));
await Promise.all(rooms.map(async (room: string) => await redis.setValue(room, room, 15 * 60)));
const holdedWithTime = await Promise.all(
holded.map(async (hold: string) => ({ id: hold, time: secondsToDhms(await redis.getExpirationTime(hold)) }))
);
return res.status(200).send({ status: 200, message: "Holded room updated successfully", data: holdedWithTime });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
export const getHoldRooms = async (req: Req, res: Response) => {
try {
if (!req.query.date) return res.status(400).send({ status: 400, message: "Date is required" });
const session = req.session;
const dateKey = new Date(new Date(req.query.date as string).setUTCHours(0, 0, 0, 0)).toISOString();
let roomsByDate = await redis.getValue(dateKey);
if (roomsByDate) roomsByDate = JSON.parse(roomsByDate);
else roomsByDate = [];
const allSessions = JSON.parse(await redis.getValue("sessions"));
let holds = await Promise.all(allSessions.map(async (s: string) => await redis.getValue(s)));
holds = holds.filter(h => h !== null);
holds = holds.map(h => JSON.parse(h)).flat();
holds = Array.from(new Set([...holds.map(h => h)]));
const holdExpirations = await Promise.all(
holds.map(async (hold: string) => ({
id: hold,
expiration: await redis.getExpirationTime(hold)
}))
);
holds = holdExpirations.filter(h => h.expiration > 0).map(h => h.id);
holds = holds.filter(h => roomsByDate.includes(h));
let ownHold = await redis.getValue(session!);
if (ownHold) {
ownHold = JSON.parse(ownHold);
ownHold = ownHold.filter((hold: string) => new Set(holds).has(hold));
ownHold = await Promise.all(ownHold.map(async (h: string) => ({ id: h, time: secondsToDhms(await redis.getExpirationTime(h)) })));
ownHold = ownHold.filter((hold: any) => roomsByDate.includes(hold.id));
} else ownHold = [];
return res.status(200).send({ status: 200, message: "Holds data retrieved", data: { totalHold: holds, holdByCurrentUser: ownHold } });
} catch (err) {
console.error(err);
return res.status(500).send({ status: 500, message: "Internal Server Error" });
}
};
Editor is loading...
Leave a Comment