From 56ce458b3fd46b0a743d7e165418dc07f08c1c5c Mon Sep 17 00:00:00 2001 From: soleil00 Date: Fri, 26 Jul 2024 17:34:39 +0200 Subject: [PATCH] emited to notofy seller whwner user place order or added their product in wish list --- src/controllers/getOrderController.ts | 84 ++++++++------- src/controllers/paymentController.ts | 90 ++++++++-------- src/controllers/wishesController.ts | 37 ++++++- src/events/handler.ts | 11 ++ src/services/OrderService.ts | 4 +- src/services/payment.service.ts | 145 ++++++++++++++------------ 6 files changed, 219 insertions(+), 152 deletions(-) diff --git a/src/controllers/getOrderController.ts b/src/controllers/getOrderController.ts index 66f8541..ea9bcbb 100644 --- a/src/controllers/getOrderController.ts +++ b/src/controllers/getOrderController.ts @@ -1,48 +1,60 @@ -import { Request, Response } from "express" -import { getOrderBuyer, updateOrderStatusService } from "../services/OrderService" +import { Request, Response } from "express"; +import { getOrderBuyer, updateOrderStatusService } from "../services/OrderService"; import * as mailService from "../services/mail.service"; import { SUBJECTS, UserId } from "../types"; import { orderStatusTemplate } from "../email-templates/orderStatus"; import Order from "../sequelize/models/orders"; import User from "../sequelize/models/users"; - +import Notification from "../sequelize/models/Notification"; +import { notificationEmitter } from "../utils/server"; export const getOrderController = async (req: Request, res: Response) => { - try { - const response = await getOrderBuyer(req, res) - return res.status(200).json({ - status: 200, - length: response?.length, - orders: response?.length === 0? "You have not order yet" : response - }) - } catch (error) { - console.log(error); - res.status(500).json({ - status: 500, - message: `error accured during fetching order ${error}` - }) - } -} + try { + const response = await getOrderBuyer(req, res); + return res.status(200).json({ + status: 200, + length: response?.length, + orders: response?.length === 0 ? "You have not order yet" : response, + }); + } catch (error) { + console.log(error); + res.status(500).json({ + status: 500, + message: `error accured during fetching order ${error}`, + }); + } +}; export const updateOrderStatus = async (req: Request, res: Response) => { - - try { - const { id: userId} = req.user as UserId; - const { id: orderId } = req.params; - const { status } = req.body; - const buyerId = await Order.findByPk(orderId) - const dataValues = await User.findByPk(buyerId?.buyerId) + try { + const { id: userId } = req.user as UserId; + const { id: orderId } = req.params; + const { status } = req.body; + const buyerOrder = await Order.findByPk(orderId); + const dataValues = await User.findByPk(buyerOrder?.buyerId); + + const updatedItems = await updateOrderStatusService(userId, orderId, status); + if (updatedItems) { + // @ts-ignore + await mailService.sendNotification( + dataValues?.dataValues.email, + SUBJECTS.ORDER_STATUS_UPDATED, + //@ts-ignore + orderStatusTemplate(dataValues?.dataValues.username, buyerOrder?.id, buyerOrder?.createdAt, status), + ); + + const notification = await Notification.create({ + title: "Order Status updated", + message: `Dear ${dataValues?.dataValues.username} your Order ${buyerOrder?.id} status updated to ${status}`, + //@ts-ignore + userId: buyerOrder?.buyerId, + }); - const updatedItems = await updateOrderStatusService(userId, orderId, status); - if (updatedItems) { - // @ts-ignore - await mailService.sendNotification(dataValues?.dataValues.email, SUBJECTS.ORDER_STATUS_UPDATED, orderStatusTemplate(dataValues?.dataValues.username, buyerId?.id, buyerId?.createdAt, status)) + notificationEmitter.emit("order updated", notification.dataValues); - return res.json({ message: 'Order items status updated', updatedItems }); - } - - } catch (error: any) { - res.status(500).json({ message: error.message }); + return res.json({ message: "Order items status updated", updatedItems }); } - }; - \ No newline at end of file + } catch (error: any) { + res.status(500).json({ message: error.message }); + } +}; diff --git a/src/controllers/paymentController.ts b/src/controllers/paymentController.ts index cd67b39..d55f415 100644 --- a/src/controllers/paymentController.ts +++ b/src/controllers/paymentController.ts @@ -7,58 +7,58 @@ import { SUBJECTS } from "../types"; import { confirmPayment } from "../email-templates/confirmPayment"; import stripe from "../config/stripe"; import dotenv from "dotenv"; -dotenv.config() +dotenv.config(); const BASE_URL = process.env.IS_REMOTE === "true" ? process.env.FE_URL : process.env.LOCAL_URL; export const createCheckoutSession = async (req: Request, res: Response) => { - const user: any = req.user; - try { - //@ts-ignore - const cart = req.cart; - const line_items = makeLineItems(cart.userCart); - const customer = await getOrCreateCustomer(user); - const session = await stripe.checkout.sessions.create({ - line_items, - mode: "payment", - customer: customer.id, - success_url: `${BASE_URL}/payment/success?sessionId={CHECKOUT_SESSION_ID}&userId=${user.id}`, - cancel_url: `${BASE_URL}/payment/canceled`, - }); - return res.status(200).json({ - message: "payment session created!", - sessionUrl: session.url - }); - } catch (err: any) { - return res.status(500).json({ - message: err.message - }) - } - + const user: any = req.user; + try { + //@ts-ignore + const cart = req.cart; + const line_items = makeLineItems(cart.userCart); + const customer = await getOrCreateCustomer(user); + const session = await stripe.checkout.sessions.create({ + line_items, + mode: "payment", + customer: customer.id, + success_url: `${BASE_URL}/payment/success?sessionId={CHECKOUT_SESSION_ID}&userId=${user.id}`, + cancel_url: `${BASE_URL}/payment/canceled`, + }); + return res.status(200).json({ + message: "payment session created!", + sessionUrl: session.url, + }); + } catch (err: any) { + return res.status(500).json({ + message: err.message, + }); + } }; export const handleSuccess = async (req: Request, res: Response) => { - try { - const { userId, sessionId } = req.query as { userId: string, sessionId: string } - const session = await stripe.checkout.sessions.retrieve(sessionId); - const user: any = await findUserById(userId); - const cart: any = await viewCart(user); - if (session.payment_status === "paid") { - const order = await placeOrder(cart); - await clearCart(user); - await mailService.sendEmailService(user, SUBJECTS.PAYMENT_CONFIRMATION, confirmPayment(user, order)); - return res.status(200).json({ - message: "you have successfully paid your products", - order - }); - } - } catch (err: any) { - return res.status(500).json({ - message: err.message - }) + try { + const { userId, sessionId } = req.query as { userId: string; sessionId: string }; + const session = await stripe.checkout.sessions.retrieve(sessionId); + const user: any = await findUserById(userId); + const cart: any = await viewCart(user); + if (session.payment_status === "paid") { + const order = await placeOrder(cart); + await clearCart(user); + await mailService.sendEmailService(user, SUBJECTS.PAYMENT_CONFIRMATION, confirmPayment(user, order)); + + return res.status(200).json({ + message: "you have successfully paid your products", + order, + }); } -} + } catch (err: any) { + return res.status(500).json({ + message: err.message, + }); + } +}; export const handleFailure = async (req: Request, res: Response) => { - return res.status(500).json({ message: "Your payment has failed!" }) -} \ No newline at end of file + return res.status(500).json({ message: "Your payment has failed!" }); +}; diff --git a/src/controllers/wishesController.ts b/src/controllers/wishesController.ts index 314df3e..284a5b2 100644 --- a/src/controllers/wishesController.ts +++ b/src/controllers/wishesController.ts @@ -1,10 +1,15 @@ import * as wishlistService from "../services/wishlist.service"; import { Request, Response } from "express"; import { wishSchema } from "../schemas/wishShema"; +import { notificationEmitter } from "../utils/server"; +import Notification from "../sequelize/models/Notification"; +import { IUser } from "../types"; +import Product from "../sequelize/models/products"; export const addToWishes = async (req: Request, res: Response) => { //@ts-ignore const id = req.user.id; + const currentUser: IUser = (req as any).user; try { const { error, value } = wishSchema.validate(req.body); if (error) { @@ -14,10 +19,10 @@ export const addToWishes = async (req: Request, res: Response) => { }); } const product = await wishlistService.getProduct(value.productId); - if(!product){ + if (!product) { return res.status(404).json({ - message: 'product not found' - }) + message: "product not found", + }); } const isProdExisting = await wishlistService.getSingleWish(id, value.productId); if (isProdExisting) { @@ -27,6 +32,14 @@ export const addToWishes = async (req: Request, res: Response) => { } const wish = await wishlistService.addToWishlist(id, value.productId); if (wish) { + const notification = await Notification.create({ + title: "Product Added to Wishlist", + message: `${currentUser.name} has added your product ${product.name} to his wishlist`, + userId: wish.sellerId, + }); + + notificationEmitter.emit("wishlist", notification.dataValues); + return res.status(201).json({ message: "product was added to your wishlist", }); @@ -92,14 +105,32 @@ export const deleteWish = async (req: Request, res: Response) => { //@ts-ignore const id = req.user.id; const productId = Number(req.params.id); + + const currentUser: IUser = (req as any).user; try { const isOwner = await wishlistService.getSingleWish(id, productId); + const product = await Product.findByPk(productId); + + if (!product) { + return res.status(404).json({ + message: "product not found", + }); + } if (!isOwner) { return res.status(404).json({ message: "product does not exist in your wishes", }); } else { await wishlistService.removeProduct(id, productId); + + const notification = await Notification.create({ + title: "Product Removed from Wishlist", + message: `${currentUser.name} has removed your product ${product?.name} from his wishlist`, + userId: product.userId, + }); + + notificationEmitter.emit("wishlist", notification.dataValues); + return res.status(200).json({ message: "product was removed from your wishes", }); diff --git a/src/events/handler.ts b/src/events/handler.ts index 2655d47..0f39557 100644 --- a/src/events/handler.ts +++ b/src/events/handler.ts @@ -3,6 +3,7 @@ import NotificationEmitter from "./emmiter"; import { INotification } from "../sequelize/models/Notification"; import { IUser } from "../types"; import { passwordEventEmitter } from "../jobs/isPasswordExpired"; +import { wishAttributes } from "../sequelize/models/wishes"; class EventHandler { public io: SocketIOServer; @@ -45,6 +46,16 @@ class EventHandler { this.io.to(`${data[0].userId}`).emit("notifications", data); }); + this.notificationEmitter.on("wishlist", (data: INotification) => { + this.io.to(`${data.userId}`).emit("notification", data); + }); + this.notificationEmitter.on("new order", (data: INotification) => { + this.io.to(`${data.userId}`).emit("notification", data); + }); + this.notificationEmitter.on("order updated", (data: INotification) => { + this.io.to(`${data.userId}`).emit("notification", data); + }); + passwordEventEmitter.on("password expired", (data: IUser) => { this.io.to(`${data.id}`).emit("password expired", data); }); diff --git a/src/services/OrderService.ts b/src/services/OrderService.ts index 9f333e2..d47d566 100644 --- a/src/services/OrderService.ts +++ b/src/services/OrderService.ts @@ -99,9 +99,9 @@ export const updateOrderStatusService = async (userId: string, orderId: string, for (const item of orderItems) { item.status = status; + await item.save(); } - + return orderItems; }; - diff --git a/src/services/payment.service.ts b/src/services/payment.service.ts index a7259ff..1b3b260 100644 --- a/src/services/payment.service.ts +++ b/src/services/payment.service.ts @@ -2,78 +2,91 @@ import stripe from "../config/stripe"; import { CartAttributes } from "../sequelize/models/Cart"; import OrderItem from "../sequelize/models/orderItems"; import Order from "../sequelize/models/orders"; -import { UserAttributes } from "../sequelize/models/users"; +import User, { UserAttributes } from "../sequelize/models/users"; import Product from "../sequelize/models/products"; - +import Notification from "../sequelize/models/Notification"; +import { notificationEmitter } from "../utils/server"; export const getOrCreateCustomer = async (user: UserAttributes) => { - try { - const existing = await stripe.customers.list({ email: user.email }); - if (existing.data.length > 0) { - return existing.data[0]; - } else { - const customer = await stripe.customers.create({ - name: `${user.name}`, - email: user.email, - }); - return customer; - } - } catch (error: any) { - throw new Error("Error while creating customer " + error.message) - } + try { + const existing = await stripe.customers.list({ email: user.email }); + if (existing.data.length > 0) { + return existing.data[0]; + } else { + const customer = await stripe.customers.create({ + name: `${user.name}`, + email: user.email, + }); + return customer; + } + } catch (error: any) { + throw new Error("Error while creating customer " + error.message); + } }; - export const makeLineItems = (cart: CartAttributes) => { - const lineItems = []; - const items: any = cart.items; - for (const item of items) { - const lineItem = { - price_data: { - currency: "rwf", - product_data: { - name: item.product.name, - - }, - unit_amount: item.product.price, - }, - quantity: item.quantity, - }; - lineItems.push(lineItem); - } - return lineItems; + const lineItems = []; + const items: any = cart.items; + for (const item of items) { + const lineItem = { + price_data: { + currency: "rwf", + product_data: { + name: item.product.name, + }, + unit_amount: item.product.price, + }, + quantity: item.quantity, + }; + lineItems.push(lineItem); + } + return lineItems; }; export const placeOrder = async (cart: CartAttributes) => { - const currentDate = new Date(Date.now()); - const deliveryDate = new Date(currentDate.setDate(currentDate.getDate() + 3)); - //@ts-ignore - const order = await Order.create({ buyerId: cart.userCart.userId, - deliveryDate - }) - //@ts-ignore - const items = cart.userCart.items; - for(const item of items){ - const cartItem = await OrderItem.create( - { - orderId: order.id as number, - // @ts-ignore - userId: item.product.userId , - productId: item.productId, - quantity: item.quantity, - } - ) - }; - const ordered = await Order.findOne({ - where: { id: order.id }, include: [ - { - model: OrderItem, - as: "items", include: [{ - model: Product, - as: "product", - },] - }, - ], - }) - return ordered; -} \ No newline at end of file + const user = await User.findByPk(cart.userId); + const currentDate = new Date(Date.now()); + const deliveryDate = new Date(currentDate.setDate(currentDate.getDate() + 3)); + //@ts-ignore + const order = await Order.create({ buyerId: cart.userCart.userId, deliveryDate }); + //@ts-ignore + const items = cart.userCart.items; + for (const item of items) { + const cartItem = await OrderItem.create({ + orderId: order.id as number, + // @ts-ignore + userId: item.product.userId, + productId: item.productId, + quantity: item.quantity, + }); + + const product = await Product.findByPk(item.productId); + + if (!product) { + throw new Error("Product not found"); + } + const notification = await Notification.create({ + title: "Your have new order", + message: `${user?.username} has successfuly placed New Order on your product ${product?.name}`, + userId: product?.userId, + }); + + notificationEmitter.emit("new order", notification.dataValues); + } + const ordered = await Order.findOne({ + where: { id: order.id }, + include: [ + { + model: OrderItem, + as: "items", + include: [ + { + model: Product, + as: "product", + }, + ], + }, + ], + }); + return ordered; +};