Skip to content

Fix product #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: backend-final
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14,938 changes: 4,337 additions & 10,601 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"test": "jest --detectOpenHandles",
"migrate": "sequelize-cli db:migrate",
"seed": "sequelize-cli db:seed:all"

},
"keywords": [],
"author": "",
Expand Down Expand Up @@ -39,7 +40,7 @@
"otpauth": "^9.2.4",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"pg": "^8.11.5",
"pg": "^8.12.0",
"pg-hstore": "^2.3.4",
"pusher": "^5.2.0",
"sequelize": "^6.37.3",
Expand Down
70 changes: 54 additions & 16 deletions src/controllers/product.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Request, Response } from "express";
import { saveProduct, searchProducts, getAllProducts } from "../services/productService";
import { saveProduct, searchProducts, getAllProducts, getProductById, fetchSimilarProducts } from "../services/productService";
import Product from "../database/models/product";
import { checkVendorModifyPermission, checkVendorPermission } from "../services/PermisionService";
import { PRODUCT_ADDED, PRODUCT_REMOVED, PRODUCT_UPDATED, productLifecycleEmitter } from "../helpers/events";
Expand All @@ -9,39 +9,51 @@ import Vendor from "../database/models/vendor";

export const createProduct = async (req: Request, res: Response) => {
try {
const tokenData = (req as any).token
const vendorId: string = req.params.id
const permissionCheck: any = await checkVendorPermission(tokenData, vendorId)
const tokenData = (req as any).token;
const vendorId: string = req.params.id;
const permissionCheck: any = await checkVendorPermission(tokenData, vendorId);

if (!permissionCheck.allowed) {
return res.status(permissionCheck.status).json({ message: permissionCheck.message })
return res.status(permissionCheck.status).json({ message: permissionCheck.message });
}

const { name, images, description, discount, price, quantity, category, expiringDate } = req.body;

if (!name || !images || !description || !price || !quantity || !category) {
return res.status(400).json({ message: "All fields are required" });
}
const { name, image, description, discount, price, quantity, category, expiringDate } = req.body
if (!name || !image || !description || !price || !quantity || !category) {
return res.status(200).json("All Field are required")

if (!Array.isArray(images) || images.length !== 4) {
return res.status(400).json({ message: "Exactly 4 images are required" });
}

const imageArray: string[] = images;

const data = {
name,
image,
images: imageArray,
description,
discount: discount ? discount : 0,
price,
quantity,
category,
vendorId: vendorId,
expiringDate
}
const save = await saveProduct(data)
expiringDate,
};

const save = await saveProduct(data);

if (!save) {
return res.status(500).json({ error: "Failed to save data" })
return res.status(500).json({ error: "Failed to save data" });
}

productLifecycleEmitter.emit(PRODUCT_ADDED, data);

return res.status(201).json({ message: "Product Created", data: save })
return res.status(201).json({ message: "Product Created", data: save });

} catch (error: any) {
res.status(500).json({ error: error.message })
res.status(500).json({ error: error.message });
}

};

export const readProduct = async (req: Request, res: Response) => {
Expand All @@ -58,6 +70,31 @@ export const readProduct = async (req: Request, res: Response) => {
}
};

export const similarProducts = async (req: Request, res: Response) => {
try {
const productId = req.params.id;
const product = await getProductById(productId);

if (!product) {

return res.status(404).json({ error: "Product not found" });
}
console.log("hhhhhggggggggghhhhh",product)
const category = product.category;
const similarProducts = await fetchSimilarProducts(productId, category);

if (similarProducts.length === 0) {
return res.status(404).json({ error: "No similar products found" });
}
console.log("hhhhhhhhhh",similarProducts)

return res.status(200).json(similarProducts);

} catch (error: any) {
res.status(500).json({ error: error.message });
}
};

