import * as mongoose from 'mongoose' import { v4 as uuidv4 } from 'uuid' import { startOfDay } from 'date-fns' import { dateFormatBackend, getDays } from '../helpers/date' import { Bill } from './bill' import { Booker } from './booker' import { BOOKING_STATUS } from './enums' export interface Booking { uuid: string booker: Booker bill: Bill startDate: Date endDate: Date status: BOOKING_STATUS purpose?: string org?: string destination?: string days?: string[] } export interface BookingDocument extends Booking, mongoose.Document, mongoose.SchemaTimestampsConfig {} export interface BookingModel extends mongoose.Model { findBookedDays(): Promise } const BookingSchema = new mongoose.Schema( { // need a seperate uuid to be able to target a booking anonimously uuid: { type: String, default: uuidv4, index: true, }, booker: { type: mongoose.Schema.Types.ObjectId, ref: 'Booker', required: true, }, bill: { type: mongoose.Schema.Types.ObjectId, ref: 'Bill', required: false, }, startDate: { type: Date, required: true, get: dateFormatBackend, min: new Date(), }, endDate: { type: Date, required: false, get: dateFormatBackend, min: new Date(), }, days: { type: [String], required: true, }, status: { type: String, enum: Object.values(BOOKING_STATUS), required: true, default: 'requested', }, purpose: { type: String, required: false }, org: { type: String, required: false }, destination: { type: String, required: false }, }, { timestamps: true, toJSON: { virtuals: true, getters: true }, toObject: { virtuals: true, getters: true }, } ) BookingSchema.pre('save', function (next) { const booking = this as BookingDocument booking.days = getDays({ startDate: new Date(booking.startDate), endDate: new Date(booking.endDate), }) next() }) BookingSchema.static('findBookedDays', async function (): Promise { const model = this as BookingModel const bookedDays = await model .find( { status: { $in: [BOOKING_STATUS.REQUESTED, BOOKING_STATUS.CONFIRMED] }, endDate: { $gt: startOfDay(new Date()) }, }, 'days' ) .exec() return bookedDays .map((b) => b.days) .flat() .sort() }) export default mongoose.models.Booking || mongoose.model('Booking', BookingSchema)