Преглед изворни кода

Bugfix: Update input handling and validation messages for category and product actions

emrecevik106 пре 1 месец
родитељ
комит
52e4a3ef8c

+ 4 - 4
src/actions/menu/addCategory/types.ts

@@ -5,12 +5,12 @@ import {
 } from "class-validator";
 
 export class AddCategoryInput {
-    @IsString()
-    @IsNotEmpty()
+    @IsString({ message: "title-must-be-a-string" })
+    @IsNotEmpty({ message: "title-is-required" })
     title!: string;
 
-    @IsNumber()
-    @IsNotEmpty()
+    @IsNumber({}, { message: "index-must-be-a-number" })
+    @IsNotEmpty({ message: "index-is-required" })
     index!: number;
 }
 

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

@@ -5,24 +5,16 @@ import {
     Product
 } from "../../../models/Product";
 import {
+    AddProductInput,
     AddProductResult
 } from "./types";
 
-const addProduct = async (body: any, context: { userID: string }): Promise<AddProductResult> => {
+const addProduct = async (userID: string, input: AddProductInput): Promise<AddProductResult> => {
     try {
         const {
-            description,
-            isAvailable,
             categoryIDs,
-            isActive,
-            photos,
-            price,
-            title
-        } = body;
-
-        const {
-            userID
-        } = context;
+            ...rest
+        } = input;
 
         const normalizedCategoryIDs = Array.isArray(categoryIDs)
             ? categoryIDs
@@ -30,13 +22,8 @@ const addProduct = async (body: any, context: { userID: string }): Promise<AddPr
 
         const newProduct = await Product.create({
             categoryIDs: normalizedCategoryIDs,
-            userID: userID,
-            description,
-            isAvailable,
-            isActive,
-            photos,
-            title,
-            price
+            ...rest,
+            userID,
         });
 
         const activeMenu = await Menu.findOne({
@@ -60,17 +47,7 @@ const addProduct = async (body: any, context: { userID: string }): Promise<AddPr
             message: "product-created-successfully",
             code: 201,
             payload: {
-                _id: newProduct._id,
-                categoryIDs: newProduct.categoryIDs,
-                userID: newProduct.userID,
-                title: newProduct.title,
-                description: newProduct.description,
-                price: newProduct.price,
-                photos: newProduct.photos,
-                isActive: newProduct.isActive,
-                isAvailable: newProduct.isAvailable,
-                createdAt: newProduct.createdAt,
-                updatedAt: newProduct.updatedAt
+                ...newProduct.toObject(),
             }
         };
     } catch (error) {

+ 3 - 6
src/actions/menu/deleteProduct/index.ts

@@ -6,18 +6,15 @@ import {
     Product
 } from "../../../models/Product";
 import {
+    DeleteProductInput,
     DeleteProductResult
 } from "./types";
 
-const deleteProduct = async (body: any, context: { userID: string }): Promise<DeleteProductResult> => {
+const deleteProduct = async (userID: string, input: DeleteProductInput): Promise<DeleteProductResult> => {
     try {
         const {
             productIDs
-        } = body;
-
-        const {
-            userID
-        } = context;
+        } = input;
 
         const normalizedProductIDs = Array.isArray(productIDs)
             ? productIDs

+ 7 - 5
src/actions/menu/getCategories/index.ts

@@ -37,15 +37,17 @@ const getCategories = async (userID: string): Promise<GetCategoriesResult> => {
             index: 1 
         });
 
+        const payload = categories.map(c => ({
+            _id: c._id.toString(),
+            title: c.title,
+            index: c.index
+        }));
+
         return {
             message: "categories-retrieved",
             code: 200,
             payload: {
-                categories: categories.map(c => ({
-                    _id: c._id.toString(),
-                    title: c.title,
-                    index: c.index
-                }))
+                categories: payload
             }
         };
     } catch (error) {

+ 8 - 20
src/actions/menu/getProducts/index.ts

@@ -10,11 +10,8 @@ import {
     Menu
 } from "../../../models/Menu";
 
-const getProducts = async (query: GetProductsInput, context: { userID: string }): Promise<GetProductsResult> => {
+const getProducts = async (userID: string , query: GetProductsInput): Promise<GetProductsResult> => {
     try {
-        const {
-            userID
-        } = context;
 
         const {
             categoryIDs,
@@ -22,11 +19,13 @@ const getProducts = async (query: GetProductsInput, context: { userID: string })
         } = query;
 
         const matchStage: any = {
-            userID: new mongoose.Types.ObjectId(userID)
+            userID: new mongoose.Types.ObjectId(userID),
+            isActive: true
         };
 
         if (categoryIDs) {
             const normalizedCatIDs = Array.isArray(categoryIDs) ? categoryIDs : [categoryIDs];
+            
             matchStage.categoryIDs = {
                 $in: normalizedCatIDs.map(id => new mongoose.Types.ObjectId(id))
             };
@@ -84,21 +83,10 @@ const getProducts = async (query: GetProductsInput, context: { userID: string })
             }
         ]);
 
-        const payload = products.map((product) => {
-            return {
-                _id: product._id,
-                categoryIDs: product.categoryIDs.map((cat: any) => cat._id.toString()),
-                userID: product.userID,
-                title: product.title,
-                description: product.description,
-                price: product.price,
-                photos: product.photos,
-                isActive: product.isActive,
-                isAvailable: product.isAvailable,
-                createdAt: product.createdAt,
-                updatedAt: product.updatedAt
-            };
-        });
+        const payload = products.map((product) => ({
+            ...product,
+            categoryIDs: product.categoryIDs.map((cat: any) => cat._id.toString())
+        }));
 
         return {
             message: "products-retrieved-successfully",

+ 10 - 8
src/actions/menu/updateCategory/index.ts

@@ -29,7 +29,7 @@ const updateCategory = async (userID: string, input: UpdateCategoryInput): Promi
             categoryID,
             updateFields,
             {
-                new: true //güncelledikten sonra döndürmesi için
+                new: true
             }
         );
         
@@ -40,16 +40,18 @@ const updateCategory = async (userID: string, input: UpdateCategoryInput): Promi
             };
         }
 
+        const payload={
+            category: {
+                _id: updatedCategory._id.toString(),
+                title: updatedCategory.title,
+                index: updatedCategory.index
+            }
+        };
+
         return {
             message: "category-updated",
             code: 200,
-            payload: {
-                category: {
-                    _id: updatedCategory._id.toString(),
-                    title: updatedCategory.title,
-                    index: updatedCategory.index
-                }
-            }
+            payload
         };
     } catch (error) {
         console.error("UpdateCategory error:", error);

+ 4 - 4
src/actions/menu/updateCategory/types.ts

@@ -8,15 +8,15 @@ import {
 } from "class-validator";
 
 export class UpdateCategoryInput {
-    @IsString()
-    @IsNotEmpty()
+    @IsString({ message: "categoryID-must-be-a-string" })
+    @IsNotEmpty({ message: "categoryID-is-required" })
     categoryID!: string;
 
-    @IsString()
+    @IsString({ message: "title-must-be-a-string" })
     @IsOptional()
     title?: string;
 
-    @IsNumber()
+    @IsNumber({}, { message: "index-must-be-a-number" })
     @IsOptional()
     index?: number;
 }

+ 12 - 34
src/actions/menu/updateProduct/index.ts

@@ -3,38 +3,25 @@ import {
     Product
 } from "../../../models/Product";
 import {
+    UpdateProductInput,
     UpdateProductResult
 } from "./types";
 
-const updateProduct = async (body: any, context: { userID: string }): Promise<UpdateProductResult> => {
+const updateProduct = async (userID: string, input: UpdateProductInput): Promise<UpdateProductResult> => {
     try {
         const {
-            description,
-            isAvailable,
             categoryIDs,
             productID,
-            isActive,
-            photos,
-            price,
-            title
-        } = body;
-
-        const {
-            userID
-        } = context;
-
+            ...rest
+        } = input;
+ 
         const updateData: any = {
+            ...rest
         };
-
-        if (categoryIDs !== undefined) updateData.categoryIDs = Array.isArray(categoryIDs) 
-            ? categoryIDs 
-            : [categoryIDs];
-        if (title !== undefined) updateData.title = title;
-        if (description !== undefined) updateData.description = description;
-        if (price !== undefined) updateData.price = price;
-        if (photos !== undefined) updateData.photos = photos;
-        if (isActive !== undefined) updateData.isActive = isActive;
-        if (isAvailable !== undefined) updateData.isAvailable = isAvailable;
+        
+        if (categoryIDs !== undefined) {
+            updateData.categoryIDs = Array.isArray(categoryIDs) ? categoryIDs : [categoryIDs];
+        }
 
         const updatedDoc = await Product.findOneAndUpdate(
             {
@@ -76,17 +63,8 @@ const updateProduct = async (body: any, context: { userID: string }): Promise<Up
             message: "product-updated-successfully",
             code: 200,
             payload: {
-                _id: aggregatedProduct[0]._id,
-                categoryIDs: aggregatedProduct[0].categoryIDs.map((cat: any) => cat._id.toString()),
-                userID: aggregatedProduct[0].userID,
-                title: aggregatedProduct[0].title,
-                description: aggregatedProduct[0].description,
-                price: aggregatedProduct[0].price,
-                photos: aggregatedProduct[0].photos,
-                isActive: aggregatedProduct[0].isActive,
-                isAvailable: aggregatedProduct[0].isAvailable,
-                createdAt: aggregatedProduct[0].createdAt,
-                updatedAt: aggregatedProduct[0].updatedAt
+                ...aggregatedProduct[0],
+                categoryIDs: aggregatedProduct[0].categoryIDs.map((cat: any) => cat._id.toString())
             }
         };
 

+ 7 - 7
src/actions/menu/updateProduct/types.ts

@@ -8,23 +8,24 @@ import {
 } from "class-validator";
 
 export class UpdateProductInput {
-    @IsString()
+    @IsString({ message: "productID-must-be-a-string" })
     @IsNotEmpty({ message: "productID-is-required" })
     productID!: string;
 
+    @IsNotEmpty({ message: "categoryIDs-cannot-be-empty" }) //categoryId hiç gelmeyebilir ancak gelecekse de "" gelemez
     @IsOptional()
     categoryIDs?: string | string[];
 
-    @IsString()
+    @IsString({ message: "title-must-be-a-string" })
     @IsOptional()
     title?: string;
 
-    @IsString()
+    @IsString({ message: "description-must-be-a-string" })
     @IsOptional()
     description?: string;
 
     @Min(0, { message: "price-cannot-be-negative" })
-    @IsNumber()
+    @IsNumber({}, { message: "price-must-be-a-number" })
     @IsOptional()
     price?: number;
 
@@ -34,14 +35,13 @@ export class UpdateProductInput {
         isPrimary: boolean;
     }[];
 
-    @IsBoolean()
+    @IsBoolean({ message: "is-active-must-be-a-boolean" })
     @IsOptional()
     isActive?: boolean;
 
-    @IsBoolean()
+    @IsBoolean({ message: "is-available-must-be-a-boolean" })
     @IsOptional()
     isAvailable?: boolean;
-
 }
 
 export type UpdateProductResult = {

+ 8 - 5
src/controllers/menuController.ts

@@ -42,7 +42,10 @@ export const updateCategory = async (req: AuthRequest, res: Response): Promise<v
     res.status(result.code)
         .json({
             message: result.message,
-            code: result.code
+            code: result.code,
+            ...(result.payload && {
+                payload: result.payload
+            })
         });
 };
 
@@ -62,7 +65,7 @@ export const getCategories = async (req: AuthRequest, res: Response): Promise<vo
 
 //#region Product Controllers
 export const addProduct = async (req: AuthRequest, res: Response): Promise<void> => {
-    const result = await _addProduct(req.body, req.context!);
+    const result = await _addProduct(req.context!.userID, req.body);
 
     res.status(result.code)
         .json({
@@ -75,7 +78,7 @@ export const addProduct = async (req: AuthRequest, res: Response): Promise<void>
 };
 
 export const getProducts = async (req: AuthRequest, res: Response): Promise<void> => {
-    const result = await _getProducts(req.query, req.context!);
+    const result = await _getProducts(req.context!.userID, req.query);
 
     res.status(result.code)
         .json({
@@ -88,7 +91,7 @@ export const getProducts = async (req: AuthRequest, res: Response): Promise<void
 };
 
 export const updateProduct = async (req: AuthRequest, res: Response): Promise<void> => {
-    const result = await _updateProduct(req.body, req.context!);
+    const result = await _updateProduct(req.context!.userID, req.body);
 
     res.status(result.code)
         .json({
@@ -101,7 +104,7 @@ export const updateProduct = async (req: AuthRequest, res: Response): Promise<vo
 };
 
 export const deleteProduct = async (req: AuthRequest, res: Response): Promise<void> => {
-    const result = await _deleteProduct(req.body, req.context!);
+    const result = await _deleteProduct(req.context!.userID, req.body);
 
     res.status(result.code)
         .json({

+ 2 - 4
src/routes/authRoutes.ts

@@ -20,8 +20,6 @@ import {
     validateBody
 } from "../middlewares/validateBody";
 import {
-    FinishMailVerifyInput,
-    StartMailVerifyInput,
     RefreshTokenInput,
     RegisterInput,
     SmsSendInput,
@@ -31,8 +29,8 @@ import {
 
 const router = Router();
 
-router.post("/finishMailVerify", authMiddleware, validateBody(FinishMailVerifyInput), finishMailVerify);
-router.post("/startMailVerify", authMiddleware, validateBody(StartMailVerifyInput), startMailVerify);
+router.post("/finishMailVerify", authMiddleware, finishMailVerify);
+router.post("/startMailVerify", authMiddleware, startMailVerify);
 router.post("/refreshToken", validateBody(RefreshTokenInput), refreshToken);
 router.post("/register", validateBody(RegisterInput), register);
 router.post("/login", validateBody(LoginInput), login);