Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 36 additions & 20 deletions api/modules/bookings/bookingRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,42 @@ export async function createBooking({ userId, deskId, date }) {
till.setUTCHours(19, 0, 0, 0);
const toDate = till.toISOString();

const { rows } = await db.query(
sql`
WITH new_booking AS (
INSERT INTO booking (user_id, desk_id, from_date, to_date)
VALUES ($1, $2, $3, $4)
RETURNING *)
SELECT
b.id AS booking_id,
b.desk_id, b.user_id,
b.from_date, b.to_date,
u.first_name, u.last_name,
d.name AS desk_name
FROM
new_booking b
JOIN "user" u ON b.user_id = u.id
JOIN desk d ON b.desk_id = d.id
`,
[userId, deskId, date, toDate],
);
return rows[0];
try {
const { rows } = await db.query(
sql`
WITH new_booking AS (
INSERT INTO booking (user_id, desk_id, from_date, to_date)
VALUES ($1, $2, $3, $4)
ON CONFLICT DO NOTHING
RETURNING *)
SELECT
b.id AS booking_id,
b.desk_id, b.user_id,
b.from_date, b.to_date,
u.first_name, u.last_name,
d.name AS desk_name
FROM
new_booking b
JOIN "user" u ON b.user_id = u.id
JOIN desk d ON b.desk_id = d.id
`,
[userId, deskId, date, toDate],
);

// If no rows returned, it means there was a conflict
if (rows.length === 0) {
return null;
}

return rows[0];
} catch (error) {
// Handle constraint violation errors
if (error.code === "23514") {
// Check constraint violation
return null;
}
throw error;
}
}

export async function getFilteredBookings({ from, to, userId }) {
Expand Down
13 changes: 12 additions & 1 deletion api/modules/bookings/bookingService.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,18 @@ export async function handleCreateBooking({ userId, deskId, date }) {
StatusCodes.CONFLICT,
);
}
return await createBooking({ userId, deskId, date: date });

const booking = await createBooking({ userId, deskId, date: date });

// If createBooking returns null, it means there was a conflict
if (!booking) {
throw new ApiError(
"Desk is already booked for this date or time range.",
StatusCodes.CONFLICT,
);
}

return booking;
}

export async function getBookingById(id) {
Expand Down
7 changes: 7 additions & 0 deletions script.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ CREATE DATABASE deskeando;

\c deskeando;

-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE "desk"(
id uuid default uuid_generate_v4() PRIMARY KEY,
"name" text not null
Expand All @@ -24,6 +27,10 @@ CREATE TABLE "booking"(
"to_date" timestamp with time zone not null
);

-- Prevent two users from booking the same desk at the same time
-- This ensures only one booking per desk per date
CREATE UNIQUE INDEX unique_desk_date ON booking (desk_id, from_date);


INSERT INTO "desk" (id, name) VALUES
('b142a09d-76f7-4140-a401-52a7bc5f22c5','Desk 1'),
Expand Down
Loading