Skip to content

Commit

Permalink
Merge branch 'ft-product-managment' of https://github.com/atlp-rwanda…
Browse files Browse the repository at this point in the history
…/knights-ecomm-be into ft-product-managment
  • Loading branch information
MC-Knight committed May 9, 2024
2 parents 8368232 + 9c53a2f commit ba17009
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 4 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ PINDO_API_URL = ********************************
PINDO_SENDER = ********************************
JWT_SECRET = ********************************
TWO_FA_MINS = ********************************

HOST = *******************
AUTH_EMAIL = *********************
AUTH_PASSWORD = ******************
Expand Down
14 changes: 13 additions & 1 deletion src/controllers/productController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Request, Response } from 'express';
import { createProductService, updateProductService, removeProductImageService } from '../services';
import { createProductService, updateProductService, removeProductImageService, readProductService, readProductsService, deleteProductService } from '../services';

export const readProduct = async (req: Request, res: Response) => {
await readProductService(req, res);
};

export const readProducts = async (req: Request, res: Response) => {
await readProductsService(req, res);
};

export const createProduct = async (req: Request, res: Response) => {
await createProductService(req, res);
Expand All @@ -12,3 +20,7 @@ export const updateProduct = async (req: Request, res: Response) => {
export const removeProductImage = async (req: Request, res: Response) => {
await removeProductImageService(req, res);
};

export const deleteProduct = async (req: Request, res: Response) => {
await deleteProductService(req, res);
};
2 changes: 1 addition & 1 deletion src/middlewares/verifyToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const authMiddleware = async (req: AuthRequest, res: Response, next: Next
next();
}
});
} catch (ex) {
} catch (error) {
return res.status(401).json({ error: 'Invalid token' });
}
}
Expand Down
12 changes: 11 additions & 1 deletion src/routes/ProductRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@ import { Router } from 'express';
import upload from '../middlewares/multer';
import { authMiddleware } from '../middlewares/verifyToken';
import { hasRole } from '../middlewares';
import { createProduct, updateProduct, removeProductImage } from '../controllers/productController';
import {
createProduct,
updateProduct,
removeProductImage,
readProducts,
readProduct,
deleteProduct,
} from '../controllers/productController';

const router = Router();

router.get('/', authMiddleware, hasRole('VENDOR'), readProducts);
router.get('/:id', authMiddleware, hasRole('VENDOR'), readProduct);
router.post('/', authMiddleware, hasRole('VENDOR'), upload.array('images', 10), createProduct);
router.put('/:id', authMiddleware, hasRole('VENDOR'), upload.array('images', 10), updateProduct);
router.delete('/images/:id', authMiddleware, hasRole('VENDOR'), removeProductImage);
router.delete('/:id', authMiddleware, hasRole('VENDOR'), deleteProduct);

export default router;
4 changes: 4 additions & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export * from './userServices/userValidateOTP';
export * from './userServices/userLoginService';
export * from './userServices/userResendOTP';
export * from './userServices/logoutServices';

// Vendor product services
export * from './productServices/createProduct';
export * from './productServices/updateProduct';
export * from './productServices/removeProductImage';
export * from './productServices/readProduct';
export * from './productServices/deleteProduct';
32 changes: 32 additions & 0 deletions src/services/productServices/deleteProduct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Request, Response } from 'express';
import { Product } from '../../entities/Product';
import { getRepository } from 'typeorm';
import { responseError, responseSuccess } from '../../utils/response.utils';


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

const productRepository = getRepository(Product);

const product = await productRepository.findOne({
where: {
id: id,
vendor: {
id: req.user?.id
}
}
});

if (product) {
await productRepository.remove(product);
return responseSuccess(res, 200, 'Product successfully deleted');
}

return responseError(res, 404, 'Product not found');

} catch (error) {
responseError(res, 400, (error as Error).message);
}
};
58 changes: 58 additions & 0 deletions src/services/productServices/readProduct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Request, Response } from 'express';
import { Product } from '../../entities/Product';
import { getRepository } from 'typeorm';
import { responseError, responseSuccess } from '../../utils/response.utils';


export const readProductsService = async (req: Request, res: Response) => {
try {

// Define pagination parameters
const page = req.query.page ? Number(req.query.page) : 1;
const limit = req.query.limit ? Number(req.query.limit) : 10;
const skip = (page - 1) * limit;

// Retrieve products
const productRepository = getRepository(Product);
const products = await productRepository.find({
where: {
vendor: {
id: req.user?.id
}
},
skip,
take: limit
});

if (!products) {
return responseError(res, 404, 'No Products available');
}
return responseSuccess(res, 200, 'Products retrieved', { products });
} catch (error) {
responseError(res, 400, (error as Error).message);
}
};

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

const productRepository = getRepository(Product);
const product = await productRepository.findOne({
where: {
id: id,
vendor: {
id: req.user?.id
}
}
});

if (!product) {
return responseError(res, 404, 'Product not found');
}

return responseSuccess(res, 200, 'Product retrieved', { product });
} catch (error) {
responseError(res, 400, (error as Error).message);
}
};
4 changes: 4 additions & 0 deletions src/services/productServices/removeProductImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const removeProductImageService = async (req: Request, res: Response) =>
return res.status(403).json({ status: 'error', error: 'You are not authorized to perform this action' });
}

if (product.images.length === 2) {
return res.status(400).json({ status: 'error', error: 'Product must have at least two image' });
}

const index = product.images.indexOf(image);

if (index === -1) {
Expand Down
3 changes: 3 additions & 0 deletions src/services/productServices/updateProduct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export const updateProductService = async (req: Request, res: Response) => {
}

if (req.files) {
if (product.images.length + req.files.length > 10) {
return res.status(400).json({ status: 'error', error: 'Product cannot have more than 10 images' });
}
const imageUrls: string[] = [];
for (const image of req.files) {
const link = await cloudinary.uploader.upload(image.path);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/response.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const responseSuccess = (
jsend.success({
code: statusCode,
message,
data,
...data,
})
);
};
Expand Down

0 comments on commit ba17009

Please sign in to comment.