diff --git a/backend/src/controllers/booking.controller.ts b/backend/src/controllers/booking.controller.ts new file mode 100644 index 0000000..ca66af1 --- /dev/null +++ b/backend/src/controllers/booking.controller.ts @@ -0,0 +1,49 @@ +import { Request, Response } from 'express'; +import { ResponseStatusCodes } from '../types/ResponseStatusCodes.types'; +import { logger } from '../middlewares/logger.middleware'; +import Validator from '../utils/Validator.utils'; +import bookingRepo from '../database/repositories/booking.repo'; + +class BookingController { + async bookItinerary(req: Request, res: Response) { + try { + Validator.validateId(req.body.itinerary_id, 'incorrect itinerary id'); + + const booking = await bookingRepo.bookItinerary(req.user.userId, req.body.itinerary_id); + + const response = { + message: 'Booking successful', + data: { booking: booking }, + }; + + res.status(ResponseStatusCodes.CREATED).send(response); + } catch (error: any) { + logger.error(`Error occurred while booking itinerary: ${error.message}`); + res.status(ResponseStatusCodes.INTERNAL_SERVER_ERROR).send({ + message: `Error occurred while booking itinerary: ${error.message}`, + }); + } + } + + async bookActivity(req: Request, res: Response) { + try { + Validator.validateId(req.body.activity_id, 'incorrect activity id'); + + const booking = await bookingRepo.bookActivity(req.user.userId, req.body.activity_id); + + const response = { + message: 'Booking successful', + data: { booking: booking }, + }; + + res.status(ResponseStatusCodes.CREATED).send(response); + } catch (error: any) { + logger.error(`Error occurred while booking activity: ${error.message}`); + res.status(ResponseStatusCodes.INTERNAL_SERVER_ERROR).send({ + message: `Error occurred while booking activity: ${error.message}`, + }); + } + } +} + +export default new BookingController(); diff --git a/backend/src/database/models/booking.model.ts b/backend/src/database/models/booking.model.ts new file mode 100644 index 0000000..aa30c4c --- /dev/null +++ b/backend/src/database/models/booking.model.ts @@ -0,0 +1,31 @@ +import { model, Schema } from 'mongoose'; + +const bookingSchema = new Schema( + { + user: { + type: Schema.Types.ObjectId, + ref: 'user', + required: true, + }, + itinerary: { + type: Schema.Types.ObjectId, + ref: 'itinerary', + }, + activity: { + type: Schema.Types.ObjectId, + ref: 'activity', + }, + status: { + type: String, + enum: ['pending', 'confirmed', 'attended', 'cancelled'], + default: 'pending', + }, + }, + { + timestamps: true, + } +); + +const Booking = model('booking', bookingSchema); + +export { bookingSchema, Booking }; diff --git a/backend/src/database/models/user.model.ts b/backend/src/database/models/user.model.ts index 1a9a013..6302848 100644 --- a/backend/src/database/models/user.model.ts +++ b/backend/src/database/models/user.model.ts @@ -82,6 +82,12 @@ const userSchema = new mongoose.Schema( average_rating: { type: Number, }, + itinerary_bookings: { + type: [{ type: Schema.Types.ObjectId, ref: 'booking' }], + }, + activity_bookings: { + type: [{ type: Schema.Types.ObjectId, ref: 'booking' }], + }, modified_by: { type: Schema.Types.ObjectId, ref: 'user', diff --git a/backend/src/database/repositories/booking.repo.ts b/backend/src/database/repositories/booking.repo.ts new file mode 100644 index 0000000..4f6b20e --- /dev/null +++ b/backend/src/database/repositories/booking.repo.ts @@ -0,0 +1,20 @@ +import { Booking } from '../models/booking.model'; +import { User } from '../models/user.model'; + +class BookingRepo { + async bookItinerary(userId: string, itineraryId: string) { + const booking = await Booking.create({ user: userId, itinerary: itineraryId }); + await User.findByIdAndUpdate(userId, { $push: { itinerary_bookings: booking._id } }); + + return booking; + } + + async bookActivity(userId: string, activityId: string) { + const booking = await Booking.create({ user: userId, activity: activityId }); + await User.findByIdAndUpdate(userId, { $push: { activity_bookings: booking._id } }); + + return booking; + } +} + +export default new BookingRepo(); diff --git a/backend/src/routes/activity.route.ts b/backend/src/routes/activity.route.ts index f736bdc..47a993d 100644 --- a/backend/src/routes/activity.route.ts +++ b/backend/src/routes/activity.route.ts @@ -7,9 +7,12 @@ import { createActivity, getActivitiesByCreator, } from '../controllers/activity.controller'; +import BookingController from '../controllers/booking.controller'; const activityRouter = Router(); +activityRouter.post('/bookings', BookingController.bookActivity); + activityRouter.get('/', getAllActivities); activityRouter.get('/mine', getActivitiesByCreator); activityRouter.get('/:id', getActivityById); diff --git a/backend/src/routes/itinerary.route.ts b/backend/src/routes/itinerary.route.ts index 6db40a6..5de56fb 100644 --- a/backend/src/routes/itinerary.route.ts +++ b/backend/src/routes/itinerary.route.ts @@ -10,9 +10,12 @@ import { toggleItineraryActive, flagItinerary, } from '../controllers/itinerary.controller'; +import BookingController from '../controllers/booking.controller'; const itineraryRouter = Router(); +itineraryRouter.post('/bookings', BookingController.bookItinerary); + itineraryRouter.get('/get', getItineraries); itineraryRouter.get('/mine', getItinerariesCreatedByUser); itineraryRouter.get('/:id', findItineraryById); diff --git a/backend/src/types/User.types.ts b/backend/src/types/User.types.ts index 70ca860..5b612f3 100644 --- a/backend/src/types/User.types.ts +++ b/backend/src/types/User.types.ts @@ -1,3 +1,5 @@ +import { Types } from 'mongoose'; + export enum accountType { Admin = 'Admin', Tourist = 'Tourist', @@ -35,4 +37,5 @@ export interface UserType { // Tourist loyalty_points: number; wallet?: number; + itinerary_bookings: [Types.ObjectId]; }