import { Schema, model } from "mongoose"; import { IDimensions, IPrice, IProductVariant, ISaleFormat, IStatistics } from "./Abstraction/IProductVariant"; import { ProductMarketStatus } from "../../../common/enums/product.enum"; const productStatisticsSchema = new Schema( { satisfied: { type: { rate: Number, count: Number } }, dissatisfied: { type: { rate: Number, count: Number } }, }, { _id: false }, ); const productSaleFormat = new Schema( { // isWholeSale: Boolean, wholeSale: { type: [{ from: Number, to: Number, price: Number }] }, }, { _id: false }, ); export const productDimensionsSchema = new Schema( { package_weight: Number, package_height: Number, package_length: Number, package_width: Number, }, { _id: false }, ); const productPriceSchema = new Schema( { order_limit: { type: Number, required: true }, retailPrice: { type: Number }, selling_price: { type: Number }, //specialSale is_specialSale: { type: Boolean, default: false }, discount_percent: { type: Number, default: 0 }, specialSale_order_limit: { type: Number, default: null }, specialSale_quantity: { type: Number, default: null }, specialSale_endDate: { type: String, default: null }, }, { _id: false }, ); const productVariantSchema = new Schema( { product: { type: Number, ref: "Product", required: true }, statistics: { type: productStatisticsSchema }, warranty: { type: Number, ref: "Warranty", required: true }, shop: { type: Schema.Types.ObjectId, ref: "Shop", required: true }, market_status: { type: String, enum: ProductMarketStatus, required: true }, postingTime: { type: Number, required: true }, price: { type: productPriceSchema, required: true }, stock: { type: Number, required: true }, isFreeShip: { type: Boolean, default: false }, isWholeSale: { type: Boolean, default: false }, saleFormat: { type: productSaleFormat }, dimensions: { type: productDimensionsSchema, required: true }, sellerSpecialCode: { type: String }, themeValue: { type: Schema.Types.ObjectId, ref: "ThemeValue", required: true }, deleted: { type: Boolean, default: false }, }, { timestamps: true, toObject: { virtuals: true, versionKey: false }, toJSON: { virtuals: true, versionKey: false }, id: false }, ); productVariantSchema.index({ product: 1, deleted: 1 }); productVariantSchema.index({ shop: 1, product: 1, deleted: 1 }); productVariantSchema.index({ market_status: 1, deleted: 1 }); productVariantSchema.pre("save", function (next) { if (this.price) { if (this.price.retailPrice) { this.price.retailPrice = Number(this.price.retailPrice); const sellingPrice = this.price.discount_percent > 0 ? this.price.retailPrice * ((100 - this.price.discount_percent) / 100) : this.price.retailPrice; this.price.selling_price = Number(sellingPrice); } } next(); }); productVariantSchema.pre(["findOneAndUpdate", "updateOne", "updateMany"], function (next) { const update = this.getUpdate() as IProductVariant; if (!update) return next(); // ensure price object exists in the update object if (update.price && update.price.retailPrice !== undefined) { const retailPrice = Number(update.price.retailPrice); const discountPercent = update.price.discount_percent || 0; // calculate selling price based on retailPrice and discount_percent const sellingPrice = discountPercent > 0 ? retailPrice * ((100 - discountPercent) / 100) : retailPrice; // set the calculated selling price in the update object update.price.retailPrice = retailPrice; update.price.selling_price = Number(sellingPrice); update.price.discount_percent = discountPercent; } next(); }); const ProductVariantModel = model("ProductVariant", productVariantSchema); export { ProductVariantModel }; // const productSpecialSale = new Schema( // { // endDate: String, // type: { type: String, enum: ProductDiscountType, required: true }, // discountValue: Number, // order_limit: Number, // quantity: Number, // priceAfterDiscount: Number, // }, // { _id: false }, // );