UNPKG

@ideal-photography/shared

Version:

Shared MongoDB and utility logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, audit logs, minimart items/orders, and push notification subscriptions.

204 lines (192 loc) 5.34 kB
import mongoose from 'mongoose'; const bookingSchema = new mongoose.Schema({ bookingNumber: { type: String, required: true, unique: true }, userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, orderId: { type: mongoose.Schema.Types.ObjectId, ref: 'Order', required: true }, // Service details serviceType: { type: String, required: true, enum: ['makeover', 'studio', 'service'] }, serviceName: { type: String, required: true }, // Booking schedule preferredDate: { type: Date, required: true }, preferredTime: { type: String, required: true }, duration: { type: Number, // in hours required: true }, // Location details location: { type: String, required: true }, address: { street: String, city: String, state: String, zipCode: String, country: { type: String, default: 'Nigeria' } }, // Special requirements specialInstructions: String, requirements: [String], // Booking status status: { type: String, enum: ['pending', 'confirmed', 'in_progress', 'completed', 'cancelled', 'rescheduled', 'overdue', 'auto_completed'], default: 'pending' }, // Metadata for automated transitions metadata: { autoTransitioned: { type: Boolean, default: false }, autoTransitionedAt: Date }, // Confirmation details confirmedDate: Date, confirmedTime: String, confirmedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, // Completion details completedAt: Date, completedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, // Cancellation details cancelledAt: Date, cancelledBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, cancellationReason: String, // Rescheduling details rescheduledFrom: { date: Date, time: String }, rescheduledAt: Date, rescheduledBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, rescheduleReason: String, // Notes and feedback notes: String, customerFeedback: String, staffNotes: String, // Timestamps createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now } }, { timestamps: true }); // Indexes (bookingNumber already has unique index from schema definition) bookingSchema.index({ userId: 1 }); bookingSchema.index({ orderId: 1 }); bookingSchema.index({ status: 1 }); bookingSchema.index({ preferredDate: 1 }); bookingSchema.index({ serviceType: 1 }); // Method to generate booking number bookingSchema.statics.generateBookingNumber = function () { const timestamp = Date.now().toString(36); const random = Math.random().toString(36).substr(2, 5); return `BK-${timestamp}-${random}`.toUpperCase(); }; // Method to confirm booking bookingSchema.methods.confirm = function (confirmedBy, confirmedDate = null, confirmedTime = null) { this.status = 'confirmed'; this.confirmedBy = confirmedBy; this.confirmedDate = confirmedDate || this.preferredDate; this.confirmedTime = confirmedTime || this.preferredTime; this.updatedAt = new Date(); return this; }; // Method to start booking bookingSchema.methods.start = function (startedBy) { this.status = 'in_progress'; this.updatedAt = new Date(); return this; }; // Method to complete booking bookingSchema.methods.complete = function (completedBy, notes = null) { this.status = 'completed'; this.completedAt = new Date(); this.completedBy = completedBy; if (notes) { this.staffNotes = notes; } this.updatedAt = new Date(); return this; }; // Method to cancel booking bookingSchema.methods.cancel = function (cancelledBy, reason = null) { this.status = 'cancelled'; this.cancelledAt = new Date(); this.cancelledBy = cancelledBy; if (reason) { this.cancellationReason = reason; } this.updatedAt = new Date(); return this; }; // Method to reschedule booking bookingSchema.methods.reschedule = function (newDate, newTime, rescheduledBy, reason = null) { this.rescheduledFrom = { date: this.preferredDate, time: this.preferredTime }; this.preferredDate = newDate; this.preferredTime = newTime; this.status = 'rescheduled'; this.rescheduledAt = new Date(); this.rescheduledBy = rescheduledBy; if (reason) { this.rescheduleReason = reason; } this.updatedAt = new Date(); return this; }; // Method to check if booking is active bookingSchema.methods.isActive = function () { return ['pending', 'confirmed', 'in_progress'].includes(this.status); }; // Method to check if booking is completed bookingSchema.methods.isCompleted = function () { return this.status === 'completed'; }; // Method to check if booking is cancelled bookingSchema.methods.isCancelled = function () { return this.status === 'cancelled'; }; export default mongoose.model('Booking', bookingSchema);