Your IP : 216.73.216.220


Current Path : /home/deltalab/PMS/partner-manager-backend/models/mongoose/
Upload File :
Current File : //home/deltalab/PMS/partner-manager-backend/models/mongoose/product.js

const mongoose = require('mongoose');

const { Schema } = mongoose;

const { AttributeSchema } = require('./category');
const { OfferSchema } = require('./offer');

// SCHEMA ============================================
const AttrbuteValueSchema = new mongoose.Schema(
  {
    attribute: AttributeSchema,
    value: Schema.Types.Mixed,
  },
  {
    _id: false,
  },
);

const ProductMediaSchema = new mongoose.Schema(
  {
    name: String,
    url: String,
    type: String,
    data: String, // Base64 media content
    filePath: String,
    showPath: String,
    imsgid: String, // The ims id associated to this media (if any)
  },
  {
    _id: false,
  },
);

const ProductBookedInventorySchema = new mongoose.Schema(
  {
    amount: Number,
    omsgid: String,
    fulfilled: Boolean,
    channelId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Channel',
      required: false,
    },
  },
  {
    timestamps: true,
    _id: false,
  },
);

/**
 * The amount of a given product in a warehouse
 */
const ProductInventorySchema = new mongoose.Schema(
  {
    warehouseId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Warehouse',
      unique: true,
    },
    amount: Number,
    bookings: [ProductBookedInventorySchema],
  },
  {
    _id: false,
  },
);

const SizeSchema = new mongoose.Schema(
  {
    height: Number,
    length: Number,
    width: Number,
  },
  {
    _id: false,
  },
);

const RecommendationSchema = new mongoose.Schema(
  {
    productId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Product',
    },
    similarProducts: [{
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Product',
    }],
  },
  {
    _id: false,
  },
);

const ProductBaseSchema = new mongoose.Schema(
  {
    masterId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Master',
    },
    title: { type: String, required: true },
    description: String,
    customDescription: String,
    brand: String,
    price: Number,
    originalPrice: Number,
    msrp: Number,
    imsgid: String, // the global idenfier provided by IMS upon creation
    customerSku: String,
    sku: { type: String, required: true },
    barcode: String, // EAN, ISBN, other
    requiresShipping: Boolean, // if this product has to be shipped
    inventoryLevels: [ProductInventorySchema],
    bookedQuantity: Number,
    trackInventory: Boolean,
    sellBelowZero: Boolean,
    showMsrp: Boolean,
    refrigerated: Boolean,
    deleted: { type: Boolean, required: true, default: false },
    weight: Number,
    size: SizeSchema,
    media: [ProductMediaSchema],
    categoryId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Category',
    },
    offers: [OfferSchema],
    imsCategories: [String],
    imsTaxCode: String,
    attributeSetId: String,
    channelId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Channel',
      required: true,
    },
    attributes: [AttrbuteValueSchema],
    linkedProducts: [RecommendationSchema],
    // linkedProducts: [{
    //   type: mongoose.Schema.Types.ObjectId,
    //   ref: 'Product',
    // }],
    recomExplanation: String,
    minimumAgeRequired: Boolean,
    fragile: Boolean,
    bottle: Boolean,
    imsEnabled: Boolean,
    isValidFrom: Boolean,
    validFrom: Date,
    isValidUntil: Boolean,
    validUntil: Date,
    urlKey: String,
  },
  {
    _id: false,
  },
);

// Product quantity is based on inventory levels
ProductBaseSchema.virtual('quantity')
  .set(() => {
    // throw new Error(`cannot set product quantity directly: use inventoryLevels`);
    console.log('cannot set product quantity directly: use inventoryLevels');
  })
  .get(() => {
    // sanity check
    if (!this.inventoryLevels || this.inventoryLevels.length === 0) return 0;
    // reduce inventory amount to a single quantity
    return this.inventoryLevels.reduce((quantity, inventory) => quantity + inventory.amount, 0);
  });

const ProductSchema = new mongoose.Schema(
  {
    partnerId: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: 'Partner',
    },
  },
  {
    timestamps: true,
    versionKey: false,
  },
).add(ProductBaseSchema); // Using add() will copy over the product base methods too!

// MODELS ============================================
const productMediaModel = mongoose.model('Media', ProductMediaSchema);
const productInventoryModel = mongoose.model('ProductInventory', ProductInventorySchema);
const productBaseModel = mongoose.model('ProductBase', ProductBaseSchema);
const productModel = mongoose.model('Product', ProductSchema);
const recommendationModel = mongoose.model('Recommendation', RecommendationSchema);

// EXPORTS ===========================================
module.exports = {
  productBaseModel,
  productInventoryModel,
  productMediaModel,
  productModel,
  recommendationModel,
  ProductBaseSchema,
  ProductInventorySchema,
  ProductMediaSchema,
  ProductSchema,
  SizeSchema,
  RecommendationSchema,
};