// delete product
export const readAllProducts = async (req: Request, res: Response) => {
try {
Expand All @@ -76,6 +113,7 @@ export const readAllProducts = async (req: Request, res: Response) => {
}
};


export const searchProduct = async (req: Request, res: Response) => {
try {
const { name, category } = req.query;
Expand Down
14 changes: 8 additions & 6 deletions src/controllers/review.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,19 @@ export const selectFeedback = async (req: Request, res: Response) => {
try {
const productId = req.params.id;
const ratings = await Rating.findAll({
where:{
where: {
productId
}
},
order: [['createdAt', 'DESC']]
});

if (!ratings || ratings.length === 0) {
return res
.status(400)
.json({ message: "There in no Ratings in your products" });
return res.status(400).json({ message: "There are no ratings for your product" });
}
return res.status(200).json({ ratings: ratings });

return res.status(200).json({ ratings });
} catch (error: any) {
console.error("Error fetching ratings:", error);
res.status(500).json({ message: error.message });
}
};
Expand Down
61 changes: 56 additions & 5 deletions src/controllers/wishlist.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,39 @@ import WishlistItem from "../database/models/wishlistItem";
import User from "../database/models/user";
import Product from "../database/models/product";

export const fetchWishlist = async (req: Request, res: Response) => {
try {
const { userId } = req.params;

const wishlist = await Wishlist.findOne({ where: { userId } });

if (!wishlist) {
return res.status(404).json({ message: "Wishlist not found" });
}

const wishlistItems = await WishlistItem.findAll({
where: { wishlistId: wishlist.wishlistId },
});

return res.status(200).json({ wishlist: wishlistItems });
} catch (error: any) {
res.status(500).json({ success: false, message: error.message });
}
};

export const addToWishlist = async (req: Request, res: Response) => {
try {
const { userId, productId, price } = req.body;

let wishlist = await Wishlist.findOne({ where: { userId } });

if (!wishlist) {
wishlist = await Wishlist.create({
userId,
});
wishlist = await Wishlist.create({ userId });
await User.update({ wishlistId: wishlist.wishlistId }, { where: { userId } });

const wishlistItem = await WishlistItem.create({
wishlistId: wishlist.wishlistId,
productId,

});
if (wishlistItem) {
return res
Expand All @@ -44,10 +61,44 @@ export const addToWishlist = async (req: Request, res: Response) => {
if (wishlistItem) {
return res
.status(200)
.json({ message: "Wishlistitem added successfully!", wishlist: wishlistItem });
.json({ message: "Wishlist item added successfully!", wishlist: wishlistItem });
}
}
} catch (error: any) {
res.status(500).json({ success: false, message: error.message });
}
};

export const removeFromWishlist = async (req: Request, res: Response) => {
try {
const { userId, productId } = req.body;

const wishlist = await Wishlist.findOne({ where: { userId } });

if (!wishlist) {
return res.status(404).json({ message: "Wishlist not found" });
}

const wishlistItem = await WishlistItem.findOne({
where: {
wishlistId: wishlist.wishlistId,
productId,
},
});

if (!wishlistItem) {
return res.status(404).json({ message: "Product not found in wishlist" });
}

await WishlistItem.destroy({
where: {
wishlistId: wishlist.wishlistId,
productId,
},
});

return res.status(200).json({ message: "Product removed from wishlist successfully" });
} catch (error: any) {
res.status(500).json({ success: false, message: error.message });
}
};
5 changes: 4 additions & 1 deletion src/database/migrations/20240520140651-create-product.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
'use strict';

const { JSONB } = require('sequelize');

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
Expand All @@ -22,7 +25,7 @@ module.exports = {
allowNull: false
},
image: {
type: Sequelize.STRING,
type: JSONB,
allowNull: false
},
description: {
Expand Down
4 changes: 2 additions & 2 deletions src/database/models/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Product extends Model {
public vendorId: any;
public name!: string;
public description!: string;
public image!: string;
public image!: any[];
public discount!: number;
public price!: string;
public quantity!: number;
Expand Down Expand Up @@ -46,7 +46,7 @@ class Product extends Model {
},
name: { type: DataTypes.STRING, allowNull: false },
description: { type: DataTypes.STRING, allowNull: false },
image: { type: DataTypes.STRING, allowNull: false },
image: { type: DataTypes.JSONB, allowNull: false },
discount: { type: DataTypes.INTEGER, allowNull: false },
price: { type: DataTypes.INTEGER, allowNull: false },
quantity: { type: DataTypes.INTEGER, allowNull: true },
Expand Down
5 changes: 4 additions & 1 deletion src/database/seeders/20240522064825-seed-products.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const { v4: uuidv4 } = require('uuid');
module.exports = {
async up(queryInterface, Sequelize) {
const imageUrl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSXhCG6nff2emBYOKGHb6jU2zQ4C2m0LBg4Mj-eydwZyg&s';
const imageUrl2 = 'https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTExL3BmLXMxMDgtcG0tNDExMy1tb2NrdXAuanBn.jpg';
const imageUrl3 = 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?fm=jpg&w=3000&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cHJvZHVjdHxlbnwwfHwwfHx8MA%3D%3D';
const imageUrl4 = 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?fm=jpg&w=3000&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8cHJvZHVjdHxlbnwwfHwwfHx8MA%3D%3D';

const [vendors] = await queryInterface.sequelize.query(`
SELECT "vendorId"
Expand All @@ -19,7 +22,7 @@ module.exports = {
// @ts-ignore
vendorId: vendor.vendorId,
name: 'nike shoes',
image: imageUrl,
image: JSON.stringify([imageUrl,imageUrl2,imageUrl3,imageUrl4]),
description: 'These are nike shoes.',
discount: 2,
price: 12000,
Expand Down
2 changes: 2 additions & 0 deletions src/routes/product.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
createProduct,
readAllProducts,
viewProducts,
similarProducts,
} from "../controllers/product.controller";
import { VerifyAccessToken } from "../middleware/verfiyToken";
const router = express.Router();
Expand All @@ -15,6 +16,7 @@ router.post("/create/product/:id", VerifyAccessToken, createProduct);
router.get("/readAllProducts", readAllProducts);
router.get("/vendorProducts/:id", VerifyAccessToken, viewProducts);
router.get("/readProduct/:id", readProduct);
router.get('/similarproducts/:id', similarProducts);
router.get("/products/search", searchProduct);
router.get("/products/vendor/:id", VerifyAccessToken, viewProducts);
router.put("/updateProduct/:id", VerifyAccessToken, updateProduct);
Expand Down
3 changes: 2 additions & 1 deletion src/routes/user.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "../controllers/user.controller";
import { VerifyAccessToken } from "../middleware/verfiyToken";

import { addFeedback, addReview } from "../controllers/review.controller";
import { addFeedback, addReview, selectFeedback } from "../controllers/review.controller";


const route = express.Router();
Expand All @@ -25,6 +25,7 @@ route.delete("/deleteuser/:id",VerifyAccessToken,deleteUser);
route.post("/login",twoFAController, login);
route.post("/addreview/:id", addReview);
route.post("/addfeedback/:id", addFeedback);
route.get("/getfeedback/:id", selectFeedback);
route.get("/verfiy-email", verifyEmail);

export default route;
4 changes: 3 additions & 1 deletion src/routes/wishlist.route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Router } from "express";
import { addToWishlist } from "../controllers/wishlist.controller";
import { addToWishlist, fetchWishlist, removeFromWishlist } from "../controllers/wishlist.controller";

const router = Router();

router.post("/toWishlist", addToWishlist);
router.get("/toWishlist/:userId", fetchWishlist);
router.delete('/toWishlist', removeFromWishlist)

export default router
20 changes: 20 additions & 0 deletions src/services/productService.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Op } from "sequelize"
import Product from "../database/models/product"

export const saveProduct = async (data:any)=>{
Expand All @@ -15,6 +16,7 @@ export const getAllProducts = async (page: number, limit: number) => {
const products = await Product.findAll();
return products;
} catch (error) {

throw new Error('Error while fetching all products');
}
};
Expand All @@ -40,4 +42,22 @@ export const searchProducts = async (criteria: any, page: number, limit: number)
} catch (error) {
throw new Error('Error while searching products');
}
};

export const fetchSimilarProducts = async (productId: string, category: string, limit: number = 10) => {
try {
const similarProducts = await Product.findAll({
where: {
category,
productId: {
[Op.ne]: productId,
},
},
limit,
});
return similarProducts;
} catch (error) {
console.error('Error while fetching similar products:', error);
throw new Error('Error while fetching similar products');
}
};
Loading