import mongoose from "mongoose"; const PromotionSchema = new mongoose.Schema( { storeId: { type: mongoose.Schema.Types.ObjectId, ref: "Store", required: [true, "Store ID is required"] }, code: { type: String, required: [true, "Promotion code is required"], trim: true, uppercase: true, minlength: [3, "Promotion code must be at least 3 characters"], maxlength: [20, "Promotion code cannot exceed 20 characters"] }, discountType: { type: String, required: [true, "Discount type is required"], enum: { values: ["percentage", "fixed"], message: "Discount type must be either percentage or fixed" } }, discountValue: { type: Number, required: [true, "Discount value is required"], validate: { validator: function(value) { if (this.discountType === "percentage") { return value > 0 && value <= 100; } return value > 0; }, message: props => props.value <= 0 ? "Discount value must be greater than 0" : "Percentage discount cannot exceed 100%" } }, minOrderAmount: { type: Number, default: 0, min: [0, "Minimum order amount cannot be negative"] }, maxUsage: { type: Number, default: null }, usageCount: { type: Number, default: 0 }, isActive: { type: Boolean, default: true }, startDate: { type: Date, default: Date.now }, endDate: { type: Date, default: null }, description: { type: String, trim: true, maxlength: [200, "Description cannot exceed 200 characters"] } }, { timestamps: true } ); // Compound index to ensure unique promo codes per store PromotionSchema.index({ storeId: 1, code: 1 }, { unique: true }); // Check if a promotion is valid and can be applied PromotionSchema.methods.isValid = function() { const now = new Date(); // Check if promotion is active if (!this.isActive) return false; // Check if promotion has expired if (this.endDate && now > this.endDate) return false; // Check if promotion has reached max usage (if set) if (this.maxUsage !== null && this.usageCount >= this.maxUsage) return false; return true; }; // Calculate discount amount for a given order total PromotionSchema.methods.calculateDiscount = function(orderTotal) { if (!this.isValid()) { return 0; } if (orderTotal < this.minOrderAmount) { return 0; } let discountAmount = 0; if (this.discountType === "percentage") { discountAmount = (orderTotal * this.discountValue) / 100; } else { // Fixed amount discount discountAmount = this.discountValue; // Ensure discount doesn't exceed order total if (discountAmount > orderTotal) { discountAmount = orderTotal; } } return parseFloat(discountAmount.toFixed(2)); }; const Promotion = mongoose.model("Promotion", PromotionSchema); export default Promotion;