Jelajahi Sumber

Merge branch 'feature/plan-and-subscription-models' into develop

emrecevik106 1 bulan lalu
induk
melakukan
a06cefa2fd

+ 7 - 3
src/actions/menu/addProduct/index.ts

@@ -8,11 +8,11 @@ import {
 const addProduct = async (body: any, context: { userID: string }): Promise<AddProductResult> => {
     try {
         const {
-            coverPhotoPath,
             description,
             isAvailable,
             categoryID,
             isActive,
+            photos,
             price,
             title
         } = body;
@@ -21,13 +21,17 @@ const addProduct = async (body: any, context: { userID: string }): Promise<AddPr
             userID
         } = context;
 
+        const normalizedCategoryID = Array.isArray(categoryID) 
+            ? categoryID 
+            : categoryID ? [categoryID] : [];
+    
         const newProduct = await Product.create({
-            coverPhotoPath,
+            categoryID: normalizedCategoryID,
             userID: userID,
             description,
             isAvailable,
-            categoryID,
             isActive,
+            photos,
             title,
             price
         });

+ 5 - 4
src/actions/menu/addProduct/types.ts

@@ -9,9 +9,8 @@ import {
 
 
 export class AddProductInput {
-    @IsString()
     @IsNotEmpty({ message: "categoryID-is-required" })
-    categoryID!: string;
+    categoryID?: string | string[];
 
     @IsString()
     @IsNotEmpty({ message: "title-is-required" })
@@ -26,9 +25,11 @@ export class AddProductInput {
     @IsNotEmpty()
     price!: number;
 
-    @IsString()
     @IsOptional()
-    coverPhotoPath?: string;
+    photos?: { 
+        coverPhotoPath: string;
+        isPrimary: boolean;
+    }[];
 
     @IsBoolean()
     @IsOptional()

+ 3 - 16
src/actions/menu/getProducts/index.ts

@@ -22,7 +22,9 @@ const getProducts = async (query: GetProductsInput, context: { userID: string })
         };
 
         if (categoryID) {
-            matchStage.categoryID = new mongoose.Types.ObjectId(categoryID);
+            matchStage.categoryID = {
+                $in: [new mongoose.Types.ObjectId(categoryID)] 
+            };
         }
 
         const products = await Product.aggregate([
@@ -37,21 +39,6 @@ const getProducts = async (query: GetProductsInput, context: { userID: string })
                     as: "categoryID"
                 }
             },
-            {
-                $unwind: {
-                    path: "$categoryID",
-                    preserveNullAndEmptyArrays: true
-                }
-            },
-            {
-                $addFields: {
-                    categoryID: {
-                        _id: "$categoryID._id",
-                        title: "$categoryID.title",
-                        isActive: "$categoryID.isActive"
-                    }
-                }
-            },
             {
                 $sort: {
                     createdAt: -1

+ 5 - 18
src/actions/menu/updateProduct/index.ts

@@ -9,12 +9,12 @@ import {
 const updateProduct = async (body: any, context: { userID: string }): Promise<UpdateProductResult> => {
     try {
         const {
-            coverPhotoPath,
             description,
             isAvailable,
             categoryID,
             productID,
             isActive,
+            photos,
             price,
             title
         } = body;
@@ -26,11 +26,13 @@ const updateProduct = async (body: any, context: { userID: string }): Promise<Up
         const updateData: any = {
         };
 
-        if (categoryID !== undefined) updateData.categoryID = new mongoose.Types.ObjectId(categoryID);
+        if (categoryID !== undefined) updateData.categoryID = Array.isArray(categoryID) 
+            ? categoryID 
+            : [categoryID];
         if (title !== undefined) updateData.title = title;
         if (description !== undefined) updateData.description = description;
         if (price !== undefined) updateData.price = price;
-        if (coverPhotoPath !== undefined) updateData.coverPhotoPath = coverPhotoPath;
+        if (photos !== undefined) updateData.photos = photos;
         if (isActive !== undefined) updateData.isActive = isActive;
         if (isAvailable !== undefined) updateData.isAvailable = isAvailable;
 
@@ -67,21 +69,6 @@ const updateProduct = async (body: any, context: { userID: string }): Promise<Up
                     foreignField: "_id",
                     as: "categoryID"
                 }
-            },
-            {
-                $unwind: {
-                    path: "$categoryID",
-                    preserveNullAndEmptyArrays: true
-                }
-            },
-            {
-                $addFields: {
-                    categoryID: {
-                        _id: "$categoryID._id",
-                        title: "$categoryID.title",
-                        isActive: "$categoryID.isActive"
-                    }
-                }
             }
         ]);
 

+ 5 - 4
src/actions/menu/updateProduct/types.ts

@@ -12,9 +12,8 @@ export class UpdateProductInput {
     @IsNotEmpty({ message: "productID-is-required" })
     productID!: string;
 
-    @IsString()
     @IsOptional()
-    categoryID?: string;
+    categoryID?: string | string[];
 
     @IsString()
     @IsOptional()
@@ -29,9 +28,11 @@ export class UpdateProductInput {
     @IsOptional()
     price?: number;
 
-    @IsString()
     @IsOptional()
-    coverPhotoPath?: string;
+    photos?: {
+        coverPhotoPath: string;
+        isPrimary: boolean;
+    }[];
 
     @IsBoolean()
     @IsOptional()

+ 57 - 0
src/models/Plan.ts

@@ -0,0 +1,57 @@
+import mongoose, {
+    Schema, Document 
+} from "mongoose";
+
+export interface IPlan extends Document {
+    type: {
+        price: number;
+        type: string; 
+    }[];
+    categoryLimit: number;
+    productLimit: number;
+    description: string;
+    isActive?: boolean;
+    menuLimit: number;
+    createdAt: Date;
+    updatedAt: Date;
+    title: string;
+}
+
+const PlanSchema = new Schema<IPlan>(
+    {
+        title: {
+            type: String
+        },
+        description: {
+            type: String
+        },
+        isActive: {
+            type: Boolean,
+            default: true
+        },
+        menuLimit: {
+            type: Number
+        },
+        categoryLimit: {
+            type: Number
+        },
+        productLimit: {
+            type: Number
+        },
+        type: [
+            {
+                type: {
+                    type: String
+                },
+                price: {
+                    type: Number
+                },
+            },
+        ],
+    },
+    {
+        timestamps: true 
+    }
+);
+
+export default mongoose.models.Plan || mongoose.model<IPlan>("Plan", PlanSchema);

+ 20 - 8
src/models/Product.ts

@@ -3,9 +3,12 @@ import mongoose, {
     Schema
 } from "mongoose";
 export interface IProduct extends Document {
-    categoryID: mongoose.Types.ObjectId;
+    categoryID: mongoose.Types.ObjectId[];
     userID: mongoose.Types.ObjectId;
-    coverPhotoPath: string;
+    photos: {
+        coverPhotoPath: string;
+        isPrimary: boolean;
+    }[];
     isAvailable: boolean;
     description: string;
     isActive: boolean;
@@ -16,8 +19,9 @@ export interface IProduct extends Document {
 const productSchema = new Schema<IProduct>(
     {
         categoryID: {
-            type: mongoose.Schema.Types.ObjectId,
-            index: true
+            type: [mongoose.Schema.Types.ObjectId],
+            index: true,
+            default: []
         },
         userID: {
             type: mongoose.Schema.Types.ObjectId,
@@ -38,10 +42,18 @@ const productSchema = new Schema<IProduct>(
             required: true,
             min: 0
         },
-        coverPhotoPath: {
-            type: String,
-            default: ""
-        },
+        photos: [
+            {
+                coverPhotoPath: {
+                    type: String 
+                },
+                isPrimary: {
+                    type: Boolean,
+                    default: false
+                },
+                _id: false
+            }
+        ],
         isActive: {
             type: Boolean,
             default: true

+ 51 - 0
src/models/Subscription.ts

@@ -0,0 +1,51 @@
+import mongoose, {
+    Schema, Document 
+} from "mongoose";
+
+export interface ISubscription extends Document {
+    planID: mongoose.Types.ObjectId;
+    status: "active" | "expired";
+    isActive?: boolean;
+    startDate: Date;
+    userID: string;
+    title: string;
+    endDate: Date;
+    price: number;
+}
+
+const SubscriptionSchema = new Schema<ISubscription>(
+    {
+        userID: {
+            type: String
+        },
+        planID: {
+            type: Schema.Types.ObjectId
+        },
+        title: {
+            type: String
+        },
+        isActive: {
+            type: Boolean,
+            default: true
+        },
+        startDate: {
+            type: Date
+        },
+        endDate: {
+            type: Date
+        },
+        status: {
+            enum: ["active", "expired"], 
+            default: "active",
+            type: String
+        },
+        price: {
+            type: Number
+        },
+    },
+    {
+        timestamps: true 
+    }
+);
+
+export default mongoose.models.Subscription || mongoose.model<ISubscription>("Subscription", SubscriptionSchema);