const mongoose = require('mongoose'); const Counter = require('./counterModel'); const orderSchema = new mongoose.Schema( { orderNumber: { type: Number, unique: true, }, user: { type: mongoose.Schema.ObjectId, ref: 'User', required: false, }, name: { type: String, required: [true, 'Customer name is required'], trim: true, }, mobile: { type: String, required: [true, 'Mobile number is required'], trim: true, }, address: { governorate: { type: String, required: [true, 'Governorate is required'], trim: true, }, city: { type: String, required: [true, 'City is required'], trim: true, }, district: { type: String, required: [true, 'District is required'], trim: true, }, street: { type: String, required: [true, 'Street is required'], trim: true, }, }, items: [ { product: { type: mongoose.Schema.ObjectId, ref: 'Product' }, name: String, quantity: { type: Number, min: 1, default: 1 }, unitPrice: Number, fulfillmentStatus: { type: String, enum: ['pending', 'preparing', 'ready', 'cancelled'], default: 'pending', }, }, ], payment: { method: { type: String, enum: ['cash', 'visa'], required: [true, 'Payment method is required'], }, status: { type: String, enum: ['pending', 'paid', 'failed'], default: 'pending', }, paidAt: { type: Date, required: false, }, paymobTransactionId: { type: String, required: false, }, paymobOrderId: { type: String, required: false, }, paymentKey: { type: String, required: false, }, frontendUrl: { type: String, required: false, }, refundedAt: { type: Date, required: false, }, refundAmount: { type: Number, required: false, }, }, promoCode: { type: String, trim: true, }, promo: { type: mongoose.Schema.ObjectId, ref: 'PromoCode', required: false, }, discountAmount: { type: Number, default: 0, }, discountType: { type: String, enum: ['percentage', 'fixed'], required: false, }, images: [ { filename: String, url: String, contentType: String, }, ], totalPrice: { type: Number, required: [true, 'Total price is required'], min: [0, 'Total price must be positive'], }, orderStatus: { type: String, enum: ['created', 'processing', 'shipped', 'cancelled', 'completed'], default: 'created', }, canceledAt: { type: Date, required: false, }, notes: { type: String, trim: true, }, estimatedDeliveryDate: { type: Date, }, shippingPrice: { type: Number, default: 0, }, source: { type: String, trim: true, default: 'direct', }, }, { timestamps: true, }, ); orderSchema.pre('save', async function (next) { if (!this.isNew) return next(); try { const counter = await Counter.findOneAndUpdate( { id: 'orderNumber' }, { $inc: { seq: 1 } }, { new: true, upsert: true }, ); this.orderNumber = counter.seq; next(); } catch (error) { next(error); } }); orderSchema.index({ user: 1, createdAt: -1 }); orderSchema.index({ orderStatus: 1 }); orderSchema.index({ createdAt: -1 }); orderSchema.index({ orderNumber: 1 }); const Order = mongoose.model('Order', orderSchema); module.exports = Order;