From 3faa89a749e1a10dcb84affa94114b4f16fbb6ef Mon Sep 17 00:00:00 2001 From: Tobias Zoghaib Date: Wed, 23 Oct 2024 13:36:21 +0200 Subject: [PATCH] Display free tickets in standing areas --- .../models/locations/location.model.ts | 3 +++ software/backend/routes/concert.routes.ts | 27 ++++++++++++++++++- software/backend/routes/exercise.routes.ts | 10 +++++++ software/backend/routes/genre.routes.ts | 3 +++ software/backend/routes/location.routes.ts | 21 ++++++++++++++- software/backend/scripts/databaseHelper.ts | 16 +++++++++++ .../components/seatPlanMap/standingArea.vue | 2 +- .../data/models/locations/locationModel.ts | 1 + .../data/models/locations/seatGroupModel.ts | 1 + 9 files changed, 81 insertions(+), 3 deletions(-) diff --git a/software/backend/models/locations/location.model.ts b/software/backend/models/locations/location.model.ts index c42a816..95b5b77 100644 --- a/software/backend/models/locations/location.model.ts +++ b/software/backend/models/locations/location.model.ts @@ -33,6 +33,9 @@ export class Location extends Model { @Column layout: number + @Column + capacity: number + // Relations diff --git a/software/backend/routes/concert.routes.ts b/software/backend/routes/concert.routes.ts index c23c142..cca6830 100644 --- a/software/backend/routes/concert.routes.ts +++ b/software/backend/routes/concert.routes.ts @@ -38,6 +38,7 @@ concert.get("/", (req: Request, res: Response) => { }) +// Get all available data about a band by it's ID concert.get("/concert/:id", (req: Request, res: Response) => { Concert.findByPk(req.params.id, { include: [ @@ -79,14 +80,22 @@ concert.get("/concert/:id", (req: Request, res: Response) => { } }) .then(concert => { + concert.dataValues["capacity"] = 0 + + // Go through every seat group for (let seatGroup of concert.dataValues.location.dataValues.seatGroups) { seatGroup.dataValues["occupied"] = 0 + // Go through every seat row for (let seatRow of seatGroup.dataValues.seatRows) { for (let seat of seatRow.dataValues.seats) { seat.dataValues["state"] = 0 + concert.dataValues["inStock"] += 1 + // Go through every seat for (let ticket of seat.dataValues.tickets) { + // Check if the seat is occupied through a ticket + // If yes, reduce number of available seats if (ticket.dataValues.concertId == req.params.id) { seat.dataValues["state"] = 1 seatGroup.dataValues["occupied"] += 1 @@ -109,19 +118,35 @@ concert.get("/search", (req: Request, res: Response) => { Concert.findAll({ where: { [Op.or]: [ + // Search by name of concert { name: { [Op.substring]: req.query.value } }, + + // Search by name of band { "$band.name$": { [Op.substring]: req.query.value } + }, + + // Search by name of city of location + { + "$location.city.name$": { + [Op.substring]: req.query.value + } } ] }, - include: [ Band, Location ] + include: [ + Band, + { + model: Location, + include: [ City ] + } + ] }) .then(concerts => { res.status(200).json(concerts) diff --git a/software/backend/routes/exercise.routes.ts b/software/backend/routes/exercise.routes.ts index dbb93f1..f22da61 100644 --- a/software/backend/routes/exercise.routes.ts +++ b/software/backend/routes/exercise.routes.ts @@ -4,6 +4,9 @@ import { Request, Response, Router } from "express"; export const exercises = Router() +/** + * Get all Exercises grouped in ExerciseGroups + */ exercises.get("/", (req: Request, res: Response) => { ExerciseGroup.findAll( { @@ -22,6 +25,13 @@ exercises.get("/", (req: Request, res: Response) => { }) }) +/** + * Update state of an Exercise + * + * @param groupNr Number of exercise group (not ID) + * @param exerciseNr Number of exercise (not ID) + * @param state New state boolean + */ exercises.post("/:groupNr/:exerciseNr/:state", (req: Request, res: Response) => { ExerciseGroup.findOne({ where: { groupNr: req.params.groupNr } diff --git a/software/backend/routes/genre.routes.ts b/software/backend/routes/genre.routes.ts index 166cbaa..131367d 100644 --- a/software/backend/routes/genre.routes.ts +++ b/software/backend/routes/genre.routes.ts @@ -5,6 +5,9 @@ import { Request, Response, Router } from "express"; export const genre = Router() +/** + * Get all available Genres + */ genre.get("/", (req: Request, res: Response) => { Genre.findAll() .then(genres => { diff --git a/software/backend/routes/location.routes.ts b/software/backend/routes/location.routes.ts index b0ea789..cda05ef 100644 --- a/software/backend/routes/location.routes.ts +++ b/software/backend/routes/location.routes.ts @@ -10,6 +10,12 @@ import { Op } from "sequelize"; export const location = Router() +/** + * Get all available Locations + * + * @query sort Sort results ascending (asc) or descending (desc) + * @query count Limit number of results + */ location.get("/", (req: Request, res: Response) => { let sort = req.query.sort let count = req.query.count @@ -52,6 +58,12 @@ location.get("/", (req: Request, res: Response) => { }) }) + +/** + * Get all data about a specific location + * + * @param urlName UrlName of the band (e.g. Red Hot Chili Peppers => red-hot-chili-peppers) + */ location.get("/location/:urlName", (req: Request, res: Response) => { Location.findOne({ where: { urlName: req.params.urlName }, @@ -89,16 +101,23 @@ location.get("/location/:urlName", (req: Request, res: Response) => { }) -// Location search +/** + * Search for Locations + * + * @query value Search term to look for + */ location.get("/search", (req: Request, res: Response) => { Location.findAll({ where: { [Op.or]: [ + // Search by name of location { name: { [Op.substring]: req.query.value }, }, + + // Search by name of city { "$city.name$": { [Op.substring]: req.query.value diff --git a/software/backend/scripts/databaseHelper.ts b/software/backend/scripts/databaseHelper.ts index 2a71cb0..a9cc106 100644 --- a/software/backend/scripts/databaseHelper.ts +++ b/software/backend/scripts/databaseHelper.ts @@ -91,6 +91,8 @@ export async function prepopulateDatabase() { await Location.create(location) .then(async locationDataset => { + let capacity = 0 + for (let seatGroup of location.seatGroups) { seatGroup["locationId"] = locationDataset.id @@ -131,6 +133,8 @@ export async function prepopulateDatabase() { seatNr: i + 1, seatRowId: seatRowRes.id }) + + capacity++ } }) } @@ -147,12 +151,24 @@ export async function prepopulateDatabase() { seatNr: col, seatRowId: seatRowRes.id }) + + capacity++ } }) } } }) } + + // Update capacity of location + await Location.update( + { capacity: capacity }, + { + where: { + id: locationDataset.dataValues.id + } + } + ) }) } }) diff --git a/software/src/components/seatPlanMap/standingArea.vue b/software/src/components/seatPlanMap/standingArea.vue index 3bbb053..c6cf8d7 100644 --- a/software/src/components/seatPlanMap/standingArea.vue +++ b/software/src/components/seatPlanMap/standingArea.vue @@ -62,7 +62,7 @@ function handleSeatClick() { - {{ seatGroup.capacity }} {{ $t('standingPlaces') }} + {{ seatGroup.capacity - seatGroup.occupied }} {{ $t('standingPlaces') }} diff --git a/software/src/data/models/locations/locationModel.ts b/software/src/data/models/locations/locationModel.ts index 1623b74..7d8c43f 100644 --- a/software/src/data/models/locations/locationModel.ts +++ b/software/src/data/models/locations/locationModel.ts @@ -4,5 +4,6 @@ export class LocationModel { address: string = "" imageIndoor: string = "" imageOutdoor: string = "" + capacity: number = 0 layout: number = 1 } \ No newline at end of file diff --git a/software/src/data/models/locations/seatGroupModel.ts b/software/src/data/models/locations/seatGroupModel.ts index 73cf90e..51eee1f 100644 --- a/software/src/data/models/locations/seatGroupModel.ts +++ b/software/src/data/models/locations/seatGroupModel.ts @@ -5,5 +5,6 @@ export class SeatGroupModel { surcharge: number = 0 standingArea: boolean = false capacity: number = 0 + occupied: number = 0 seatRows: Array } \ No newline at end of file