diff --git a/src/controller/chatbotController.ts b/src/controller/chatbotController.ts new file mode 100644 index 00000000..d6aa82a1 --- /dev/null +++ b/src/controller/chatbotController.ts @@ -0,0 +1,26 @@ +import { Request, Response } from 'express'; +import * as chatbotService from '../service/chatbotService'; +import errorHandler from '../middlewares/errorHandler'; + +export const getChatResponse = errorHandler( + async ( + req: Request, + res: Response + ): Promise> | undefined> => { + const { message } = req.body; + const userId = req.user?.id; + const response = await chatbotService.processMessage(userId, message); + return res.status(200).json({ message: response }); + } +); + +export const getChatHistory = errorHandler( + async ( + req: Request, + res: Response + ): Promise> | undefined> => { + const userId = req.user?.id; + const history = await chatbotService.getChatHistory(userId); + return res.status(200).json({ history }); + } +); diff --git a/src/controller/productController.ts b/src/controller/productController.ts index eb13774b..328a1862 100644 --- a/src/controller/productController.ts +++ b/src/controller/productController.ts @@ -7,9 +7,6 @@ import { check, validationResult } from 'express-validator'; import errorHandler from '../middlewares/errorHandler'; import productQuantityWatch from '../middlewares/productAvailabilityWatch'; - - - const userRepository = dbConnection.getRepository(UserModel); const productRepository = dbConnection.getRepository(Product); @@ -70,7 +67,7 @@ export const createProduct = [ if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } - + const vendorId = req.user!.id; const { @@ -366,17 +363,21 @@ export const AvailableProducts = errorHandler( message: 'Items retrieved successfully.', availableProducts, totalPages: Math.ceil(totalCount / limit), - currentPage: page - }); -}) + currentPage: page, + }); + } +); // From Bernard #38 -export const updateProductAvailability = async (req: Request, res: Response) => { +export const updateProductAvailability = async ( + req: Request, + res: Response +) => { const { productId } = req.params; const { availability } = req.body; const user = await userRepository.findOne({ - where: { id: (req.user as User).id}, + where: { id: (req.user as User).id }, }); if (!user) { @@ -385,7 +386,7 @@ export const updateProductAvailability = async (req: Request, res: Response) => const product = await productRepository.findOne({ where: { id: Number(productId) }, - relations: ['vendor'] + relations: ['vendor'], }); if (!product) { @@ -402,18 +403,16 @@ export const updateProductAvailability = async (req: Request, res: Response) => res.json({ msg: 'Product availability updated' }); }; - export const checkProductAvailability = async (req: Request, res: Response) => { const { productId } = req.params; const product = await productRepository.findOne({ where: { id: Number(productId) }, - relations: ['vendor'] + relations: ['vendor'], }); - const user = await userRepository.findOne({ - where: { id: (req.user as User).id}, + where: { id: (req.user as User).id }, }); if (!user) { @@ -423,7 +422,7 @@ export const checkProductAvailability = async (req: Request, res: Response) => { if (!product) { return res.status(404).json({ msg: 'Product not found' }); } - if (product.vendor.id!== user.id) { + if (product.vendor.id !== user.id) { return res.status(403).json({ msg: 'Product not owned by vendor' }); } diff --git a/src/database/models/chatbotModel.ts b/src/database/models/chatbotModel.ts new file mode 100644 index 00000000..57d0a966 --- /dev/null +++ b/src/database/models/chatbotModel.ts @@ -0,0 +1,20 @@ +import { Entity,PrimaryGeneratedColumn,Column,ManyToOne,CreateDateColumn } from 'typeorm'; +import User from './userModel'; + +@Entity() +export default class chat{ + @PrimaryGeneratedColumn() + id:number; + + @ManyToOne(()=>User) + user: User; + + @Column() + message:string; + + @Column() + response:string; + + @CreateDateColumn() + createdAt:Date; +} \ No newline at end of file diff --git a/src/middlewares/errorHandler.ts b/src/middlewares/errorHandler.ts index 3d741642..a4cd06a2 100644 --- a/src/middlewares/errorHandler.ts +++ b/src/middlewares/errorHandler.ts @@ -10,6 +10,7 @@ function errorHandler(func: MiddlewareFunction): MiddlewareFunction { try { return await func(req, res); } catch (error) { + // console.log({'Error':error}) const message = (error as { detail?: string }).detail || 'Internal Server Error'; return res.status(500).send(message); diff --git a/src/routes/chatbotRoutes.ts b/src/routes/chatbotRoutes.ts new file mode 100644 index 00000000..6f9d3a8e --- /dev/null +++ b/src/routes/chatbotRoutes.ts @@ -0,0 +1,11 @@ +import { Router } from 'express'; +import { getChatResponse, getChatHistory } from '../controller/chatbotController'; +import { IsLoggedIn } from '../middlewares/isLoggedIn'; +import { checkRole } from '../middlewares/authorize'; + +const router = Router(); + +router.post('/chat', IsLoggedIn,checkRole(['Buyer']), getChatResponse); +router.get('/chat/history', IsLoggedIn,checkRole(['Buyer']), getChatHistory); + +export default router; diff --git a/src/routes/index.ts b/src/routes/index.ts index bdf772b4..bfeff81b 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -7,6 +7,7 @@ import buyerRoutes from './buyerRoutes'; import cartRoutes from '../routes/cartRoutes'; import couponRouter from './couponRoute'; import chekoutRoutes from './checkoutRoutes'; +import chatRoutes from './chatbotRoutes'; const router = Router(); router.use('/user', userRouter); @@ -17,5 +18,6 @@ router.use('/buyer', buyerRoutes); router.use('/cart', cartRoutes); router.use('/coupons', couponRouter); router.use('/checkout', chekoutRoutes); +router.use('/', chatRoutes); export default router; diff --git a/src/service/chatbotService.ts b/src/service/chatbotService.ts new file mode 100644 index 00000000..0d2a8865 --- /dev/null +++ b/src/service/chatbotService.ts @@ -0,0 +1,32 @@ +import Chat from '../database/models/chatbotModel'; +import User from '../database/models/userModel'; +import dbConnection from '../database'; +import { analyzeMessege, generateResponse } from '../utilis/nlp'; + +export const processMessage = async (userId: number, message: string): Promise => { + const userRepo = dbConnection.getRepository(User); + const chatRepo = dbConnection.getRepository(Chat); + + const user = await userRepo.findOne({ + where:{ id:userId } + }); + if (!user) { + throw new Error('User not found'); + } + + const analyzedMessage = analyzeMessege(message); + const response = await generateResponse(analyzedMessage); + + const chat = new Chat(); + chat.user = user; + chat.message = message; + chat.response = response; + await chatRepo.save(chat); + + return response; +}; + +export const getChatHistory = async (userId: number): Promise => { + const chatRepo = dbConnection.getRepository(Chat); + return chatRepo.find({ where: { user: { id: userId } }, order: { createdAt: 'DESC' } }); +}; diff --git a/src/utilis/nlp.ts b/src/utilis/nlp.ts new file mode 100644 index 00000000..71a4587b --- /dev/null +++ b/src/utilis/nlp.ts @@ -0,0 +1,19 @@ +export const analyzeMessege = (message: string): string => { + return message.toLowerCase() +}; + +export const generateResponse= async(message:string):Promise=>{ + if (message.includes('product')) { + return 'We sell various products such as electronics, clothing, and home appliances.'; + } + if (message.includes('recommend')) { + return 'Based on your history, we recommend our latest smartphones and laptops.'; + } + if (message.includes('delivery')) { + return 'Our delivery process usually takes 3-5 business days.'; + } + if (message.includes('help')) { + return 'How can I assist you with navigating our platform or completing an order?'; + } + return 'I am sorry, I did not understand that. Could you please rephrase?'; +} \ No newline at end of file diff --git a/src/utils/couponCalculator.ts b/src/utils/couponCalculator.ts deleted file mode 100644 index 5f23f470..00000000 --- a/src/utils/couponCalculator.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Coupon from '../database/models/couponEntity'; -import Product from '../database/models/productEntity'; -import dbConnection from '../database'; - -const couponRepository = dbConnection.getRepository(Coupon); - -export default async function applyCoupon(product: Product, couponCode: string, price: number): Promise { - const coupon = await couponRepository.findOne({ where: { code: couponCode }, relations: ['applicableProducts'] }); - - if (!coupon) { - return price; - } - - if (!coupon.applicableProducts.find(applicableProduct => applicableProduct.id === product.id)) { - return price; - } - const percentage = coupon.percentage / 100; - return price * (1 - percentage); -} \ No newline at end of file