UNPKG

@everytravel/shared

Version:

A comprehensive shared package for Everytravel containing Mongoose models and CRUD operations for hotel booking, user management, and transaction handling. Updated with improved model syntax and enhanced error handling.

103 lines (95 loc) 5.03 kB
import mongoose from "mongoose"; const { Schema } = mongoose; import { arrayOfStringsSanitizer, trimIfString, } from '../validation/index.js'; /** * Suite model for hotel properties. * * @typedef {Object} Suite * @property {ObjectId} property - Reference to the Property. * @property {String} roomType - Type of room (e.g., "suite", "apartment", "room"). * @property {Number} stars - Number of stars for the property. * @property {Number} rating - Average rating of the suite. * @property {ObjectId[]} reviews - References to Review documents. * @property {Object} location - Location details (address, city, country, zipCode, coordinates). * @property {Object} pricePerNight - Price per night details (from, to, currency). * @property {Number} sizeSqMeters - Size of the suite in square meters. * @property {Number} numBeds - Number of beds in the suite. * @property {String} bedType - Type of bed (e.g., "king", "queen", "twin"). * @property {Number} availabilityCount - Number of available suites. * @property {Number} sleeps - Number of people the suite can sleep. * @property {Number} numBathrooms - Number of bathrooms in the suite. * @property {String[]} features - Array of features (e.g., "wifi", "pool"). * @property {String[]} metaTags - Array of meta tags (e.g., "luxury", "budget"). */ const SuiteSchema = new Schema({ property: { type: Schema.Types.ObjectId, ref: 'Property' }, roomType: { type: String, enum: ['suite', 'room'], required: true, }, stars: { type: Number, min: 0, max: 5 },// 1-5 stars will programmatically be set based on reviews rating: { type: Number, min: 0, max: 5 },// 1-5 stars will programmatically be set based on reviews reviews: [{ type: Schema.Types.ObjectId, ref: 'Review' }], roomNumber: { type: String, set: trimIfString },// e.g. "101", "102", "103" pricePerNight: { from: { type: Number, min: 0 },// Minimum price per night to: { type: Number, min: 0, validate: { validator(value) { return value == null || this.pricePerNight?.from == null || value >= this.pricePerNight.from; }, message: 'pricePerNight.to must be >= pricePerNight.from' } },// Maximum price per night currency: { type: String, default: 'NGN' }// Currency of the price }, sizeSqMeters: { type: Number, min: 0 },// Size of the suite in square meters numBeds: { type: Number, min: 0 },// Number of beds in the suite bedType: { type: String, set: trimIfString },// Type of bed (e.g., "king", "queen", "twin") quantity: { type: Number, min: 0 },// Number of this particular suite in the property availabilityCount: { type: Number, min: 0 },// Number of this particular suite that is available for booking sleeps: { type: Number, min: 0 }, // should be compatible with guests number in Booking numBathrooms: { type: Number, min: 0 },// Number of bathrooms in the suite show: { type: Boolean, default: true },// Whether the suite is visible to the public softDeleted: { type: Boolean, default: false },// Whether the suite is deleted (soft delete) deletedAt: Date,// When the suite was deleted (for soft delete) features: { type: [String], set: arrayOfStringsSanitizer }, metaTags: { type: [String], set: arrayOfStringsSanitizer }, refundPolicy: { zero: { name: { type: String, required: true }, description: String, refundPercentage: { type: Number, default: 0 } }, full: { name: { type: String, required: true }, description: String, refundPercentage: { type: Number, default: 100 } }, partial: { name: { type: String, required: true }, description: String, refundPercentage: { type: Number, default: 75 } } }, images: [{ url: { type: String, set: trimIfString, validate: { validator: (v) => v === undefined || v === null || isNonEmptyString(v), message: 'images.url must be a non-empty string' } }, tags: { type: [String], set: arrayOfStringsSanitizer }, order: { type: Number, min: 0 }, isCover: { type: Boolean, default: false }, }], }); // Indexes to optimize common queries // - Public visibility filters SuiteSchema.index({ show: 1, softDeleted: 1 }); // - Property scoping and soft-deletion checks SuiteSchema.index({ property: 1, softDeleted: 1 }); // - Common filters and sorting keys SuiteSchema.index({ roomType: 1 }); SuiteSchema.index({ 'pricePerNight.from': 1 }); SuiteSchema.index({ sizeSqMeters: 1 }); SuiteSchema.index({ numBeds: 1 }); SuiteSchema.index({ numBathrooms: 1 }); SuiteSchema.index({ sleeps: 1 }); SuiteSchema.index({ availabilityCount: 1 }); SuiteSchema.index({ metaTags: 1 }); // multikey SuiteSchema.index({ features: 1 }); // multikey const Suite = mongoose.model('Suite', SuiteSchema); export default Suite;