Introducing Table, the successor to Table Mini! This backend helps customers make reservations for a table at a restaurant of their choice.
The solution branch contains documented solution code. The commit history of that branch follows the instructions below.
- Create a new repository using this one as a template.
- Configure your
.env
file. Usetable
as the name of the database for this activity.
textual representation of schema in DBML
-
Create the
Restaurant
,Reservation
, andCustomer
models in the Prisma schema. Refer to the Prisma docs on many-to-many relations.- One Restaurant can have many Reservations.
- There is an implicit many-to-many relation between Reservations and Customers.
- One Customer can have many Reservations.
- One Reservation can have many Customers.
- Reservation is the relation table for the explicit many-to-many relation between Restaurants and Customers.
See Solution
model Restaurant { id Int @id @default(autoincrement()) name String reservations Reservation[] } model Reservation { id Int @id @default(autoincrement()) date String restaurant Restaurant @relation(fields: [restaurantId], references: [id]) restaurantId Int party Customer[] } model Customer { id Int @id @default(autoincrement()) name String email String reservations Reservation[] }
-
Create the initial migration with
npx prisma migrate dev
.
Write the following code in the seed
function.
-
Create 3 restaurants.
See Solution
const restaurants = Array.from({ length: numRestaurants }, (_, i) => ({ name: `Restaurant ${i + 1}`, })); await prisma.restaurant.createMany({ data: restaurants });
-
Create 5 customers.
See Solution
const customers = Array.from({ length: numCustomers }, (_, i) => ({ name: `Customer ${i + 1}`, email: `customer${i + 1}@foo.bar`, })); await prisma.customer.createMany({ data: customers });
-
Read the Prisma example on connecting a new record to multiple existing records.
-
Create 8 reservations that are each connected to a single restaurant and multiple customers. In each iteration:
- Generate a random integer between 1 and 3, inclusive. This will be the number of customers in this reservation.
- Create an array of that length. It should be filled with objects. Each object should have an
id
key. The value of that key should be a random customer id. - Create a new reservation with a random restaurant id. You can use an arbitrary date. Use the array you created to connect it to the corresponding customers.
See Sample Solution
for (let i = 0; i < numReservations; i++) { // Size of party randomly in [1,3] const partySize = 1 + Math.floor(Math.random() * 3); // Create array of objects w/ random customer ids const party = Array.from({ length: partySize }, () => ({ id: 1 + Math.floor(Math.random() * numCustomers), })); // Create a new reservation w/ random id and connect to customers in party await prisma.reservation.create({ data: { date: new Date().toDateString(), restaurantId: 1 + Math.floor(Math.random() * numRestaurants), party: { connect: party }, }, }); }
The API for this activity will only serve one route, so there is no need for a separate router file. In server.js
, add a handler for POST /reservations
.
- The request body should include
date
,restaurantId
andcustomerIds
, which will be an array of numbers. - A reservation should be created for the specific restaurant and connected to the specified customers.
- Send the newly created reservation as a response with status 201. This should include the restaurant and customers.
See Solution
const prisma = require("./prisma");
app.post("/reservations", async (req, res, next) => {
try {
const { date, restaurantId, customerIds } = req.body;
// Converts array of ids into shape needed for `connect`
const party = customerIds.map((id) => ({ id: +id }));
const reservation = await prisma.reservation.create({
data: {
date,
restaurantId: +restaurantId,
party: { connect: party },
},
include: {
restaurant: true,
party: true,
},
});
res.status(201).json(reservation);
} catch (e) {
next(e);
}
});