Ver código fonte

Enhancement: Refactor getRecommendedProductsForCustomer to improve sample size handling and add query validation middleware

emrecevik106 4 semanas atrás
pai
commit
4480f29d3d

+ 6 - 6
src/actions/customer/getRecommendedProductsForCustomer/index.ts

@@ -22,7 +22,7 @@ const getRecommendedProductsForCustomer = async (query: GetRecommendedForCustome
         }
 
         const objectMenuID = new mongoose.Types.ObjectId(menuID);
-        const sampleSize = parseInt(limit, 10);
+        const sampleSize = Number(limit) || 5;
 
         const recommendedProducts = await RecommendedProduct.aggregate([
             {
@@ -31,11 +31,6 @@ const getRecommendedProductsForCustomer = async (query: GetRecommendedForCustome
                     isActive: true
                 }
             },
-            {
-                $sample: {
-                    size: sampleSize
-                }
-            },
             {
                 $lookup: {
                     from: "products",
@@ -54,6 +49,11 @@ const getRecommendedProductsForCustomer = async (query: GetRecommendedForCustome
                 $match: {
                     "productDetails.isAvailable": true
                 }
+            },
+            {
+                $sample: {
+                    size: sampleSize
+                }
             }
         ]);
 

+ 4 - 3
src/actions/customer/getRecommendedProductsForCustomer/types.ts

@@ -1,7 +1,8 @@
 import {
     IsNotEmpty,
-    IsString,
     IsOptional,
+    IsString,
+    IsNumber,
     IsNumberString
 } from "class-validator";
 
@@ -10,9 +11,9 @@ export class GetRecommendedForCustomerInput {
     @IsNotEmpty({ message: "menuID-is-required" })
     menuID!: string;
 
-    @IsNumberString({}, { message: "limit-must-be-a-number-string" })
+    @IsNumberString({}, { message: "limit-must-be-a-number-string" }) 
     @IsOptional()
-    limit?: string;
+    limit?: string; 
 }
 
 export type GetRecommendedForCustomerResult = {

+ 1 - 1
src/actions/menu/getCategories/index.ts

@@ -11,7 +11,7 @@ const getCategories = async (userID: string): Promise<GetCategoriesResult> => {
         const objectUserID = new mongoose.Types.ObjectId(userID);
 
         const categories = await Category.find({
-            objectUserID
+            userID: objectUserID
         }).sort({
             index: 1 
         });

+ 5 - 1
src/actions/menu/getProducts/index.ts

@@ -11,10 +11,14 @@ import {
 const getProducts = async (userID: string, query: GetProductsInput): Promise<GetProductsResult> => {
     try {
         const {
-            categoryIDs,
+            categoryIDs: rawCategoryIDs,
             search
         } = query;
 
+        const categoryIDs = rawCategoryIDs
+            ? (Array.isArray(rawCategoryIDs) ? rawCategoryIDs : [rawCategoryIDs])
+            : undefined;
+    
         const matchStage: any = {
             userID: new mongoose.Types.ObjectId(userID),
             isActive: true

+ 1 - 2
src/controllers/customerController.ts

@@ -10,8 +10,7 @@ import {
 } from "../actions/customer/getRecommendedProductsForCustomer/types";
 
 export const getRecommendedProductsForCustomer = async (req: Request, res: Response): Promise<void> => {
-    const query = req.query as unknown as GetRecommendedForCustomerInput;
-
+    const query = (req as any).validatedQuery as GetRecommendedForCustomerInput;
     const result = await _getRecommendedProductsForCustomer(query);
 
     res.status(result.code)

+ 36 - 0
src/middlewares/validateQuery.ts

@@ -0,0 +1,36 @@
+import {
+    NextFunction,
+    Response,
+    Request
+} from "express";
+import {
+    plainToInstance 
+} from "class-transformer";
+import {
+    validate 
+} from "class-validator";
+
+export const validateQuery = (dtoClass: any) => {
+    return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
+        const instance = plainToInstance(dtoClass, req.query) as object;
+
+        const errors = await validate(instance, {
+            whitelist: true,
+            forbidNonWhitelisted: false
+        });
+
+        if (errors.length > 0) {
+            const formattedErrors = errors.map((err) => Object.values(err.constraints || {
+            })).flat();
+            res.status(400).json({
+                message: "validation-error",
+                code: 400,
+                errors: formattedErrors
+            });
+            return;
+        }
+
+        (req as any).validatedQuery = instance;
+        next();
+    };
+};

+ 4 - 4
src/routes/customerRoutes.ts

@@ -4,15 +4,15 @@ import {
 import {
     getRecommendedProductsForCustomer
 } from "../controllers/customerController";
-import {
-    validateBody
-} from "../middlewares/validateBody";
 import {
     GetRecommendedForCustomerInput
 } from "../actions/customer/types";
+import {
+    validateQuery 
+} from "../middlewares/validateQuery";
 
 const router = Router();
 
-router.get("/getRecommendedProducts", validateBody(GetRecommendedForCustomerInput), getRecommendedProductsForCustomer);
+router.get("/getRecommendedProductsForCustomer", validateQuery(GetRecommendedForCustomerInput), getRecommendedProductsForCustomer);
 
 export default router;