From b381932ccddc0ac0baf8820f6686e6697ca53945 Mon Sep 17 00:00:00 2001 From: 13XAVI Date: Wed, 29 May 2024 20:49:26 +0200 Subject: [PATCH] adde some file added coverages fix(review-swagger-docs): fix swagger documentation of thereview task (#114) - add missing security tag in review docs [Fixes #113] adde some file added some tests added coverages fix(review-swagger-docs): fix swagger documentation of thereview task (#114) - add missing security tag in review docs [Fixes #113] adde some file * fix(create-review): fix failing create review function -add validation before processing data [Fixes #116] * fix(create-review): fix failing create review function -add validation before processing data [Fixes #116] dockerizing project by creating containers for app & postgres (#110) fix minor issue in deployment of render latest commit Update Readme file to include Docker-specific information Update Readme file to include Docker-specific information * fix(create-review): fix failing create review function -add validation before processing data [Fixes #116] * fix(create-review): fix failing create review function -add validation before processing data [Fixes #116] dockerizing project by creating containers for app & postgres (#110) fix minor issue in deployment of render latest commit Update Readme file to include Docker-specific information Update Readme file to include Docker-specific information fix(review-swagger-docs): fix swagger documentation of thereview task (#114) (#115) - add missing security tag in review docs [Fixes #113] update profile (#72) (#104) review controller adding testing fix lint issue update profile (#72) (#104) review controller adding testing fix lint issue Co-authored-by: Joslyn Manzi Karenzi fix(stripe-payment): fix minor issue in stripe payment (#120) - add status check on the stripe response before setting order.paid to true [Fixes #119] --- package-lock.json | 42 ++++- package.json | 2 +- src/__test__/buyerWishlist.test.ts | 143 ++++++++++++++ src/__test__/payment.test.ts | 1 - src/controller/buyerController.ts | 67 +++---- src/controller/buyerWishlistController.ts | 157 +++++++++++++++ src/database/models/buyerWishList.ts | 26 +++ src/docs/buyerDocs.ts | 210 +++++++++++++++------ src/docs/buyerWishlist.ts | 220 ++++++++++++++++++++++ src/routes/buyerRoutes.ts | 12 +- 10 files changed, 778 insertions(+), 102 deletions(-) create mode 100644 src/__test__/buyerWishlist.test.ts create mode 100644 src/controller/buyerWishlistController.ts create mode 100644 src/database/models/buyerWishList.ts create mode 100644 src/docs/buyerWishlist.ts diff --git a/package-lock.json b/package-lock.json index 16615fa2..aa3d2039 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,11 +22,11 @@ "express": "^4.19.2", "express-validator": "^7.0.1", "handlebars": "^4.7.8", - "jest": "^29.7.0", "joi": "^17.13.1", "jsonwebtoken": "^9.0.2", "mailgun-js": "^0.22.0", "morgan": "^1.10.0", + "nock": "^13.5.4", "nodemailer": "^6.9.13", "nodemon": "^3.1.0", "otplib": "^12.0.1", @@ -66,7 +66,7 @@ "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "prettier": "^3.2.5", - "ts-jest": "^29.1.2", + "ts-jest": "^29.1.4", "ts-node-dev": "^2.0.0", "typescript": "^5.4.5" } @@ -6667,6 +6667,11 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -7210,6 +7215,19 @@ "node": ">= 0.4.0" } }, + "node_modules/nock": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", + "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -8212,6 +8230,14 @@ "node": ">= 6" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -9451,9 +9477,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", - "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "version": "29.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz", + "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -9469,10 +9495,11 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^16.10.0 || ^18.0.0 || >=20.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -9482,6 +9509,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, diff --git a/package.json b/package.json index 3e78368c..27a40937 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "format": "prettier --write .", "test": "cross-env NODE_ENV=test jest --runInBand --no-cache --detectOpenHandles", "test:ci": "cross-env NODE_ENV=test jest --runInBand --coverage --detectOpenHandles" - }, + }, "repository": { "type": "git", "url": "git+https://github.com/atlp-rwanda/dynamites-ecomm-be.git" diff --git a/src/__test__/buyerWishlist.test.ts b/src/__test__/buyerWishlist.test.ts new file mode 100644 index 00000000..084b07b3 --- /dev/null +++ b/src/__test__/buyerWishlist.test.ts @@ -0,0 +1,143 @@ +import request from 'supertest'; +import app from '../app'; +import { afterAllHook, beforeAllHook } from './testSetup'; +import { getBuyerToken, getVendorToken } from './testSetup'; + +beforeAll(beforeAllHook); +afterAll(afterAllHook); +export let buyerToken: string; +let vendorToken: string; +let productId: number; +let categoryId: number; + +beforeAll(async () => { + buyerToken = await getBuyerToken(); + vendorToken = await getVendorToken(); + + const categoryData = { + name: 'Category4', + description: 'category description', + }; + + const categoryResponse = await request(app) + .post('/api/v1/category') + .set('Authorization', `Bearer ${vendorToken}`) + .send(categoryData); + + categoryId = categoryResponse.body.data.id; + + const productData = { + name: 'New Product Two', + image: 'new_product.jpg', + gallery: [], + shortDesc: 'This is a new product', + longDesc: 'Detailed description of the new product', + categoryId: categoryId, + quantity: 10, + regularPrice: 5, + salesPrice: 4, + tags: ['tag1', 'tag2'], + type: 'Simple', + isAvailable: true, + }; + + const response = await request(app) + .post('/api/v1/product') + .set('Authorization', `Bearer ${vendorToken}`) + .send(productData); + + productId = response.body.data.id; + + const getResponse = await request(app) + .get(`/api/v1/buyer/get_product/${productId}`) + .set('Authorization', `Bearer ${buyerToken}`); + + expect(getResponse.statusCode).toEqual(200); + expect(getResponse.body.msg).toEqual('Product retrieved successfully'); +}); + +describe('POST /api/v1/buyer/addItemToWishList', () => { + it('should add an item to the wishlist', async () => { + const res = await request(app) + .post('/api/v1/buyer/addItemToWishList') + .set('Authorization', `Bearer ${buyerToken}`) + .send({ + productId: productId, + time: '2024-05-21T12:00:00Z', + }); + + expect(res.statusCode).toEqual(201); + expect(res.body.message).toContain('Wishlist successfully created'); + }); + + it('should not allow adding an item already in the wishlist', async () => { + await request(app) + .post('/api/v1/buyer/addItemToWishList') + .set('Authorization', `Bearer ${buyerToken}`) + .send({ + productId: productId, + time: '2024-05-21T12:00:00Z', + }); + + const res = await request(app) + .post('/api/v1/buyer/addItemToWishList') + .set('Authorization', `Bearer ${buyerToken}`) + .send({ + productId: productId, + time: '2024-05-21T12:00:00Z', + }); + + expect(res.statusCode).toEqual(409); + expect(res.body.message).toContain('Product is already in the wishlist'); + }); +}); + +describe('DELETE /api/v1/buyer/removeToWishList', () => { + it('should remove a product from the wishlist', async () => { + const res = await request(app) + .delete('/api/v1/buyer/removeToWishList') + .set('Authorization', `Bearer ${buyerToken}`) + .send({ + productId: productId, + }); + + expect(res.statusCode).toEqual(200); + expect(res.body.message).toContain( + 'Product successfully removed from wishlist' + ); + }); +}); + +describe('GET /api/v1/buyer/getWishList', () => { + it('should get all wishlists', async () => { + const res = await request(app) + .get('/api/v1/buyer/getWishList') + .set('Authorization', `Bearer ${buyerToken}`); + + expect(res.statusCode).toEqual(200); + expect(res.body.message).toContain('Data retrieved successfully'); + }); +}); +describe('GET /api/v1/buyer/getOneWishList', () => { + it('should get all wishlists', async () => { + const res = await request(app) + .get('/api/v1/buyer/getOneWishList') + .set('Authorization', `Bearer ${buyerToken}`); + + expect(res.statusCode).toEqual(200); + expect(res.body.message).toContain('Data retrieved successfully'); + }); +}); + +describe('RemoveProductFromWishList', () => { + it('should return an error when the wishlist or product is not found', async () => { + const res = await request(app) + .delete('/api/v1/buyer/removeToWishList') + .set('Authorization', `Bearer ${buyerToken}`) + .send({ + productId: 9999, + }); + expect(res.statusCode).toEqual(404); + expect(res.body.message).toContain('Product not found in wishlist'); + }); +}); diff --git a/src/__test__/payment.test.ts b/src/__test__/payment.test.ts index cfca6ce4..254d6aa4 100644 --- a/src/__test__/payment.test.ts +++ b/src/__test__/payment.test.ts @@ -36,7 +36,6 @@ describe('handlePayment', () => { id: 'charge_id', amount: 10000, currency: 'usd', - status: 'succeeded', } as Stripe.Charge); MockedStripe.prototype.charges = { diff --git a/src/controller/buyerController.ts b/src/controller/buyerController.ts index dcb28d83..8a16f8bc 100644 --- a/src/controller/buyerController.ts +++ b/src/controller/buyerController.ts @@ -5,59 +5,51 @@ import errorHandler from '../middlewares/errorHandler'; import Stripe from 'stripe'; import { Order } from '../database/models/orderEntity'; - -const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '', { apiVersion: '2024-04-10' }); +const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '', { + apiVersion: '2024-04-10', +}); const productRepository = dbConnection.getRepository(Product); const orderRepository = dbConnection.getRepository(Order); - - export const getOneProduct = errorHandler( async (req: Request, res: Response) => { const productId = parseInt(req.params.id); - - + const product = await productRepository.findOne({ where: { id: productId }, relations: ['category'], }); - - + if (!product) { return res.status(404).json({ msg: 'Product not found' }); } - - + return res .status(200) .json({ msg: 'Product retrieved successfully', product }); } - ); - - - - - export const handlePayment = errorHandler( +); + +export const handlePayment = errorHandler( async (req: Request, res: Response) => { const { token, orderId } = req.body; - - + const order = await orderRepository.findOne({ where: { id: orderId } }); - - + if (!order) { - return res.status(404).json({ success: false, message: 'Order not found' }); + return res + .status(404) + .json({ success: false, message: 'Order not found' }); } - - + if (order.paid) { - return res.status(400).json({ success: false, message: 'Order has already been paid' }); + return res + .status(400) + .json({ success: false, message: 'Order has already been paid' }); } - - + const amountInCents = order.totalAmount * 100; - - + const charge = await stripe.charges.create({ amount: amountInCents, currency: 'usd', @@ -67,14 +59,15 @@ export const getOneProduct = errorHandler( if (charge.status === 'succeeded') { order.paid = true; - await orderRepository.save(order) + await orderRepository.save(order); - return res.status(200).json({ success: true, paid: true, charge}); - }else{ - return res - .status(400) - .json({ success: false, paid: false, message: `Charge status: ${charge.status}` }); - } + return res.status(200).json({ success: true, paid: true, charge }); + } else { + return res.status(400).json({ + success: false, + paid: false, + message: `Charge status: ${charge.status}`, + }); + } } - ); - \ No newline at end of file +); diff --git a/src/controller/buyerWishlistController.ts b/src/controller/buyerWishlistController.ts new file mode 100644 index 00000000..49b7389e --- /dev/null +++ b/src/controller/buyerWishlistController.ts @@ -0,0 +1,157 @@ +import { check, validationResult } from 'express-validator'; +import { Request, Response } from 'express'; +import BuyerWishList from '../database/models/buyerWishList'; +import UserModel from '../database/models/userModel'; +import Product from '../database/models/productEntity'; +import errorHandler from '../middlewares/errorHandler'; +import dbConnection from '../database'; + +const userRepository = dbConnection.getRepository(UserModel); +const productRepository = dbConnection.getRepository(Product); +const buyerWishListRepository = dbConnection.getRepository(BuyerWishList); + +const AddToWishListRules = [ + check('productId').isLength({ min: 1 }).withMessage('Product ID is required'), +]; + +export const AddItemInWishList = [ + ...AddToWishListRules, + errorHandler(async (req: Request, res: Response) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + const userId = req.user!.id; + const { productId, time } = req.body; + const wishListTime = time ? new Date(time) : new Date(); + + const user = await userRepository.findOne({ where: { id: userId } }); + if (!user) { + return res.status(404).json({ message: 'User not found' }); + } + + const product = await productRepository.findOne({ + where: { id: productId }, + }); + if (!product) { + return res.status(404).json({ message: 'Product not found' }); + } + + const existingWishListEntry = await buyerWishListRepository.findOne({ + where: { user: { id: userId } }, + relations: ['product'], + }); + + if (existingWishListEntry) { + const productExists = existingWishListEntry.product.some( + (p) => p.id === productId + ); + if (productExists) { + return res + .status(409) + .json({ message: 'Product is already in the wishlist' }); + } + existingWishListEntry.product.push(product); + existingWishListEntry.time = wishListTime; + const updatedWishList = await buyerWishListRepository.save( + existingWishListEntry + ); + return res.status(200).json({ + message: 'Product added to existing wishlist', + data: updatedWishList, + }); + } + + const newWishList = new BuyerWishList(); + newWishList.user = user; + newWishList.product = [product]; + newWishList.time = wishListTime; + + const savedWishList = await buyerWishListRepository.save(newWishList); + return res.status(201).json({ + message: 'Wishlist successfully created', + data: savedWishList, + }); + }), +]; + +const RemoveProductRules = [ + check('productId').isLength({ min: 1 }).withMessage('Product ID is required'), +]; + +export const RemoveProductFromWishList = [ + ...RemoveProductRules, + errorHandler(async (req: Request, res: Response) => { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }); + } + + const userId = req.user?.id; + const { productId } = req.body; + + const wishList = await buyerWishListRepository.findOne({ + where: { user: { id: userId } }, + relations: ['product'], + }); + + if (!wishList) { + return res.status(404).json({ message: 'Wishlist not found' }); + } + + const productIndex = wishList.product.findIndex((p) => p.id === productId); + if (productIndex === -1) { + return res.status(404).json({ message: 'Product not found in wishlist' }); + } + + wishList.product.splice(productIndex, 1); + await buyerWishListRepository.save(wishList); + + return res.status(200).json({ + message: 'Product successfully removed from wishlist', + data: wishList, + }); + }), +]; + +export const getAllWishList = errorHandler( + async (req: Request, res: Response) => { + const wishList = await buyerWishListRepository.find({ + select: { + product: true, + time: true, + user: { + lastName: true, + isVerified: true, + picture: true, + userType: { + name: true, + }, + }, + }, + relations: ['user', 'product'], + }); + + return res + .status(200) + .json({ message: 'Data retrieved successfully', data: wishList }); + } +); + +export const getOneWishList = errorHandler( + async (req: Request, res: Response) => { + const userId = req.user?.id; + if (!userId) { + return res.status(404).json({ message: 'User ID not found' }); + } + + const wishList = await buyerWishListRepository.findOne({ + where: { user: { id: userId } }, + relations: ['product'], + }); + + return res + .status(200) + .json({ message: 'Data retrieved successfully', data: wishList }); + } +); diff --git a/src/database/models/buyerWishList.ts b/src/database/models/buyerWishList.ts new file mode 100644 index 00000000..f7aaaf47 --- /dev/null +++ b/src/database/models/buyerWishList.ts @@ -0,0 +1,26 @@ +import { Column, Entity, ManyToMany, PrimaryGeneratedColumn, OneToOne, JoinColumn, JoinTable, ManyToOne } from 'typeorm'; +import Product from './productEntity'; +import UserModel from './userModel'; +import Category from './categoryEntity'; + +@Entity() +export default class BuyerWishList { + + @PrimaryGeneratedColumn() + id: number; + + @OneToOne(() => UserModel) + @JoinColumn() + user: UserModel; + + @ManyToMany(() => Product) + @JoinTable() + product: Product[]; + + @ManyToOne(() => Category) + category: Category; + + @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) + time: Date; + +} diff --git a/src/docs/buyerDocs.ts b/src/docs/buyerDocs.ts index 3c8aa4b2..c2716a3a 100644 --- a/src/docs/buyerDocs.ts +++ b/src/docs/buyerDocs.ts @@ -1,20 +1,136 @@ /** * @swagger - * /api/v1/buyer/get_product/{id}: + * tags: + * name: buyer + * description: Category management + */ + +/** + * @openapi + * /buyer/addItemToWishList: + * post: + * tags: [buyer] + * @security bearerAuth + * summary: Adds an item to the wishlist + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: integer + * productId: + * type: integer + * time: + * type: string + * categoryId: + * type: integer + * responses: + * 201: + * description: Wishlist item added successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @openapi + * /buyer/removeToWishList: + * delete: + * tags: [buyer] + * @security bearerAuth + * summary: Removes a product from the wishlist + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: integer + * productId: + * type: integer + * responses: + * 200: + * description: Product successfully removed from wishlist + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @openapi + * /buyer/getWishList: * get: + * tags: [buyer] + * @security bearerAuth + * summary: Retrieves all wishlists + * responses: + * 200: + * description: Data retrieved successfully + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @swagger + * /buyer/addItemToWishList: + * post: * summary: Get a specific product * tags: [Buyer] * security: * - bearerAuth: [] - * parameters: - * - in: path - * name: id - * type: string - * required: true - * description: ID of the product to get + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * productId: + * type: integer + * time: + * type: string * responses: * '200': - * description: Successful + * description: Wishlist item added successfully + * '400': + * description: Bad request + * '404': + * description: Wishlist not found + * '500': + * description: Internal server error + */ + +/** + * @swagger + * /api/v1/buyer/removeToWishList: + * delete: + * summary: Remove a product to WishList + * tags: [Buyer] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * productId: + * type: integer + * responses: + * '200': + * description: Successful Removed a Product * '404': * description: Product not found * '500': @@ -22,51 +138,35 @@ */ /** -* @swagger -* /api/v1/buyer/payment: -* post: -* summary: Create a charge -* tags: [Buyer] -* security: -* - bearerAuth: [] -* requestBody: -* content: -* application/json: -* schema: -* type: object -* properties: -* token: -* type: string -* description: Stripe token -* orderId: -* type: number -* description: Order ID -* required: -* - token -* - orderId -* responses: -* '200': -* description: Successful operation -* content: -* application/json: -* schema: -* type: object -* properties: -* success: -* type: boolean -* description: Whether the charge was successful -* charge: -* type: object -* description: The charge object returned by Stripe -* required: -* - success -* - charge -* '400': -* description: Invalid input or order has already been paid -* '404': -* description: Order not found -* '500': -* description: Internal Server Error -*/ - + * @swagger + * /api/v1/buyer/getWishList: + * get: + * summary: Get a All Wish List + * tags: [Buyer] + * security: + * - bearerAuth: [] + * responses: + * '200': + * description: Successful + * '404': + * description: Product not found + * '500': + * description: Internal Server Error + */ +/** + * @swagger + * /api/v1/buyer/getOneWishList: + * get: + * summary: Get One Wish List + * tags: [Buyer] + * security: + * - bearerAuth: [] + * responses: + * '200': + * description: Successful + * '404': + * description: Product not found + * '500': + * description: Internal Server Error + */ diff --git a/src/docs/buyerWishlist.ts b/src/docs/buyerWishlist.ts new file mode 100644 index 00000000..45b8520a --- /dev/null +++ b/src/docs/buyerWishlist.ts @@ -0,0 +1,220 @@ +/** + * @swagger + * tags: + * name: buyer + * description: Category management + */ + +/** + * @openapi + * /buyer/addItemToWishList: + * post: + * tags: [buyer] + * @security bearerAuth + * summary: Adds an item to the wishlist + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: integer + * productId: + * type: integer + * time: + * type: string + * categoryId: + * type: integer + * responses: + * 201: + * description: Wishlist item added successfully + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @openapi + * /buyer/removeToWishList: + * delete: + * tags: [buyer] + * @security bearerAuth + * summary: Removes a product from the wishlist + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * userId: + * type: integer + * productId: + * type: integer + * responses: + * 200: + * description: Product successfully removed from wishlist + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @openapi + * /buyer/getWishList: + * get: + * tags: [buyer] + * @security bearerAuth + * summary: Retrieves all wishlists + * responses: + * 200: + * description: Data retrieved successfully + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/BuyerWishList' + */ + +/** + * @swagger + * /buyer/addItemToWishList: + * post: + * summary: Get a specific product + * tags: [Buyer] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * productId: + * type: integer + * time: + * type: string + * responses: + * '200': + * description: Wishlist item added successfully + * '400': + * description: Bad request + * '404': + * description: Wishlist not found + * '500': + * description: Internal server error + */ + +/** + * @swagger + * /api/v1/buyer/removeToWishList: + * delete: + * summary: Remove a product to WishList + * tags: [Buyer] + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * productId: + * type: integer + * responses: + * '200': + * description: Successful Removed a Product + * '404': + * description: Product not found + * '500': + * description: Internal Server Error + */ + +/** + * @swagger + * /api/v1/buyer/getWishList: + * get: + * summary: Get a All Wish List + * tags: [Buyer] + * security: + * - bearerAuth: [] + * responses: + * '200': + * description: Successful + * '404': + * description: Product not found + * '500': + * description: Internal Server Error + */ + +/** + * @swagger + * /api/v1/buyer/getOneWishList: + * get: + * summary: Get One Wish List + * tags: [Buyer] + * security: + * - bearerAuth: [] + * responses: + * '200': + * description: Successful + * '404': + * description: Product not found + * '500': + * description: Internal Server Error + */ + +/** + * @swagger + * /api/v1/buyer/payment: + * post: + * summary: Create a charge + * tags: [Buyer] + * security: + * - bearerAuth: [] + * requestBody: + * content: + * application/json: + * schema: + * type: object + * properties: + * token: + * type: string + * description: Stripe token + * orderId: + * type: number + * description: Order ID + * required: + * - token + * - orderId + * responses: + * '200': + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * description: Whether the charge was successful + * charge: + * type: object + * description: The charge object returned by Stripe + * required: + * - success + * - charge + * '400': + * description: Invalid input or order has already been paid + * '404': + * description: Order not found + * '500': + * description: Internal Server Error + */ diff --git a/src/routes/buyerRoutes.ts b/src/routes/buyerRoutes.ts index 4159a39f..0952c5af 100644 --- a/src/routes/buyerRoutes.ts +++ b/src/routes/buyerRoutes.ts @@ -2,17 +2,25 @@ import { Router } from 'express'; import { checkRole } from '../middlewares/authorize'; import { getOneProduct } from '../controller/buyerController'; import { IsLoggedIn } from '../middlewares/isLoggedIn'; +import { + AddItemInWishList, + RemoveProductFromWishList, + getAllWishList, + getOneWishList, +} from '../controller/buyerWishlistController'; import { handlePayment } from '../controller/buyerController'; const buyerRouter = Router(); buyerRouter.use(IsLoggedIn, checkRole(['Buyer'])); - buyerRouter.get('/get_product/:id', getOneProduct); +buyerRouter.post('/addItemToWishList', IsLoggedIn, AddItemInWishList); +buyerRouter.delete('/removeToWishList', IsLoggedIn, RemoveProductFromWishList); +buyerRouter.get('/getWishList', IsLoggedIn, getAllWishList); +buyerRouter.get('/getOneWishList', IsLoggedIn, getOneWishList); buyerRouter.post('/payment', handlePayment); - export default buyerRouter;