Files
shop-api/src/modules/product/models/productVariant.model.ts
T
morteza f5a803d86f
Build and Deploy / build_and_deploy (push) Has been cancelled
index products
2026-07-07 23:08:04 +03:30

122 lines
4.2 KiB
TypeScript

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<IStatistics>(
{
satisfied: { type: { rate: Number, count: Number } },
dissatisfied: { type: { rate: Number, count: Number } },
},
{ _id: false },
);
const productSaleFormat = new Schema<ISaleFormat>(
{
// isWholeSale: Boolean,
wholeSale: { type: [{ from: Number, to: Number, price: Number }] },
},
{ _id: false },
);
export const productDimensionsSchema = new Schema<IDimensions>(
{
package_weight: Number,
package_height: Number,
package_length: Number,
package_width: Number,
},
{ _id: false },
);
const productPriceSchema = new Schema<IPrice>(
{
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<IProductVariant>(
{
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<IProductVariant>("ProductVariant", productVariantSchema);
export { ProductVariantModel };
// const productSpecialSale = new Schema<ISpecialSale>(
// {
// endDate: String,
// type: { type: String, enum: ProductDiscountType, required: true },
// discountValue: Number,
// order_limit: Number,
// quantity: Number,
// priceAfterDiscount: Number,
// },
// { _id: false },
// );